DS18B20.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. /* include ---------------------------------------------------------*/
  2. #include "main.h"
  3. /* private define -------------------------------------------------*/
  4. #define DS18B20_DQ_SCK_APBxClock_FUN RCC_APB2PeriphClockCmd
  5. #define DS18B20_DQ_GPIO_CLK RCC_APB2Periph_GPIOA
  6. #define DS18B20_DQ_GPIO_PORT GPIOA
  7. #define DS18B20_DQ_GPIO_PIN GPIO_Pin_7
  8. #define DS18B20_DQ_0 GPIO_ResetBits(DS18B20_DQ_GPIO_PORT,DS18B20_DQ_GPIO_PIN )
  9. #define DS18B20_DQ_1 GPIO_SetBits(DS18B20_DQ_GPIO_PORT,DS18B20_DQ_GPIO_PIN )
  10. #define DS18B20_DQ_IN() GPIO_ReadInputDataBit( DS18B20_DQ_GPIO_PORT,DS18B20_DQ_GPIO_PIN)
  11. /* private variables ----------------------------------------------*/
  12. /* private function prototypes ------------------------------------*/
  13. static void DS18B20_Mode_IPU(void);
  14. static void DS18B20_Mode_Out_PP(void);
  15. static void DS18B20_Rst(void);
  16. static uint8_t DS18B20_Presence(void);
  17. static uint8_t DS18B20_ReadBit(void);
  18. static uint8_t DS18B20_ReadByte(void);
  19. static void DS18B20_WriteByte(uint8_t dat);
  20. static void DS18B20_SkipRom(void);
  21. static void DS18B20_MatchRom(void);
  22. static uint8_t Init(void);
  23. static void ReadId(uint8_t * ds18b20_id);
  24. static float GetTemp_SkipRom(void);
  25. static float GetTemp_MatchRom( uint8_t * ds18b20_id );
  26. /* public variables -----------------------------------------------*/
  27. DS18B20_t DS18B20 =
  28. {
  29. Init,
  30. ReadId,
  31. GetTemp_SkipRom,
  32. GetTemp_MatchRom
  33. };
  34. /**
  35. * @brief 初始化
  36. * @param None
  37. * @retval None
  38. * @note None
  39. */
  40. static uint8_t Init(void)
  41. {
  42. GPIO_InitTypeDef GPIO_InitStructure;
  43. DS18B20_DQ_SCK_APBxClock_FUN ( DS18B20_DQ_GPIO_CLK, ENABLE);
  44. GPIO_InitStructure.GPIO_Pin = DS18B20_DQ_GPIO_PIN;
  45. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  46. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  47. GPIO_Init ( DS18B20_DQ_GPIO_PORT , &GPIO_InitStructure );
  48. DS18B20_DQ_1;
  49. DS18B20_Rst();
  50. return DS18B20_Presence ();
  51. }
  52. /**
  53. * @brief 使DS18B20-DATA引脚变为输入模式
  54. * @param None
  55. * @retval None
  56. * @note None
  57. */
  58. static void DS18B20_Mode_IPU(void)
  59. {
  60. GPIO_InitTypeDef GPIO_InitStructure;
  61. GPIO_InitStructure.GPIO_Pin = DS18B20_DQ_GPIO_PIN;
  62. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  63. GPIO_Init(DS18B20_DQ_GPIO_PORT, &GPIO_InitStructure);
  64. }
  65. /**
  66. * @brief 使DS18B20-DATA引脚变为输出模式
  67. * @param None
  68. * @retval None
  69. * @note None
  70. */
  71. static void DS18B20_Mode_Out_PP(void)
  72. {
  73. GPIO_InitTypeDef GPIO_InitStructure;
  74. GPIO_InitStructure.GPIO_Pin = DS18B20_DQ_GPIO_PIN;
  75. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  76. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  77. GPIO_Init(DS18B20_DQ_GPIO_PORT, &GPIO_InitStructure);
  78. }
  79. /**
  80. * @brief 主机给从机发送复位脉冲
  81. * @param None
  82. * @retval None
  83. * @note None
  84. */
  85. static void DS18B20_Rst(void)
  86. {
  87. /* 主机设置为推挽输出 */
  88. DS18B20_Mode_Out_PP();
  89. DS18B20_DQ_0;
  90. /* 主机至少产生480us的低电平复位信号 */
  91. DelayClass.DelayUs(750);
  92. /* 主机在产生复位信号后,需将总线拉高 */
  93. DS18B20_DQ_1;
  94. /*从机接收到主机的复位信号后,会在15~60us后给主机发一个存在脉冲*/
  95. DelayClass.DelayUs(15);
  96. }
  97. /**
  98. * @brief 检测从机给主机返回的存在脉冲
  99. * @param None
  100. * @retval 0 成功 1 失败
  101. * @note None
  102. */
  103. static uint8_t DS18B20_Presence(void)
  104. {
  105. uint8_t pulse_time = 0;
  106. /* 主机设置为上拉输入 */
  107. DS18B20_Mode_IPU();
  108. /* 等待存在脉冲的到来,存在脉冲为一个60~240us的低电平信号
  109. * 如果存在脉冲没有来则做超时处理,从机接收到主机的复位信号后,会在15~60us后给主机发一个存在脉冲
  110. */
  111. while( DS18B20_DQ_IN() && pulse_time<100 )
  112. {
  113. pulse_time++;
  114. DelayClass.DelayUs(1);
  115. }
  116. /* 经过100us后,存在脉冲都还没有到来*/
  117. if( pulse_time >=100 )
  118. return 1;
  119. else
  120. pulse_time = 0;
  121. /* 存在脉冲到来,且存在的时间不能超过240us */
  122. while( !DS18B20_DQ_IN() && pulse_time<240 )
  123. {
  124. pulse_time++;
  125. DelayClass.DelayUs(1);
  126. }
  127. if( pulse_time >=240 )
  128. return 1;
  129. else
  130. return 0;
  131. }
  132. /**
  133. * @brief 从DS18B20读取一个bit
  134. * @param None
  135. * @retval None
  136. * @note None
  137. */
  138. static uint8_t DS18B20_ReadBit(void)
  139. {
  140. uint8_t dat;
  141. /* 读0和读1的时间至少要大于60us */
  142. DS18B20_Mode_Out_PP();
  143. /* 读时间的起始:必须由主机产生 >1us <15us 的低电平信号 */
  144. DS18B20_DQ_0;
  145. DelayClass.DelayUs(10);
  146. /* 设置成输入,释放总线,由外部上拉电阻将总线拉高 */
  147. DS18B20_Mode_IPU();
  148. if( DS18B20_DQ_IN() == SET )
  149. {
  150. dat = 1;
  151. }
  152. else
  153. {
  154. dat = 0;
  155. }
  156. /* 这个延时参数请参考时序图 */
  157. DelayClass.DelayUs(45);
  158. return dat;
  159. }
  160. /**
  161. * @brief 从DS18B20读一个字节,低位先行
  162. * @param None
  163. * @retval None
  164. * @note None
  165. */
  166. static uint8_t DS18B20_ReadByte(void)
  167. {
  168. uint8_t i, j, dat = 0;
  169. for(i=0; i<8; i++)
  170. {
  171. j = DS18B20_ReadBit();
  172. dat = (dat) | (j<<i);
  173. }
  174. return dat;
  175. }
  176. /**
  177. * @brief 写一个字节到DS18B20,低位先行
  178. * @param None
  179. * @retval None
  180. * @note None
  181. */
  182. static void DS18B20_WriteByte(uint8_t dat)
  183. {
  184. uint8_t i, testb;
  185. DS18B20_Mode_Out_PP();
  186. for( i=0; i<8; i++ )
  187. {
  188. testb = dat&0x01;
  189. dat = dat>>1;
  190. /* 写0和写1的时间至少要大于60us */
  191. if (testb)
  192. {
  193. DS18B20_DQ_0;
  194. /* 1us < 这个延时 < 15us */
  195. DelayClass.DelayUs(8);
  196. DS18B20_DQ_1;
  197. DelayClass.DelayUs(58);
  198. }
  199. else
  200. {
  201. DS18B20_DQ_0;
  202. /* 60us < Tx 0 < 120us */
  203. DelayClass.DelayUs(70);
  204. DS18B20_DQ_1;
  205. /* 1us < Trec(恢复时间) < 无穷大*/
  206. DelayClass.DelayUs(2);
  207. }
  208. }
  209. }
  210. /**
  211. * @brief 跳过匹配 DS18B20 ROM
  212. * @param None
  213. * @retval None
  214. * @note None
  215. */
  216. static void DS18B20_SkipRom(void)
  217. {
  218. DS18B20_Rst();
  219. DS18B20_Presence();
  220. DS18B20_WriteByte(0XCC);/* 跳过 ROM */
  221. }
  222. /**
  223. * @brief 执行匹配 DS18B20 ROM
  224. * @param None
  225. * @retval None
  226. * @note None
  227. */
  228. static void DS18B20_MatchRom(void)
  229. {
  230. DS18B20_Rst();
  231. DS18B20_Presence();
  232. DS18B20_WriteByte(0X55); /* 匹配 ROM */
  233. }
  234. /**
  235. * @brief 在跳过匹配 ROM 情况下获取 DS18B20 温度值
  236. * @param None
  237. * @retval None
  238. * @note None
  239. */
  240. static float GetTemp_SkipRom(void)
  241. {
  242. uint8_t tpmsb, tplsb;
  243. short s_tem;
  244. float f_tem;
  245. DS18B20_SkipRom ();
  246. DS18B20_WriteByte(0X44); /* 开始转换 */
  247. DS18B20_SkipRom ();
  248. DS18B20_WriteByte(0XBE); /* 读温度值 */
  249. tplsb = DS18B20_ReadByte();
  250. tpmsb = DS18B20_ReadByte();
  251. s_tem = tpmsb<<8;
  252. s_tem = s_tem | tplsb;
  253. if( s_tem < 0 ) /* 负温度 */
  254. {
  255. f_tem = (~s_tem+1) * 0.0625;
  256. }
  257. else
  258. {
  259. f_tem = s_tem * 0.0625;
  260. }
  261. return f_tem;
  262. }
  263. /**
  264. * @brief 在匹配 ROM 情况下获取 DS18B20 ID
  265. * @param ds18b20_id 用于存放 DS18B20 序列号的数组的首地址
  266. * @retval None
  267. * @note None
  268. */
  269. static void ReadId(uint8_t * ds18b20_id)
  270. {
  271. uint8_t uc;
  272. DS18B20_WriteByte(0x33); //读取序列号
  273. for ( uc = 0; uc < 8; uc ++ )
  274. {
  275. ds18b20_id [ uc ] = DS18B20_ReadByte();
  276. }
  277. }
  278. /**
  279. * @brief 在匹配 ROM 情况下获取 DS18B20 温度值
  280. * @param ds18b20_id 存放 DS18B20 序列号的数组的首地址
  281. * @retval None
  282. * @note None
  283. */
  284. static float GetTemp_MatchRom( uint8_t * ds18b20_id )
  285. {
  286. uint8_t tpmsb, tplsb, i;
  287. short s_tem;
  288. float f_tem;
  289. DS18B20_MatchRom (); //匹配ROM
  290. for(i=0;i<8;i++)
  291. {
  292. DS18B20_WriteByte ( ds18b20_id [i]);
  293. }
  294. DS18B20_WriteByte(0X44); /* 开始转换 */
  295. DS18B20_MatchRom (); //匹配ROM
  296. for(i=0;i<8;i++)
  297. {
  298. DS18B20_WriteByte (ds18b20_id [i]);
  299. }
  300. DS18B20_WriteByte(0XBE); /* 读温度值 */
  301. tplsb = DS18B20_ReadByte();
  302. tpmsb = DS18B20_ReadByte();
  303. s_tem = tpmsb<<8;
  304. s_tem = s_tem | tplsb;
  305. if( s_tem < 0 ) /* 负温度 */
  306. {
  307. f_tem = (~s_tem+1) * 0.0625;
  308. }
  309. else
  310. {
  311. f_tem = s_tem * 0.0625;
  312. }
  313. return f_tem;
  314. }