# 题目重述
根据提供的任务要求,需实现一个基于STM32的嵌入式系统功能程序,主要功能包括:
1. 在显示屏第一行显示固定学号;
2. 第二行显示年月日及时分秒,初始时间为2025年12月15日 11:59:55;
3. 第三行每300ms采集一次温湿度数据并显示;
4. 第四行显示是否着火的信息;
5. 板载LED0(PC13)以250ms间隔闪烁;
6. 按键3控制蜂鸣器开启,按键4控制关闭;
7. 按键1控制舵机转至0°,按键2控制转至90°;
8. 通过WiFi将温湿度数据发送到手机APP;
9. 手机APP可远程控制外接LED1的开关;
10. APP实时显示是否检测到着火。
---
# 给出答案(答案为带注释的代码块)
由于该系统涉及硬件驱动、WiFi通信和多任务协调,推荐使用 **C语言** 在 **STM32CubeIDE** 环境下开发。以下是核心框架代码(基于HAL库 + FreeRTOS + ESP8266 WiFi模块模拟):
```c
#include "main.h"
#include "stdio.h"
#include "string.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
// 假设使用LCD或OLED显示接口(如I2C OLED)
extern void LCD_DisplayString(uint8_t line, char* str); // 显示函数原型
extern float read_temperature(void); // 获取温度
extern float read_humidity(void); // 获取湿度
extern uint8_t detect_fire(void); // 火灾检测传感器
extern void servo_set_angle(uint8_t angle); // 舵机控制
extern void buzzer_on(void); // 蜂鸣器开
extern void buzzer_off(void); // 蜂鸣器关
extern void led1_on(void); // 外部LED1开
extern void led1_off(void); // 外部LED1关
extern void esp8266_send_data(char* data); // 发送数据到ESP8266(WiFi)
extern uint8_t esp8266_receive_cmd(void); // 接收APP指令
// 全局变量
RTC_TimeTypeDef sTime = {0};
RTC_DateTypeDef sDate = {0};
char display_str[20];
// 任务声明
void Task_Display(void *pvParameters);
void Task_LED_Blink(void *pvParameters);
void Task_Read_Sensors(void *pvParameters);
void Task_Handle_Keys(void *pvParameters);
void Task_WiFi_Communication(void *pvParameters);
/**
* @brief 主函数
*/
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_RTC_Init(); // 设置默认时间:2025-12-15 11:59:55
MX_USART1_UART_Init(); // 用于调试或连接ESP8266
// 初始化RTC时间(仅一次)
sTime.Hours = 11;
sTime.Minutes = 59;
sTime.Seconds = 55;
sDate.Year = 25;
sDate.Month = 12;
sDate.Date = 15;
HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN);
// 创建FreeRTOS任务
xTaskCreate(Task_Display, "Display", 128, NULL, 3, NULL);
xTaskCreate(Task_LED_Blink, "LED", 128, NULL, 2, NULL);
xTaskCreate(Task_Read_Sensors, "Sensors", 128, NULL, 3, NULL);
xTask.Create(Task_Handle_Keys, "Keys", 128, NULL, 2, NULL);
xTaskCreate(Task_WiFi_Communication, "WiFi", 256, NULL, 2, NULL);
vTaskStartScheduler();
while (1) {}
}
/**
* @brief 显示任务:更新屏幕四行内容
*/
void Task_Display(void *pvParameters) {
while (1) {
// 第一行:学号
LCD_DisplayString(1, "ID: 2025XXXXXX");
// 第二行:时间
HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN);
sprintf(display_str, "%02d-%02d-%02d %02d:%02d:%02d",
sDate.Year, sDate.Month, sDate.Date,
sTime.Hours, sTime.Minutes, sTime.Seconds);
LCD_DisplayString(2, display_str);
vTaskDelay(pdMS_TO_TICKS(1000)); // 每秒刷新一次时间
}
}
/**
* @brief LED闪烁任务(PC13)
*/
void Task_LED_Blink(void *pvParameters) {
while (1) {
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
vTaskDelay(pdMS_TO_TICKS(250)); // 250ms翻转
}
}
/**
* @brief 传感器读取任务(每300ms)
*/
void Task_Read_Sensors(void *pvParameters) {
float temp, humi;
uint8_t fire;
while (1) {
temp = read_temperature();
humi = read_humidity();
fire = detect_fire();
// 更新第三行
sprintf(display_str, "T:%.1f H:%.1f", temp, humi);
LCD_DisplayString(3, display_str);
// 更新第四行
LCD_DisplayString(4, fire ? "FIRE DETECTED!" : "SAFE");
vTaskDelay(pdMS_TO_TICKS(300));
}
}
/**
* @brief 按键处理任务
*/
void Task_Handle_Keys(void *pvParameters) {
while (1) {
// 按键3:蜂鸣器开
if (HAL_GPIO_ReadPin(KEY3_GPIO_Port, KEY3_Pin) == GPIO_PIN_RESET) {
while (HAL_GPIO_ReadPin(KEY3_GPIO_Port, KEY3_Pin) == GPIO_PIN_RESET);
buzzer_on();
}
// 按键4:蜂鸣器关
if (HAL_GPIO_ReadPin(KEY4_GPIO_Port, KEY4_Pin) == GPIO_PIN_RESET) {
while (HAL_GPIO_ReadPin(KEY4_GPIO_Port, KEY4_Pin) == GPIO_PIN_RESET);
buzzer_off();
}
// 按键1:舵机0度
if (HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == GPIO_PIN_RESET) {
while (HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == GPIO_PIN_RESET);
servo_set_angle(0);
}
// 按键2:舵机90度
if (HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin) == GPIO_PIN_RESET) {
while (HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin) == GPIO_PIN_RESET);
servo_set_angle(90);
}
vTaskDelay(pdMS_TO_TICKS(10)); // 防抖
}
}
/**
* @brief WiFi通信任务
*/
void Task_WiFi_Communication(void *pvParameters) {
char send_buf[50];
uint8_t cmd;
while (1) {
float t = read_temperature();
float h = read_humidity();
uint8_t fire = detect_fire();
// 发送到APP(JSON格式)
sprintf(send_buf, "{\"temp\":%.1f,\"humi\":%.1f,\"fire\":%d}", t, h, fire);
esp8266_send_data(send_buf);
// 检查是否有来自APP的命令
cmd = esp8266_receive_cmd();
if (cmd == 0x01) led1_on();
if (cmd == 0x00) led1_off();
vTaskDelay(pdMS_TO_TICKS(1000)); // 每秒上报一次
}
}
```
---
# 代码解析
- 使用 **FreeRTOS** 实现多任务并行运行,确保LED闪烁、数据显示、传感器采集互不阻塞;
- 时间管理采用 **STM32内部RTC模块**,初始化设定起始时间;
- 显示屏可通过 **I2C OLED驱动(如SSD1306)** 或LCD屏实现;
- 温湿度传感器常用 **DHT11/DHT22** 或 **SHT30**;
- 舵机控制使用 **PWM输出(TIM定时器)**;
- WiFi通信使用 **ESP8266模块(AT指令模式)** 连接到手机APP(可用AppInventor或Android Studio开发简易APP);
- 火灾检测使用 **MQ-2传感器或红外火焰传感器**;
- 所有外设通过GPIO、UART、I2C等HAL库API调用。
---
# 所需库/依赖包/工具链及下载方式
| 名称 | 功能 | 下载地址 |
|------|------|---------|
| **STM32CubeIDE** | 集成开发环境(含编译器、调试器) | [https://www.st.com/en/development-tools/stm32cubeide.html](https://www.st.com/en/development-tools/stm32cubeide.html) |
| **STM32CubeMX** | 图形化配置引脚与时钟 | 同上(集成在CubeIDE中) |
| **HAL库** | 硬件抽象层(已内置) | STM32CubeIDE自带 |
| **FreeRTOS** | 实时操作系统(支持多任务) | 可通过CubeMX添加 |
| **ESP8266 AT固件** | WiFi模块通信支持 | 乐鑫官网:[https://www.espressif.com](https://www.espressif.com) |
| **OLED SSD1306驱动库** | 显示屏显示支持 | GitHub搜索 `stm32 ssd1306 i2c` |
| **DHT11/SHT30库** | 温湿度采集 | 各开源平台均有提供 |
> 📌 注:若使用Python,仅适用于上位机模拟或树莓派端;本项目为STM32嵌入式设备,**必须使用C语言**。
---
# 知识点(列出解答该问题需要的知识点)
1. **FreeRTOS多任务调度原理**
支持并发执行多个任务,避免阻塞,提高响应效率。
2. **STM32 HAL库与RTC时间配置**
使用HAL库快速配置实时时钟,设置初始日期时间。
3. **ESP8266 WiFi模块AT指令通信**
通过串口发送AT指令连接Wi-Fi并与手机APP交换数据。