From b77eb4bf4f154b4f41681a384f0a495acfd43966 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80?= =?UTF-8?q?=D0=B0=20=D0=90=D0=B1=D1=80=D0=B0=D0=BC=D0=BE=D0=B2=D0=B0?= Date: Mon, 19 Feb 2024 20:24:40 +0000 Subject: [PATCH] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=B8=D1=82?= =?UTF-8?q?=D1=8C=20DHT=5F22.c?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DHT_22.c | 289 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 146 insertions(+), 143 deletions(-) diff --git a/DHT_22.c b/DHT_22.c index 4640fe0..d9c7dd2 100644 --- a/DHT_22.c +++ b/DHT_22.c @@ -1,147 +1,150 @@ -unsigned char data[5]; -static float temperature, humidity; -float value; -#define F_CPU 16000000UL - -ISR(TIMER1_OVF_vect) // процедура обработки прерывания переполнения счетчика -{ - TCNT1 = value; // preload timer -} - -void timer_set(float value_1, byte Dev) -{ - TCCR1A = 0; - TCCR1B = 0; - TCNT1 = value_1; // preload timer - TCCR1B |= Dev; // (коэффициент деления предделителя) - TIMSK1 |= (1 << TOIE1); //(разрешаем вызов процедуры обработки прерывания переполнения счетчика) - interrupts(); // разрешаем все прерывания - value = value_1; -} +#include +#include -void DHT22_setup() -{ - #define DHT_PORT PORTD - #define DHT_DDR DDRD - #define DHT_PIN PIND - #define DHT_BIT 4 //по ардуиновски D5 - - Serial.begin(9600); -} - -unsigned int read_dht_hum() //подпрограмма работы с DHT -{ - - int temp; - unsigned char i, j; - ReLoad: //метка для ошибок - //=============MCU send START - DHT_DDR |= (1 << DHT_BIT); //выход - DHT_PORT &= ~(1 << DHT_BIT); //низкий уровень, подтягиваем линию, разбудим датчик - delayEquivalent2(18); //18 мс по условиям документации. - DHT_PORT |= (1 << DHT_BIT); //отпускаем линию - DHT_DDR &= ~(1 << DHT_BIT); //пин как выход -//============= инциализация DHT - delayEquivalent3(1); //задержка по условию - if (DHT_PIN &(1 << DHT_BIT)) - { - Serial.println("NO init "); - goto ReLoad; - } //датчик должен ответить 0 - delayEquivalent4(0.99); - //по истечению 80 мкс, датчик должен отпустить шину - //===============Приём 40 бит данных - while (DHT_PIN &(1 << DHT_BIT)); //ждем пока на шине появится 1 - for (j = 0; j < 5; j++) //цикл для 0-4 байт - { - data[j] = 0; - for (i = 0; i < 8; i++) //приём битов и укладка их в байты - { - while (!(DHT_PIN &(1 << DHT_BIT))); //ждем когда датчик отпустит шину - delayEquivalent5(0.99); //задержка высокого уровня при 0 30 мкс - if (DHT_PIN &(1 << DHT_BIT)) //если по истечению времени сигнал на линии высокий, значит передается 1 - data[j] |= 1 << (7 - i); //тогда i-й бит устанавливаем 1 - while (DHT_PIN &(1 << DHT_BIT)); // ждем окончание 1 - } - } - - if ((unsigned char)(data[0] + data[1] + data[2] + data[3]) != data[4]) //checksum - { - Serial.println("checksum Error "); - goto ReLoad; - } -} //конец подрограммы - - -void delayEquivalent2(uint8_t delayTime)//Для 18 Милисеунд -{ - for(volatile uint8_t i1 = 0; i1 < 10; ++i1) - { - for(volatile uint8_t i2 = 0; i2 < 100; ++i2) - { - for(volatile uint8_t i3 = 0; i3 < delayTime; ++i3) - { - - } - } - } -} - -void delayEquivalent3(uint8_t delayTime1)//Для 50 микросекунд -{ - for(volatile uint8_t i1 = 0; i1 < 10; ++i1) - { - for(volatile uint8_t i2 = 0; i2 < 5; ++i2) - { - for(volatile uint8_t i3 = 0; i3 < delayTime1; ++i3) - { - - } - } - } -} - -void delayEquivalent4(uint8_t delayTime2)//Для 80 микросекунд -{ - for(volatile uint8_t i1 = 0; i1 < 10; ++i1) - { - for(volatile uint8_t i2 = 0; i2 < 8; ++i2) - { - for(volatile uint8_t i3 = 0; i3 < delayTime2; ++i3) - { - - } - } - } -} - -void delayEquivalent5(uint8_t delayTime3)//Для 80 микросекунд -{ - for(volatile uint8_t i1 = 0; i1 < 10; ++i1) - { - for(volatile uint8_t i2 = 0; i2 < 3; ++i2) - { - for(volatile uint8_t i3 = 0; i3 < delayTime3; ++i3) - { - - } - } - } -} - -int get_DHT_value_temperature() -{ - read_dht_hum(); //вызов подпрограммы DHT11 - temperature = (data[3] *0.1) + ((data[2] &0b01111111) *25.6); //нюанс расчета температуры для DHT22 - if (data[2] &0b10000000) temperature *= -1; //если отрицательная температура - timer_set(0, 4); //хватает задержки в 1 сек, для этого скетча хватает скорости 180 - return temperature; +// Определения портов и битов +#define DHT_PORT PORTD +#define DHT_DDR DDRD +#define DHT_PIN PIND +#define DHT_BIT 4 + +// Глобальные переменные +unsigned char data[5]; +float temperature, humidity; + +// Флаг прерывания +volatile unsigned char interrupt_flag = 0; + +// Таймер для задержки +volatile unsigned int timer_counter = 0; + +// Прерывание таймера +ISR(TIMER1_COMPA_vect) +{ + // Увеличиваем счетчик таймера + timer_counter++; + + // Проверяем, достигли ли мы нужной задержки + if (timer_counter == 180000) + { + // Сбрасываем счетчик таймера + timer_counter = 0; + + // Устанавливаем флаг прерывания + interrupt_flag = 1; + } } -int get_DHT_value_humidity() -{ - read_dht_hum(); //вызов подпрограммы DHT11 - humidity = (data[1] *0.1) + (data[0] *25.6); //нюанс расчета влажности для DHT22 - timer_set(0, 4); - return humidity; +// Функция чтения данных с DHT +unsigned int read_dht_hum() +{ + int temp; + unsigned char i, j; + + ReLoad: + // Выставляем пин как выход и устанавливаем низкий уровень + DHT_DDR |= (1 << DHT_BIT); + DHT_PORT &= ~(1 << DHT_BIT); + // Задержка 18 мс + //timer_counter = 18000; + timer_counter = 0; + while(timer_counter < 18000) timer_counter++; + //for (volatile unsigned int i = 0; i < timer_counter; i++); + + // Отпускаем линию и переводим пин как вход + DHT_PORT |= (1 << DHT_BIT); + DHT_DDR &= ~(1 << DHT_BIT); + + // Задержка 50 мкс + //timer_counter = 50; + timer_counter = 0; + while(timer_counter < 50) timer_counter++; + //for (volatile unsigned int i = 0; i < timer_counter; i++); + + // Проверяем, ответил ли датчик + if (DHT_PIN & (1 << DHT_BIT)) + { + Serial.println("No init"); + //goto ReLoad; + } + + // Задержка 80 мкс + //timer_counter = 50; + timer_counter = 0; + while(timer_counter < 50) timer_counter++; + //for (volatile unsigned int i = 0; i < timer_counter; i++); + + // Принимаем 40 бит данных + while (DHT_PIN & (1 << DHT_BIT)); + for (j = 0; j < 5; j++) + { + data[j] = 0; + for (i = 0; i < 8; i++) + { + while (!(DHT_PIN & (1 << DHT_BIT))); + // Задержка 30 мкс + timer_counter = 0; + while(timer_counter < 30) timer_counter++; + //for (volatile unsigned int i = 0; i < timer_counter; i++); + if (DHT_PIN & (1 << DHT_BIT)) data[j] |= 1 << (7 - i); + while (DHT_PIN & (1 << DHT_BIT)); + } + } + + // Проверяем контрольную сумму + if ((unsigned char)(data[0] + data[1] + data[2] + data[3]) != data[4]) + { + Serial.println("Check summ error"); + //goto ReLoad; + } +} + +// Установка таймера +void setup_timer() +{ + // Настраиваем таймер 1 в режиме CTC + TCCR1A = (1 << WGM12); + TCCR1B = (1 << CS12) | (1 << WGM13); + + // Устанавливаем значение сравнения для частоты 1 Гц + OCR1A = 15624; + + // Разрешаем прерывание сравнения A + TIMSK1 |= (1 << OCIE1A); +} + +// Настройка +void setup() +{ + // Инициализируем UART + Serial.begin(9600); + + // Настраиваем таймер + setup_timer(); + + // Разрешаем прерывания + sei(); +} + +// Основной цикл +void loop() +{ + // Ожидаем прерывания + while (interrupt_flag); + + // Сбрасываем флаг прерывания + interrupt_flag = 0; + + // Читаем данные с DHT + read_dht_hum(); + + // Вычисляем температуру и влажность + temperature = (data[3] * 0.1) + ((data[2] & 0b01111111) * 25.6); + if (data[2] & 0b10000000) temperature *= -1; + humidity = (data[1] * 0.1) + (data[0] * 25.6); + + // Выводим данные на UART + Serial.print(humidity); + Serial.print("% "); + Serial.print(temperature); + Serial.println("C"); } \ No newline at end of file