[STM32F4] 基于STM32自码 DS18B20驱动程序

[复制链接]
1135|2
 楼主| 643757107 发表于 2018-1-31 14:57 | 显示全部楼层 |阅读模式
  1. #include <ds18b20.h>
  2. #include "delay.h"
  3. #include "usart.h"       

  4. //ds18b20初始化
  5. void  init_ds18b20( void )
  6. {
  7.         init_onewire_out();
  8.         GPIO_ResetBits(GPIOG,GPIO_Pin_9);
  9.         delay_us(480);
  10.         init_onewire_in();
  11.         delay_us(60);
  12.         if( !DQ_In)
  13.         {
  14.                 delay_us(120);
  15.                                
  16.         }
  17. }
  18. //ds18b20 检测
  19. void  chack_ds18b20( void )
  20. {
  21.         init_onewire_out();
  22.         GPIO_ResetBits(GPIOG,GPIO_Pin_9);
  23.         delay_us(240);
  24.         init_onewire_in();
  25.         delay_us(60);
  26.         if( !DQ_In)
  27.         {
  28.                 delay_us(80);
  29.                 if( !DQ_In )
  30.                         printf("检测到DS18B20!\r\n");
  31.                                
  32.         }

  33. }
  34. //设置为主设备写总线,从设备读总线
  35. void init_onewire_out( void )
  36. {
  37.         GPIO_InitTypeDef  GPIO_InitStructure;

  38.         RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);//使能GPIOG时钟
  39.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  40.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
  41.         GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
  42.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
  43.         GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
  44.         GPIO_Init(GPIOG, &GPIO_InitStructure);//初始化
  45. }
  46. //设置为主设备读取总线,从设备写总线
  47. void init_onewire_in( void )
  48. {
  49.        
  50.         GPIO_InitTypeDef  GPIO_InitStructure;

  51.         RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);//使能GPIOG时钟
  52.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  53.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//普通输入模式
  54. //        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
  55.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
  56.         GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
  57.         GPIO_Init(GPIOG, &GPIO_InitStructure);//初始化
  58. }

  59. void ds18b20_write_byte( u8 data )
  60. {
  61.         u8 i;
  62.         u8 j=0;
  63.         init_onewire_out();
  64.         for(i=0;i<8;i++)
  65.                 {
  66.                         j=data & 0x01;
  67.                         if(j)
  68.                         {
  69.                                 DQ_Out=0;                //写1
  70.                                 delay_us(15);
  71.                                 DQ_Out=1;
  72.                                 delay_us(60);
  73.                                
  74.                         }
  75.                         else
  76.                         {
  77.                                 DQ_Out=0;                //写0
  78.                                 delay_us(60);
  79.                                 DQ_Out=1;
  80.                                 delay_us(1);
  81.                         }
  82.                         data = data>>1;
  83.                 }       
  84. }
  85. //读取DS18B20 的一位
  86. u8 ds18b20_read_bit( void )
  87. {       
  88.         u8 bit;
  89.         init_onewire_out();
  90.         DQ_Out=0;
  91.         delay_us(2);
  92.         DQ_Out=1;
  93.         init_onewire_in();
  94.         delay_us(12);
  95.         if(DQ_In)
  96.                 bit=1;
  97.         else
  98.                 bit=0;
  99.         delay_us(50);
  100.         return bit;
  101. }
  102. //读ds18b20的字节
  103. u8 ds18b20_read_byte ( void )
  104. {
  105.         u8 data=0;
  106.         u8 i;
  107.         u8 j=0;
  108.         for(i=0;i<8;i++)
  109.         {
  110.                 j=ds18b20_read_bit();
  111.                 if(j)                        //注意顺序即可,ds18b20先发送地位到总线上
  112.                         j=j<<i;
  113.                 data |=j;

  114.         }
  115.         return data;
  116. }
  117. //获取ds18b20的系列码和48位唯一序列号
  118. void ds18b20_read_rom_number()
  119. {
  120.         u32 number=0;
  121.         u8 data,i,serial_num,ds18b20_crc;
  122.         init_ds18b20();
  123.         ds18b20_write_byte(0x33);
  124.         serial_num = ds18b20_read_byte();
  125.         for(i=0;i<6;i++)
  126.         {
  127.                 data = ds18b20_read_byte();
  128.                 number |= data;
  129.                 number = number<<8;
  130.         }
  131.         ds18b20_crc = ds18b20_read_byte();
  132.        
  133.         printf("系列号是:%d\r\n",serial_num);
  134.         printf("序列号是:%d\r\n",number);
  135.         printf("CRC校验为:%d\r\n",ds18b20_crc);
  136.        
  137. }
  138. //开启ds18b20温度转换
  139. void tem_chage( void )
  140. {
  141.         init_ds18b20();
  142.         ds18b20_write_byte(0xcc);                //忽略rom指令
  143.         ds18b20_write_byte(0x44);        //开启转换
  144. }

  145. short  get_temp( void )
  146. {
  147.         int temp=0;
  148.         u8 i,TH,TL;
  149.         short tem;

  150.         tem_chage();
  151.         delay_us(10);
  152.         init_ds18b20();
  153.         ds18b20_write_byte(0xcc);                //忽略rom指令
  154.         ds18b20_write_byte(0xbe);        //读取温度转换值
  155.         TL=ds18b20_read_byte();
  156.         TH=ds18b20_read_byte();
  157.        
  158.         if(TH > 7)                 //通过判读存储器的高五位的0,1来判断温度的正负,
  159.         {
  160.                 temp = 0;        //为负
  161.                 TH =~TH;
  162.                 TL =~TL;
  163.         }
  164.         else
  165.                 temp = 1;        //为正
  166.         tem = TH;
  167.         tem =tem<<8;
  168.         tem =tem+TL;
  169.         tem = (double)tem * 0.625;
  170.         if(temp)
  171.                 return tem;
  172.         else
  173.                 return -tem;
  174.        
  175. }
  176. void ds18b20_return_TH_TL_CONF( void )
  177. {
  178.         char data,data_TH,data_TL,CONF;
  179.         init_ds18b20();
  180.         ds18b20_write_byte(0xcc);                //忽略rom指令
  181.         ds18b20_write_byte(0xbe);        //读取温度转换值
  182.         data = ds18b20_read_byte();
  183.         data = ds18b20_read_byte();
  184.         data_TH = ds18b20_read_byte();
  185.         data_TL = ds18b20_read_byte();
  186.         CONF =ds18b20_read_byte();
  187.         printf("过温报警的温度为:%d℃\r\n",data_TH);
  188.         printf("低温报警的温度为:%d℃\r\n",-(data_TL-128));
  189.         CONF &=0x60 ;
  190.         CONF =CONF>>5;
  191.         switch (CONF) {
  192.                 case 0:
  193.                         printf("ds18b20的测量精度为9位,精度为0.5℃\r\n");
  194.                         break;
  195.                 case 1:
  196.                         printf("ds18b20的测量精度为10位,精度为0.25℃\r\n");
  197.                         break;
  198.                 case 2:
  199.                         printf("ds18b20的测量精度为11位,精度为0.125℃\r\n");
  200.                         break;
  201.                 case 3:
  202.                         printf("ds18b20的测量精度为12位,精度为0.0625℃\r\n");
  203.                         break;
  204.                 default:
  205.                         printf("error!!\r\n");
  206.                         break;
  207.         }
  208. }
  209. //设置温度报警值和配置精度,TH过温报警值(TH>0),TL低温报警值(TL为负数 ),mode配置模式0,1,2,3
  210. //mode=0 精度为9位        00011111 dat=31
  211. //mode=1 精度为10位  00111111        dat=63
  212. //mode=2 精度为11位        01011111        dat=95
  213. //mode=3 精度为12位  01111111        dat =127
  214. void ds18b20_write_TH_TL_CONF(u8 TH,u8 TL,u8 mode)
  215. {
  216.         u8 dat;
  217.         switch (mode){
  218.                 case 0:
  219.                         dat=31;
  220.                         break;
  221.                 case 1:
  222.                         dat=63;
  223.                         break;
  224.                 case 2:
  225.                         dat=95;
  226.                         break;
  227.                 case 3:
  228.                         dat=127;
  229.                         break;
  230.                 default:
  231.                         printf("mode error!!\r\n");
  232.                         dat=127;
  233.                         break;
  234.         }
  235.         TL=TL+128;
  236.         init_ds18b20();
  237.         ds18b20_write_byte(0xcc);                //忽略rom指令
  238.         ds18b20_write_byte(0x4e);        //写入暂存寄存器 ,过温和低温报警值
  239.         ds18b20_write_byte(TH);        //写入20°为过温报警值
  240.         ds18b20_write_byte(TL);        //写入-20°为低温报警值
  241.         ds18b20_write_byte(dat);        //写入精度
  242.         init_ds18b20();
  243.         ds18b20_write_byte(0xcc);                //忽略rom指令
  244.         ds18b20_write_byte(0x48);        //将写入的暂存寄存器拷入EEPROM
  245. }
  246. void ds18b20_chack_self( void )
  247. {
  248.         chack_ds18b20();
  249.         ds18b20_read_rom_number();
  250.         ds18b20_return_TH_TL_CONF();
  251. }





 楼主| 643757107 发表于 2018-1-31 14:57 | 显示全部楼层
1.初始化时序要注意,笔者亲测,在MCU控制单总线为低电平240us即可(数据手册上要求至少480us)释放总线,等待60us后即可检测到到DS18B20返回的拉低单总线信号,此处,需注意至少应在此等待120us,否则可能会导致温度传感器无**常工作。
 楼主| 643757107 发表于 2018-1-31 14:57 | 显示全部楼层
2.初学者需注意时序,对于DS18B20的操作都必需经过三步:初始化,ROM命令(多为跳过指令0xCC),DS18B20功能命令。再次强调对其的每一个操作必须经过这三步,可阅读code加深理解。

3.在读取DS18B20时,注意顺序,DS18B20先发送低位,在字节读取时应当注意。

4.初学者应尝试实现对于DS18B20内部ROM的8位系列号(28H),和48位唯一序列号进行读取,以及修改温度传感器内部EEPROM的过温、低温报警值。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

223

主题

3972

帖子

11

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