本帖最后由 zhouminjie 于 2021-4-15 13:09 编辑
本次实现开发板挂载1个DS18B20测量温度,硬件如下:
VDD接到电源,DQ接MCU引脚,GND接地,由于DQ引脚为开漏输出,不具有输出高电平的能力,必须要接一个上拉电阻
①新建工程
②初始化DS18B20
初始化时序如下:
MCU拉低总线至少480us,产生复位脉冲,然后释放总线(拉高电平);这时DS8B20检测到请求之后,会拉低信号,大约60~240us表示应答;DS8B20拉低电平的60~240us之间,单片机读取总线的电平,如果是低电平,那么表示初始化成功;DS18B20拉低电平60~240us之后,会释放总线
代码实现:
//复位DS18B20
void DS18B20_Rst(void)
{
DS18B20_SetDigitalOutput(); //输出模式
DS18B20_SetLow(); //拉低DQ
_delay_us(750); //拉低750us(480~960us)
DS18B20_SetHigh(); //拉高DQ
}
//等待DS18B20应答,有应答返回0,无应答返回1
uint8_t DS18B20_Check(void)
{
uint8_t retry = 0;
//进入接收模式,等待应答信号
//等待时间
DS18B20_SetDigitalInput(); //输入模式
_delay_us(15); //等待15~60us
while(DS18B20_GetValue() && retry<120) //最多再等待120us
{
retry++;
_delay_us(1);
};
if(retry >= 120)
return 1; //120us未响应,则判断未检测到
else
retry = 0;
//DS18B20开始拉低DQ
while(!DS18B20_GetValue() && retry<240) //最长拉低240us
{
retry++;
_delay_us(1);
};
if(retry >= 240)
return 1;
return 0;
}
③写DS18B20时序
写时序如下:
MCU给DS18B20写0时,MCU引脚拉低,延时60us,然后释放总线,延时2us
MCU给DS18B20写1时,MCU引脚拉低,延时2us,然后释放总线,延时60us
在写时序起始后15μs到60μs期间,DS18B20处于采样单总线电平状态。如果在此期间总线为高电平,则向DS18B20写入1;如果总线为低电平,则向DSl8B20写入0
代码实现:
//写字节到DS18B20
void DS18B20_Write_Byte(uint8_t dat)
{
uint8_t j;
uint8_t temp;
DS18B20_SetDigitalOutput(); //输出模式
for(j=1; j<=8; j++)
{
temp = dat & 0x01;
dat = dat >> 1;
if (temp) //输出高
{
DS18B20_SetLow(); //拉低DQ
_delay_us(2); //延时2us
DS18B20_SetHigh(); //拉高DQ
_delay_us(60); //延时60us
}
else //输出低
{
DS18B20_SetLow(); //拉低DQ
_delay_us(60); //延时60us
DS18B20_SetHigh(); //拉高DQ
_delay_us(2); //延时2us
}
}
DS18B20_SetDigitalInput(); //输入模式
}
④读DS18B20时序
读时序如下:
MCU拉低电平,延时2us;MCU转为输入模式,延时12us;然后读取单总线当前的电平,延时50us
代码实现:
//从DS18B20读位
uint8_t DS18B20_Read_Bit(void)
{
uint8_t data;
DS18B20_SetDigitalOutput(); //输出模式
DS18B20_SetLow(); //拉低DQ
_delay_us(2); //延时2us
DS18B20_SetHigh(); //拉高DQ
DS18B20_SetDigitalInput(); //输入模式
_delay_us(12); //延时12us
if(DS18B20_GetValue()) //读DQ数据
data = 1;
else
data = 0;
_delay_us(50); //延时50us
return data;
}
//从DS18B20读字节
uint8_t DS18B20_Read_Byte(void)
{
uint8_t i, j, dat = 0;
for(i=1; i<=8; i++)
{
j = DS18B20_Read_Bit();
dat = (j << 7) | (dat >> 1);
}
return dat;
}
⑤温度读取
MCU发送复位信号,发送SKIP ROM命令(0XCC,匹配指令)
发开始转换命令(0X44)
延时等待转换完成(12bit分辨率时需要750ms)
MCU发送复位信号,发送SKIP ROM命令(0XCC)
发读存储器命令(0XBE),读取暂存器内容
连续读出两个字节数据
对读取的温度值进行转换
代码实现:
//开始温度转换
void DS18B20_Start(void)
{
DS18B20_Rst();
DS18B20_Check();
DS18B20_Write_Byte(0xcc);
DS18B20_Write_Byte(0x44);
}
//读取温度值
uint16_t DS18B20_Get_Temp(void)
{
uint8_t sign; //温度符号,0为-,1为+
uint8_t TL, TH;
uint16_t temp;
float temp1;
DS18B20_Start ();
_delay_ms(800); //等待转换完成
DS18B20_Rst();
DS18B20_Check();
DS18B20_Write_Byte(0xcc);
DS18B20_Write_Byte(0xbe);
TL = DS18B20_Read_Byte();
TH = DS18B20_Read_Byte();
if(TH > 7)
{
TH = ~TH;
TL = ~TL;
sign = 0; //温度为负
}
else
sign = 1; //温度为正
temp = TH; //高八位
temp <<= 8;
temp += TL; //低八位
temp1 = (float)temp * 0.625 + 0.5; //转换实际温度(放大10倍),+0.5四舍五入
temp = (uint16_t)temp1;
if(sign)
return temp; //返回温度值
else
return -temp;
}
⑥实现如下:
测试代码:
AVR_DS18B20.X.rar
(149.58 KB)
|