am2303.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. #include "am2303.h"
  2. #include "dwt.h"
  3. //复位AM2303
  4. void am2303_rst(void)
  5. {
  6. AM2303_IO_OUT; // SET OUTPUT
  7. AM2303_DO_LOW; //拉低DQ
  8. ms_delay(20); //拉低至少18ms
  9. AM2303_DO_HIGH; // DQ=1
  10. us_delay(30); //主机拉高20~40us
  11. }
  12. //等待AM2303的回应
  13. //返回1:未检测到AM2303的存在
  14. //返回0:存在
  15. INT8U am2303_check(void)
  16. {
  17. INT8U retry = 0;
  18. AM2303_IO_IN; // SET INPUT
  19. while ((GPIO_ReadInputDataBit(AM2303_PORT, AM2303_PIN) == 1) && retry < 100) // AM2303会拉低40~80us
  20. {
  21. retry++;
  22. us_delay(1);
  23. };
  24. if (retry >= 100)
  25. return 1;
  26. else
  27. retry = 0;
  28. while ((GPIO_ReadInputDataBit(AM2303_PORT, AM2303_PIN) == 0) && retry < 100) // AM2303拉低后会再次拉高40~80us
  29. {
  30. retry++;
  31. us_delay(1);
  32. };
  33. if (retry >= 100)
  34. return 1;
  35. return 0;
  36. }
  37. //从AM2303读取一个位
  38. //返回值:1/0
  39. INT8U am2303_read_bit(void)
  40. {
  41. INT8U retry = 0;
  42. while ((GPIO_ReadInputDataBit(AM2303_PORT, AM2303_PIN) == 1) && retry < 100) //等待变为低电平
  43. {
  44. retry++;
  45. us_delay(1);
  46. }
  47. retry = 0;
  48. while ((GPIO_ReadInputDataBit(AM2303_PORT, AM2303_PIN) == 0) && retry < 100) //等待变高电平
  49. {
  50. retry++;
  51. us_delay(1);
  52. }
  53. us_delay(40); //等待40us
  54. if (GPIO_ReadInputDataBit(AM2303_PORT, AM2303_PIN) == 1)
  55. return 1;
  56. else
  57. return 0;
  58. }
  59. //从AM2303读取一个字节
  60. //返回值:读到的数据
  61. INT8U am2303_read_byte(void)
  62. {
  63. INT8U i, dat;
  64. dat = 0;
  65. for (i = 0; i < 8; i++)
  66. {
  67. dat <<= 1;
  68. dat |= am2303_read_bit();
  69. }
  70. return dat;
  71. }
  72. //从AM2303读取一次数据
  73. // temp:温度值(范围:0~50°)
  74. // humi:湿度值(范围:20%~90%)
  75. //返回值:0,正常;1,读取失败
  76. // INT8U am2303_read_data(INT8U *temp, INT8U *humi)
  77. // {
  78. // INT8U buf[5];
  79. // INT8U i;
  80. // am2303_rst();
  81. // if (am2303_check() == 0)
  82. // {
  83. // for (i = 0; i < 5; i++) //读取40位数据
  84. // {
  85. // buf[i] = am2303_read_byte();
  86. // }
  87. // if ((buf[0] + buf[1] + buf[2] + buf[3]) == buf[4])
  88. // {
  89. // *humi = buf[0];
  90. // *temp = buf[2];
  91. // }
  92. // }
  93. // else
  94. // return 1;
  95. // return 0;
  96. // }
  97. /*
  98. *********************************************************************************************************
  99. * 函 数 名: DHT11_ReadData
  100. * 功能说明: 复位DHT11。 拉低DQ为低,持续最少480us,然后等待
  101. * 形 参: 无
  102. * 返 回 值: 0 失败; 1 表示成功
  103. *********************************************************************************************************
  104. */
  105. INT8U am2303_read_data(INT8U *temp, INT8U *humi)
  106. {
  107. INT8U buf[5];
  108. INT8U i;
  109. INT8U k;
  110. /*
  111. 时序:
  112. 1. MCU拉低QD持续时间大于 18ms, 然后释放QD = 1
  113. */
  114. /* 1. 主机发送起始信号, DQ拉低时间 > 18ms */
  115. AM2303_DO_LOW; /* DQ = 0 */
  116. ms_delay(20);
  117. AM2303_DO_HIGH; /* DQ = 1 */
  118. us_delay(15); /* 等待15us */
  119. /* 2. 等待DQ电平变低 ( 超时100us) */
  120. for (k = 0; k < 10; k++)
  121. {
  122. if (DQ_IS_LOW())
  123. {
  124. break;
  125. }
  126. us_delay(10);
  127. }
  128. if (k >= 10)
  129. {
  130. goto quit; /* 超时无应答,失败 */
  131. }
  132. /* 3.等待DQ电平变高 (超时100us) */
  133. for (k = 0; k < 10; k++)
  134. {
  135. if (!DQ_IS_LOW())
  136. {
  137. break;
  138. }
  139. us_delay(10);
  140. }
  141. if (k >= 10)
  142. {
  143. goto quit; /* 超时无应答,失败 */
  144. }
  145. /* 4.等待DQ电平变低 (超时100us) */
  146. for (k = 0; k < 10; k++)
  147. {
  148. if (DQ_IS_LOW())
  149. {
  150. break;
  151. }
  152. us_delay(10);
  153. }
  154. if (k >= 10)
  155. {
  156. goto quit; /* 超时无应答,失败 */
  157. }
  158. /* 读40bit 数据 */
  159. for (i = 0; i < 5; i++)
  160. {
  161. buf[i] = DHT11_ReadByte();
  162. }
  163. us_delay(100);
  164. if ((buf[0] + buf[1] + buf[2] + buf[3]) == buf[4])
  165. {
  166. *humi = buf[0];
  167. *temp = buf[2];
  168. return 1;
  169. }
  170. quit:
  171. return 0;
  172. }
  173. //初始化AM2303的IO口 DQ 同时检测AM2303的存在
  174. //返回1:不存在
  175. //返回0:存在
  176. #if 0
  177. INT8U am2303_init(void)
  178. {
  179. am2303_rst(); //复位AM2303
  180. return am2303_check(); //等待AM2303的回应
  181. }
  182. #else
  183. INT8U am2303_init(void)
  184. {
  185. AM2303_DO_LOW;
  186. }
  187. #endif
  188. /*
  189. *********************************************************************************************************
  190. * 函 数 名: DHT11_ReadByte
  191. * 功能说明: 向DHT11读取1字节数据
  192. * 形 参: 无
  193. * 返 回 值: 无
  194. *********************************************************************************************************
  195. */
  196. uint8_t DHT11_ReadByte(void)
  197. {
  198. /*
  199. 写数据时序, 见DHT11 page 16
  200. */
  201. uint8_t i, k;
  202. uint8_t read = 0;
  203. for (i = 0; i < 8; i++)
  204. {
  205. read <<= 1;
  206. /* 等待DQ电平变高 (超时100us) */
  207. for (k = 0; k < 10; k++)
  208. {
  209. if (!DQ_IS_LOW())
  210. {
  211. break;
  212. }
  213. us_delay(10);
  214. }
  215. if (k >= 10)
  216. {
  217. goto quit; /* 超时无应答,失败 */
  218. }
  219. /* 等待DQ电平变低,统计DQ高电平时长 (超时100us) */
  220. for (k = 0; k < 10; k++)
  221. {
  222. if (DQ_IS_LOW())
  223. {
  224. break;
  225. }
  226. us_delay(10);
  227. }
  228. if (k > 3) /* 高脉冲持续时间大于40us ,认为是1,否则是0 */
  229. {
  230. read++;
  231. }
  232. }
  233. return read;
  234. quit:
  235. return 0xFF;
  236. }