[PIC®/AVR®/dsPIC®产品] 【CuriosityNano测评报告】AVR128DB48+DS18B20测温

[复制链接]
 楼主| zhouminjie 发表于 2021-4-10 19:38 | 显示全部楼层 |阅读模式
本帖最后由 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之后,会释放总线
代码实现:
  1. //复位DS18B20
  2. void DS18B20_Rst(void)
  3. {
  4.     DS18B20_SetDigitalOutput(); //输出模式
  5.     DS18B20_SetLow(); //拉低DQ
  6.      _delay_us(750); //拉低750us(480~960us)
  7.     DS18B20_SetHigh(); //拉高DQ
  8. }

  9. //等待DS18B20应答,有应答返回0,无应答返回1
  10. uint8_t DS18B20_Check(void)
  11. {
  12.     uint8_t retry = 0;
  13.     //进入接收模式,等待应答信号
  14.     //等待时间
  15.     DS18B20_SetDigitalInput(); //输入模式
  16.     _delay_us(15); //等待15~60us
  17.     while(DS18B20_GetValue() && retry<120) //最多再等待120us
  18.     {
  19.         retry++;
  20.         _delay_us(1);
  21.     };
  22.     if(retry >= 120)
  23.         return 1; //120us未响应,则判断未检测到
  24.     else
  25.         retry = 0;
  26.     //DS18B20开始拉低DQ
  27.     while(!DS18B20_GetValue() && retry<240) //最长拉低240us
  28.     {
  29.         retry++;
  30.         _delay_us(1);
  31.     };
  32.     if(retry >= 240)
  33.         return 1;
  34.     return 0;
  35. }
③写DS18B20时序
写时序如下:

MCU给DS18B20写0时,MCU引脚拉低,延时60us,然后释放总线,延时2us
MCU给DS18B20写1时,MCU引脚拉低,延时2us,然后释放总线,延时60us
在写时序起始后15μs到60μs期间,DS18B20处于采样单总线电平状态。如果在此期间总线为高电平,则向DS18B20写入1;如果总线为低电平,则向DSl8B20写入0
代码实现:
  1. //写字节到DS18B20
  2. void DS18B20_Write_Byte(uint8_t dat)
  3. {
  4.     uint8_t j;
  5.     uint8_t temp;

  6.     DS18B20_SetDigitalOutput(); //输出模式
  7.     for(j=1; j<=8; j++)
  8.     {
  9.         temp = dat & 0x01;
  10.         dat = dat >> 1;
  11.         if (temp) //输出高
  12.         {
  13.             DS18B20_SetLow(); //拉低DQ
  14.             _delay_us(2); //延时2us
  15.             DS18B20_SetHigh(); //拉高DQ
  16.             _delay_us(60); //延时60us
  17.         }
  18.         else //输出低
  19.         {
  20.             DS18B20_SetLow(); //拉低DQ
  21.             _delay_us(60); //延时60us
  22.             DS18B20_SetHigh(); //拉高DQ
  23.             _delay_us(2); //延时2us
  24.         }
  25.     }
  26.     DS18B20_SetDigitalInput(); //输入模式
  27. }
④读DS18B20时序
读时序如下:

MCU拉低电平,延时2us;MCU转为输入模式,延时12us;然后读取单总线当前的电平,延时50us
代码实现:
  1. //从DS18B20读位
  2. uint8_t DS18B20_Read_Bit(void)
  3. {
  4.     uint8_t data;

  5.     DS18B20_SetDigitalOutput(); //输出模式
  6.     DS18B20_SetLow(); //拉低DQ
  7.     _delay_us(2); //延时2us
  8.     DS18B20_SetHigh(); //拉高DQ
  9.     DS18B20_SetDigitalInput(); //输入模式
  10.     _delay_us(12); //延时12us
  11.     if(DS18B20_GetValue()) //读DQ数据
  12.         data = 1;
  13.     else
  14.         data = 0;
  15.     _delay_us(50); //延时50us
  16.     return data;
  17. }

  18. //从DS18B20读字节
  19. uint8_t DS18B20_Read_Byte(void)
  20. {
  21.     uint8_t i, j, dat = 0;

  22.     for(i=1; i<=8; i++)
  23.     {
  24.         j = DS18B20_Read_Bit();
  25.         dat = (j << 7) | (dat >> 1);
  26.     }
  27.     return dat;
  28. }
⑤温度读取
MCU发送复位信号,发送SKIP ROM命令(0XCC,匹配指令)
发开始转换命令(0X44)
延时等待转换完成(12bit分辨率时需要750ms)
MCU发送复位信号,发送SKIP ROM命令(0XCC)
发读存储器命令(0XBE),读取暂存器内容
连续读出两个字节数据
对读取的温度值进行转换
代码实现:
  1. //开始温度转换
  2. void DS18B20_Start(void)
  3. {
  4.     DS18B20_Rst();
  5.     DS18B20_Check();
  6.     DS18B20_Write_Byte(0xcc);
  7.     DS18B20_Write_Byte(0x44);
  8. }

  9. //读取温度值
  10. uint16_t DS18B20_Get_Temp(void)
  11. {
  12.     uint8_t sign; //温度符号,0为-,1为+
  13.     uint8_t TL, TH;
  14.     uint16_t temp;
  15.     float temp1;

  16.     DS18B20_Start ();
  17.     _delay_ms(800); //等待转换完成
  18.     DS18B20_Rst();
  19.     DS18B20_Check();
  20.     DS18B20_Write_Byte(0xcc);
  21.     DS18B20_Write_Byte(0xbe);
  22.     TL = DS18B20_Read_Byte();
  23.     TH = DS18B20_Read_Byte();
  24.     if(TH > 7)
  25.     {
  26.         TH = ~TH;
  27.         TL = ~TL;
  28.         sign = 0; //温度为负
  29.     }
  30.     else
  31.         sign = 1; //温度为正
  32.     temp = TH; //高八位
  33.     temp <<= 8;
  34.     temp += TL; //低八位
  35.     temp1 = (float)temp * 0.625 + 0.5; //转换实际温度(放大10倍),+0.5四舍五入
  36.     temp = (uint16_t)temp1;
  37.     if(sign)
  38.         return temp; //返回温度值
  39.     else
  40.         return -temp;
  41. }
⑥实现如下:

测试代码:


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
wanduzi 发表于 2021-4-11 10:09 | 显示全部楼层
非常不错,这个用的多
pzsh 发表于 2021-4-20 22:20 | 显示全部楼层
谢谢分享源代码
kkzz 发表于 2021-5-3 13:20 | 显示全部楼层
DS18B20的技术参数  
hudi008 发表于 2021-5-3 13:21 | 显示全部楼层

基于DS18B20单线多点温度测量系统  
lzmm 发表于 2021-5-3 13:21 | 显示全部楼层
ds18b20和单片机之间的距离多少  
minzisc 发表于 2021-5-3 13:21 | 显示全部楼层
ds18b20正常工作的工作电压是多少?
selongli 发表于 2021-5-3 13:22 | 显示全部楼层
ds18b20精度怎么设置
fentianyou 发表于 2021-5-3 13:22 | 显示全部楼层
要加10k上拉电阻   
xiaoyaodz 发表于 2021-5-3 13:22 | 显示全部楼层

用DS18B20单总线温度传感器实现一个温度计  
febgxu 发表于 2021-5-3 13:23 | 显示全部楼层
通过模拟时序来完成单线读写  
sdlls 发表于 2021-5-3 13:24 | 显示全部楼层
18B20是可以用数据线供电的  
pixhw 发表于 2021-5-3 13:25 | 显示全部楼层
  感谢分享。
lzmm 发表于 2021-5-3 13:25 | 显示全部楼层
温度传感器使用方  
hudi008 发表于 2021-5-3 13:25 | 显示全部楼层
如何实现多个DS18B20并联在唯一的单线上
minzisc 发表于 2021-5-3 13:25 | 显示全部楼层
为什么要上拉电阻  
kkzz 发表于 2021-5-3 13:25 | 显示全部楼层
单线通信的经典。   
sdlls 发表于 2021-5-3 13:25 | 显示全部楼层
单线挂多个DS18B20  
febgxu 发表于 2021-5-3 13:25 | 显示全部楼层
通过这根线的电平高低以及延时时间的情况来告知从机下一步的动作。
pixhw 发表于 2021-5-3 13:25 | 显示全部楼层
就是延时不好控制的。  
您需要登录后才可以回帖 登录 | 注册

本版积分规则

33

主题

140

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部

33

主题

140

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部