【分享】 STM32 DS18B20 程序。。

2019-12-10 18:28发布

论坛好像没有STM32 驱动DS18B20 的程序,分享一个找到的程序。

经过测试,通讯正常,温度读取正确。。 注意程序的读取函数,返回值的说明喔。 我之前没仔细分析,把返回值乘以0.0625....结果不对。后来发现,返回的值,已经是温度的16进制形式。

假如 返回值为 0x1504 那么温度即 21.4。 0x15=16+5=21  0x04=4    21.4 ℃。

程序调用方法:
int main(void)
{
        unsigned int value;
                ds18b20_init();
        while(1)
        {       
                value = ds18b20_read();
                }
}




DS18B20.C
  1. #include "ds18b20.h"

  2. #define EnableINT()  
  3. #define DisableINT()

  4. #define DS_PORT   GPIOA
  5. #define DS_DQIO   GPIO_Pin_1

  6. #define DS_RCC_PORT  RCC_APB2Periph_GPIOA

  7. #define DS_PRECISION 0x7f   //精度配置寄存器 1f=9位; 3f=10位; 5f=11位; 7f=12位;
  8. #define DS_AlarmTH  0x64
  9. #define DS_AlarmTL  0x8a
  10. #define DS_CONVERT_TICK 1000

  11. #define ResetDQ() GPIO_ResetBits(DS_PORT,DS_DQIO)
  12. #define SetDQ()  GPIO_SetBits(DS_PORT,DS_DQIO)
  13. #define GetDQ()  GPIO_ReadInputDataBit(DS_PORT,DS_DQIO)


  14. static unsigned char TempX_TAB[16]={0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09};


  15. void Delay_us(u32 Nus)
  16. {  
  17. SysTick->LOAD=Nus*9;          //时间加载      
  18. SysTick->CTRL|=0x01;             //开始倒数     
  19. while(!(SysTick->CTRL&(1<<16))); //等待时间到达  
  20. SysTick->CTRL=0X00000000;        //关闭计数器
  21. SysTick->VAL=0X00000000;         //清空计数器      
  22. }



  23. unsigned char ResetDS18B20(void)
  24. {
  25. unsigned char resport;
  26. SetDQ();
  27. Delay_us(50);

  28. ResetDQ();
  29. Delay_us(500);  //500us (该时间的时间范围可以从480到960微秒)
  30. SetDQ();
  31. Delay_us(40);  //40us
  32. //resport = GetDQ();
  33. while(GetDQ());
  34. Delay_us(500);  //500us
  35. SetDQ();
  36. return resport;
  37. }

  38. void DS18B20WriteByte(unsigned char Dat)
  39. {
  40. unsigned char i;
  41. for(i=8;i>0;i--)
  42. {
  43.    ResetDQ();     //在15u内送数到数据线上,DS18B20在15-60u读数
  44.   Delay_us(5);    //5us
  45.   if(Dat & 0x01)
  46.    SetDQ();
  47.   else
  48.    ResetDQ();
  49.   Delay_us(65);    //65us
  50.   SetDQ();
  51.   Delay_us(2);    //连续两位间应大于1us
  52.   Dat >>= 1;
  53. }
  54. }


  55. unsigned char DS18B20ReadByte(void)
  56. {
  57. unsigned char i,Dat;
  58. SetDQ();
  59. Delay_us(5);
  60. for(i=8;i>0;i--)
  61. {
  62.    Dat >>= 1;
  63.     ResetDQ();     //从读时序开始到采样信号线必须在15u内,且采样尽量安排在15u的最后
  64.   Delay_us(5);   //5us
  65.   SetDQ();
  66.   Delay_us(5);   //5us
  67.   if(GetDQ())
  68.     Dat|=0x80;
  69.   else
  70.    Dat&=0x7f;  
  71.   Delay_us(65);   //65us
  72.   SetDQ();
  73. }
  74. return Dat;
  75. }


  76. void ReadRom(unsigned char *Read_Addr)
  77. {
  78. unsigned char i;

  79. DS18B20WriteByte(ReadROM);
  80.   
  81. for(i=8;i>0;i--)
  82. {
  83.   *Read_Addr=DS18B20ReadByte();
  84.   Read_Addr++;
  85. }
  86. }


  87. void DS18B20Init(unsigned char Precision,unsigned char AlarmTH,unsigned char AlarmTL)
  88. {
  89. DisableINT();
  90. ResetDS18B20();
  91. DS18B20WriteByte(SkipROM);
  92. DS18B20WriteByte(WriteScratchpad);
  93. DS18B20WriteByte(AlarmTL);
  94. DS18B20WriteByte(AlarmTH);
  95. DS18B20WriteByte(Precision);

  96. ResetDS18B20();
  97. DS18B20WriteByte(SkipROM);
  98. DS18B20WriteByte(CopyScratchpad);
  99. EnableINT();

  100. while(!GetDQ());  //等待复制完成 ///////////
  101. }


  102. void DS18B20StartConvert(void)
  103. {
  104. DisableINT();
  105. ResetDS18B20();
  106. DS18B20WriteByte(SkipROM);
  107. DS18B20WriteByte(StartConvert);
  108. EnableINT();
  109. }

  110. void DS18B20_Configuration(void)
  111. {
  112. GPIO_InitTypeDef GPIO_InitStructure;

  113. RCC_APB2PeriphClockCmd(DS_RCC_PORT, ENABLE);

  114. GPIO_InitStructure.GPIO_Pin = DS_DQIO;
  115. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; //开漏输出
  116. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //2M时钟速度
  117. GPIO_Init(DS_PORT, &GPIO_InitStructure);
  118. }


  119. void ds18b20_init(void)
  120. {
  121. DS18B20_Configuration();
  122. DS18B20Init(DS_PRECISION, DS_AlarmTH, DS_AlarmTL);
  123. DS18B20StartConvert();
  124. }


  125. unsigned short ds18b20_read(void)
  126. {
  127. unsigned char TemperatureL,TemperatureH;
  128. unsigned int  Temperature;

  129. DisableINT();
  130.   ResetDS18B20();
  131. DS18B20WriteByte(SkipROM);
  132. DS18B20WriteByte(ReadScratchpad);
  133. TemperatureL=DS18B20ReadByte();
  134. TemperatureH=DS18B20ReadByte();
  135. ResetDS18B20();
  136. EnableINT();

  137. if(TemperatureH & 0x80)
  138.   {
  139.   TemperatureH=(~TemperatureH) | 0x08;
  140.   TemperatureL=~TemperatureL+1;
  141.   if(TemperatureL==0)
  142.    TemperatureH+=1;
  143.   }

  144. TemperatureH=(TemperatureH<<4)+((TemperatureL&0xf0)>>4);
  145. TemperatureL=TempX_TAB[TemperatureL&0x0f];

  146. //bit0-bit7为小数位,bit8-bit14为整数位,bit15为正负位
  147. Temperature=TemperatureH;
  148. Temperature=(Temperature<<8) | TemperatureL;

  149. DS18B20StartConvert();

  150. return  Temperature;
  151. //返回16位数据  bit0-bit7为小数位,bit8-bit14为整数位,bit15为正负位
  152. }
复制代码DS18B20.H
  1. #ifndef __DS18B20_H__
  2. #define __DS18B20_H__

  3. #include"stm32f10x.h"


  4. #define  SkipROM    0xCC     //跳过ROM
  5. #define  SearchROM  0xF0  //搜索ROM
  6. #define  ReadROM    0x33  //读ROM
  7. #define  MatchROM   0x55  //匹配ROM
  8. #define  AlarmROM   0xEC  //告警ROM

  9. #define  StartConvert    0x44  //开始温度转换,在温度转换期间总线上输出0,转换结束后输出1
  10. #define  ReadScratchpad  0xBE  //读暂存器的9个字节
  11. #define  WriteScratchpad 0x4E  //写暂存器的温度告警TH和TL
  12. #define  CopyScratchpad  0x48  //将暂存器的温度告警复制到EEPROM,在复制期间总线上输出0,复制完后输出1
  13. #define  RecallEEPROM    0xB8    //将EEPROM的温度告警复制到暂存器中,复制期间输出0,复制完成后输出1
  14. #define  ReadPower       0xB4    //读电源的供电方式:0为寄生电源供电;1为外部电源供电


  15. void ds18b20_init(void);
  16. unsigned short ds18b20_read(void);


  17. #endif
复制代码
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
65条回答
njjh1718
1楼-- · 2019-12-17 12:18
标记下    鼓励   
a515509429
2楼-- · 2019-12-17 13:34
正准备用 谢谢分享和详细的介绍说明
roc2
3楼-- · 2019-12-17 13:45
 精彩回答 2  元偷偷看……
TKZXJ
4楼-- · 2019-12-17 17:23
多谢分享!
culapple
5楼-- · 2019-12-17 20:34
多谢分享 前来移植

一周热门 更多>