03_01.cs

  1. using System;
  2. namespace _03_01{
  3. class Car{
  4. public string color;
  5. private float weight;
  6. private DateTime releasedate;
  7. }
  8. class Class_03_01{
  9. public static void main(String[] args){
  10. Car car1=new Car();
  11. car1.color="red";
  12. car1.weight=1.1;//出错!因为weight是private成员
  13. }
  14. }
  15. }
本课题设计了一种利用Matlab平台开发的植物叶片健康状态识别方案,重点融合了色彩与纹理双重特征以实现对叶片病害的自动化判别。该系统构建了直观的图形操作界面,便于用户提交叶片影像并快速获得分析结论。Matlab作为具备高效数值计算与数据处理能力的工具,在图像分析与模式分类领域应用广泛,本项目正是借助其功能解决农业病害监测的实际问题。 在色彩特征分析方面,叶片影像的颜色分布常与其生理状态密切相关。通常,健康的叶片呈现绿色,而出现黄化、褐变等异常色彩往往指示病害或虫害的发生。Matlab提供了一系列图像处理函数,例如可通过色彩空间转换与直方图统计来量化颜色属性。通过计算各颜色通道的统计参数(如均值、标准差及主成分等),能够提取具有判别力的色彩特征,从而为不同病害类别的区分提供依据。 纹理特征则用于描述叶片表面的微观结构与形态变化,如病斑、皱缩或裂纹等。Matlab中的灰度共生矩阵计算函数可用于提取对比度、均匀性、相关性等纹理指标。此外,局部二值模式与Gabor滤波等方法也能从多尺度刻画纹理细节,进一步增强病害识别的鲁棒性。 系统的人机交互界面基于Matlab的图形用户界面开发环境实现。用户可通过该界面上传待检图像,系统将自动执行图像预处理、特征抽取与分类判断。采用的分类模型包括支持向量机、决策树等机器学习方法,通过对已标注样本的训练,模型能够依据新图像的特征向量预测其所属的病害类别。 此类课题设计有助于深化对Matlab编程、图像处理技术与模式识别原理的理解。通过完整实现从特征提取到分类决策的流程,学生能够将理论知识与实际应用相结合,提升解决复杂工程问题的能力。总体而言,该叶片病害检测系统涵盖了图像分析、特征融合、分类算法及界面开发等多个技术环节,为学习与掌握基于Matlab的智能检测技术提供了综合性实践案例。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
<think>我们已有一个主程序框架,现在需要完善各个模块。由于问题中要求使用DHT11和TFT显示屏,并且使用STM32F103RC,我们将分别实现这些模块。注意:由于代码量较大,我们只给出关键部分的实现,并假设您已经配置好了STM32CubeMX生成的基本外设初始化代码(如GPIO、SPI、定时器等)。步骤:1.首先,完成DHT11的驱动代码(dht11.c和dht11.h)。2.完成TFT显示屏的驱动代码(tft_gfx.c,tft_gfx.h,tft_fonts.c,tft_fonts.h)。3.在主程序(main.c)中整合这些模块,并实现功能。由于TFT显示屏的驱动通常依赖于具体的屏幕型号(例如ILI9341),我们以ILI9341为例。下面分别给出各个文件的关键代码:一、dht11.h```c#ifndef__DHT11_H#define__DHT11_H#include"stm32f1xx_hal.h"typedefenum{DHT11_OK,DHT11_ERROR,DHT11_TIMEOUT}DHT11_Status;voidDHT11_Init(void);DHT11_StatusDHT11_Read(uint8_t*temperature,uint8_t*humidity);#endif```二、dht11.c注意:DHT11需要精确的时序,这里我们使用定时器来产生微秒延时。假设我们使用TIM2,并且已经配置为1us计数。```c#include"dht11.h"//定义DHT11的数据引脚#defineDHT11_PORTGPIOA#defineDHT11_PINGPIO_PIN_4//使用TIM2进行微秒延时externTIM_HandleTypeDefhtim2;voidDHT11_Init(void){//设置引脚为输出模式,并初始化为高电平GPIO_InitTypeDefGPIO_InitStruct={0};GPIO_InitStruct.Pin=DHT11_PIN;GPIO_InitStruct.Mode=GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Speed=GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(DHT11_PORT,&GPIO_InitStruct);HAL_GPIO_WritePin(DHT11_PORT,DHT11_PIN,GPIO_PIN_SET);}//微秒延时函数voiddelay_us(uint16_tus){__HAL_TIM_SET_COUNTER(&htim2,0);HAL_TIM_Base_Start(&htim2);while(__HAL_TIM_GET_COUNTER(&htim2)<us);HAL_TIM_Base_Stop(&htim2);}DHT11_StatusDHT11_Read(uint8_t*temperature,uint8_t*humidity){uint8_tdata[5]={0};uint8_ti,j;//主机发送开始信号HAL_GPIO_WritePin(DHT11_PORT,DHT11_PIN,GPIO_PIN_RESET);delay_us(18000);//至少18msHAL_GPIO_WritePin(DHT11_PORT,DHT11_PIN,GPIO_PIN_SET);delay_us(40);//等待20-40us//设置引脚为输入模式GPIO_InitTypeDefGPIO_InitStruct={0};GPIO_InitStruct.Pin=DHT11_PIN;GPIO_InitStruct.Mode=GPIO_MODE_INPUT;GPIO_InitStruct.Pull=GPIO_PULLUP;HAL_GPIO_Init(DHT11_PORT,&GPIO_InitStruct);//等待DHT11响应delay_us(40);if(HAL_GPIO_ReadPin(DHT11_PORT,DHT11_PIN)!=GPIO_PIN_RESET){returnDHT11_TIMEOUT;}delay_us(80);if(HAL_GPIO_ReadPin(DHT11_PORT,DHT11_PIN)!=GPIO_PIN_SET){returnDHT11_TIMEOUT;}//开始接收数据for(i=0;i<5;i++){for(j=0;j<8;j++){//等待低电平结束(每个数据位前有一个50us的低电平)while(HAL_GPIO_ReadPin(DHT11_PORT,DHT11_PIN)==GPIO_PIN_RESET);//高电平持续时间决定数据位是0还是1delay_us(40);if(HAL_GPIO_ReadPin(DHT11_PORT,DHT11_PIN)==GPIO_PIN_SET){data[i]|=(1<<(7-j));//等待高电平结束while(HAL_GPIO_ReadPin(DHT11_PORT,DHT11_PIN)==GPIO_PIN_SET);}}}//检查校验和if(data[4]==(data[0]+data[1]+data[2]+data[3])){*humidity=data[0];*temperature=data[2];returnDHT11_OK;}returnDHT11_ERROR;}```三、tft_fonts.h这里我们定义一种简单的字体(例如8x16)的字符点阵数据。由于点阵数据较长,这里只给出部分示例。```c#ifndef__TFT_FONTS_H#define__TFT_FONTS_H#include<stdint.h>typedefstruct{constuint8_twidth;constuint8_theight;constuint16_t*data;}FontDef;externFontDefFont_8x16;#endif```四、tft_fonts.c```c#include"tft_fonts.h"//这里只给出部分字符(例如数字和字母)的点阵数据constuint16_tFont8x16_Data[]={//每个字符16行,每行8位(实际按16位存储,高8位不用)//字符'0'0x00,0x00,0x3E,0x7F,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x7F,0x3E,0x00,0x00,//...其他字符};FontDefFont_8x16={.width=8,.height=16,.data=Font8x16_Data};```五、tft_gfx.h```c#ifndef__TFT_GFX_H#define__TFT_GFX_H#include"stm32f1xx_hal.h"#include"tft_fonts.h"//TFT屏幕尺寸#defineTFT_WIDTH240#defineTFT_HEIGHT320//常用颜色定义(RGB565)#defineBLACK0x0000#defineBLUE0x001F#defineRED0xF800#defineGREEN0x07E0#defineCYAN0x07FF#defineMAGENTA0xF81F#defineYELLOW0xFFE0#defineWHITE0xFFFFvoidTFT_Init(void);voidTFT_SetRotation(uint8_trotation);voidTFT_FillScreen(uint16_tcolor);voidTFT_DrawPixel(uint16_tx,uint16_ty,uint16_tcolor);voidTFT_DrawLine(uint16_tx0,uint16_ty0,uint16_tx1,uint16_ty1,uint16_tcolor);voidTFT_DrawRect(uint16_tx,uint16_ty,uint16_tw,uint16_th,uint16_tcolor);voidTFT_FillRect(uint16_tx,uint16_ty,uint16_tw,uint16_th,uint16_tcolor);voidTFT_DrawCircle(uint16_tx0,uint16_ty0,uint16_tr,uint16_tcolor);voidTFT_FillCircle(uint16_tx0,uint16_ty0,uint16_tr,uint16_tcolor);voidTFT_SetTextColor(uint16_tcolor,uint16_tbgcolor);voidTFT_SetTextSize(uint8_tsize);voidTFT_SetCursor(uint16_tx,uint16_ty);voidTFT_PrintChar(charc);voidTFT_Print(char*str);#endif```六、tft_gfx.c这里我们只实现部分关键函数,具体实现依赖于SPI发送数据。假设我们使用SPI1,并且已经配置好,同时有CS(片选)、DC(数据/命令)、RST(复位)引脚。```c#include"tft_gfx.h"#include"spi.h"#include<string.h>//定义TFT的控制引脚#defineTFT_CS_PORTGPIOA#defineTFT_CS_PINGPIO_PIN_15#defineTFT_DC_PORTGPIOB#defineTFT_DC_PINGPIO_PIN_5#defineTFT_RST_PORTGPIOB#defineTFT_RST_PINGPIO_PIN_6//全局变量staticuint16_ttextColor=WHITE;staticuint16_ttextBgColor=BLACK;staticuint8_ttextSize=1;staticuint16_tcursorX=0;staticuint16_tcursorY=0;//发送命令staticvoidTFT_SendCommand(uint8_tcmd){HAL_GPIO_WritePin(TFT_DC_PORT,TFT_DC_PIN,GPIO_PIN_RESET);//命令模式HAL_GPIO_WritePin(TFT_CS_PORT,TFT_CS_PIN,GPIO_PIN_RESET);//片选HAL_SPI_Transmit(&hspi1,&cmd,1,HAL_MAX_DELAY);HAL_GPIO_WritePin(TFT_CS_PORT,TFT_CS_PIN,GPIO_PIN_SET);//取消片选}//发送数据staticvoidTFT_SendData(uint8_tdata){HAL_GPIO_WritePin(TFT_DC_PORT,TFT_DC_PIN,GPIO_PIN_SET);//数据模式HAL_GPIO_WritePin(TFT_CS_PORT,TFT_CS_PIN,GPIO_PIN_RESET);HAL_SPI_Transmit(&hspi1,&data,1,HAL_MAX_DELAY);HAL_GPIO_WritePin(TFT_CS_PORT,TFT_CS_PIN,GPIO_PIN_SET);}//发送16位数据(用于颜色)staticvoidTFT_SendData16(uint16_tdata){uint8_tbuf[2]={data>>8,data&0xFF};HAL_GPIO_WritePin(TFT_DC_PORT,TFT_DC_PIN,GPIO_PIN_SET);HAL_GPIO_WritePin(TFT_CS_PORT,TFT_CS_PIN,GPIO_PIN_RESET);HAL_SPI_Transmit(&hspi1,buf,2,HAL_MAX_DELAY);HAL_GPIO_WritePin(TFT_CS_PORT,TFT_CS_PIN,GPIO_PIN_SET);}//初始化TFTvoidTFT_Init(void){//复位HAL_GPIO_WritePin(TFT_RST_PORT,TFT_RST_PIN,GPIO_PIN_RESET);HAL_Delay(100);HAL_GPIO_WritePin(TFT_RST_PORT,TFT_RST_PIN,GPIO_PIN_SET);HAL_Delay(100);//初始化命令序列(以ILI9341为例)TFT_SendCommand(0x01);//软件复位HAL_Delay(120);TFT_SendCommand(0xCF);//电源控制BTFT_SendData(0x00);TFT_SendData(0xC1);TFT_SendData(0x30);//...其他初始化命令TFT_SendCommand(0x3A);//颜色格式TFT_SendData(0x55);//16位TFT_SendCommand(0x29);//开启显示HAL_Delay(100);//设置方向(旋转)TFT_SetRotation(0);}//设置旋转方向voidTFT_SetRotation(uint8_trotation){TFT_SendCommand(0x36);switch(rotation){case0://竖屏TFT_SendData(0x48);break;case1://横屏TFT_SendData(0x28);break;//...其他方向}}//填充屏幕voidTFT_FillScreen(uint16_tcolor){TFT_FillRect(0,0,TFT_WIDTH,TFT_HEIGHT,color);}//画点voidTFT_DrawPixel(uint16_tx,uint16_ty,uint16_tcolor){if(x>=TFT_WIDTH||y>=TFT_HEIGHT)return;TFT_SendCommand(0x2A);//列地址设置TFT_SendData16(x);TFT_SendData16(x);TFT_SendCommand(0x2B);//行地址设置TFT_SendData16(y);TFT_SendData16(y);TFT_SendCommand(0x2C);//写入RAMTFT_SendData16(color);}//填充矩形voidTFT_FillRect(uint16_tx,uint16_ty,uint16_tw,uint16_th,uint16_tcolor){if(x>=TFT_WIDTH||y>=TFT_HEIGHT)return;if(x+w>TFT_WIDTH)w=TFT_WIDTH-x;if(y+h>TFT_HEIGHT)h=TFT_HEIGHT-y;TFT_SendCommand(0x2A);TFT_SendData16(x);TFT_SendData16(x+w-1);TFT_SendCommand(0x2B);TFT_SendData16(y);TFT_SendData16(y+h-1);TFT_SendCommand(0x2C);for(uint32_ti=0;i<(uint32_t)w*h;i++){TFT_SendData16(color);}}//设置文本颜色voidTFT_SetTextColor(uint16_tcolor,uint16_tbgcolor){textColor=color;textBgColor=bgcolor;}//设置文本大小voidTFT_SetTextSize(uint8_tsize){textSize=size;}//设置光标位置voidTFT_SetCursor(uint16_tx,uint16_ty){cursorX=x;cursorY=y;}//打印一个字符voidTFT_PrintChar(charc){//这里使用8x16字体if(c=='\n'){cursorY+=Font_8x16.height*textSize;cursorX=0;return;}//计算字符在点阵数据中的位置uint8_tindex=c-'';constuint16_t*charData=&Font_8x16.data[index*Font_8x16.height];for(uint8_ti=0;i<Font_8x16.height;i++){uint8_tline=charData[i];for(uint8_tj=0;j<Font_8x16.width;j++){if(line&(1<<(7-j))){TFT_FillRect(cursorX+j*textSize,cursorY+i*textSize,textSize,textSize,textColor);}elseif(textBgColor!=textColor){TFT_FillRect(cursorX+j*textSize,cursorY+i*textSize,textSize,textSize,textBgColor);}}}cursorX+=Font_8x16.width*textSize;}//打印字符串voidTFT_Print(char*str){while(*str){TFT_PrintChar(*str++);}}```七、main.c这里使用之前已经给出的主程序框架,但需要根据实际硬件调整引脚定义。注意:主程序中需要初始化外设(在`MX_GPIO_Init`,`MX_SPI1_Init`,`MX_TIM2_Init`中配置),并调用各模块的初始化函数。由于代码较长,这里不再重复。请参考之前的主程序框架,结合上述模块完成。八、注意事项1.DHT11的时序要求严格,如果读取失败,请检查延时精度和中断干扰。2.TFT驱动需要根据具体型号调整初始化命令。3.字体数据较大,可以根据需要裁剪。九、相关函数说明1.DHT11_Read:读取温湿度,返回状态,并将温湿度值通过指针参数返回。2.TFT_Init:初始化TFT屏幕。3.TFT_FillScreen:填充屏幕颜色。4.TFT_SetTextColor:设置文本颜色和背景色。5.TFT_SetTextSize:设置文本大小(倍数)。6.TFT_SetCursor:设置文本光标位置。7.TFT_Print:在屏幕上打印字符串。十、主循环流程1.每2秒读取一次DHT11。2.根据按键状态控制风扇。3.更新TFT显示。4.检查温湿度阈值,触发报警。由于完整代码量非常大,以上只提供了关键部分。请根据实际硬件连接修改引脚定义,并确保外设初始化正确。§§相关问题§§:1.如何优化DHT11的读取精度和稳定性?2.在TFT屏幕上显示中文字符有哪些方法?3.如何实现温湿度数据的存储和回放?4.怎样通过PWM控制风扇转速?</think>以下是基于STM32F103RC系列微控制器的完整解决方案,使用DHT11温湿度传感器和RGB TFT显示屏,在Keil环境中实现温湿度监测、风扇控制和报警功能。代码分为四个主要文件:`main.c`、`dht11.c/h`、`tft_gfx.c/h` 和 `tft_fonts.c/h`。 ### 完整代码实现 #### 1. `main.c` - 主程序 ```c #include "stm32f1xx_hal.h" #include "dht11.h" #include "tft_gfx.h" #include "tft_fonts.h" #include <stdio.h> /* 硬件配置 */ #define FAN_ENABLE_PIN GPIO_PIN_0 #define FAN_ENABLE_PORT GPIOA #define FAN_DIR1_PIN GPIO_PIN_8 #define FAN_DIR2_PIN GPIO_PIN_9 #define FAN_DIR_PORT GPIOC #define BUZZER_PIN GPIO_PIN_10 #define BUZZER_PORT GPIOC #define BUTTON_DIR1_PIN GPIO_PIN_8 #define BUTTON_DIR2_PIN GPIO_PIN_9 #define BUTTON_PORT GPIOC /* 阈值设置 */ #define TEMP_THRESHOLD 30 // 温度报警阈值(℃) #define HUMID_THRESHOLD 80 // 湿度报警阈值(%) /* 全局变量 */ uint8_t fanState = 0; // 0=关闭, 1=开启 uint8_t fanDirection = 0; // 0=正转, 1=反转 uint8_t tempValue = 0; uint8_t humidValue = 0; uint8_t alertActive = 0; char displayBuffer[40]; /* 函数原型 */ void SystemClock_Config(void); void Error_Handler(void); static void MX_GPIO_Init(void); static void MX_SPI1_Init(void); static void MX_TIM2_Init(void); void updateTFTDisplay(void); void checkThresholds(void); void drawFanIcon(uint16_t x, uint16_t y, uint16_t color); int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_SPI1_Init(); MX_TIM2_Init(); /* 外设初始化 */ DHT11_Init(GPIOA, GPIO_PIN_4); // DHT11 on PA4 TFT_Init(); // 初始化TFT TFT_FillScreen(BLACK); // 清屏 /* 初始显示 */ TFT_SetTextColor(WHITE, BLACK); TFT_SetTextSize(2); TFT_SetCursor(30, 10); TFT_Print("温湿度监控系统"); HAL_Delay(1000); /* 主循环 */ while (1) { /* 读取温湿度 */ if (DHT11_Read(&tempValue, &humidValue) == DHT11_OK) { updateTFTDisplay(); checkThresholds(); } else { TFT_SetTextColor(RED, BLACK); TFT_SetCursor(50, 200); TFT_Print("传感器错误!"); } HAL_Delay(2000); // 每2秒读取一次 /* 按键扫描 */ if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET) { HAL_Delay(50); // 消抖 if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET) { fanState = !fanState; updateTFTDisplay(); } while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET); } if (HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_DIR1_PIN) == GPIO_PIN_RESET) { HAL_Delay(50); if (HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_DIR1_PIN) == GPIO_PIN_RESET) { fanDirection = 0; updateTFTDisplay(); } while (HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_DIR1_PIN) == GPIO_PIN_RESET); } if (HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_DIR2_PIN) == GPIO_PIN_RESET) { HAL_Delay(50); if (HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_DIR2_PIN) == GPIO_PIN_RESET) { fanDirection = 1; updateTFTDisplay(); } while (HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_DIR2_PIN) == GPIO_PIN_RESET); } /* 控制风扇 */ if (fanState) { HAL_GPIO_WritePin(FAN_ENABLE_PORT, FAN_ENABLE_PIN, GPIO_PIN_SET); if (fanDirection == 0) { HAL_GPIO_WritePin(FAN_DIR_PORT, FAN_DIR1_PIN, GPIO_PIN_SET); HAL_GPIO_WritePin(FAN_DIR_PORT, FAN_DIR2_PIN, GPIO_PIN_RESET); } else { HAL_GPIO_WritePin(FAN_DIR_PORT, FAN_DIR1_PIN, GPIO_PIN_RESET); HAL_GPIO_WritePin(FAN_DIR_PORT, FAN_DIR2_PIN, GPIO_PIN_SET); } } else { HAL_GPIO_WritePin(FAN_ENABLE_PORT, FAN_ENABLE_PIN, GPIO_PIN_RESET); HAL_GPIO_WritePin(FAN_DIR_PORT, FAN_DIR1_PIN, GPIO_PIN_RESET); HAL_GPIO_WritePin(FAN_DIR_PORT, FAN_DIR2_PIN, GPIO_PIN_RESET); } /* 报警处理 */ if (alertActive) { HAL_GPIO_TogglePin(BUZZER_PORT, BUZZER_PIN); HAL_Delay(200); } else { HAL_GPIO_WritePin(BUZZER_PORT, BUZZER_PIN, GPIO_PIN_RESET); } } } /* 更新TFT显示 */ void updateTFTDisplay(void) { // 清空显示区域 TFT_FillRect(0, 50, 240, 190, BLACK); // 显示温度 TFT_SetTextColor(YELLOW, BLACK); TFT_SetTextSize(2); TFT_SetCursor(20, 60); TFT_Print("温度:"); sprintf(displayBuffer, "%2d C", tempValue); TFT_SetCursor(100, 60); TFT_Print(displayBuffer); // 显示湿度 TFT_SetTextColor(CYAN, BLACK); TFT_SetCursor(20, 90); TFT_Print("湿度:"); sprintf(displayBuffer, "%2d %%", humidValue); TFT_SetCursor(100, 90); TFT_Print(displayBuffer); // 显示风扇状态 TFT_SetTextColor(GREEN, BLACK); TFT_SetCursor(20, 120); TFT_Print("风扇:"); TFT_SetCursor(100, 120); TFT_Print(fanState ? "开启" : "关闭"); // 显示风扇方向 TFT_SetCursor(20, 150); TFT_Print("方向:"); TFT_SetCursor(100, 150); TFT_Print(fanDirection ? "反转" : "正转"); // 绘制风扇图标 drawFanIcon(180, 120, fanState ? GREEN : RED); // 报警状态显示 if (alertActive) { TFT_SetTextColor(RED, BLACK); TFT_SetCursor(20, 180); if (tempValue > TEMP_THRESHOLD && humidValue > HUMID_THRESHOLD) { TFT_Print("警告: 温湿度过高!"); } else if (tempValue > TEMP_THRESHOLD) { TFT_Print("警告: 温度过高!"); } else { TFT_Print("警告: 湿度过高!"); } } } /* 绘制风扇图标 */ void drawFanIcon(uint16_t x, uint16_t y, uint16_t color) { TFT_FillCircle(x, y, 15, color); TFT_DrawCircle(x, y, 15, WHITE); TFT_DrawLine(x, y, x+15, y, WHITE); TFT_DrawLine(x, y, x, y-15, WHITE); TFT_DrawLine(x, y, x-10, y+10, WHITE); TFT_DrawLine(x, y, x+10, y+10, WHITE); } /* 检查阈值 */ void checkThresholds(void) { alertActive = (tempValue > TEMP_THRESHOLD || humidValue > HUMID_THRESHOLD) ? 1 : 0; } /* GPIO初始化 */ static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); // 风扇控制 GPIO_InitStruct.Pin = FAN_ENABLE_PIN; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(FAN_ENABLE_PORT, &GPIO_InitStruct); GPIO_InitStruct.Pin = FAN_DIR1_PIN | FAN_DIR2_PIN; HAL_GPIO_Init(FAN_DIR_PORT, &GPIO_InitStruct); // 蜂鸣器 GPIO_InitStruct.Pin = BUZZER_PIN; HAL_GPIO_Init(BUZZER_PORT, &GPIO_InitStruct); // 按键 (PA0, PC8, PC9) GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = BUTTON_DIR1_PIN | BUTTON_DIR2_PIN; HAL_GPIO_Init(BUTTON_PORT, &GPIO_InitStruct); } // 其他初始化函数(SystemClock_Config, MX_SPI1_Init, MX_TIM2_Init)需根据具体硬件配置 ``` #### 2. `dht11.h` - DHT11头文件 ```c #ifndef __DHT11_H #define __DHT11_H #include "stm32f1xx_hal.h" typedef enum { DHT11_OK, DHT11_ERROR, DHT11_TIMEOUT } DHT11_Status; void DHT11_Init(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); DHT11_Status DHT11_Read(uint8_t *temperature, uint8_t *humidity); #endif ``` #### 3. `dht11.c` - DHT11驱动 ```c #include "dht11.h" #include "main.h" static GPIO_TypeDef* DHT11_GPIO; static uint16_t DHT11_PIN; static TIM_HandleTypeDef* DHT11_TIMER = &htim2; // 使用TIM2 void DHT11_Init(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) { DHT11_GPIO = GPIOx; DHT11_PIN = GPIO_Pin; // 初始化GPIO GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = DHT11_PIN; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(DHT11_GPIO, &GPIO_InitStruct); HAL_GPIO_WritePin(DHT11_GPIO, DHT11_PIN, GPIO_PIN_SET); } static void delay_us(uint16_t us) { __HAL_TIM_SET_COUNTER(DHT11_TIMER, 0); HAL_TIM_Base_Start(DHT11_TIMER); while (__HAL_TIM_GET_COUNTER(DHT11_TIMER) < us); HAL_TIM_Base_Stop(DHT11_TIMER); } DHT11_Status DHT11_Read(uint8_t *temperature, uint8_t *humidity) { uint8_t data[5] = {0}; uint8_t i, j; // 主机发送开始信号 HAL_GPIO_WritePin(DHT11_GPIO, DHT11_PIN, GPIO_PIN_RESET); delay_us(18000); // 18ms HAL_GPIO_WritePin(DHT11_GPIO, DHT11_PIN, GPIO_PIN_SET); delay_us(30); // 30us // 设置为输入模式 GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = DHT11_PIN; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(DHT11_GPIO, &GPIO_InitStruct); // 等待响应 delay_us(40); if (HAL_GPIO_ReadPin(DHT11_GPIO, DHT11_PIN) != GPIO_PIN_RESET) return DHT11_TIMEOUT; delay_us(80); if (HAL_GPIO_ReadPin(DHT11_GPIO, DHT11_PIN) != GPIO_PIN_SET) return DHT11_TIMEOUT; // 读取40位数据 for (i = 0; i < 5; i++) { for (j = 0; j < 8; j++) { while (HAL_GPIO_ReadPin(DHT11_GPIO, DHT11_PIN) == GPIO_PIN_RESET); delay_us(40); if (HAL_GPIO_ReadPin(DHT11_GPIO, DHT11_PIN) == GPIO_PIN_SET) { data[i] |= (1 << (7 - j)); while (HAL_GPIO_ReadPin(DHT11_GPIO, DHT11_PIN) == GPIO_PIN_SET); } } } // 校验和检查 if (data[4] == (data[0] + data[1] + data[2] + data[3])) { *humidity = data[0]; *temperature = data[2]; return DHT11_OK; } return DHT11_ERROR; } ``` #### 4. `tft_gfx.h` - TFT图形库头文件 ```c #ifndef __TFT_GFX_H #define __TFT_GFX_H #include "stm32f1xx_hal.h" #include "tft_fonts.h" #define TFT_WIDTH 240 #define TFT_HEIGHT 320 // RGB565颜色定义 #define BLACK 0x0000 #define BLUE 0x001F #define RED 0xF800 #define GREEN 0x07E0 #define CYAN 0x07FF #define MAGENTA 0xF81F #define YELLOW 0xFFE0 #define WHITE 0xFFFF // 函数声明 void TFT_Init(void); void TFT_SetRotation(uint8_t rotation); void TFT_FillScreen(uint16_t color); void TFT_DrawPixel(int16_t x, int16_t y, uint16_t color); void TFT_DrawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color); void TFT_DrawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color); void TFT_FillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color); void TFT_DrawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color); void TFT_FillCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color); void TFT_SetTextColor(uint16_t color, uint16_t bgcolor); void TFT_SetTextSize(uint8_t size); void TFT_SetCursor(int16_t x, int16_t y); void TFT_PrintChar(char c); void TFT_Print(char *str); #endif ``` #### 5. `tft_gfx.c` - TFT图形库实现 ```c #include "tft_gfx.h" #include "spi.h" // 硬件配置 #define TFT_CS_PORT GPIOA #define TFT_CS_PIN GPIO_PIN_15 #define TFT_DC_PORT GPIOB #define TFT_DC_PIN GPIO_PIN_5 #define TFT_RST_PORT GPIOB #define TFT_RST_PIN GPIO_PIN_6 // 全局变量 static uint16_t _textColor = WHITE; static uint16_t _textBgColor = BLACK; static uint8_t _textSize = 1; static int16_t _cursorX = 0; static int16_t _cursorY = 0; static uint8_t _rotation = 0; // 发送命令 static void TFT_SendCommand(uint8_t cmd) { HAL_GPIO_WritePin(TFT_DC_PORT, TFT_DC_PIN, GPIO_PIN_RESET); HAL_GPIO_WritePin(TFT_CS_PORT, TFT_CS_PIN, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY); HAL_GPIO_WritePin(TFT_CS_PORT, TFT_CS_PIN, GPIO_PIN_SET); } // 发送数据 static void TFT_SendData(uint8_t data) { HAL_GPIO_WritePin(TFT_DC_PORT, TFT_DC_PIN, GPIO_PIN_SET); HAL_GPIO_WritePin(TFT_CS_PORT, TFT_CS_PIN, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, &data, 1, HAL_MAX_DELAY); HAL_GPIO_WritePin(TFT_CS_PORT, TFT_CS_PIN, GPIO_PIN_SET); } static void TFT_SendData16(uint16_t data) { uint8_t buf[2] = {data >> 8, data & 0xFF}; HAL_GPIO_WritePin(TFT_DC_PORT, TFT_DC_PIN, GPIO_PIN_SET); HAL_GPIO_WritePin(TFT_CS_PORT, TFT_CS_PIN, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, buf, 2, HAL_MAX_DELAY); HAL_GPIO_WritePin(TFT_CS_PORT, TFT_CS_PIN, GPIO_PIN_SET); } // TFT初始化 void TFT_Init(void) { // 硬件复位 HAL_GPIO_WritePin(TFT_RST_PORT, TFT_RST_PIN, GPIO_PIN_RESET); HAL_Delay(100); HAL_GPIO_WritePin(TFT_RST_PORT, TFT_RST_PIN, GPIO_PIN_SET); HAL_Delay(120); // 初始化序列 (ILI9341) TFT_SendCommand(0x01); // 软件复位 HAL_Delay(150); TFT_SendCommand(0xCF); // 电源控制B TFT_SendData(0x00); TFT_SendData(0xC1); TFT_SendData(0x30); TFT_SendCommand(0xED); // 电源开启序列 TFT_SendData(0x64); TFT_SendData(0x03); TFT_SendData(0x12); TFT_SendData(0x81); TFT_SendCommand(0xE8); // 驱动时序控制A TFT_SendData(0x85); TFT_SendData(0x00); TFT_SendData(0x78); TFT_SendCommand(0xCB); // 电源控制A TFT_SendData(0x39); TFT_SendData(0x2C); TFT_SendData(0x00); TFT_SendData(0x34); TFT_SendData(0x02); TFT_SendCommand(0xF7); // 泵比控制 TFT_SendData(0x20); TFT_SendCommand(0xEA); // 驱动时序控制B TFT_SendData(0x00); TFT_SendData(0x00); TFT_SendCommand(0xC0); // 电源控制1 TFT_SendData(0x23); TFT_SendCommand(0xC1); // 电源控制2 TFT_SendData(0x10); TFT_SendCommand(0xC5); // VCOM控制1 TFT_SendData(0x3E); TFT_SendData(0x28); TFT_SendCommand(0xC7); // VCOM控制2 TFT_SendData(0x86); TFT_SendCommand(0x36); // 内存访问控制 TFT_SendData(0x48); // 竖屏模式 TFT_SendCommand(0x3A); // 像素格式 TFT_SendData(0x55); // 16位像素 TFT_SendCommand(0xB1); // 帧率控制 TFT_SendData(0x00); TFT_SendData(0x18); TFT_SendCommand(0xB6); // 显示功能控制 TFT_SendData(0x08); TFT_SendData(0x82); TFT_SendData(0x27); TFT_SendCommand(0xF2); // 3G控制 TFT_SendData(0x00); TFT_SendCommand(0x26); // Gamma设置 TFT_SendData(0x01); TFT_SendCommand(0xE0); // 正伽马校正 TFT_SendData(0x0F); TFT_SendData(0x31); TFT_SendData(0x2B); TFT_SendData(0x0C); TFT_SendData(0x0E); TFT_SendData(0x08); TFT_SendData(0x4E); TFT_SendData(0xF1); TFT_SendData(0x37); TFT_SendData(0x07); TFT_SendData(0x10); TFT_SendData(0x03); TFT_SendData(0x0E); TFT_SendData(0x09); TFT_SendData(0x00); TFT_SendCommand(0xE1); // 负伽马校正 TFT_SendData(0x00); TFT_SendData(0x0E); TFT_SendData(0x14); TFT_SendData(0x03); TFT_SendData(0x11); TFT_SendData(0x07); TFT_SendData(0x31); TFT_SendData(0xC1); TFT_SendData(0x48); TFT_SendData(0x08); TFT_SendData(0x0F); TFT_SendData(0x0C); TFT_SendData(0x31); TFT_SendData(0x36); TFT_SendData(0x0F); TFT_SendCommand(0x11); // 退出睡眠 HAL_Delay(120); TFT_SendCommand(0x29); // 开启显示 } void TFT_SetRotation(uint8_t m) { _rotation = m % 4; TFT_SendCommand(0x36); switch (_rotation) { case 0: // 竖屏 TFT_SendData(0x48); break; case 1: // 横屏 TFT_SendData(0x28); break; case 2: // 倒竖屏 TFT_SendData(0x88); break; case 3: // 倒横屏 TFT_SendData(0xE8); break; } } void TFT_FillScreen(uint16_t color) { TFT_FillRect(0, 0, TFT_WIDTH, TFT_HEIGHT, color); } void TFT_FillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) { if (x >= TFT_WIDTH || y >= TFT_HEIGHT) return; if (x + w > TFT_WIDTH) w = TFT_WIDTH - x; if (y + h > TFT_HEIGHT) h = TFT_HEIGHT - y; TFT_SendCommand(0x2A); // 列地址设置 TFT_SendData16(x); TFT_SendData16(x + w - 1); TFT_SendCommand(0x2B); // 行地址设置 TFT_SendData16(y); TFT_SendData16(y + h - 1); TFT_SendCommand(0x2C); // 写入RAM HAL_GPIO_WritePin(TFT_DC_PORT, TFT_DC_PIN, GPIO_PIN_SET); HAL_GPIO_WritePin(TFT_CS_PORT, TFT_CS_PIN, GPIO_PIN_RESET); for (uint32_t i = 0; i < (uint32_t)w * h; i++) { uint8_t buf[2] = {color >> 8, color & 0xFF}; HAL_SPI_Transmit(&hspi1, buf, 2, HAL_MAX_DELAY); } HAL_GPIO_WritePin(TFT_CS_PORT, TFT_CS_PIN, GPIO_PIN_SET); } // 其他图形函数(TFT_DrawPixel, TFT_DrawLine等)根据需求实现 void TFT_SetTextColor(uint16_t color, uint16_t bgcolor) { _textColor = color; _textBgColor = bgcolor; } void TFT_SetTextSize(uint8_t size) { _textSize = (size > 0) ? size : 1; } void TFT_SetCursor(int16_t x, int16_t y) { _cursorX = x; _cursorY = y; } void TFT_PrintChar(char c) { if (c == '\n') { _cursorY += Font_8x16.height * _textSize; _cursorX = 0; return; } uint8_t charIndex = c - ' '; const uint16_t *charData = &Font_8x16.data[charIndex * Font_8x16.height]; for (uint8_t i = 0; i < Font_8x16.height; i++) { uint8_t line = charData[i]; for (uint8_t j = 0; j < Font_8x16.width; j++) { if (line & (1 << (7 - j))) { TFT_FillRect(_cursorX + j * _textSize, _cursorY + i * _textSize, _textSize, _textSize, _textColor); } else if (_textBgColor != _textColor) { TFT_FillRect(_cursorX + j * _textSize, _cursorY + i * _textSize, _textSize, _textSize, _textBgColor); } } } _cursorX += Font_8x16.width * _textSize; } void TFT_Print(char *str) { while (*str) { TFT_PrintChar(*str++); } } ``` #### 6. `tft_fonts.h` - 字体定义 ```c #ifndef __TFT_FONTS_H #define __TFT_FONTS_H #include <stdint.h> typedef struct { const uint8_t width; const uint8_t height; const uint16_t *data; } FontDef; extern FontDef Font_8x16; #endif ``` #### 7. `tft_fonts.c` - 字体数据 ```c #include "tft_fonts.h" // 8x16 ASCII 字体 const uint16_t Font8x16_Data[] = { // 空格 (ASCII 32) 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 数字0-9和字母等 // 这里只展示部分,完整字体需自行添加 // '0' 0x0000, 0x3E00, 0x7F00, 0x6300, 0x6300, 0x6300, 0x6300, 0x6300, 0x6300, 0x6300, 0x6300, 0x6300, 0x7F00, 0x3E00, 0x0000, 0x0000, // '1' 0x0000, 0x0C00, 0x1C00, 0x3C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x3F00, 0x3F00, 0x0000, 0x0000, // ... 其他字符 }; FontDef Font_8x16 = { .width = 8, .height = 16, .data = Font8x16_Data }; ``` ### 代码解释 #### 1. 系统架构 - **主程序(main.c)**:协调整个系统,处理传感器数据、用户输入和设备控制 - **DHT11驱动(dht11.c/h)**:实现温湿度传感器的读取协议 - **TFT图形库(tft_gfx.c/h)**:提供TFT显示屏的基本绘图功能 - **字体数据(tft_fonts.c/h)**:包含字符点阵数据用于文本显示 #### 2. 关键功能实现 - **温湿度监测**: - 每2秒读取一次DHT11传感器 - 使用TIM2定时器提供精确的微秒级延时 - **TFT显示**: - 显示温度、湿度数值 - 实时显示风扇状态和方向 - 超阈值时显示红色警告信息 - 绘制风扇状态图标 - **风扇控制**: - PA0按键切换风扇开关 - PC8按键设置正转 - PC9按键设置反转 - **报警功能**: - 温度>30℃或湿度>80%时触发蜂鸣器 - 蜂鸣器以200ms间隔闪烁报警 - TFT显示红色警告信息 #### 3. 硬件连接 ```plaintext DHT11: VCC: 3.3V GND: GND DATA: PA4 TFT (SPI ILI9341): CS: PA15 DC: PB5 RST: PB6 MOSI: PA7 (SPI1_MOSI) SCK: PA5 (SPI1_SCK) 风扇控制: ENABLE: PA0 IN1: PC8 IN2: PC9 蜂鸣器: PC10 按键: FAN_SW: PA0 (与风扇使能共用) DIR_FWD: PC8 DIR_REV: PC9 ``` ### Keil项目配置 1. **创建项目**: - 选择STM32F103RC设备 - 启用HAL库 - 配置系统时钟为72MHz 2. **外设配置**: - SPI1: 全双工主机模式,时钟分频32 - TIM2: 基本定时器,预分频71,计数范围50000(1MHz时钟) - GPIO: 配置所有使用的引脚 3. **项目结构**: ``` Project/ ├── Core/ │ ├── Inc/ │ │ ├── dht11.h │ │ ├── tft_fonts.h │ │ └── tft_gfx.h │ ├── Src/ │ │ ├── main.c │ │ ├── dht11.c │ │ ├── tft_fonts.c │ │ └── tft_gfx.c │ └── ... ├── Drivers/ │ ├── CMSIS/ │ └── STM32F1xx_HAL_Driver/ └── ... ``` ### 优化建议 1. **DHT11稳定性**: - 添加CRC校验 - 实现多次读取取平均值 - 增加读取失败重试机制 2. **显示性能**: - 实现部分区域刷新 - 使用双缓冲技术 - 优化SPI传输速度 3. **系统健壮性**: - 添加看门狗定时器 - 实现按键长按检测 - 添加温度补偿算法
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

郭兴华2007

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值