AM2301.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. #include "common_config.h"
  2. #include "stm32f4xx.h"
  3. #include "gpio.h"
  4. #include "AM2301.h"
  5. #ifdef PRINTF_STDLIB
  6. #include <stdio.h>
  7. #endif
  8. #ifdef PRINTF_CUSTOM
  9. #include "tinystdio.h"
  10. #endif
  11. #include "FreeRTOS.h"
  12. #include "task.h"
  13. #include "semphr.h"
  14. #define AM2301_ERRORS_LIMIT 5
  15. /* Force remove debug output */
  16. #undef DBG
  17. #define DBG if(0)
  18. static void one_wire_delay_us(uint16_t time);
  19. static void am2301_pin_as_output(at2301_sensor *sensor);
  20. static void am2301_pin_as_input(at2301_sensor *sensor);
  21. AM2301_t am2301_reset(at2301_sensor *sensor);
  22. at2301_data_t sAM2301Sensorsdata[MAX_T_SENSORS];
  23. at2301_sensor sAM2301Sensors[MAX_T_SENSORS];
  24. TIM_TypeDef *timer = TIM2;
  25. static bool dht_present = false;
  26. static bool dht_finish = false;
  27. static bool new_hum_request = false;
  28. static uint8_t rawData[50];
  29. static void am2301_pin_as_output(at2301_sensor *sensor) {
  30. gpio_pindef_t *pin = &gpio_pins[sensor->ow_pin];
  31. gpio_hw_config_pin(pin->port, pin->pin, (GPIO_MODE_OUT_CFG | GPIO_SPEED_HIGH_CFG));
  32. gpio_set(sensor->ow_pin, GPIO_SET);
  33. }
  34. static void am2301_pin_as_input(at2301_sensor *sensor) {
  35. gpio_pindef_t *pin = &gpio_pins[sensor->ow_pin];
  36. gpio_hw_config_pin(pin->port, pin->pin, (GPIO_MODE_IN_CFG | GPIO_PU_CFG));
  37. }
  38. AM2301_t am2301_reset(at2301_sensor *sensor)
  39. {
  40. uint8_t flag_err = 0;
  41. new_hum_request = true;
  42. /* Запрос данных у датчика */
  43. //Перевод пина "на выход"
  44. am2301_pin_as_output(sensor);
  45. //Опускание линии данных на 500 мкс
  46. gpio_set(sensor->ow_pin, 0);
  47. one_wire_delay_us(500);
  48. //Подъём линии, перевод порта "на вход"
  49. gpio_set(sensor->ow_pin, 1);
  50. am2301_pin_as_input(sensor);
  51. for(uint8_t i = 0; i < 120; i++);
  52. NVIC_EnableIRQ(sensor->irq);
  53. flag_err = 0;
  54. while(!dht_present) {
  55. vTaskDelay(1);
  56. flag_err ++;
  57. if(flag_err > 5) {
  58. break;
  59. }
  60. }
  61. if (flag_err > 5) {
  62. DBG printf("CONNECT ERR\r\n\r\n");
  63. return CONNECTION_ERR;
  64. }
  65. return CONNECTION_OK;
  66. }
  67. AM2301_t am2301_get_data(at2301_sensor *sensor, at2301_data_t *data) {
  68. uint8_t flag_err = 0;
  69. dht_present = false;
  70. dht_finish = false;
  71. if (am2301_reset(sensor) != CONNECTION_OK) {
  72. dht_present = false;
  73. dht_finish = false;
  74. NVIC_DisableIRQ(sensor->irq);
  75. return CONNECTION_ERR;
  76. }
  77. flag_err = 0;
  78. while(!dht_finish) {
  79. vTaskDelay(1);
  80. if(flag_err > 5) {
  81. break;
  82. }
  83. flag_err ++;
  84. }
  85. if (flag_err > 5) {
  86. dht_present = false;
  87. dht_finish = false;
  88. NVIC_DisableIRQ(sensor->irq);
  89. return READ_ERR;
  90. }
  91. dht_present = false;
  92. dht_finish = false;
  93. NVIC_DisableIRQ(sensor->irq);
  94. uint8_t data_sensor[5] = {0, 0, 0, 0, 0};
  95. for(uint8_t a = 0; a < 5; a++) {
  96. for(uint8_t b = 0; b < 8; b ++) {
  97. if(rawData[a*8 + b] > 100) data_sensor[a] |= (1<<(7 - b));
  98. }
  99. }
  100. memset(rawData, 0, sizeof(rawData));
  101. /* Проверка целостности данных */
  102. if((uint8_t)(data_sensor[0] + data_sensor[1] + data_sensor[2] + data_sensor[3]) == data_sensor[4]) {
  103. //Если контрольная сумма совпадает, то конвертация и возврат полученных значений
  104. data->hum = (float)(((uint16_t)data_sensor[0]<<8) | data_sensor[1])*0.1f;
  105. //Проверка на отрицательность температуры
  106. if(!(rawData[2] & (1<<7))) {
  107. data->temp = (float)(((uint16_t)data_sensor[2]<<8) | data_sensor[3])*0.1f;
  108. } else {
  109. rawData[2] &= ~(1<<7);
  110. data->temp = (float)(((uint16_t)data_sensor[2]<<8) | data_sensor[3])*-0.1f;
  111. }
  112. } else {
  113. DBG printf("TEMP ERR\r\n\r\n");
  114. return PARITY_ERR;
  115. }
  116. DBG printf("TEMP = %.1f\r\n\r\n", data->temp);
  117. DBG printf("HUM = %.1f\r\n\r\n", data->hum);
  118. return DATA_OK;
  119. }
  120. void am2301_init_port(void)
  121. {
  122. // Setup clock
  123. if (timer == TIM2)
  124. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
  125. else if (timer == TIM3)
  126. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
  127. else
  128. while(1){} // not implemented
  129. TIM_TimeBaseInitTypeDef TIM_InitStructure;
  130. TIM_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
  131. TIM_InitStructure.TIM_Prescaler = 84 - 1; // For 84 MHz APB1 timer clock
  132. TIM_InitStructure.TIM_Period = 0xFFFF;
  133. TIM_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  134. TIM_InitStructure.TIM_RepetitionCounter = 0;
  135. TIM_TimeBaseInit(timer, &TIM_InitStructure);
  136. //TIM_ITConfig(timer, TIM_IT_Update, ENABLE);
  137. TIM_Cmd(timer, ENABLE);
  138. RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
  139. // Selects the GPIOA pin 0 used as external interrupt source
  140. SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);
  141. // Selects the GPIOC pin 12 used as external interrupt source
  142. SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, EXTI_PinSource12);
  143. // External interrupt settings
  144. EXTI_InitTypeDef EXTI_InitStruct;
  145. EXTI_InitStruct.EXTI_Line = EXTI_Line0 | EXTI_Line12;
  146. EXTI_InitStruct.EXTI_LineCmd = ENABLE;
  147. EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
  148. EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;
  149. EXTI_Init(&EXTI_InitStruct);
  150. // Nested vectored interrupt settings
  151. NVIC_InitTypeDef NVIC_InitStruct;
  152. NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn | EXTI15_10_IRQn;
  153. NVIC_InitStruct.NVIC_IRQChannelCmd = DISABLE;
  154. // EXTI0_IRQn has Most important interrupt
  155. NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x00;
  156. NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x00;
  157. NVIC_Init(&NVIC_InitStruct);
  158. }
  159. void am2301_init_sensors(void)
  160. {
  161. uint8_t i;
  162. for (i = 0; i < MAX_T_SENSORS; i++) {
  163. sAM2301Sensorsdata[i].hum = 0.0;
  164. sAM2301Sensorsdata[i].temp = 0.0;
  165. sAM2301Sensorsdata[i].ErrorCycle = 0;
  166. sAM2301Sensorsdata[i].SensorState = 1; // По умолчанию устанавливаем признак неисправности
  167. }
  168. sAM2301Sensors[0].ow_pin = WDATA1;
  169. sAM2301Sensors[0].irq = EXTI0_IRQn;
  170. sAM2301Sensors[1].ow_pin = WDATA2;
  171. sAM2301Sensors[1].irq = EXTI15_10_IRQn;
  172. }
  173. /**
  174. * @brief Задача чтения температуры 1-wire
  175. */
  176. void vTaskDHT(void *pvParameters)
  177. {
  178. (void)pvParameters;
  179. am2301_init_port();
  180. am2301_init_sensors();
  181. vTaskDelay(1000);
  182. for (;;)
  183. {
  184. for(uint8_t i = 0; i < MAX_T_SENSORS; i++) {
  185. if (am2301_get_data(&sAM2301Sensors[i], &sAM2301Sensorsdata[i]) != DATA_OK) {
  186. sAM2301Sensorsdata[i].ErrorCycle ++;
  187. } else {
  188. sAM2301Sensorsdata[i].ErrorCycle = 0;
  189. sAM2301Sensorsdata[i].SensorState = 0;
  190. }
  191. if (sAM2301Sensorsdata[i].ErrorCycle == AM2301_ERRORS_LIMIT) {
  192. sAM2301Sensorsdata[i].SensorState = 1;
  193. sAM2301Sensorsdata[i].ErrorCycle = 0;
  194. }
  195. }
  196. vTaskDelay(2000);
  197. }
  198. }
  199. void DHT_Task_Init(void) {
  200. xTaskCreate(vTaskDHT, "vTaskDHT", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);
  201. }
  202. void TIM2_IRQHandler(void)
  203. {
  204. TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
  205. // gpio_invert_output(LED_GREEN);
  206. }
  207. void one_wire_delay_us(uint16_t time) {
  208. timer->CNT = 0;
  209. time -= 1;
  210. while (timer->CNT <= time) {
  211. ;
  212. }
  213. }
  214. void EXTI_IRQHandler(void)
  215. {
  216. static bool start_meas = false;
  217. static uint8_t cnt_bit = 0;
  218. // Checks whether the interrupt from EXTI0 or not
  219. if (EXTI_GetITStatus(EXTI_Line0) || EXTI_GetITStatus(EXTI_Line12))
  220. {
  221. if(!dht_present) {
  222. cnt_bit = 0;
  223. if(new_hum_request) {
  224. start_meas = false;
  225. new_hum_request = false;
  226. }
  227. if (!start_meas) {
  228. timer->CNT = 0;
  229. start_meas = true;
  230. } else {
  231. if (timer->CNT >= 120){
  232. dht_present = true;
  233. start_meas = false;
  234. timer->CNT = 0;
  235. }
  236. }
  237. } else {
  238. rawData[cnt_bit++] = timer->CNT;
  239. if (cnt_bit == 40){
  240. dht_finish = true;
  241. }
  242. timer->CNT = 0;
  243. }
  244. // Clears the EXTI line pending bit
  245. EXTI_ClearITPendingBit(EXTI_Line0);
  246. EXTI_ClearITPendingBit(EXTI_Line12);
  247. }
  248. }