你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32驱动DS18B20

[复制链接]
STMCU小助手 发布时间:2022-1-17 21:41
DS18B20 是由 DALLAS 半导体公司推出的一种的“一线总线”接口的温度传感器。与传统的热敏电阻等测温元件相比,它是一种新型的体积小、适用电压宽、与微处理器接口简单的数字化温度传感器。一线总线结构具有简洁且经济的特点,可使用户轻松地组建传感器网络,从而为测量系统的构建引入全新概念,测量温度范围为-55~+125℃  ,精度为±0.5℃。现场温度直接以“一线总线”的数字方式传输,大大提高了系统的抗干扰性。它能直接读出被测温度,并且可根据实际要求通过简单的编程实现 9~l2 位的数字值读数方式。它工作在 3—5. 5 V 的电压范围,采用多种封装形式,从而使系统设计灵活、方便,设定分辨率及用户设定的报警温度
存储在 EEPROM 中,掉电后依然保存

其内部结构如下所示

20141003203258788.jpg

DS18B20的通讯方式是单总线的,一般而言,我们遇到的封装都是如下

20141003203431920.jpg

其中DQ就是主要的通讯线路,对DS的读取和写入都需要主机来控制DQ线路的DQ高低电平的时间来确定,具体如下
一般而言,DQ线需要接一个上拉电阻,所以,才写操作的最后一步都需要将总线拉高

20141003203910718.jpg


向DS写0需要总线拉低至少60US最多120US就算完成,也就是说,1-->0(持续60-120us)-->1 写入了0
像DS写入1需要总线拉低最少1us最多15US,然后总线拉高,拉高时间至少15us,一般40us以上即可  1->0(1-15us,推荐5us)-->1(持续15us以上,推荐40us)
由此可见,DS的总线采样实在总线拉低之后的15us开始的

20141003205456007.jpg

读取DS分别为读取1和读取0,但是这两者时序是统一的
首先总线拉低至少1us,最多15us,还是选择2us,然后释放总线(也就是说进入输入模式),等待15us以上的事件,然后采样,高电平为1低电平为0
1-->0(持续2us,最多15us)-->等待15us以上60us以下-->采样总线电平,得到1或者0,记得采样完成之后切换到输出模式将总线拉高便于下一次使用

DS18B20的命令
DS1820有三个主要数字部件:1)64位激光ROM,2)温度传感器,3)非易失性温度报警触发器TH和TL

20141003210358124.jpg

20141003210654201.jpg
20141003210728942.jpg



启动温度转换的命令是0X44,读取命令是0XBE
所以一般而言,对于DS的驱动包含以下几步
复位-->发 SKIP ROM 命令(0XCC)-->发开始转换命令(0X44)-->延时-->复
位-->发送 SKIP  ROM 命令(0XCC)-->发读存储器命令(0XBE)-->连续读出两个字节数据(即
温度)-->结束
我们在读取的时候只读取两个字节的原因在于DS的存储器布局

20141003211233907.jpg

前两个就是我们需要的温度,当然也可以读取全部的,扩展驱动达到其他目的

以下是驱动代码,STM32驱动代码中使用了位段操作
  1. #ifndef __Ds18b20H
  2. #define __Ds18b20H
  3. #include "ioremap.h"   
  4. #include "delay.h"
  5. #include "uart.h"


  6. //IO方向设置
  7. #define Ds18b20IO_IN()  {GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=8<<12;}
  8. #define Ds18b20IO_OUT() {GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=3<<12;}



  9. ////IO操作函数                                                                                          
  10. #define        Ds18b20DQ_OUT PGout(11) //数据端口        PG11
  11. #define        Ds18b20DQ_IN  PGin(11)  //数据端口        PG11




  12. u8 Ds18b20Init(void);                        //初始化DS18B20


  13. short Ds18b20GetTemp(void);        //获取温度


  14. void Ds18b20Start(void);                //开始温度转换


  15. void Ds18b20WriteByte(u8 dat);//写入一个字节


  16. u8 Ds18b20ReadByte(void);                //读出一个字节


  17. u8 Ds18b20ReadBit(void);                //读出一个位


  18. u8 Ds18b20Check(void);                        //检测是否存在DS18B20


  19. void Ds18b20Rst(void);                        //复位DS18B20   

  20. void Ds18b20Show(void);


  21. #endif
复制代码
  1. #include "ds18b20.h"

  2. //复位DS18B20
  3. void Ds18b20Rst(void)          
  4. {                 
  5.     Ds18b20IO_OUT(); //SET PA0 OUTPUT
  6.     Ds18b20DQ_OUT=0; //拉低DQ
  7.     DelayUs(750);    //拉低750us
  8.     Ds18b20DQ_OUT=1; //DQ=1
  9.     DelayUs(15);     //15US
  10. }


  11. //等待DS18B20的回应
  12. //返回1:未检测到DS18B20的存在
  13. //返回0:存在
  14. u8 Ds18b20Check(void)           
  15. {   
  16.     u8 retry=0;
  17.     Ds18b20IO_IN();//SET PA0 INPUT         
  18.     while (Ds18b20DQ_IN&&retry<200)
  19.     {
  20.         retry++;
  21.         DelayUs(1);
  22.     };         
  23.     if(retry>=200)return 1;
  24.     else retry=0;
  25.     while (!Ds18b20DQ_IN&&retry<240)
  26.     {
  27.         retry++;
  28.         DelayUs(1);
  29.     };
  30.     if(retry>=240)return 1;            
  31.     return 0;
  32. }


  33. //从DS18B20读取一个位
  34. //返回值:1/0
  35. u8 Ds18b20ReadBit(void)                          // read one bit
  36. {
  37.     u8 data;
  38.     Ds18b20IO_OUT();//SET PA0 OUTPUT
  39.     Ds18b20DQ_OUT=0;
  40.     DelayUs(2);
  41.     Ds18b20DQ_OUT=1;
  42.     Ds18b20IO_IN();//SET PA0 INPUT
  43.     DelayUs(12);
  44.     if(Ds18b20DQ_IN)data=1;
  45.     else data=0;         
  46.     DelayUs(50);           
  47.     return data;
  48. }


  49. //从DS18B20读取一个字节
  50. //返回值:读到的数据
  51. u8 Ds18b20ReadByte(void)    // read one byte
  52. {        
  53.     u8 i,j,dat;
  54.     dat=0;
  55.     for (i=1;i<=8;i++)
  56.     {
  57.         j=Ds18b20ReadBit();
  58.         dat=(j<<7)|(dat>>1);
  59.     }                                                    
  60.     return dat;
  61. }


  62. //写一个字节到DS18B20
  63. //dat:要写入的字节
  64. void Ds18b20WriteByte(u8 dat)     
  65. {            
  66.     u8 j;
  67.     u8 testb;
  68.     Ds18b20IO_OUT();//SET PA0 OUTPUT;
  69.     for (j=1;j<=8;j++)
  70.     {
  71.         testb=dat&0x01;
  72.         dat=dat>>1;
  73.         if (testb)
  74.         {
  75.             Ds18b20DQ_OUT=0;// Write 1
  76.             DelayUs(2);                           
  77.             Ds18b20DQ_OUT=1;
  78.             DelayUs(60);            
  79.         }
  80.         else
  81.         {
  82.             Ds18b20DQ_OUT=0;// Write 0
  83.             DelayUs(60);            
  84.             Ds18b20DQ_OUT=1;
  85.             DelayUs(2);                          
  86.         }
  87.     }
  88. }


  89. //开始温度转换
  90. void Ds18b20Start(void)// ds1820 start convert
  91. {                                                                 
  92.     Ds18b20Rst();          
  93.     Ds18b20Check();         
  94.     Ds18b20WriteByte(0xcc);// skip rom
  95.     Ds18b20WriteByte(0x44);// convert
  96. }


  97. //初始化DS18B20的IO口 DQ 同时检测DS的存在
  98. //返回1:不存在
  99. //返回0:存在             
  100. u8 Ds18b20Init(void)
  101. {
  102.     GPIO_InitTypeDef  GPIO_InitStructure;
  103.    
  104.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE);         //使能PORTG口时钟
  105.    
  106.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;                                //PORTG.11 推挽输出
  107.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                   
  108.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  109.     GPIO_Init(GPIOG, &GPIO_InitStructure);
  110.    
  111.     GPIO_SetBits(GPIOG,GPIO_Pin_11);    //输出1
  112.    
  113.     Ds18b20Rst();
  114.    
  115.     return Ds18b20Check();
  116. }  


  117. //从ds18b20得到温度值
  118. //精度:0.1C
  119. //返回值:温度值 (-550~1250)
  120. short Ds18b20GetTemp(void)
  121. {
  122.     u8 temp;
  123.     u8 TL,TH;
  124.     short tem;
  125.     Ds18b20Start ();                    // ds1820 start convert
  126.     Ds18b20Rst();
  127.     Ds18b20Check();         
  128.     Ds18b20WriteByte(0xcc);// skip rom
  129.     Ds18b20WriteByte(0xbe);// convert            
  130.     TL=Ds18b20ReadByte(); // LSB   
  131.     TH=Ds18b20ReadByte(); // MSB  
  132.    
  133.     if(TH>7)
  134.     {
  135.         TH=~TH;
  136.         TL=~TL;
  137.         temp=0;//温度为负  
  138.     }else temp=1;//温度为正                    
  139.     tem=TH; //获得高八位
  140.     tem<<=8;   
  141.     tem+=TL;//获得底八位
  142.     tem=(short)((float)tem*0.625);//转换     
  143.     if(temp)return tem; //返回温度值
  144.     else return -tem;   
  145. }

  146. void Ds18b20Show(void)
  147. {
  148.         short t = 0;
  149.         t = Ds18b20GetTemp();
  150.         printf("ds18b20 temp is %d\r\n",t);
  151. }
复制代码


收藏 评论0 发布时间:2022-1-17 21:41

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版