150 lines
4.2 KiB
C
150 lines
4.2 KiB
C
#include <avr/interrupt.h>
|
||
#include <avr/io.h>
|
||
|
||
// Определения портов и битов
|
||
#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;
|
||
}
|
||
}
|
||
|
||
// Функция чтения данных с 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");
|
||
} |