[Kinetis] DS18B20温度采集+串口发送

[复制链接]
1684|10
 楼主| ideafor 发表于 2016-1-23 21:34 | 显示全部楼层 |阅读模式
FSL官方KSDK固件库编译出的lib过大,因此采用超核的固件库实现DS18B20温度采集和串口发送,超核库的有许多便捷的设置函数,如delay函数、GPIO位带操作等。
首先是创建基于超核固件库的keil project,加入必要的*.c和*.h文件:

然后确定DS18B20的data引脚接口为PTC16,编写DS18B20的相关函数:

DS18B20共有6种信号类型:复位脉冲、应答脉冲、写0、写1、读0和读1。所有这些信号,除了应答脉冲以外,都由主机发出同步信号。并且发送所有的命令和数据都是字节的低位在前。
这几个信号的时序如下:
1)复位脉冲和应答脉冲
单总线上的所有通信都是以初始化序列开始。主机输出低电平,保持低电平时间至少480us,以产生复位脉冲。接着主机释放总线,4.7K的上拉电阻将单总线拉高,延时15~60us,并进入接收模式(Rx)。接着DS18B20拉低总线60~240us,以产生低电平应答脉冲,若为低电平,再延时480us。
2)写时序
写时序包括写0时序和写1时序。所有写时序至少需要60us,且在2次独立的写时序之间至少需要1us的恢复时间,两种写时序均起始于主机拉低总线。写1时序:主机输出低电平,延时2us,然后释放总线,延时60us。写0时序:主机输出低电平,延时60us,然后释放总线,延时2us。
3)读时序
单总线器件仅在主机发出读时序时,才向主机传输数据,所以,在主机发出读数据命令后,必须马上产生读时序,以便从机能够传输数据。所有读时序至少需要60us,且在2次独立的读时序之间至少需要1us的恢复时间。每个读时序都由主机发起,至少拉低总线1us。主机在读时序期间必须释放总线,并且在时序起始后的15us之内采样总线状态。典型的读时序过程为:主机输出低电平延时2us,然后主机转入输入模式延时12us,然后读取单总线当前的电平,然后延时50us。
DS18B20的温度读取过程一般为:复位->发SKIPROM命令(0XCC)->发开始转换命令(0X44)->延时->复位->发送SKIPROM命令(0XCC)->发读存储器命令(0XBE)->连续读出两个字节数据(即温度)->结束。
主函数中代码如下,实现了温度读取和串口发送,LED闪烁以表明程序运行:
 楼主| ideafor 发表于 2016-1-23 21:35 | 显示全部楼层


程序运行结果如下:


 楼主| ideafor 发表于 2016-1-23 21:38 | 显示全部楼层
  1. #include "ds18b20.h"

  2. //复位DS18B20
  3. void DS18B20_Rst(void)     
  4. {                 
  5. CLR_DS18B20();    //拉低DQ
  6. DelayUs(750);    //拉低750us
  7. SET_DS18B20();;   //DQ=1
  8. DelayUs(15);     //15US
  9. }


  10. //等待DS18B20的回应
  11. //返回1:未检测到ds18b20的存在
  12. //返回0:存在
  13. uint8_t DS18B20_Check(void)        
  14. {   
  15. uint8_t retry=0;

  16. while (DS18B20_DQ_IN&&retry<200)
  17. {
  18.     retry++;
  19.     DelayUs(1);
  20. };   
  21. if(retry>=200)return 1;
  22. else retry=0;
  23. while (!DS18B20_DQ_IN&&retry<240)
  24. {
  25.     retry++;
  26.     DelayUs(1);
  27. };
  28. if(retry>=240)return 1;     
  29. return 0;
  30. }


  31. //从DS18B20读取一个位
  32. //返回值:1/0
  33. uint8_t DS18B20_Read_Bit(void)           // read one bit
  34. {
  35. uint8_t data;

  36. CLR_DS18B20();   //拉低DQ
  37. DelayUs(2);
  38. SET_DS18B20();;  //DQ=1
  39. DelayUs(12);
  40. if(DS18B20_DQ_IN)data=1;
  41. else data=0;   
  42. DelayUs(50);  

  43. return data;
  44. }


  45. //从ds18b20读取一个字节
  46. //返回值:读取到的数据
  47. uint8_t DS18B20_Read_Byte(void)    // read one byte
  48. {        
  49. uint8_t i,j,dat;
  50. dat=0;

  51. for (i=1;i<=8;i++)
  52. {
  53.     j=DS18B20_Read_Bit();
  54.     dat=(j<<7)|(dat>>1);
  55. }                           
  56. return dat;
  57. }


  58. //写一个字节到DS18B20
  59. //dat:要写入的字节
  60. void DS18B20_Write_Byte(uint8_t dat)     
  61. {            
  62. uint8_t j;
  63. uint8_t testb;

  64. for (j=1;j<=8;j++)
  65. {
  66.     testb=dat&0x01;
  67.     dat=dat>>1;
  68.     if (testb)
  69.     {
  70.         CLR_DS18B20(); //DS18B20_DQ_OUT=0;// Write 1
  71.         DelayUs(2);                           
  72.         SET_DS18B20(); //DS18B20_DQ_OUT=1;
  73.         DelayUs(60);            
  74.     }
  75.     else
  76.     {
  77.         CLR_DS18B20(); //DS18B20_DQ_OUT=0;// Write 0
  78.         DelayUs(60);            
  79.         SET_DS18B20(); //DS18B20_DQ_OUT=1;
  80.         DelayUs(2);                          
  81.     }
  82. }
  83. }


  84. //开始温度转换
  85. void DS18B20_Start(void)// ds1820 start convert
  86. {                                          
  87. DS18B20_Rst();     
  88.   DS18B20_Check();   
  89. DS18B20_Write_Byte(0xcc);// skip rom
  90. DS18B20_Write_Byte(0x44);// convert
  91. }


  92. //初始化DS18B20的IO口DQ同时检查DS的存在
  93. //返回1:不存在
  94. //返回0:存在         
  95. uint8_t DS18B20_Init(void)
  96. {
  97. //配置PC16口   
  98. GPIO_QuickInit(HW_GPIOC, 16, kGPIO_Mode_OPP);

  99. SET_DS18B20();         //使PA2输出高电平

  100. DS18B20_Rst();
  101. return DS18B20_Check();
  102. }


  103. //从ds18b20得到温度值
  104. //精度:0.1C
  105. //返回值:温度值 (-550~1250)
  106. float DS18B20_Get_Temp(void)
  107. {
  108.     uint8_t temp;
  109.     uint8_t TL,TH;
  110.                 int16_t tem;
  111.     DS18B20_Start ();                    // ds1820 start convert
  112.     DS18B20_Rst();
  113.     DS18B20_Check();         
  114.     DS18B20_Write_Byte(0xcc);// skip rom
  115.     DS18B20_Write_Byte(0xbe);// convert            
  116.     TL=DS18B20_Read_Byte(); // LSB   
  117.     TH=DS18B20_Read_Byte(); // MSB  
  118.                       
  119.     if(TH>7)
  120.     {
  121.         TH=~TH;
  122.         TL=~TL;
  123.         temp=0;//温度为负  
  124.     }else temp=1;//温度为正                    
  125.     tem=TH; //获得高八位
  126.     tem<<=8;   
  127.     tem+=TL;//获得低八位
  128.     tem=(float)tem*0.625;//转换     
  129.         if(temp)return tem/10.00; //返回温度值
  130.         else return -tem/10.00;   
  131. }

 楼主| ideafor 发表于 2016-1-23 21:39 | 显示全部楼层
  1. #include "gpio.h"
  2. #include "common.h"
  3. #include "uart.h"
  4. #include "ds18b20.h"

  5. /* CH Kinetis固件库 V2.50 版本 */
  6. /* 修改主频 请使用 CMSIS标准文件 system_MKxxxx.c 中的 CLOCK_SETUP 宏 */

  7. /* UART 快速初始化结构所支持的引脚* 使用时还是推荐标准初始化 */
  8. /*
  9. UART1_RX_PE01_TX_PE00   
  10. UART0_RX_PF17_TX_PF18   
  11. UART3_RX_PE05_TX_PE04   
  12. UART5_RX_PF19_TX_PF20   
  13. UART5_RX_PE09_TX_PE08   
  14. UART2_RX_PE17_TX_PE16   
  15. UART4_RX_PE25_TX_PE24   
  16. UART0_RX_PA01_TX_PA02   
  17. UART0_RX_PA15_TX_PA14   
  18. UART3_RX_PB10_TX_PB11   
  19. UART0_RX_PB16_TX_PB17   
  20. UART1_RX_PC03_TX_PC04   
  21. UART4_RX_PC14_TX_PC15   
  22. UART3_RX_PC16_TX_PC17   
  23. UART2_RX_PD02_TX_PD03   
  24. UART0_RX_PD06_TX_PD07   
  25. UART2_RX_PF13_TX_PF14   
  26. UART5_RX_PD08_TX_PD09   
  27. */


  28. int main(void)
  29. {
  30.                 float temp;
  31.     DelayInit();
  32.     /* 初始化一个引脚 设置为推挽输出 */
  33.     GPIO_QuickInit(HW_GPIOE, 26, kGPIO_Mode_OPP);
  34.     /* 初始化一个串口 使用UART0端口的PTD6引脚和PTD7引脚作为接收和发送,默认设置 baud 115200 */
  35.     UART_QuickInit(UART0_RX_PB16_TX_PB17, 115200);
  36.                 printf("DS18B20 DEMO:\r\n");
  37.                 while(DS18B20_Init()){;}
  38.     while(1)
  39.     {
  40.                 temp=DS18B20_Get_Temp();
  41.                 printf("Temperate:%4.2f \r\n",temp);
  42.     GPIO_ToggleBit(HW_GPIOE, 26);
  43.     DelayMs(1000);
  44.     }
  45. }


 楼主| ideafor 发表于 2016-1-23 21:40 | 显示全部楼层
  1. #ifndef __DS18B20_H
  2. #define __DS18B20_H
  3. #include "gpio.h"
  4. #include "common.h"

  5. #define CLR_DS18B20()   PCout(16)=0
  6. #define SET_DS18B20()   PCout(16)=1
  7. #define DS18B20_DQ_IN   PCin(16)

  8. uint8_t DS18B20_Init(void);          //初始化DS18B20
  9. float DS18B20_Get_Temp(void);   //获取温度
  10. void DS18B20_Start(void);       //开始温度转换
  11. void DS18B20_Write_Byte(uint8_t dat);//写入一个字节
  12. uint8_t DS18B20_Read_Byte(void);     //读出一个字节
  13. uint8_t DS18B20_Read_Bit(void);      //读出一个位
  14. uint8_t DS18B20_Check(void);         //检测是否存在DS18b20
  15. void DS18B20_Rst(void);         //复位DS18B20   

  16. #endif
MJM_WSY 发表于 2016-1-24 12:40 | 显示全部楼层
不错!好东西啊
ljqdsj 发表于 2016-1-24 17:23 | 显示全部楼层
谢谢分享啊
wg3613 发表于 2016-1-24 21:52 | 显示全部楼层
好资料,比较详细,最好被整个工程文件上传一下
64xiaodian 发表于 2016-1-25 00:29 | 显示全部楼层
赞一个:)
justinlin2015 发表于 2016-1-25 16:43 | 显示全部楼层

谢谢分享啊
Thethree 发表于 2016-1-25 20:25 | 显示全部楼层
DS18B20应该是I2C接口吧,那读取速率最快能达到多少呢?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

30

主题

149

帖子

1

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