OneWire.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  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. UnitempStatus unitemp_oneWire_getData(Sensor* sensor) {
  32. OneWireSensor* instance = sensor->instance;
  33. //Проверка на допустимость опроса датчика
  34. if(furi_get_tick() - instance->lastPollingTime < POLLING_INTERVAL) {
  35. //Выход в случае раннего опроса
  36. return UT_EARLYPOOL;
  37. }
  38. //Массив для приёма данных
  39. uint8_t data[5] = {0};
  40. //Сохранение времени последнего опроса
  41. instance->lastPollingTime = furi_get_tick();
  42. /* Запрос */
  43. //Опускание линии
  44. furi_hal_gpio_write(instance->gpio->pin, false);
  45. //Ожидание более 18 мс
  46. furi_delay_ms(19);
  47. //Выключение прерываний, чтобы ничто не мешало обработке данных
  48. __disable_irq();
  49. //Подъём линии
  50. furi_hal_gpio_write(instance->gpio->pin, true);
  51. /* Ответ датчика */
  52. //Переменная-счётчик
  53. uint16_t timeout = 0;
  54. //Ожидание подъёма линии
  55. while(!furi_hal_gpio_read(instance->gpio->pin)) {
  56. timeout++;
  57. if(timeout > POLLING_TIMEOUT_TICKS) {
  58. //Включение прерываний
  59. __enable_irq();
  60. //Запись неправильных значений
  61. sensor->hum = -128.0f;
  62. sensor->temp = -128.0f;
  63. //Возврат признака отсутствующего датчика
  64. return UT_TIMEOUT;
  65. }
  66. }
  67. timeout = 0;
  68. //Ожидание спада линии
  69. while(furi_hal_gpio_read(instance->gpio->pin)) {
  70. timeout++;
  71. if(timeout > POLLING_TIMEOUT_TICKS) {
  72. //Включение прерываний
  73. __enable_irq();
  74. //Запись неправильных значений
  75. sensor->hum = -128.0f;
  76. sensor->temp = -128.0f;
  77. //Возврат признака отсутствующего датчика
  78. return UT_TIMEOUT;
  79. }
  80. }
  81. //Ожидание подъёма линии
  82. while(!furi_hal_gpio_read(instance->gpio->pin)) {
  83. timeout++;
  84. if(timeout > POLLING_TIMEOUT_TICKS) {
  85. //Включение прерываний
  86. __enable_irq();
  87. //Запись неправильных значений
  88. sensor->hum = -128.0f;
  89. sensor->temp = -128.0f;
  90. //Возврат признака отсутствующего датчика
  91. return UT_TIMEOUT;
  92. }
  93. }
  94. timeout = 0;
  95. //Ожидание спада линии
  96. while(furi_hal_gpio_read(instance->gpio->pin)) {
  97. timeout++;
  98. if(timeout > POLLING_TIMEOUT_TICKS) {
  99. //Включение прерываний
  100. __enable_irq();
  101. //Запись неправильных значений
  102. sensor->hum = -128.0f;
  103. sensor->temp = -128.0f;
  104. //Возврат признака отсутствующего датчика
  105. return UT_TIMEOUT;
  106. }
  107. }
  108. /* Чтение данных с датчика*/
  109. //Приём 5 байт
  110. for(uint8_t a = 0; a < 5; a++) {
  111. for(uint8_t b = 7; b != 255; b--) {
  112. uint16_t hT = 0, lT = 0;
  113. //Пока линия в низком уровне, инкремент переменной lT
  114. while(!furi_hal_gpio_read(instance->gpio->pin) && lT != 65535) lT++;
  115. //Пока линия в высоком уровне, инкремент переменной hT
  116. while(furi_hal_gpio_read(instance->gpio->pin) && hT != 65535) hT++;
  117. //Если hT больше lT, то пришла единица
  118. if(hT > lT) data[a] |= (1 << b);
  119. }
  120. }
  121. //Включение прерываний
  122. __enable_irq();
  123. //Проверка контрольной суммы
  124. if((uint8_t)(data[0] + data[1] + data[2] + data[3]) != data[4]) {
  125. //Запись неправильных значений
  126. sensor->hum = -128.0f;
  127. sensor->temp = -128.0f;
  128. //Если контрольная сумма не совпала, возврат ошибки
  129. return UT_BADCRC;
  130. }
  131. /* Преобразование данных в явный вид */
  132. //DHT11 и DHT12
  133. if(sensor->type == DHT11 || sensor->type == DHT12_1W) {
  134. sensor->hum = (float)data[0];
  135. sensor->temp = (float)data[2];
  136. //Проверка на отрицательность температуры
  137. if(data[3] != 0) {
  138. //Проверка знака
  139. if(!(data[3] & (1 << 7))) {
  140. //Добавление положительной дробной части
  141. sensor->temp += data[3] * 0.1f;
  142. } else {
  143. //А тут делаем отрицательное значение
  144. data[3] &= ~(1 << 7);
  145. sensor->temp += data[3] * 0.1f;
  146. sensor->temp *= -1;
  147. }
  148. }
  149. }
  150. //DHT21, DHT22, AM2320
  151. if(sensor->type == DHT21 || sensor->type == DHT22 || sensor->type == AM2320_1W) {
  152. sensor->hum = (float)(((uint16_t)data[0] << 8) | data[1]) / 10;
  153. //Проверка на отрицательность температуры
  154. if(!(data[2] & (1 << 7))) {
  155. sensor->temp = (float)(((uint16_t)data[2] << 8) | data[3]) / 10;
  156. } else {
  157. data[2] &= ~(1 << 7);
  158. sensor->temp = (float)(((uint16_t)data[2] << 8) | data[3]) / 10 * -1;
  159. }
  160. }
  161. //Возврат признака успешного опроса
  162. return UT_OK;
  163. }