OneWire.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. #include "OneWire.h"
  2. #include "Sensors.h"
  3. //Интервал опроса датчиков (мс)
  4. #define POLLING_INTERVAL 2000
  5. //Максимальное количество попугаев ожидания датчика
  6. #define POLLING_TIMEOUT_TICKS 10000
  7. bool unitemp_oneWire_sensorInit(OneWireSensor* sensor) {
  8. if(sensor == NULL || sensor->gpio == NULL) return false;
  9. //Высокий уровень по умолчанию
  10. furi_hal_gpio_write(sensor->gpio->pin, true);
  11. //Режим работы - OpenDrain, подтяжка включается на всякий случай
  12. furi_hal_gpio_init(
  13. sensor->gpio->pin, //Порт FZ
  14. GpioModeOutputOpenDrain, //Режим работы - открытый сток
  15. GpioPullUp, //Принудительная подтяжка линии данных к питанию
  16. GpioSpeedVeryHigh); //Скорость работы - максимальная
  17. return true;
  18. }
  19. bool unitemp_oneWire_sensorDeInit(OneWireSensor* sensor) {
  20. if(sensor == NULL || sensor->gpio == NULL) return false;
  21. //Низкий уровень по умолчанию
  22. furi_hal_gpio_write(sensor->gpio->pin, false);
  23. //Режим работы - аналог, подтяжка выключена
  24. furi_hal_gpio_init(
  25. sensor->gpio->pin, //Порт FZ
  26. GpioModeAnalog, //Режим работы - аналог
  27. GpioPullNo, //Подтяжка выключена
  28. GpioSpeedLow); //Скорость работы - минимальная
  29. return true;
  30. }
  31. bool unitemp_oneWire_sensorSetGPIO(Sensor* sensor, const GPIO* gpio) {
  32. if(sensor == NULL || gpio == NULL) return false;
  33. OneWireSensor* instance = sensor->instance;
  34. instance->gpio = gpio;
  35. return true;
  36. }
  37. const GPIO* unitemp_oneWire_sensorGetGPIO(Sensor* sensor) {
  38. if(sensor == NULL) return NULL;
  39. OneWireSensor* instance = sensor->instance;
  40. return instance->gpio;
  41. }
  42. UnitempStatus unitemp_oneWire_getData(Sensor* sensor) {
  43. OneWireSensor* instance = sensor->instance;
  44. //Проверка на допустимость опроса датчика
  45. if(furi_get_tick() - instance->lastPollingTime < POLLING_INTERVAL) {
  46. //Возврат ошибки если последний опрос датчика был неудачным
  47. if(instance->lastHum == -128.0f && instance->lastTemp == -128.0f) {
  48. sensor->hum = instance->lastHum;
  49. sensor->temp = instance->lastTemp;
  50. return UT_TIMEOUT;
  51. }
  52. //Выход в случае раннего опроса
  53. sensor->hum = instance->lastHum;
  54. sensor->temp = instance->lastTemp;
  55. return UT_EARLYPOOL;
  56. }
  57. //Массив для приёма данных
  58. uint8_t data[5] = {0};
  59. //Сохранение времени последнего опроса
  60. instance->lastPollingTime = furi_get_tick();
  61. /* Запрос */
  62. //Опускание линии
  63. furi_hal_gpio_write(instance->gpio->pin, false);
  64. //Ожидание более 18 мс
  65. furi_delay_ms(19);
  66. //Выключение прерываний, чтобы ничто не мешало обработке данных
  67. __disable_irq();
  68. //Подъём линии
  69. furi_hal_gpio_write(instance->gpio->pin, true);
  70. /* Ответ датчика */
  71. //Переменная-счётчик
  72. uint16_t timeout = 0;
  73. //Ожидание подъёма линии
  74. while(!furi_hal_gpio_read(instance->gpio->pin)) {
  75. timeout++;
  76. if(timeout > POLLING_TIMEOUT_TICKS) {
  77. //Включение прерываний
  78. __enable_irq();
  79. //Запись неправильных значений
  80. instance->lastHum = -128.0f;
  81. instance->lastTemp = -128.0f;
  82. //Возврат признака отсутствующего датчика
  83. return UT_TIMEOUT;
  84. }
  85. }
  86. timeout = 0;
  87. //Ожидание спада линии
  88. while(furi_hal_gpio_read(instance->gpio->pin)) {
  89. timeout++;
  90. if(timeout > POLLING_TIMEOUT_TICKS) {
  91. //Включение прерываний
  92. __enable_irq();
  93. //Запись неправильных значений
  94. instance->lastHum = -128.0f;
  95. instance->lastTemp = -128.0f;
  96. //Возврат признака отсутствующего датчика
  97. return UT_TIMEOUT;
  98. }
  99. }
  100. //Ожидание подъёма линии
  101. while(!furi_hal_gpio_read(instance->gpio->pin)) {
  102. timeout++;
  103. if(timeout > POLLING_TIMEOUT_TICKS) {
  104. //Включение прерываний
  105. __enable_irq();
  106. //Запись неправильных значений
  107. instance->lastHum = -128.0f;
  108. instance->lastTemp = -128.0f;
  109. //Возврат признака отсутствующего датчика
  110. return UT_TIMEOUT;
  111. }
  112. }
  113. timeout = 0;
  114. //Ожидание спада линии
  115. while(furi_hal_gpio_read(instance->gpio->pin)) {
  116. timeout++;
  117. if(timeout > POLLING_TIMEOUT_TICKS) {
  118. //Включение прерываний
  119. __enable_irq();
  120. //Запись неправильных значений
  121. instance->lastHum = -128.0f;
  122. instance->lastTemp = -128.0f;
  123. //Возврат признака отсутствующего датчика
  124. return UT_TIMEOUT;
  125. }
  126. }
  127. /* Чтение данных с датчика*/
  128. //Приём 5 байт
  129. for(uint8_t a = 0; a < 5; a++) {
  130. for(uint8_t b = 7; b != 255; b--) {
  131. uint16_t hT = 0, lT = 0;
  132. //Пока линия в низком уровне, инкремент переменной lT
  133. while(!furi_hal_gpio_read(instance->gpio->pin) && lT != 65535) lT++;
  134. //Пока линия в высоком уровне, инкремент переменной hT
  135. while(furi_hal_gpio_read(instance->gpio->pin) && hT != 65535) hT++;
  136. //Если hT больше lT, то пришла единица
  137. if(hT > lT) data[a] |= (1 << b);
  138. }
  139. }
  140. //Включение прерываний
  141. __enable_irq();
  142. //Проверка контрольной суммы
  143. if((uint8_t)(data[0] + data[1] + data[2] + data[3]) != data[4]) {
  144. //Запись неправильных значений
  145. instance->lastHum = -128.0f;
  146. instance->lastTemp = -128.0f;
  147. //Если контрольная сумма не совпала, возврат ошибки
  148. return UT_BADCRC;
  149. }
  150. /* Преобразование данных в явный вид */
  151. //DHT11 и DHT12
  152. if(sensor->type == DHT11 || sensor->type == DHT12_1W) {
  153. instance->lastHum = (float)data[0];
  154. instance->lastTemp = (float)data[2];
  155. //Проверка на отрицательность температуры
  156. if(data[3] != 0) {
  157. //Проверка знака
  158. if(!(data[3] & (1 << 7))) {
  159. //Добавление положительной дробной части
  160. instance->lastTemp += data[3] * 0.1f;
  161. } else {
  162. //А тут делаем отрицательное значение
  163. data[3] &= ~(1 << 7);
  164. instance->lastTemp += data[3] * 0.1f;
  165. instance->lastTemp *= -1;
  166. }
  167. }
  168. }
  169. //DHT21, DHT22, AM2320
  170. if(sensor->type == DHT21 || sensor->type == DHT22 || sensor->type == AM2320_1W) {
  171. instance->lastHum = (float)(((uint16_t)data[0] << 8) | data[1]) / 10;
  172. //Проверка на отрицательность температуры
  173. if(!(data[2] & (1 << 7))) {
  174. instance->lastTemp = (float)(((uint16_t)data[2] << 8) | data[3]) / 10;
  175. } else {
  176. data[2] &= ~(1 << 7);
  177. instance->lastTemp = (float)(((uint16_t)data[2] << 8) | data[3]) / 10 * -1;
  178. }
  179. }
  180. sensor->hum = instance->lastHum;
  181. sensor->temp = instance->lastTemp;
  182. //Возврат признака успешного опроса
  183. return UT_OK;
  184. }