使用STM32编写DS18B20温度传感器代码
起因是制作恒温箱,csdn现有的温度传感器代码在使用中都或多或少有问题,现分享一下。(32版本!!!)
使用的是DS18B20温度传感器模块,三根线直接连接到最小核心系统板,再加上显示屏就能读取显示温度了。本人亲测并使用的代码,完美运行,代码逻辑很简单,看懂不难。
以下为运行代码,可自己更改一下引脚配置,在这我的DQ线连接的PB14口。
DS18B20.c:
#include "stm32f10x.h" // Device header
#include "Delay.h"
#define DS18B20_GPIO GPIOB
#define DS18B20_Pin GPIO_Pin_14
#define DQ_H GPIO_SetBits(DS18B20_GPIO,DS18B20_Pin) //PB14拉高
#define DQ_L GPIO_ResetBits(DS18B20_GPIO,DS18B20_Pin) //PB14拉低
#define DQ_Read GPIO_ReadInputDataBit(DS18B20_GPIO,DS18B20_Pin) //PB14读取
uint8_t flag=0;
void DS18B20_Init(void) //PB1初始化
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = DS18B20_Pin;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DS18B20_GPIO, &GPIO_InitStructure);
}
void DS18B20_Output(void) //输出模式
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = DS18B20_Pin;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DS18B20_GPIO, &GPIO_InitStructure);
}
void DS18B20_Input(void) //输入模式
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = DS18B20_Pin;
GPIO_Init(DS18B20_GPIO, &GPIO_InitStructure);
}
uint8_t DS18B20_Reset(void) //复位
{
uint8_t flag;
DS18B20_Output();
DQ_H;
Delay_us(5);
DQ_L;
Delay_us(480);
DQ_H;
Delay_us(60);
DS18B20_Input();
flag=DQ_Read;
Delay_us(480);
DS18B20_Output();
DQ_H;
return flag;
}
void DS18B20_WriteData(uint8_t data) // 写数据
{
for(uint8_t i=0;i<8;i++)
{
DS18B20_Output(); //输出状态
DQ_L;
Delay_us(2);
if(data&0x01) //低位开始
{
DQ_H;
}
else
{
DQ_L;
}
Delay_us(60);
DQ_H;
data = data>>1;
}
}
uint8_t DS18B20_ReadData(void) //读数据
{
uint8_t data =0;
for(uint8_t i=0;i<8;i++)
{
data=data>>1;
DS18B20_Output(); //输出状态
DQ_L;
Delay_us(2);
DQ_H;
Delay_us(2);
DS18B20_Input(); //输入状态
if(DQ_Read)
data|=0x80; //放入高位,再移位到低位
Delay_us(60);
}
return data;
}
uint16_t DS18B20_ReadTemp(void) //读取温度
{
uint8_t DL,DH;
uint16_t data;
uint16_t Temperature=0;
flag=0;
DS18B20_Reset(); //复位
DS18B20_WriteData(0XCC); //跳过ROM检测
DS18B20_WriteData(0X44); //启动温度转换
Delay_ms(750); //延时,等待转换完成
DS18B20_Reset(); //复位
DS18B20_WriteData(0XCC); //跳过ROM检测
DS18B20_WriteData(0XBE); //读取暂存器指令
DL=DS18B20_ReadData(); //读温度低位
DH=DS18B20_ReadData(); //读温度高位
data=DH;
data=data<<8;
data|=DL;
if((data&0XF800)==0XF800)
{
data=~data+0X01;
flag=1;
}
Temperature=data * 0.0625*10; //数据格式的问题 扩大了10倍没有小数
return Temperature; //例如返回225 要处理为22.5度
}
尤其需要注意最后的数据读取格式,本人出错就在这(读取到的全是0)。
DS18B20.h:
#ifndef __DS18B20_H
#define __DS18B20_H
void DS18B20_Init(void);
unsigned char DS18B20_Reset(void);
extern unsigned char flag;
uint16_t DS18B20_ReadTemp(void);
#endif
main.c:
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "DS18B20.h"
int Temp; //读取的温度参数
int FLAG=1; //标志位
int main(void)
{
OLED_Init( );
DS18B20_Init();
FLAG=DS18B20_Reset();
Delay_s(1);
while(1)
{
if(FLAG==0)
{
OLED_ShowChinese(1,1,0);
OLED_ShowChinese(1,2,1);
Temp=DS18B20_ReadTemp();
if(flag==1)
{
OLED_ShowString(1, 5, ":-");
OLED_ShowString(1, 10, ".");
OLED_ShowNum(1,7,Temp/10%100,3);
OLED_ShowNum(1,11,Temp%10,1);
}
else
{
OLED_ShowString(1, 5, ":+");
OLED_ShowString(1, 10, ".");
OLED_ShowNum(1,7,Temp/10%100,3);
OLED_ShowNum(1,11,Temp%10,1);
}
}
else
{
OLED_ShowString(1,1,"No sensor ");
Delay_ms(5);
}
}
}
需要注意的还是数据格式的问题,在显示的时候要对数据进行处理,oled显示就自己按需求配置一下。
若还需要在别处用到读取到的温度参数,同样的要进行数据处理后再传参等。简单的就是Temp/10.0
作者:森森森1