В предыдущей части урока мы познакомились с датчиком, создали и настроили проект, написали функцию инициализации датчика, а также функцию снятия с него показаний.
Переходим в файл main.c и внесём изменения и там.
Пока мы будем выводить показания датчика в шину USART через переходник, а уж затем, если всё будет нормально, займёмся выводом данных в индикатор.
Локальные переменные в функции main() у нас будут только следующие
/* USER CODE BEGIN 1 */
uint8_t dt[5];
float temper, hum;
/* USER CODE END 1 */
Исправим вызов функции инициализации и удалим вывод статуса в USART
/* USER CODE BEGIN 2 */
port_init();
dht22_init();
/* USER CODE END 2 */
Из бесконечного цикла удалим весь код и начнем писать новый.
Добавим условие успешной инициализации и задержку на 2 секунды, так как именно такое время нужно датчику на конвертацию
/* USER CODE BEGIN 3 */
if(dht22_GetData(dt))
{
}
HAL_Delay(2000);
}
В теле условия мы заберём из массива данные температуры, обнулив самый старший бит (бит знака)
if(dht22_GetData(dt))
{
temper = (float)((*(uint16_t*)(dt+1)) & 0x3FFF) / 10;
Проверим бит знака, если он есть, то присвоим его значению температуры, умножив его на -1
temper = (float)((*(uint16_t*)(dt+1)) & 0x3FFF) / 10;
if((*(uint16_t*)(dt+1)) & 0x8000) temper *= -1.0;
Далее считаем значение влажности из массива, только уже ничего не обнуляя
if((*(uint16_t*)(dt+1)) & 0x8000) temper *= -1.0;
hum = (float)(*(int16_t*)(dt+3)) / 10;
Передадим наши данные в USART
hum = (float)(*(int16_t*)(dt+3)) / 10;
sprintf(str1,"Hum: %.1f, Temper: %.1frn", hum, temper);
HAL_UART_Transmit(&huart1,(uint8_t*)str1,strlen(str1),0x1000);
Соберём проект и посмотрим в терминальной программе, как будут выводиться показания влажности и температуры
Отлично!
Теперь для большей красоты эксперимента давайте также выведем показания на восьмиразрядный индикатор.
Для этого подключим наши библиотечные файлы max7219.h и max7219.c из проекта урока 105 для приёмника NRF24_RX. Скопируем данные файлы в соответствующие папки нашего проекта и подключим файл max7219.c в дерево проектов.
В файле main.h подключим также библиотеку индикатора
#include "dht22.h"
#include "max7219.h"
Затем в файле max7219.h мы исправим подключение библиотеки HAL и подключим ещё один файл для понимания стандартных типов
#include "stm32f1xx_hal.h"
#include "main.h"
#include "stdint.h"
Перейдём в файл max7219.c и исправим там ножку порта в макросах управления ножкой CS
#define cs_set() HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET)
#define cs_reset() HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET)
Также исправим номер подключенной шины SPI
extern SPI_HandleTypeDef hspi2;
Аналогичные исправления проделаем в функции Send_7219
HAL_SPI_Transmit (&hspi2, (uint8_t*)aTxBuf, 1, 5000);
aTxBuf[0]=dt;
HAL_SPI_Transmit (&hspi2, (uint8_t*)aTxBuf, 1, 5000);
Над функцией инициализации добавим две функции вывода числа с плавающей точкой в левую и правую часть
//-------------------------------------------------------
void NumberF_7219 (float f) //пишем в левую тетраду c десятичной цифрой
{
int n = (int)(f * 10);
uint8_t ng=0;//переменная для минуса
if(n<0)
{
ng=1;
n*=-1;
}
int m = n;
uint8_t i=0;
do
{
if(i==1) Send_7219(++i,(n%10) | 0x80);//символ цифры и точка
else Send_7219(++i,n%10);//символ цифры
n/=10;
} while(n);
if(ng)
{
if(m<10)
{
Send_7219(i+1,0x80);//ноль с точкой
Send_7219(i+2,0x0A);//символ -
}
else Send_7219(i+1,0x0A);//символ -
}
else
{
if((m<10)&&(m!=0))
{
Send_7219(i+1,0x80);//ноль с точкой
}
}
}
//-------------------------------------------------------
void NumberLF_7219 (float f) //пишем в левую тетраду c десятичной цифрой
{
int n = (int)(f * 10);
uint8_t ng=0;//переменная для минуса
if(n<0)
{
ng=1;
n*=-1;
}
int m = n;
uint8_t i=4;
do
{
if(i==5) Send_7219(++i,(n%10) | 0x80);//символ цифры и точка
else Send_7219(++i,n%10);//символ цифры
n/=10;
} while(n);
if(ng)
{
if(m<10)
{
Send_7219(i+1,0x80);//ноль с точкой
Send_7219(i+2,0x0A);//символ -
}
else Send_7219(i+1,0x0A);//символ -
}
else
{
if((m<10)&&(m!=0))
{
Send_7219(i+1,0x80);//ноль с точкой
}
}
}
//-------------------------------------------------------
Эти функции были написаны по образу и подобию функций вывода целочисленных величин с внесением некоторых незначительных изменений по выводу точки в нужное место. Данные функции работают с числами с плавающей точкой, отображая только один знак после запятой (десятые доли). Но, думаю, этого нам будет достаточно для отображения данных температуры и влажности окружающего воздуха.
Напишем прототипы для данных функций в заголовочном файле и перейдём в файл main.c.
Инициализируем наш индикатор, а заодно погасим светодиод, что будет свидетельствовать о том, что у нас ничего не повисло при инициализации, в функции main()
dht22_init();
Init_7219();
HAL_Delay(200);
Clear_7219();
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
Отобразим теперь показания влажности и температуры на индикаторе в бесконечном цикле
HAL_UART_Transmit(&huart1,(uint8_t*)str1,strlen(str1),0x1000);
Clear_7219();
NumberF_7219(temper);
NumberLF_7219(hum);
}
HAL_Delay(2000);
Теперь у нас показания отображаются и в терминальной программе, и на индикаторе
Также я провёл вот такой эксперимент по измерению отрицательной температуры, вытащив датчик за окно
И получил вот такой результат, тем самым убедившись в работоспособности датчика при отрицательных температурах и способность проекта правильно их измерять
Итак, сегодня мы с вами изучили работу с ещё одним датчиком, способным измерять относительную влажность и температуру в широких диапазонах и с отличной точностью — DHT22.
Всем спасибо за внимание!
Предыдущая часть Программирование МК STM32 Следующий урок
Отладочную плату можно приобрести здесь STM32F103C8T6
Датчик температуры и влажности можно приобрести здесь DHT22
Переходник USB to TTL можно приобрести здесь ftdi ft232rl
Смотреть ВИДЕОУРОК (нажмите на картинку)
Возник вопрос, решил совместить 2 проекта: термодатчик и датчик влажности (урок 92 и 107), т.е. делал не замену, а добавление. Функции и переменные проверил — ничего не пересекается. Проект собрался без ошибок. На порту PB11 — термодатчик, на PB10 — датчик влажности.
Сделал вывод значений обоих датчиков в терминал. Чтение через преобразователь USB-UART.
Почему в результате плата игнорирует датчик влажности, а видит только один термодатчик ???