/** ****************************************************************************** * @file main.c * @author fire * @version V1.0 * @date 2025-05-20 * @brief DHT11温湿度+实时时钟显示实验(智能刷新版) ****************************************************************************** */ #include "stm32f10x.h" #include "./systick/bsp_SysTick.h" #include "./dht11/bsp_dht11.h" #include "./usart/bsp_usart.h" #include "./lcd/bsp_ili9341_lcd.h" #include "./Timbase/bsp_TiMbase.h" #include "./Key/bsp_key.h" #include "./Led/bsp_led.h" /* 全局时间变量 */ volatile uint8_t hours = 9, minutes = 7, seconds = 0; volatile uint8_t time_update_flag = 0; /* 保存上一次的温湿度值 */ static uint8_t last_temp_int = 0xFF, last_humi_int = 0xFF; static uint8_t last_temp_deci = 0xFF, last_humi_deci = 0xFF; /* 函数声明 */ static void Show_Time_On_LCD(void); void TIM6_IRQHandler(void); /********************** 硬件初始化区域 **********************/ /** * @brief 定时器6中断服务程序(用于时钟计时) */ void TIM6_IRQHandler(void) { if (TIM_GetITStatus(BASIC_TIM, TIM_IT_Update) != RESET) { TIM_ClearITPendingBit(BASIC_TIM, TIM_IT_Update); /* 时间递增逻辑 */ if (++seconds == 60) { seconds = 0; if (++minutes == 60) { minutes = 0; if (++hours == 24) hours = 0; } } time_update_flag = 1; // 设置更新标志 } } int main(void) { char dispBuff[100]; DHT11_Data_TypeDef DHT11_Data; /* 外设初始化 */ Key_GPIO_Config();//按键端口初始化 SysTick_Init(); ILI9341_Init(); ILI9341_GramScan(6); DHT11_Init(); BASIC_TIM_Init(); // 初始化基础定时器(TIM6) /* 启用定时器中断 */ TIM_ITConfig(BASIC_TIM, TIM_IT_Update, ENABLE); /* 初始化显示 */ ILI9341_Clear(0,0,LCD_X_LENGTH,LCD_Y_LENGTH); Show_Time_On_LCD(); // 初始时间显示 while(1) { /* 温湿度检测 */ if(DHT11_Read_TempAndHumidity(&DHT11_Data) == SUCCESS) { /* 仅在数据变化时更新显示 */ if(DHT11_Data.temp_int != last_temp_int || DHT11_Data.temp_deci != last_temp_deci || DHT11_Data.humi_int != last_humi_int || DHT11_Data.humi_deci != last_humi_deci) { /* 更新温度显示(不整行清除) */ sprintf(dispBuff,"Temperature: %d.%dC", DHT11_Data.temp_int, DHT11_Data.temp_deci); ILI9341_DispStringLine_EN(LINE(3), dispBuff); // 直接覆盖写入 /* 更新湿度显示(不整行清除) */ sprintf(dispBuff,"Humidity: %d.%d%%", DHT11_Data.humi_int, DHT11_Data.humi_deci); ILI9341_DispStringLine_EN(LINE(4), dispBuff); // 直接覆盖写入 /* 更新最后记录值 */ last_temp_int = DHT11_Data.temp_int; last_temp_deci = DHT11_Data.temp_deci; last_humi_int = DHT11_Data.humi_int; last_humi_deci = DHT11_Data.humi_deci; } } else { /* 错误处理(仅在状态变化时刷新) */ static uint8_t error_flag = 0; if(!error_flag) // 避免重复打印错误信息 { ILI9341_DispStringLine_EN(LINE(3),"Temp/Humi ERROR"); LCD_ClearLine(LINE(4)); error_flag = 1; } } /* 时间更新显示(始终刷新) */ if(time_update_flag) { time_update_flag = 0; Show_Time_On_LCD(); } Delay_ms(1000); // 调整刷新间隔为1秒(匹配DHT11特性) } } /********************** 辅助功能实现 **********************/ /** * @brief 在LCD上显示当前时间(HH:MM:SS) */ static void Show_Time_On_LCD(void) { char time_str[9]; sprintf(time_str, "%02d:%02d:%02d", hours, minutes, seconds); // 强制刷新时间显示(覆盖写入) ILI9341_DispStringLine_EN(LINE(0),"YH Smart Watch"); ILI9341_DispStringLine_EN(LINE(1),"Time:"); ILI9341_DispStringLine_EN(LINE(2),time_str); // 保持温湿度显示位置(不清除,依赖智能刷新) } /*********************************************END OF FILE**********************/ /** ****************************************************************************** * @file main.c * @author fire * @version V1.0 * @date 2025-05-20 * @brief 串口指令控制实验(LED/蜂鸣器/时钟/温湿度) * * 功能列表: * 1. LED灯控制(开/关) * 2. 蜂鸣器控制(开/关) * 3. 实时时钟显示(HH:MM:SS) * 4. DHT11温湿度检测 ****************************************************************************** */ #include "stm32f10x.h" #include "./led/bsp_led.h" #include "./usart/bsp_usart.h" #include "./beep/bsp_beep.h" #include "./Timbase/bsp_TiMbase.h" #include "./key/bsp_exti.h" #include "./systick/bsp_SysTick.h" #include "./dht11/bsp_dht11.h" #include "stm32f10x_tim.h" // 定时器外设 #include "stm32f10x_rcc.h" // 时钟控制 /* 全局时间变量 */ volatile uint8_t hours = 9, minutes = 7, seconds = 0; volatile uint8_t time_update_flag = 0; // 时间更新标志 volatile uint8_t alarm_hours = 10, alarm_minutes = 03; volatile uint8_t alarm_enabled = 0; volatile uint8_t alarm_triggered = 0; volatile uint32_t alarm_duration = 10; // 闹钟持续时间(秒) volatile uint32_t alarm_start_time = 0; #define TEMP_ALERT_THRESHOLD 35 #define HUMI_ALERT_THRESHOLD 45 volatile uint8_t temp_alert_enabled = 1; volatile uint8_t humi_alert_enabled = 1; /* 函数声明 */ static void Show_Message(void); void Send_Time_To_UART(void); void Update_Time(void); // 保留声明但未实现(可根据需要补充) void Check_Alarms(void); void Check_TempHumi_Alerts(DHT11_Data_TypeDef *data); void Handle_Alarm(void); /********************** 硬件初始化区域 **********************/ /** * @brief 定时器6中断服务程序(用于时钟计时) */ void TIM6_IRQHandler(void) { if (TIM_GetITStatus(BASIC_TIM, TIM_IT_Update) != RESET) { TIM_ClearITPendingBit(BASIC_TIM, TIM_IT_Update); // 时间递增逻辑 if (++seconds == 60) { seconds = 0; if (++minutes == 60) { minutes = 0; if (++hours == 24) hours = 0; } } time_update_flag = 1; // 设置更新标志 Check_Alarms(); } } /********************** 主函数入口 **********************/ int main(void) { char ch; DHT11_Data_TypeDef DHT11_Data; /* 外设初始化(按功能分组) */ LED_GPIO_Config(); // LED初始化 BEEP_GPIO_Config(); // 蜂鸣器初始化 EXTI_Key_Config(); // 按键中断初始化 USART_Config(); // 串口初始化(115200 8-N-1) BASIC_TIM_Init(); // 基础定时器初始化(TIM6) SysTick_Init(); // 系统滴答定时器初始化 DHT11_Init(); // 温湿度传感器初始化 // 启用定时器中断(确保NVIC配置已完成) TIM_ITConfig(BASIC_TIM, TIM_IT_Update, ENABLE); /* 显示操作提示 */ Show_Message(); while(1) { Handle_Alarm(); /* 串口指令接收 */ if(USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) != RESET) { ch = USART_ReceiveData(DEBUG_USARTx); printf("接收到字符:%c\n", ch); /* 指令处理 */ switch(ch) { case '1': // LED控制 LED_RED; break; case '2': LED_RGBOFF; break; case '3': // 蜂鸣器控制 BEEP(BEEP_ON); break; case '4': BEEP(BEEP_OFF); break; case '5': // 时间显示 if (time_update_flag) { time_update_flag = 0; Send_Time_To_UART(); } break; case '6': // 温湿度检测 if(DHT11_Read_TempAndHumidity(&DHT11_Data) == SUCCESS) { printf("\r\n读取DHT11成功!\r\n"); printf("湿度:%d.%d %%RH 温度:%d.%d ℃\r\n", DHT11_Data.humi_int, DHT11_Data.humi_deci, DHT11_Data.temp_int, DHT11_Data.temp_deci); // 检查温湿度警报 Check_TempHumi_Alerts(&DHT11_Data); } else { printf("DHT11读取失败!\r\n"); } Delay_ms(2000); break; case '7': // 设置闹钟时间 (格式: HHMM) { // 变量声明 char time_str[5] = {0}; uint8_t i = 0; uint8_t new_hours = 0; uint8_t new_minutes = 0; printf("请输入闹钟时间(HHMM,24小时制): "); // 等待接收4位数字 while(i < 4) { if(USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) != RESET) { char c = USART_ReceiveData(DEBUG_USARTx); if(c >= '0' && c <= '9') { time_str[i++] = c; printf("%c", c); // 回显输入的数字 } } } printf("\r\n"); // 解析输入的时间 new_hours = (time_str[0] - '0') * 10 + (time_str[1] - '0'); new_minutes = (time_str[2] - '0') * 10 + (time_str[3] - '0'); // 验证时间有效性 if(new_hours < 24 && new_minutes < 60) { alarm_hours = new_hours; alarm_minutes = new_minutes; alarm_enabled = 1; // 设置后自动启用闹钟 printf("闹钟已设置为: %02d:%02d\r\n", alarm_hours, alarm_minutes); } else { printf("错误: 无效的时间格式!\r\n"); } break; } case '8': //关闭/开启闹钟 alarm_enabled = !alarm_enabled; if(alarm_enabled) { printf("闹钟已开启\r\n"); } else { printf("闹钟已关闭\r\n"); // 如果闹钟正在响,关闭它 if(alarm_triggered) { BEEP(BEEP_OFF); LED_RGBOFF; alarm_triggered = 0; } } break; case '9': // 关闭/开启警报 temp_alert_enabled = !temp_alert_enabled; printf("温度警报已%s\r\n", temp_alert_enabled ? "开启" : "关闭"); break; case '0': // 关闭/开启警报 humi_alert_enabled = !humi_alert_enabled; printf("湿度警报已%s\r\n", humi_alert_enabled ? "开启" : "关闭"); break; case 'a': // 关闭闹钟 (新增功能) if(alarm_triggered) { BEEP(BEEP_OFF); LED_RGBOFF; alarm_triggered = 0; printf("闹钟已关闭\r\n"); } else { printf("当前没有响铃的闹钟\r\n"); } break; default: // 无效指令提示 Show_Message(); break; } } } } /********************** 辅助功能实现 **********************/ /** * @brief 显示操作提示信息 */ static void Show_Message(void) { printf("\r\n=== STM32智能手环实验 ===\r\n"); printf("USART配置:%d 8-N-1\r\n", DEBUG_USART_BAUDRATE); printf("指令列表:\r\n"); printf("1 - 打开LED\r\n"); printf("2 - 关闭LED\r\n"); printf("3 - 打开蜂鸣器\r\n"); printf("4 - 关闭蜂鸣器\r\n"); printf("5 - 显示当前时间\r\n"); printf("6 - 显示温湿度\r\n"); printf("7 - 设置闹钟时间(HHMM)\r\n"); printf("8 - 开启/关闭闹钟\r\n"); printf("9 - 开启/关闭温度警报\r\n"); printf("0 - 开启/关闭湿度警报\r\n"); printf("a - 关闭正在响铃的闹钟\r\n"); } /** * @brief 发送时间到串口(HH:MM:SS格式) */ void Send_Time_To_UART(void) { char time_str[9]; sprintf(time_str, "%02d:%02d:%02d\r\n", hours, minutes, seconds); Usart_SendString(DEBUG_USARTx, time_str); } void Check_Alarms(void) { // 只有当闹钟启用且未触发时才检查 if (alarm_enabled && !alarm_triggered) { // 检查是否到达闹钟时间 if (hours == alarm_hours && minutes == alarm_minutes && seconds == 0) { alarm_triggered = 1; alarm_start_time = seconds; // 记录开始时间 printf("闹钟时间到! %02d:%02d\r\n", alarm_hours, alarm_minutes); } } } void Handle_Alarm(void) { if (alarm_triggered) { // 闹钟持续响铃 BEEP(BEEP_ON); LED_RED; // LED闪烁效果 // 检查是否超过闹钟持续时间 if ((seconds - alarm_start_time) >= alarm_duration) { BEEP(BEEP_OFF); LED_RGBOFF; alarm_triggered = 0; printf("闹钟自动关闭\r\n"); } } } void Check_TempHumi_Alerts(DHT11_Data_TypeDef *data) { uint8_t alert_triggered = 0; // 检查温度警报 if (temp_alert_enabled && data->temp_int >= TEMP_ALERT_THRESHOLD) { if (!alert_triggered) { printf("温度警报! 当前温度: %d.%d ℃\r\n", data->temp_int, data->temp_deci); alert_triggered = 1; } BEEP(BEEP_ON); // 触发警报 } // 检查湿度警报 if (humi_alert_enabled && data->humi_int >= HUMI_ALERT_THRESHOLD) { if (!alert_triggered) { printf("湿度警报! 当前湿度: %d.%d %%RH\r\n", data->humi_int, data->humi_deci); alert_triggered = 1; } BEEP(BEEP_ON); // 触发警报 } // 如果没有警报,关闭蜂鸣器 if (!alert_triggered) { BEEP(BEEP_OFF); } } 将两个代码整理到一个代码里,不要删减以前的内容,同时包含串口和LCD的功能
时间: 2025-06-01 18:11:05 浏览: 52
### 合并两个STM32代码片段的解决方案
在STM32开发中,将两个代码片段整合为一个完整程序时,需要确保功能模块化、资源分配合理以及避免冲突。以下是一个完整的解决方案:
#### 1. 功能模块化设计
将串口指令控制(如LED、蜂鸣器、闹钟、温湿度)和LCD显示(时间、温湿度)分别封装为独立的功能模块。这样可以提高代码的可维护性和扩展性。
#### 2. 硬件初始化
确保所有硬件外设(如UART、LCD、GPIO等)都正确初始化。例如,UART用于串口通信,GPIO用于控制LED和蜂鸣器,I2C或SPI可能用于连接LCD模块[^1]。
```c
// 初始化UART用于串口通信
void UART_Init(void) {
// 配置UART参数
}
// 初始化LCD模块
void LCD_Init(void) {
// 配置LCD接口(如I2C或SPI)
}
// 初始化GPIO用于控制LED和蜂鸣器
void GPIO_Init(void) {
// 配置GPIO引脚
}
```
#### 3. 串口指令解析与执行
通过串口接收指令,并根据指令内容控制相应设备(如LED、蜂鸣器、闹钟、温湿度传感器)。可以使用状态机或回调函数来处理不同的指令。
```c
void Process_UART_Command(char* command) {
if (strcmp(command, "LED_ON") == 0) {
LED_TurnOn(); // 打开LED
} else if (strcmp(command, "BEEP") == 0) {
Buzzer_Start(); // 启动蜂鸣器
} else if (strcmp(command, "TEMP") == 0) {
float temperature = Read_Temperature_Sensor();
Display_Temperature(temperature); // 显示温度
}
// 其他指令...
}
```
#### 4. LCD显示功能
在LCD上显示时间、温湿度等信息。可以使用定时器定期更新显示内容。
```c
void Update_LCD_Display(void) {
char buffer[50];
time_t now = Get_Current_Time(); // 获取当前时间
float temperature = Read_Temperature_Sensor(); // 读取温度
float humidity = Read_Humidity_Sensor(); // 读取湿度
sprintf(buffer, "Time: %s\nTemp: %.2f C\nHumidity: %.2f %%", ctime(&now), temperature, humidity);
LCD_Show_Text(buffer); // 在LCD上显示文本
}
```
#### 5. 主循环逻辑
在主循环中,结合串口指令解析和LCD显示功能,实现完整的交互逻辑。
```c
int main(void) {
UART_Init(); // 初始化UART
LCD_Init(); // 初始化LCD
GPIO_Init(); // 初始化GPIO
while (1) {
if (UART_Data_Available()) { // 检查是否有串口数据
char command[50];
UART_Read_String(command, sizeof(command)); // 读取串口命令
Process_UART_Command(command); // 处理命令
}
Update_LCD_Display(); // 更新LCD显示
HAL_Delay(1000); // 延时1秒
}
}
```
#### 6. 注意事项
- **资源冲突**:确保不同功能模块之间不会争夺同一硬件资源(如GPIO引脚)。
- **中断优先级**:如果使用了中断(如UART接收中断),需要合理设置中断优先级,避免高优先级任务阻塞低优先级任务。
- **代码优化**:对于频繁调用的功能(如温度读取、LCD显示),可以考虑使用DMA或定时器减少CPU占用[^2]。
---
阅读全文