目录
stm32g0xx_it.c(串口中断服务程序所在的.c文件)
设计要求
知识点
需要⽤到GPIO输⼊输出,定时器,串⼝通信,ADC(DMA⽅式实现),LCD屏幕,DHT11
功能概述
模块 | 功能 |
LCD | 显示温湿度,风机开关情况,制冷片开关情况,加热片开关情况,温湿度上下阈值,设备ID |
LED | 三个灯分别模拟风机、制冷片、加热片,灯亮表示开,灯灭表示关 |
DHT11 | 温湿度传感器 |
PA0 | 电池电压采集 |
串口 | 数据接收及下发数据控制 |
低温加热 | 当环境温度低于设置的阈值时,加热片开启,加热到最低温阈值加5摄氏度停止加热 |
高温降温 | 当环境温度高于设置的阈值时,制冷片开启,降温到最高温阈值减5摄氏度停止降温 |
高湿干燥 | 当环境湿度高于设置的阈值时,风机开启,干燥到低于最高湿度阈值停止 |
基本要求
加湿器上电设备⾃检(检查传感器采集是否正常,这个DHT11有存在响应,可以⾃检使⽤,有电池电压检 测,这⾥可以判断电压是否正常),⾃检通过后进⼊⾃动模式,LCD显示温湿度信息以及电池电压。当 湿度达到启动阀值⾃动启动,低于(启动阀值)则停⽌⼯作。 通过五向按键选择并调整温湿度的阙值⼤⼩,以及设备ID号。 与上位机通信(串⼝助⼿),每2s发送设备状态信息到上位机。上位机可发送命令设置除湿器(这⾥需 要识别设备ID),上位机可发送指令获取设备状态信息。
通信要求
• 通讯协议
• 通讯⽅式(暂时使⽤串⼝):9600-N-8-1,MODBUS 协议,参数及内容如下表所示
地址 | 数据信息 | 备注 |
0 | 包头 | 0x55 |
1 | 设备ID | 可读 |
2 | 环境温度 | 可读 |
3 | 环境湿度 | 可读 |
4 | 湿度启动值 | 可读可写 |
5 | 加热启动值 | 可读可写 |
6 | 设备ID设置 | 只写 |
7 | 包尾 | 0xFF |
• 除湿原理(作为了解简单看看就⾏)
当潮湿空⽓经⻛扇吸⼊后,通过特殊设计的⻛道流动,先经半导体制冷器降温结露,制冷器的结露在重 ⼒作⽤下滴⼊引⽔槽,再由导⽔管流出柜外。在设定启动值内经过充分循环除湿,使柜内空⽓湿度降⾄ 结露点以下,完成整个防潮引凝加热过程。同时,除湿装置信号采集传感器外置,能实时准确的采集到 柜内的真实湿度,保证除湿装置在柜内将要达到凝露条件时提前启动除湿。
根据⾃身情况分级做:
1、根据阙值控制LED,并且上传串⼝助⼿,串⼝助⼿可下发配置
2、根据阙值控制LED,并且上传串⼝助⼿,串⼝助⼿可下发配置,LCD显示
3、除了modbus外所有功 能
4、全部功能
STM32配置
LCD屏设置
UARR串口设置
RCC时钟设置
LED引脚设置
ADC设置
PA0采集电源电压值,PA1采集五向键五个不同方向按键按下的电压
再将五向键设置为外部中断,PA8的值判断是否按下按键,当按下的时候调用外部中断函数
温湿度传感器数据输入输出引脚设置
DMA设置
NVIC中断设置
代码示例
lcd.h和lcd.c的导入
main.c
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2022 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "dma.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "dht11.h"
#include <stdio.h>
#include "lcd.h"
#include <string.h>
static uint32_t fac_us = 0; //us延时倍乘数
void delay_init(uint8_t SYSCLK)
{
fac_us = SYSCLK;
}
void delay_us(uint32_t nus)//100 6800
{
uint32_t ticks;
uint32_t told, tnow, tcnt = 0;
uint32_t reload = SysTick->LOAD; //LOAD的值
ticks = nus * fac_us; //需要的节拍数
told = SysTick->VAL; // 24 刚进入时的计数器值
while (1)
{
tnow = SysTick->VAL;//22 20 0
if (tnow != told)
{
if (tnow < told)
tcnt += told - tnow; //这里注意一下SYSTICK是一个递减的计数器就可以了.
else
tcnt += reload - tnow + told;
told = tnow;
if (tcnt >= ticks)
break; //时间超过/等于要延迟的时间,则退出.
}
};
}
void delay_ms(uint16_t nms)
{
uint32_t i;
for (i = 0; i < nms; i++)
delay_us(1000);
}
/* USER CODE END 4 */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
uint8_t humiH;
uint8_t humiL;
uint8_t tempH;
uint8_t tempL;
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
uint8_t tempHthres=30; //高温阈值
uint8_t tempLthres=26; //低温阈值
uint8_t humiHthres=60; //湿度阈值
uint16_t buf[2];//获取到的电压和按键值
int val,key;//获取按键值
int flag=0;//标志位
char Buf[128];
uint8_t cmdbuf[128];
uint8_t valuebuf[128];
float temp;//温度
uint8_t fj;//风机制冷制热
uint8_t zl;
uint8_t zr;
uint8_t FJ[12];
uint8_t JR[12];
uint8_t ZL[12];
extern int flag1;
void recivemag();
void show();
void setstatus();
uint16_t chartoint();
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_USART1_UART_Init();
MX_ADC1_Init();
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
delay_init(64);
FS_DHT11_Init();
Lcd_Init();//初始化LCD屏
Lcd_Clear(BLACK);
Gui_DrawFont_GBK16(40,60,WHITE,BLACK,"Weclome");//显示welcome
HAL_Delay(500);
Lcd_Clear(BLACK);
Gui_DrawFont_GBK16(0,15,WHITE,BLACK,"Volt:");//显示电压
Gui_DrawFont_GBK16(0,15,WHITE,BLACK,"Elect:");//显示电量
Gui_DrawFont_GBK16(0,30,WHITE,BLACK,"Tempe:");//显示温度
Gui_DrawFont_GBK16(0,45,WHITE,BLACK,"humi:");//显示湿度
Gui_DrawFont_GBK16(0,60,WHITE,BLACK,"HThres:");//高温阈值
float H=tempHthres;
char ht[32];
sprintf(ht,"%.2fC",H);
Gui_DrawFont_GBK16(55,60,WHITE,BLACK,(uint8_t *)ht);
Gui_DrawFont_GBK16(0,75,WHITE,BLACK,"LThres:");//低温阈值
float L=tempLthres;
char lt[32];
sprintf(lt,"%.2lfC",L);
Gui_DrawFont_GBK16(55,75,WHITE,BLACK,lt);
Gui_DrawFont_GBK16(0,90,WHITE,BLACK,"HumThres:");//湿度阈值
int Hu=humiHthres;
char hum[32];
sprintf(hum,"%d%%%",Hu);
Gui_DrawFont_GBK16(75,90,WHITE,BLACK,(uint8_t *)hum);
fj='F';
zl='F';
zr='F';
sprintf(FJ,"FJ:%c",fj);
sprintf(ZL,"ZL:%c",zl);
sprintf(JR,"ZR:%c",zr);
Gui_DrawFont_GBK16(0,105,WHITE,BLACK,FJ);//风机开关
Gui_DrawFont_GBK16(45,105,WHITE,BLACK,ZL);//制冷片开关
Gui_DrawFont_GBK16(90,105,WHITE,BLACK,JR);//加热片开关
char t[128],h[128];//温度、湿度实时监测
// Gui_DrawFont_GBK16(25,105,WHITE,BLACK,&fj);//风机开关状态
// Gui_DrawFont_GBK16(70,105,WHITE,BLACK,&zl);//制冷片开关状态
// Gui_DrawFont_GBK16(115,105,WHITE,BLACK,&zr);//加热片开关状态
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2,GPIO_PIN_SET);
HAL_UART_Receive_DMA(&huart1,(uint8_t *)Buf,128);
__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_ADC_Start_DMA(&hadc1,(uint32_t *)buf,2);
DHT11_Read_Data(&humiH,&humiL,&tempH,&tempL);
temp = tempH + tempL*0.1;
HAL_Delay(500);
//printf("temp = %.2fC humi = %d%%",temp,humiH);
sprintf(t,"%.2fC",temp);
sprintf(h,"%d%%",humiH);
Gui_DrawFont_GBK16(50,30,WHITE,BLACK,(uint8_t *)t);
Gui_DrawFont_GBK16(50,45,WHITE,BLACK,(uint8_t *)h);
if(temp>tempHthres)//超过高温阈值,制冷打开,直到温度低于高温阈值-5
{
zl='T';
sprintf(ZL,"ZL:%c",zl);
Gui_DrawFont_GBK16(45,105,WHITE,BLACK,ZL);//制冷片开关
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET);
}
else if(temp<tempHthres-5)
{
zl='F';
sprintf(ZL,"ZL:%c",zl);
Gui_DrawFont_GBK16(45,105,WHITE,BLACK,ZL);//制冷片开关
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET);
}
if(temp<tempLthres)//低于低温阈值
{
zr='T';
sprintf(JR,"ZR:%c",zr);
Gui_DrawFont_GBK16(90,105,WHITE,BLACK,JR);//加热片开关
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_RESET);
}
else if(temp>tempLthres+5)
{
zr='F';
sprintf(JR,"ZR:%c",zr);
Gui_DrawFont_GBK16(90,105,WHITE,BLACK,JR);//加热片开关
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_SET);
}
if(humiH>humiHthres)//大于湿度阈值
{
fj='T';
sprintf(FJ,"FJ:%c",fj);
Gui_DrawFont_GBK16(0,105,WHITE,BLACK,FJ);//风机开关
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,GPIO_PIN_RESET);
}
else if(humiH<humiHthres)
{
fj='F';
sprintf(FJ,"FJ:%c",fj);
Gui_DrawFont_GBK16(0,105,WHITE,BLACK,FJ);//风机开关
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,GPIO_PIN_SET);
}
show();
if(flag1==1)
{
flag1=0;
recivemag();
}
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
/** Configure the main internal regulator output voltage
*/
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1;
RCC_OscInitStruct.PLL.PLLN = 12;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV3;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
/** Initializes the peripherals clocks
*/
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1|RCC_PERIPHCLK_ADC;
PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK1;
PeriphClkInit.AdcClockSelection = RCC_ADCCLKSOURCE_SYSCLK;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
int fputc(int ch,FILE *p)
{
while(!(USART1->ISR &(1<<7)));
USART1->TDR = ch;
return ch;
}
//按键中断
void HAL_GPIO_EXTI_Rising_Callback(uint16_t GPIO_Pin)
{
int val,key;
if(GPIO_Pin==GPIO_PIN_8)
{
HAL_ADC_Start_DMA(&hadc1,(uint32_t *)buf,2);
//按键操作
HAL_ADC_Start(&hadc1);
while(!(ADC1->ISR&(1<<2)));
val=HAL_ADC_GetValue(&hadc1);
while(!(ADC1->ISR&(1<<3)));
key=HAL_ADC_GetValue(&hadc1);
HAL_ADC_Stop(&hadc1);
printf("%d",key);
if(key>800&&key<1000)//向下选择
{
if(flag==0||flag==3)
{
flag=1;
Gui_DrawFont_GBK16(0,60,RED,BLACK,"HThres:");//高温阈值
Gui_DrawFont_GBK16(0,75,WHITE,BLACK,"LThres:");//低温阈值
Gui_DrawFont_GBK16(0,90,WHITE,BLACK,"HumThres:");//湿度阈值
}
else if(flag==1)
{
flag=2;
Gui_DrawFont_GBK16(0,60,WHITE,BLACK,"HThres:");//高温阈值
Gui_DrawFont_GBK16(0,75,RED,BLACK,"LThres:");//低温阈值
Gui_DrawFont_GBK16(0,90,WHITE,BLACK,"HumThres:");//湿度阈值
}
else if(flag==2)
{
flag=3;
Gui_DrawFont_GBK16(0,60,WHITE,BLACK,"HThres:");//高温阈值
Gui_DrawFont_GBK16(0,75,WHITE,BLACK,"LThres:");//低温阈值
Gui_DrawFont_GBK16(0,90,RED,BLACK,"HumThres:");//湿度阈值
}
}
if(key>2000&&key<2500)//向上选择
{
if(flag==0||flag==3)
{
flag=1;
Gui_DrawFont_GBK16(0,60,WHITE,BLACK,"HThres:");//高温阈值
Gui_DrawFont_GBK16(0,75,WHITE,BLACK,"LThres:");//低温阈值
Gui_DrawFont_GBK16(0,90,RED,BLACK,"HumThres:");//湿度阈值
}
else if(flag==1)
{
flag=2;
Gui_DrawFont_GBK16(0,60,WHITE,BLACK,"HThres:");//高温阈值
Gui_DrawFont_GBK16(0,75,RED,BLACK,"LThres:");//低温阈值
Gui_DrawFont_GBK16(0,90,WHITE,BLACK,"HumThres:");//湿度阈值
}
else if(flag==2)
{
flag=3;
Gui_DrawFont_GBK16(0,60,RED,BLACK,"HThres:");//高温阈值
Gui_DrawFont_GBK16(0,75,WHITE,BLACK,"LThres:");//低温阈值
Gui_DrawFont_GBK16(0,90,WHITE,BLACK,"HumThres:");//湿度阈值
}
}
if(key>1500&&key<1800)//向左选择
{
if(flag==1)//高温阈值降低
{
tempHthres--;
float H=tempHthres;
char ht[32];
sprintf(ht,"%.2fC",H);
Gui_DrawFont_GBK16(55,60,WHITE,BLACK,(uint8_t *)ht);
}
if(flag==2)//低温阈值降低
{
tempLthres--;
float L=tempLthres;
char lt[32];
sprintf(lt,"%.2lfC",L);
Gui_DrawFont_GBK16(55,75,WHITE,BLACK,lt);
}
if(flag==3)//湿度阈值降低
{
printf("11111");
humiHthres--;
int Hu=humiHthres;
char hum[32];
sprintf(hum,"%d%%%",Hu);
Gui_DrawFont_GBK16(75,90,WHITE,BLACK,(uint8_t *)hum);
}
}
if(key>2900&&key<3100)//向右选择
{
if(flag==1)//高温阈值增加
{
tempHthres++;
float H=tempHthres;
char ht[32];
sprintf(ht,"%.2fC",H);
Gui_DrawFont_GBK16(55,60,WHITE,BLACK,(uint8_t *)ht);
}
if(flag==2)//低温阈值增加
{
tempLthres++;
float L=tempLthres;
char lt[32];
sprintf(lt,"%.2lfC",L);
Gui_DrawFont_GBK16(55,75,WHITE,BLACK,lt);
}
if(flag==3)//湿度阈值增加
{
printf("22222");
humiHthres++;
int Hu=humiHthres;
char hum[32];
sprintf(hum,"%d%%%",Hu);
Gui_DrawFont_GBK16(75,90,WHITE,BLACK,(uint8_t *)hum);
}
}
}
if(key>2500&&key<2700)//选择中间
{
Gui_DrawFont_GBK16(0,60,WHITE,BLACK,"HThres:");//高温阈值
Gui_DrawFont_GBK16(0,75,WHITE,BLACK,"LThres:");//低温阈值
Gui_DrawFont_GBK16(0,90,WHITE,BLACK,"HumThres:");//湿度阈值
}
}
//获取电压
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
HAL_ADC_Stop_DMA(&hadc1);
buf[0]=buf[0]*3000/4096/1000*2;
float Volt=buf[0];
char volt[2];
sprintf(volt,"%1.2fV",Volt);
Gui_DrawFont_GBK16(50,15,WHITE,BLACK,(uint8_t *)volt);
// buf[1]=buf[1]/4096*100;
// float Elect=buf[1];
// char elect[2];
// sprintf(elect,"%.2f%%",Elect);
// Gui_DrawFont_GBK16(50,15,WHITE,BLACK,(uint8_t *)elect);
//printf("电压=%1.2f",Volt);
}
void show()
{
printf("temp = %.2fC humi = %d%% FJ:%c ZL:%c JR:%c", temp, humiH,fj,zl,zr);
HAL_Delay(2000);
}
void recivemag()
{
printf("rrrr");
uint8_t *p =Buf;
uint8_t i=0;
while(*p!='\0')
{
while(*p!='=')
{
cmdbuf[i++]=*p;
p++;
}
cmdbuf[i]='\0';
i=0;
p++;
while(*p!='\0')
{
valuebuf[i++]=*p;
p++;
}
valuebuf[i]='\0';
}
setstatus();
}
uint16_t chartoint()
{
uint8_t *valuep=valuebuf;
uint16_t sum=0;
while(*valuep!='\0')
{
sum=sum*10+(*valuep-48);
valuep++;
}
return sum;
}
void setstatus()
{
printf("0000");
if(strncmp("th=",Buf,3)==0)
{
//printf("1111");
tempHthres=chartoint();
//tempHthres=Buf[4];
float H=tempHthres;
char ht[32];
sprintf(ht,"%.2fC",H);
Gui_DrawFont_GBK16(55,60,WHITE,BLACK,(uint8_t *)ht);
}
if(strncmp("lh=",Buf,3)==0)
{
tempLthres=chartoint();
//tempLthres=Buf[4];
float L=tempLthres;
char lt[32];
sprintf(lt,"%.2lfC",L);
Gui_DrawFont_GBK16(55,75,WHITE,BLACK,(uint8_t*)lt);
}
if(strncmp("hh=",Buf,3)==0)
{
humiHthres=chartoint();
//humiHthres=Buf[4];
int Hu=humiHthres;
char hum[32];
sprintf(hum,"%d%%%",Hu);
Gui_DrawFont_GBK16(75,90,WHITE,BLACK,(uint8_t *)hum);
}
if (strncmp("zl=T",Buf,4)==0)
{
zl = 'T';
sprintf(ZL,"ZL:%c",zl);
Gui_DrawFont_GBK16(45,105,WHITE,BLACK,ZL);//制冷片开关
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET);
}
else if (strncmp("zl=F",Buf,4)==0)
{
zl = 'F';
sprintf(ZL,"ZL:%c",zl);
Gui_DrawFont_GBK16(45,105,WHITE,BLACK,ZL);//制冷片开关
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET);
}
if (strncmp("zr=T",Buf,4)==0)
{
zr = 'T';
sprintf(JR,"ZR:%c",zr);
Gui_DrawFont_GBK16(90,105,WHITE,BLACK,JR);//加热片开关
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_RESET);
}
else if (strncmp("zr=F",Buf,4)==0)
{
zr = 'F';
sprintf(JR,"ZR:%c",zr);
Gui_DrawFont_GBK16(90,105,WHITE,BLACK,JR);//加热片开关
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_RESET);
}
if (strncmp("fj=T",Buf,4)==0)
{
fj = 'T';
sprintf(FJ,"FJ:%c",fj);
Gui_DrawFont_GBK16(0,105,WHITE,BLACK,FJ);//风机开关
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,GPIO_PIN_RESET);
}
else if (strncmp("fj=F",Buf,4)==0)
{
fj = 'F';
sprintf(FJ,"FJ:%c",fj);
Gui_DrawFont_GBK16(0,105,WHITE,BLACK,FJ);//风机开关
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,GPIO_PIN_RESET);
}
}
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
stm32g0xx_it.c(串口中断服务程序所在的.c文件)
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32g0xx_it.c
* @brief Interrupt Service Routines.
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2022 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32g0xx_it.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN TD */
/* USER CODE END TD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/* External variables --------------------------------------------------------*/
extern DMA_HandleTypeDef hdma_adc1;
extern ADC_HandleTypeDef hadc1;
extern DMA_HandleTypeDef hdma_usart1_rx;
extern DMA_HandleTypeDef hdma_usart1_tx;
extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart2;
/* USER CODE BEGIN EV */
/* USER CODE END EV */
/******************************************************************************/
/* Cortex-M0+ Processor Interruption and Exception Handlers */
/******************************************************************************/
/**
* @brief This function handles Non maskable interrupt.
*/
void NMI_Handler(void)
{
/* USER CODE BEGIN NonMaskableInt_IRQn 0 */
/* USER CODE END NonMaskableInt_IRQn 0 */
/* USER CODE BEGIN NonMaskableInt_IRQn 1 */
while (1)
{
}
/* USER CODE END NonMaskableInt_IRQn 1 */
}
/**
* @brief This function handles Hard fault interrupt.
*/
void HardFault_Handler(void)
{
/* USER CODE BEGIN HardFault_IRQn 0 */
/* USER CODE END HardFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_HardFault_IRQn 0 */
/* USER CODE END W1_HardFault_IRQn 0 */
}
}
/**
* @brief This function handles System service call via SWI instruction.
*/
void SVC_Handler(void)
{
/* USER CODE BEGIN SVC_IRQn 0 */
/* USER CODE END SVC_IRQn 0 */
/* USER CODE BEGIN SVC_IRQn 1 */
/* USER CODE END SVC_IRQn 1 */
}
/**
* @brief This function handles Pendable request for system service.
*/
void PendSV_Handler(void)
{
/* USER CODE BEGIN PendSV_IRQn 0 */
/* USER CODE END PendSV_IRQn 0 */
/* USER CODE BEGIN PendSV_IRQn 1 */
/* USER CODE END PendSV_IRQn 1 */
}
/**
* @brief This function handles System tick timer.
*/
void SysTick_Handler(void)
{
/* USER CODE BEGIN SysTick_IRQn 0 */
/* USER CODE END SysTick_IRQn 0 */
HAL_IncTick();
/* USER CODE BEGIN SysTick_IRQn 1 */
/* USER CODE END SysTick_IRQn 1 */
}
/******************************************************************************/
/* STM32G0xx Peripheral Interrupt Handlers */
/* Add here the Interrupt Handlers for the used peripherals. */
/* For the available peripheral interrupt handler names, */
/* please refer to the startup file (startup_stm32g0xx.s). */
/******************************************************************************/
/**
* @brief This function handles EXTI line 4 to 15 interrupts.
*/
void EXTI4_15_IRQHandler(void)
{
/* USER CODE BEGIN EXTI4_15_IRQn 0 */
/* USER CODE END EXTI4_15_IRQn 0 */
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_8);
/* USER CODE BEGIN EXTI4_15_IRQn 1 */
/* USER CODE END EXTI4_15_IRQn 1 */
}
/**
* @brief This function handles DMA1 channel 1 interrupt.
*/
void DMA1_Channel1_IRQHandler(void)
{
/* USER CODE BEGIN DMA1_Channel1_IRQn 0 */
/* USER CODE END DMA1_Channel1_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_adc1);
/* USER CODE BEGIN DMA1_Channel1_IRQn 1 */
/* USER CODE END DMA1_Channel1_IRQn 1 */
}
/**
* @brief This function handles DMA1 channel 2 and channel 3 interrupts.
*/
void DMA1_Channel2_3_IRQHandler(void)
{
/* USER CODE BEGIN DMA1_Channel2_3_IRQn 0 */
/* USER CODE END DMA1_Channel2_3_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_usart1_rx);
HAL_DMA_IRQHandler(&hdma_usart1_tx);
/* USER CODE BEGIN DMA1_Channel2_3_IRQn 1 */
/* USER CODE END DMA1_Channel2_3_IRQn 1 */
}
/**
* @brief This function handles ADC1 interrupt.
*/
void ADC1_IRQHandler(void)
{
/* USER CODE BEGIN ADC1_IRQn 0 */
/* USER CODE END ADC1_IRQn 0 */
HAL_ADC_IRQHandler(&hadc1);
/* USER CODE BEGIN ADC1_IRQn 1 */
/* USER CODE END ADC1_IRQn 1 */
}
/**
* @brief This function handles USART1 global interrupt / USART1 wake-up interrupt through EXTI line 25.
*/
extern char Buf[128];
uint8_t len=0;
int flag1=0;
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE)) // 1. 获得串口空闲中断标志
{
__HAL_UART_CLEAR_FLAG(&huart1,UART_CLEAR_IDLEF); // 2. 清除空闲中断标志
HAL_UART_DMAStop(&huart1); // 3. 清除->空闲->停止DMA
len = 128 - hdma_usart1_rx.Instance->CNDTR; // 4. 设定的传输长度-剩余传输数量(DMA_CNDTRx)=实际长度
HAL_UART_Transmit(&huart1,Buf,len,100); // 5. 数据处理——发送
HAL_UART_Receive_DMA(&huart1 ,Buf,128); // 6. 重新开启DMA
flag1=1;
}
/* USER CODE END USART1_IRQn 1 */
}
/**
* @brief This function handles USART2 global interrupt / USART2 wake-up interrupt through EXTI line 26.
*/
void USART2_IRQHandler(void)
{
/* USER CODE BEGIN USART2_IRQn 0 */
/* USER CODE END USART2_IRQn 0 */
HAL_UART_IRQHandler(&huart2);
/* USER CODE BEGIN USART2_IRQn 1 */
/* USER CODE END USART2_IRQn 1 */
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
lcd.c
#include "gpio.h"
#include "stdint.h"
#include "lcd.h"
#include "lcd_font.h"
#include <string.h>
//static uint8_t lcd_send_data = 0;
//extern void HalLcd_HW_WaitUs(uint16 i);
/*
* Initialize LCD Service
*/
void HalLcdInit(void);
//LCD Init For 1.44Inch LCD Panel with ST7735R.
void Lcd_Init(void)
{
HAL_Delay(10);
//开LCD背光
HAL_GPIO_WritePin(LCD_GPIO_Port, LCD_Pin, GPIO_PIN_SET);
Lcd_WriteIndex(0x11);
HAL_Delay(3);//Sleep exit HAL_Delay(10);
Lcd_WriteIndex(0x11);
// HAL_Delay(1000);
// HAL_Delay(1000);
// HAL_Delay(1000);
HAL_Delay(5);
Lcd_WriteIndex(0x36);
HAL_Delay(5);
Lcd_WriteIndex(0x36);//MX, MY, RGB mode
HAL_Delay(5);
Lcd_WriteData(0xC8);
HAL_Delay(5);
Lcd_WriteData(0xC8);
HAL_Delay(5);
Lcd_WriteIndex(0x3A);
HAL_Delay(5);
Lcd_WriteIndex(0x3A);//65k mode
HAL_Delay(5);
Lcd_WriteData(0x05);
HAL_Delay(5);
Lcd_WriteData(0x05);
HAL_Delay(20);
Lcd_WriteIndex(0x29);
HAL_Delay(5);
Lcd_WriteIndex(0x29);//Display on//有问题
}
//
///*
// * Write a string to the LCD
// */
//
//void HalLcdWriteString ( char *str, uint8 option);
//
///*
// * Write a value to the LCD
// */
//extern void HalLcdWriteValue ( uint32 value, const uint8 radix, uint8 option);
//
///*
// * Write a value to the LCD
// */
//extern void HalLcdWriteScreen( char *line1, char *line2 );
//
///*
// * Write a string followed by a value to the LCD
// */
//extern void HalLcdWriteStringValue( char *title, uint16 value, uint8 format, uint8 line );
//
///*
// * Write a string followed by 2 values to the LCD
// */
//extern void HalLcdWriteStringValueValue( char *title, uint16 value1, uint8 format1, uint16 value2, uint8 format2, uint8 line );
//
///*
// * Write a percentage bar to the LCD
// */
//extern void HalLcdDisplayPercentBar( char *title, uint8 value );
//
//extern void Gui_DrawFont_GBK16(uint16 x, uint16 y, uint16 fc, uint16 bc, uint8 *s);
//void Line_Dsp_single_colour(unsigned int x_start,unsigned int y_start,unsigned int x_end,unsigned int y_end,unsigned int color);
//void dsp_single_colour(int color);
void Delay_ms(int time)
{
int i,j;
for(i=0; i<time*10; i++)
{
for(j=0; j<100; j++)
{
}
}
}
void SPI_WriteData(uint8_t Data)
{
unsigned char i;
for(i=8; i>0; i--)
{
if(Data & 0x80)
{
LCD_SDA_SET; //数据输出高电平
}
else
{
LCD_SDA_CLR; //数据输出低电平
}
LCD_SCL_SET; //时钟高
LCD_SCL_CLR; //时钟低
Data <<= 1;
}
}
void LCD_WriteData_16Bit(uint16_t Data)
{
LCD_CS_CLR;
LCD_RS_SET;
SPI_WriteData(Data>>8); //写入高8位数据
SPI_WriteData(Data); //写入低8位数据
LCD_CS_SET;
}
//向液晶屏写一个8位指令
void Lcd_WriteIndex(uint8_t Index)
{
//SPI 写命令时序开始
LCD_CS_CLR;
LCD_RS_CLR; //LCD_RS_CLR
SPI_WriteData(Index);
LCD_CS_SET;
}
//向液晶屏写一个8位数据
void Lcd_WriteData(uint8_t Data)
{
LCD_CS_CLR;
LCD_RS_SET;
SPI_WriteData(Data);
LCD_CS_SET;
}
void Lcd_WriteReg(uint8_t Index,uint8_t Data)
{
LCD_CS_CLR;
Lcd_WriteIndex(Index);
Lcd_WriteData(Data);
LCD_CS_SET;
}
LCD Init For 1.44Inch LCD Panel with ST7735R.
//void Lcd_Init(void)
//{
// Lcd_WriteIndex(0x11);//Sleep exit
// HAL_Delay(120);
//
// Lcd_WriteIndex(0x36); //MX, MY, RGB mode
// Lcd_WriteData(0xC8);
//
// Lcd_WriteIndex(0x3A); //65k mode
// Lcd_WriteData(0x05);
//
// Lcd_WriteIndex(0x29);//Display on
//}
/*************************************************
函数名:LCD_Set_Region
功能:设置lcd显示区域,在此区域写点数据自动换行
入口参数:xy起点和终点
返回值:无
*************************************************/
void Lcd_SetRegion(uint16_t x_start,uint16_t y_start,uint16_t x_end,uint16_t y_end)
{
Lcd_WriteIndex(0x2a);
Lcd_WriteData(0x00);
Lcd_WriteData(x_start+2);
Lcd_WriteData(0x00);
Lcd_WriteData(x_end+2);
Lcd_WriteIndex(0x2b);
Lcd_WriteData(0x00);
Lcd_WriteData(y_start+3);
Lcd_WriteData(0x00);
Lcd_WriteData(y_end+3);
Lcd_WriteIndex(0x2c);
}
/*************************************************
函数名:LCD_Set_XY
功能:设置lcd显示起始点
入口参数:xy坐标
返回值:无
*************************************************/
void Lcd_SetXY(uint16_t x,uint16_t y)
{
Lcd_SetRegion(x,y,x,y);
}
/*************************************************
函数名:LCD_DrawPoint
功能:画一个点
入口参数:无
返回值:无
*************************************************/
void Gui_DrawPoint(uint16_t x,uint16_t y,uint16_t Data)
{
Lcd_SetRegion(x,y,x+1,y+1);
LCD_WriteData_16Bit(Data);
}
/*****************************************
函数功能:读TFT某一点的颜色
出口参数:color 点颜色值
******************************************/
//unsigned int Lcd_ReadPoint(uint16_t x,uint16_t y)
//{
// unsigned int Data;
// Lcd_SetXY(x,y);
//
// //Lcd_ReadData();//丢掉无用字节
// //Data=Lcd_ReadData();
// Lcd_WriteData(Data);
// return Data;
//}
/*************************************************
函数名:Lcd_Clear
功能:全屏清屏函数
入口参数:填充颜色COLOR
返回值:无
*************************************************/
void Lcd_Clear(uint16_t Color)
{
unsigned int i,m;
Lcd_SetRegion(0,0,X_MAX_PIXEL-1,Y_MAX_PIXEL-1);
Lcd_WriteIndex(0x2C);
for(i=0; i<X_MAX_PIXEL; i++)
for(m=0; m<Y_MAX_PIXEL; m++)
{
LCD_WriteData_16Bit(Color);
}
}
//取模方式 水平扫描 从左到右 低位在前
void showimage_farsight(const unsigned char *p) //显示128*35 QQ图片
{
int i;
unsigned char picH,picL;
//Lcd_Clear(WHITE); //清屏
Lcd_SetRegion(0,0,127,34); //坐标设置
for(i=0; i<128*35; i++)
{
picL=*(p+i*2); //数据低位在前
picH=*(p+i*2+1);
LCD_WriteData_16Bit(picH<<8|picL);
}
}
void showimage(const unsigned char *p) //显示128*35 QQ图片
{
int i;
unsigned char picH,picL;
//Lcd_Clear(WHITE); //清屏
Lcd_SetRegion(0,0,127,127); //坐标设置
for(i=0; i<128*128; i++)
{
picL=*(p+i*2); //数据低位在前
picH=*(p+i*2+1);
LCD_WriteData_16Bit(picH<<8|picL);
}
}
//void Gui_DrawFont_GBK16(uint16_t x, uint16_t y, uint16_t fc, uint16_t bc, uint8_t *s)
//{
// unsigned char i,j;
// unsigned short k,x0;
// x0=x;
//
// while(*s)
// {
// if((*s) < 128)
// {
// k=*s;
// if (k == 13)
// {
// x=x0;
// y+=16;
// }
// else
// {
// if (k>32) k-=32; else k=0;
//
// for(i=0;i<16;i++)
// for(j=0;j<8;j++)
// {
// if(asc16[k*16+i]&(0x80>>j)) Gui_DrawPoint(x+j,y+i,fc);
// else
// {
// if (fc!=bc) Gui_DrawPoint(x+j,y+i,bc);
// }
// }
// x+=8;
// }
// s++;
// }
//
// else
// {
//
//
// for (k=0;k<hz16_num;k++)
// {
// if ((hz16[k].Index[0]==*(s))&&(hz16[k].Index[1]==*(s+1)))
// {
// for(i=0;i<16;i++)
// {
// for(j=0;j<8;j++)
// {
// if(hz16[k].Msk[i*2]&(0x80>>j)) Gui_DrawPoint(x+j,y+i,fc);
// else {
// if (fc!=bc) Gui_DrawPoint(x+j,y+i,bc);
// }
// }
// for(j=0;j<8;j++)
// {
// if(hz16[k].Msk[i*2+1]&(0x80>>j)) Gui_DrawPoint(x+j+8,y+i,fc);
// else
// {
// if (fc!=bc) Gui_DrawPoint(x+j+8,y+i,bc);
// }
// }
// }
// }
// }
// s+=2;x+=16;
// }
//
// }
//}
void Gui_DrawFont_GBK16(uint16_t x0, uint16_t y0, uint16_t fc, uint16_t bc, uint8_t *s)
{
int i,j,k,x,y,xx;
unsigned char qm;
long int ulOffset;
char ywbuf[32];
// char temp[2];
for(i = 0; i<strlen((char*)s); i++)
{
if(((unsigned char)(*(s+i))) >= 161)
{
// temp[0] = *(s+i);
// temp[1] = '\0';
return;
}
else
{
qm = *(s+i);
ulOffset = (long int)(qm) * 16;
for (j = 0; j < 16; j ++)
{
ywbuf[j]=Zk_ASCII8X16[ulOffset+j];
}
for(y = 0; y < 16; y++)
{
for(x=0; x<8; x++)
{
k=x % 8;
if(ywbuf[y]&(0x80 >> k))
{
xx=x0+x+i*8;
Gui_DrawPoint(xx,y+y0,fc);
}
else
{
xx=x0+x+i*8;
Gui_DrawPoint(xx,y+y0,bc);
}
}
}
}
}
}
void Gui_DrawFont_1616(uint16_t x0, uint16_t y0, uint16_t fc, uint16_t bc,const char tfont16[][32],int num)
{
uint16_t i,j;
uint8_t Hznum;
for(Hznum = 0;Hznum < num;Hznum++)
{
// 设置汉子显示的区域
Lcd_SetRegion(x0+Hznum*16,y0,x0+16-1+Hznum*16,y0+16-1);
for(i = 0;i < 32;i++) //一个汉字的字模由32个元素组成
{
for(j = 0;j < 8;j++) //每个元素有8位,每一位代表一个亮点
{
if(tfont16[Hznum][i] & (0x80 >> j))
{
LCD_WriteData_16Bit(fc);
}
else
{
LCD_WriteData_16Bit(bc);
}
}
}
}
}
lcd.h
#ifndef __LCD_H
#define __LCD_H
#include "stdint.h"
#include "main.h"
#define RED 0xf800
#define GREEN 0x07e0
#define BLUE 0x001f
#define WHITE 0xffff
#define BLACK 0x0000
#define YELLOW 0xFFE0
#define CYAN 0x07ff
#define BRIGHT_RED 0xf810
#define GRAY0 0xEF7D //灰色0 3165 00110 001011 00101
#define GRAY1 0x8410 //灰色1 00000 000000 00000
#define GRAY2 0x4208 //灰色2 1111111111011111
#define X_MAX_PIXEL 128
#define Y_MAX_PIXEL 128
//LCD的SPI引脚的定义
#define LCD_CTRL_PORT GPIOB //定义TFT数据端口
#define LCD_LED LCD_Pin //LCD背光--->>TFT --BL
#define LCD_RS MISO_Pin //MISO--->>TFT --RS/DC
#define LCD_SDA MOSI_Pin //MOSI--->>TFT --SDA/DIN
#define LCD_SCL SCLK_Pin //SCK--->>TFT --SCL/SCK
#define LCD_CS_PORT CSS_GPIO_Port
#define LCD_CS CSS_Pin //MCU_PB11--->>TFT --CS/CE
//液晶控制口置1操作语句宏定义
#define LCD_CS_SET LCD_CS_PORT->BSRR=LCD_CS
#define LCD_RS_SET LCD_CTRL_PORT->BSRR=LCD_RS
#define LCD_SDA_SET LCD_CTRL_PORT->BSRR=LCD_SDA
#define LCD_SCL_SET LCD_CTRL_PORT->BSRR=LCD_SCL
#define LCD_LED_SET LCD_CTRL_PORT->BSRR=LCD_LED
//液晶控制口置0操作语句宏定义
#define LCD_CS_CLR LCD_CS_PORT->BRR=LCD_CS
#define LCD_RS_CLR LCD_CTRL_PORT->BRR=LCD_RS
#define LCD_SDA_CLR LCD_CTRL_PORT->BRR=LCD_SDA
#define LCD_SCL_CLR LCD_CTRL_PORT->BRR=LCD_SCL
#define LCD_LED_CLR LCD_CTRL_PORT->BRR=LCD_LED
void LCD_GPIO_Init(void);
void Lcd_WriteIndex(uint8_t Index);
void Lcd_WriteData(uint8_t Data);
void Lcd_WriteReg(uint8_t Index,uint8_t Data);
uint16_t Lcd_ReadReg(uint8_t LCD_Reg);
void Lcd_Reset(void);
void Lcd_Init(void);
void Lcd_Clear(uint16_t Color);
void Lcd_SetXY(uint16_t x,uint16_t y);
void Gui_DrawPoint(uint16_t x,uint16_t y,uint16_t Data);
unsigned int Lcd_ReadPoint(uint16_t x,uint16_t y);
void Lcd_SetRegion(uint16_t x_start,uint16_t y_start,uint16_t x_end,uint16_t y_end);
void LCD_WriteData_16Bit(uint16_t Data);
void showimage(const unsigned char *p);
void Lcd_ReadID(void);
void showimage_farsight(const unsigned char *p);
void Gui_DrawFont_GBK16(uint16_t x, uint16_t y, uint16_t fc, uint16_t bc, uint8_t *s);
void Gui_DrawFont_1616(uint16_t x0, uint16_t y0, uint16_t fc, uint16_t bc,const char tfont16[][32],int num);
#endif
dht11.c
#include "dht11.h"
#define DHT11_GPIO_PORT GPIOB
#define DHT11_GPIO_PIN GPIO_PIN_8
#define DHT11_DQ_IN HAL_GPIO_ReadPin(DHT11_GPIO_PORT, DHT11_GPIO_PIN)
static void DHT11_IO_IN(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = DHT11_GPIO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStruct);
}
static void DHT11_IO_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = DHT11_GPIO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStruct);
}
//复位DHT11 \\起始
void DHT11_Rst(void)
{
DHT11_IO_OUT(); //SET OUTPUT 转换成输出模式
HAL_GPIO_WritePin(DHT11_GPIO_PORT, DHT11_GPIO_PIN, GPIO_PIN_RESET); //拉低DQ
HAL_Delay(20); //拉低至少18ms
HAL_GPIO_WritePin(DHT11_GPIO_PORT, DHT11_GPIO_PIN, GPIO_PIN_SET); //DQ=1
delay_us(30); //主机拉高20~40us
}
//等待DHT11的回应
//返回1:未检测到DHT11的存在
//返回0:存在
uint8_t DHT11_Check(void)
{
uint8_t retry=0;
DHT11_IO_IN();//SET INPUT 转换成输入模式
while (!DHT11_DQ_IN&&retry<100)//DHT11会拉低40~80us
{
retry++;
delay_us(1);
}
if(retry>=100)
return 1;
else
retry=0;
while (DHT11_DQ_IN&&retry<100)//DHT11拉低后会再次拉高40~80us
{
retry++;
delay_us(1);
}
if(retry>=100)
return 1;
return 0;
}
//从DHT11读取一个位
//返回值:1/0
uint8_t DHT11_Read_Bit(void)
{
uint8_t retry=0;
while(DHT11_DQ_IN&&retry<100)//等待变为低电平
{
retry++;
delay_us(1);
}//延时100
retry=0;
while(!DHT11_DQ_IN&&retry<100)//等待变高电平
{
retry++;
delay_us(1);
}
delay_us(40);//等待40us
if(DHT11_DQ_IN)return 1;
else return 0;
}
//从DHT11读取一个字节
//返回值:读到的数据
uint8_t DHT11_Read_Byte(void)
{
uint8_t i,dat;
dat=0;
for (i=0; i<8; i++)
{
dat<<=1;
dat|=DHT11_Read_Bit();
}
return dat;
}
//从DHT11读取一次数据
//temp:温度值(范围:0~50°)
//humi:湿度值(范围:20%~90%)
//返回值:HAL_OK,正常;1,读取失败
uint8_t DHT11_Read_Data(uint8_t *humiH,uint8_t *humiL,uint8_t *tempH,uint8_t *tempL)
{
uint8_t buf[5];
uint8_t i;
DHT11_Rst();
if(DHT11_Check()==0)
{
for(i=0; i<5; i++) //读取40位数据
{
buf[i]=DHT11_Read_Byte();
}
if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
{
*humiH=buf[0];
*humiL=buf[1];
*tempH=buf[2];
*tempL=buf[3];
}
} else
return HAL_ERROR;
return HAL_OK;
}
//初始化DHT11的IO口 DQ 同时检测DHT11的存在
//返回1:不存在
//返回0:存在
uint8_t FS_DHT11_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = DHT11_GPIO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStruct);
HAL_GPIO_WritePin(DHT11_GPIO_PORT, DHT11_GPIO_PIN, GPIO_PIN_SET); // 输出高
DHT11_Rst(); //复位DHT11
return DHT11_Check();//等待DHT11的回应
}
dht11.h
#ifndef __DHT11_H__
#define __DHT11_H__
#include "main.h"
uint8_t DHT11_Read_Data(uint8_t *humiH,uint8_t *humiL,uint8_t *tempH,uint8_t *tempL);
uint8_t FS_DHT11_Init(void);
#endif