找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3541|回复: 0
打印 上一主题 下一主题
收起左侧

stm32驱动ds18b20温度读取源程序

[复制链接]
跳转到指定楼层
楼主
       发上来的程序是主要基于stm32f1的驱动程序,如果你需要清楚了解ds18b20的工作时序,寄存器配置,那么在论坛上找找看看数据手册,如果你想直接用,那么把头文件和c文件直接添加到你的工程中就可以了。       本程序在实质上和51驱动的没有区别,都是模拟I2C。两者区别在于大部分51对于IO口的输入输出配置没有硬性规定,既可以当输入又可以当输出,而stm32的输入输出必须明确模式配置。而ds18b20是一线通信,所以需要输入输出模式来回配置。
       本程序我通过硬件明确测试过,可以准确读出数据,如果数据无法读出,可能是以下几点问题:
       1、引脚配置未修改。可在h文件中修改宏定义即可
       2、请注意该函数void DS18B20_DQ_DDR(uint8_t ddr),他是用于修改IO输入输出模式的,本程序使用的标准库函数进行操作,用到的时间可能会有一点长,影响到了I2C的模拟时序,建议可以直接对寄存器进行操作,库函数的实质也是修改寄存器,只是由于为了程序兼容性,牺牲了时间。
       3、由于是模拟的I2C时序,请务必注意中断对于通信时序的影响。

单片机源程序如下:
  1. #include "ds18b20.h"//主要包含了一些引脚宏定义,移植时必须包含
  2. #include "delay.h"//主要是声明了延时函数,由于是模拟I2C,延时必须精准
  3. #include "math.h"//使用了库函数pow()函数,该函数为幂次函数,如pow(10,2),相当于10^2,移植时必须包含
  4. /*******************************************************************************
  5. 函数名:DS18B20_DQ_DDR
  6. 功能:配置IO输入/输出状态
  7. 输入:0/1    输入0配置为输入,输入1配置为输出
  8. 输出:
  9. 返回值:
  10. *******************************************************************************/
  11. void DS18B20_DQ_DDR(uint8_t ddr)
  12. {
  13.         GPIO_InitTypeDef  GPIO_InitStructure;
  14.         //使能GPIO时钟
  15.   RCC_APB2PeriphClockCmd(DS18B20_GPIO_CLK, ENABLE);       
  16.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;       
  17.   //配置为输出
  18.   if(ddr == 1)
  19.   {
  20.                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;        
  21.                 GPIO_InitStructure.GPIO_Pin = DS18B20_GPIO_PIN;                                          
  22.                 GPIO_Init(DS18B20_GPIO_PORT, &GPIO_InitStructure);               
  23.                
  24.   }
  25.   //配置为输入
  26.   else
  27.         {
  28.                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;        
  29.                 GPIO_InitStructure.GPIO_Pin = DS18B20_GPIO_PIN;                                          
  30.                 GPIO_Init(DS18B20_GPIO_PORT, &GPIO_InitStructure);       
  31.   }
  32. }
  33. /*******************************************************************************
  34. 函数名:DS18B20_Init
  35. 功能:初始化DS18B20
  36. 输入:
  37. 输出:
  38. 返回值:初始化成功为0,不成功为1
  39. 备注:
  40. *******************************************************************************/
  41. u8 DS18B20_Init(void)
  42. {
  43.         u8 x = 0;
  44.   //改变DQ引脚为输出
  45.   DS18B20_DQ_DDR(1);
  46.   //先置高
  47.   DS18B20_DQ_H;  
  48.   //延时700us,使总线稳定
  49.   delay_us(700);
  50.   //复位脉冲,低电位
  51.   DS18B20_DQ_L;  
  52.   //保持至少480us,这里500us
  53.   delay_us(500);
  54.   //改变DQ引脚为输入
  55.   DS18B20_DQ_DDR(0);
  56.   //拉高数据线,释放总线
  57.   DS18B20_DQ_H;  
  58.   //等待15-60us,这里40us
  59.   delay_us(40);
  60.   //等待35us
  61.   delay_us(35);
  62.   //聆听,判断有没有初始化成功(DS18B20有没有发送应答脉冲)
  63.   x = DS18B20_DQ_ReadPin;   
  64.   //至少480us后进入接收状态,这里500us
  65.   delay_us(500);
  66.   return x;
  67. }
  68. /*******************************************************************************
  69. 函数名:DS18B20_Wbyte
  70. 功能:写一个字节
  71. 输入:uint8_t xbyte
  72. 输出:
  73. 返回值:
  74. 备注:
  75. *******************************************************************************/
  76. void DS18B20_Wbyte(uint8_t xbyte)
  77. {
  78.         //i:循环控制变量,x:取位运算变量
  79.   int8_t i ,x = 0;
  80.   //改变DQ引脚为输出
  81.   DS18B20_DQ_DDR(1);
  82.   //8次循环实现逐位写入
  83.   for(i = 1; i <= 8; i++)
  84.   {
  85.                 //先取低位
  86.     x = xbyte & 0x01;
  87.     //写1
  88.     if(x)
  89.     {
  90.       DS18B20_DQ_H;
  91.       //拉低总线
  92.       DS18B20_DQ_L;
  93.       //延时15us
  94.       delay_us(15);
  95.       //总线写1
  96.       DS18B20_DQ_H;
  97.       //延时15us
  98.       delay_us(15);
  99.       //保持高电平
  100.       DS18B20_DQ_H;
  101.       delay_us(4);
  102.                 }
  103.                 //写0
  104.                 else
  105.     {
  106.                         DS18B20_DQ_H;
  107.       //总线拉低
  108.       DS18B20_DQ_L;
  109.       //延时15us
  110.       delay_us(15);
  111.       //总线写0
  112.       DS18B20_DQ_L;
  113.       //延时15us
  114.       delay_us(15);
  115.       //保持高电平
  116.       DS18B20_DQ_H;
  117.       delay_us(4);
  118.     }
  119.     //xbyte右移一位
  120.     xbyte = xbyte >> 1;
  121.         }
  122. }
  123. /*******************************************************************************
  124. 函数名:DS18B20_Rbit
  125. 功能:从DS18B20读一个位
  126. 输入:
  127. 输出:
  128. 返回值:读取到的位
  129. 备注:
  130. *******************************************************************************/
  131. uint8_t DS18B20_Rbit(void)
  132. {
  133.         //rbit是最终位数据,x是取状态变量
  134.   uint8_t rbit = 0x00,x = 0;
  135.   //改变DQ为输出模式
  136.   DS18B20_DQ_DDR(1);
  137.   DS18B20_DQ_H;
  138.   //总线写0
  139.   DS18B20_DQ_L;
  140.   //延时15us以内
  141.   delay_us(5);
  142.   //释放总线
  143.   DS18B20_DQ_H;
  144.   //改变DQ为输入模式
  145.   DS18B20_DQ_DDR(0);
  146.   //延时大约3us
  147.   delay_us(3);
  148.   //获取总线电平状态
  149.   x = DS18B20_DQ_ReadPin;
  150.   //如果是1,则返回0x80,否则返回0x00
  151.   if(x)
  152.                 rbit = 0x80;
  153.   //延时大约60us
  154.   delay_us(60);
  155.         return rbit;
  156. }
  157. /*******************************************************************************
  158. 函数名:DS18B20_Rbyte
  159. 功能:从DS18B20读一个字节
  160. 输入:
  161. 输出:
  162. 返回值:读取到的字节
  163. 备注:
  164. *******************************************************************************/
  165. uint8_t DS18B20_Rbyte(void)
  166. {
  167.   //rbyte:最终得到的字节
  168.   //tempbit:中间运算变量
  169.   uint8_t rbyte = 0,i = 0, tempbit =0;
  170.   for (i = 1; i <= 8; i++)
  171.   {
  172.     //读取位
  173.     tempbit = DS18B20_Rbit();
  174.     //右移实现高低位排序
  175.     rbyte = rbyte >> 1;
  176.     //或运算移入数据
  177.     rbyte = rbyte|tempbit;
  178.   }
  179.   return rbyte;
  180. }
  181. int ReadTemperature(void)
  182. {
  183.   //fg:符号位
  184.   //data:温度的整数部分
  185.   int fg;
  186.   int data;
  187.   //DS18B20初始化
  188.   DS18B20_Init();
  189.   //跳过读序列号
  190.   DS18B20_Wbyte(0xcc);
  191.   //启动温度转换
  192.   DS18B20_Wbyte(0x44);
  193.   //等待温度转换
  194.   delay_ms(1);
  195.   DS18B20_Init();
  196.   DS18B20_Wbyte(0xcc);
  197.   //读温度寄存器
  198.   DS18B20_Wbyte(0xbe);
  199.   uint8_t TempL = DS18B20_Rbyte();//读取低8位
  200.   uint8_t TempH = DS18B20_Rbyte();//读取高8位
  201.   //符号位为负
  202.   if(TempH > 0x70)
  203.   {
  204.     TempL = ~TempL;
  205.     TempH = ~TempH;
  206.     fg = 0;
  207.   }
  208.   else fg = 1;
  209.                
  210.         //将数据高低位合并
  211.   data = TempH;//数据高八位
  212.   data <<=  8;//左移8位
  213.   data += TempL;//加上低八位

  214.         //data的"1"相当于0.0625℃
  215.         //换句话说,想要多少精度可以这样写:data=(float)data*0.0625*pow(10,n)
  216.         //其中n为保留的小数精度位数,可以从目前对ds18b20配置情况下看出最高保留小数的精度位数为4位
  217.         //这样只需要对返回值进行处理就可以用于显示了
  218.         //特别注意的是,int类型的数据长度为16位,最大值为65535,因此需要注意使用范围
  219.         data=(float)data*0.0625*pow(10,1);//这样写等同于下面一句
  220.   //data = (float)data*0.625;//这样相当于精度为0.1℃
  221.   if(fg)
  222.     return data;
  223.   else
  224.      return -data;
  225. }
复制代码

所有资料51hei提供下载:
DS18B20.rar (2.56 KB, 下载次数: 101)



评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶1 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表