【嵌入式开发学习】第10天:项目实战(智能温湿度报警器)

核心目标:整合前 9 天所有知识点(GPIO、定时器、串口、I2C、DMA、FreeRTOS),开发一个 “智能温湿度报警器”—— 实时采集温湿度、通过按键设置阈值、超标时 LED + 蜂鸣器报警、支持串口查看数据和远程修改阈值,完成从 “知识点” 到 “产品级应用” 的闭环,体验嵌入式开发的完整流程。

一、项目需求与架构设计(20 分钟)

1. 核心功能
  • 实时采集:通过 AHT10 传感器(I2C)采集温湿度,1 秒更新一次;
  • 阈值设置:板载按键(GPIO 输入)设置温度上限(如 30℃)和湿度上限(如 60% RH);
  • 报警功能:温湿度超限时,LED 闪烁 + 蜂鸣器鸣叫(GPIO 输出);
  • 数据交互:串口(DMA)上传实时数据和报警信息,支持电脑发送指令修改阈值;
  • 多任务管理:用 FreeRTOS 实现 “采集 + 按键检测 + 报警 + 串口通信”4 任务并行,互不阻塞。
2. 硬件清单
  • STM32F103C8T6 开发板、AHT10 温湿度传感器(I2C);
  • 按键 2 个(设置温度阈值 / 湿度阈值)、蜂鸣器 1 个(有源)、LED1 个;
  • USB-TTL 模块(串口通信)、杜邦线、面包板。
3. 系统架构(FreeRTOS 任务分配)
任务名称优先级功能描述核心外设
采集任务21 秒采集一次温湿度,更新全局变量I2C、定时器
按键检测任务3检测按键按下,修改阈值(高优先级)GPIO 输入
报警判断任务2对比实时数据与阈值,触发报警GPIO 输出(蜂鸣器、LED)
串口通信任务1DMA 发送数据,接收远程指令USART1、DMA

二、硬件接线(10 分钟,关键!)

外设引脚连接(STM32F103C8T6)备注
AHT10VCC→3.3V,GND→GND,SCL→PB6,SDA→PB7I2C1 通信
按键 1(温度阈值)一端→PA0,另一端→GND下拉输入(按下时为低电平)
按键 2(湿度阈值)一端→PA1,另一端→GND下拉输入(按下时为低电平)
蜂鸣器VCC→3.3V,GND→PB8(通过三极管驱动)低电平触发鸣叫(GPIO 输出)
LED正极→PC13(串联 1k 电阻),负极→GND低电平点亮(GPIO 输出)
串口(USB-TTL)TX→PA10,RX→PA9,GND→GNDUSART1 通信,DMA 发送

三、CubeIDE 配置(30 分钟,模块化配置)

1. 基础配置
  • 芯片选择:STM32F103C8T6;
  • 时钟配置:HSE=8MHz,系统时钟 = 72MHz,APB1=36MHz,APB2=72MHz。
2. 外设配置
  • I2C1:Mode=I2C,时钟频率 = 100kHz,PB6=SCL,PB7=SDA(上拉);
  • USART1:异步模式,波特率 = 9600,PA9=TX,PA10=RX;DMA 配置:添加 TX 方向(DMA1_Channel4,内存→外设,正常模式);
  • GPIO
    • PA0、PA1:GPIO_Input(按键,下拉输入);
    • PB8:GPIO_Output(蜂鸣器,推挽输出);
    • PC13:GPIO_Output(LED,推挽输出);
  • FreeRTOS:CMSIS_V1,创建 4 个任务(按架构设计配置优先级和栈大小);
  • NVIC:使能 I2C、USART1、按键中断(若用中断检测按键)。
3. 生成代码

点击 “Project→Generate Code”,CubeIDE 自动生成初始化代码和 FreeRTOS 任务框架。

四、核心代码实现(60 分钟,分模块编写)

1. 全局变量定义(main.c头部,任务间共享数据)

c

/* USER CODE BEGIN 0 */
#include <string.h>

// 传感器数据
float temp = 0.0, humi = 0.0;
// 阈值(默认温度30℃,湿度60%RH)
float temp_threshold = 30.0, humi_threshold = 60.0;
// 报警状态(0=正常,1=温度超标,2=湿度超标,3=两者都超标)
uint8_t alarm_state = 0;
// 串口发送缓冲区
uint8_t uart_send_buf[100];
/* USER CODE END 0 */
2. AHT10 传感器驱动(复用第八天代码,略作修改)

c

/* USER CODE BEGIN 0 */
// AHT10初始化和数据读取函数(同第八天,确保返回温度和湿度)
uint8_t AHT10_Init(I2C_HandleTypeDef *hi2c) { ... }
uint8_t AHT10_ReadData(I2C_HandleTypeDef *hi2c, float *temp, float *humi) { ... }
/* USER CODE END 0 */
3. FreeRTOS 任务实现(main.c的 “USER CODE BEGIN 5”)
任务 1:温湿度采集任务(1 秒一次)

c

void TempHumi_Collect_Task(void const * argument)
{
  AHT10_Init(&hi2c1);  // 初始化传感器
  for(;;)
  {
    // 读取温湿度(更新全局变量temp、humi)
    AHT10_ReadData(&hi2c1, &temp, &humi);
    vTaskDelay(1000);  // 1秒采集一次
  }
}
任务 2:按键检测任务(检测阈值设置)

c

void Key_Detect_Task(void const * argument)
{
  uint8_t key1_state = 1, key2_state = 1;  // 按键初始状态(高电平,未按下)
  for(;;)
  {
    // 检测按键1(温度阈值+1℃,按下一次加1)
    if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == 0) {  // 按键按下(低电平)
      if (key1_state == 1) {  // 边沿检测(只触发一次)
        temp_threshold += 1.0;
        if (temp_threshold > 40.0) temp_threshold = 40.0;  // 上限40℃
        // 串口反馈阈值修改
        sprintf((char*)uart_send_buf, "温度阈值已修改为:%.1f℃\r\n", temp_threshold);
        HAL_UART_Transmit_DMA(&huart1, uart_send_buf, strlen((char*)uart_send_buf));
      }
      key1_state = 0;
    } else {
      key1_state = 1;
    }

    // 检测按键2(湿度阈值+5%RH,按下一次加5)
    if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == 0) {
      if (key2_state == 1) {
        humi_threshold += 5.0;
        if (humi_threshold > 90.0) humi_threshold = 90.0;  // 上限90%RH
        sprintf((char*)uart_send_buf, "湿度阈值已修改为:%.1f%%RH\r\n", humi_threshold);
        HAL_UART_Transmit_DMA(&huart1, uart_send_buf, strlen((char*)uart_send_buf));
      }
      key2_state = 0;
    } else {
      key2_state = 1;
    }

    vTaskDelay(50);  // 50ms检测一次,消抖
  }
}
任务 3:报警判断任务(实时对比阈值)

c

void Alarm_Check_Task(void const * argument)
{
  for(;;)
  {
    // 判断报警状态
    alarm_state = 0;
    if (temp > temp_threshold) alarm_state |= 1;  // 温度超标
    if (humi > humi_threshold) alarm_state |= 2;  // 湿度超标

    // 执行报警动作
    if (alarm_state != 0) {
      // 超标:LED闪烁+蜂鸣器鸣叫
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_RESET);  // 蜂鸣器响
      HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);  // LED亮
      vTaskDelay(300);
      HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);    // LED灭
      vTaskDelay(300);
    } else {
      // 正常:关闭报警
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);    // 蜂鸣器关
      HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);    // LED灭
      vTaskDelay(100);  // 100ms检测一次
    }
  }
}
任务 4:串口通信任务(数据上传 + 远程指令)

c

void UART_Comm_Task(void const * argument)
{
  uint8_t uart_recv_buf[20] = {0};
  for(;;)
  {
    // 1. 每2秒发送一次实时数据
    sprintf((char*)uart_send_buf, 
            "实时数据:温度=%.1f℃(阈值=%.1f),湿度=%.1f%%RH(阈值=%.1f),状态:%s\r\n",
            temp, temp_threshold, humi, humi_threshold,
            (alarm_state == 0) ? "正常" : "超标报警");
    HAL_UART_Transmit_DMA(&huart1, uart_send_buf, strlen((char*)uart_send_buf));
    vTaskDelay(2000);

    // 2. 接收电脑指令(格式:"T30"→温度阈值30℃,"H60"→湿度阈值60%RH)
    HAL_UART_Receive(&huart1, uart_recv_buf, 4, 100);  // 超时100ms
    if (uart_recv_buf[0] == 'T') {  // 修改温度阈值
      temp_threshold = atof((char*)&uart_recv_buf[1]);  // 字符串转浮点数
      sprintf((char*)uart_send_buf, "远程修改温度阈值为:%.1f℃\r\n", temp_threshold);
      HAL_UART_Transmit_DMA(&huart1, uart_send_buf, strlen((char*)uart_send_buf));
    } else if (uart_recv_buf[0] == 'H') {  // 修改湿度阈值
      humi_threshold = atof((char*)&uart_recv_buf[1]);
      sprintf((char*)uart_send_buf, "远程修改湿度阈值为:%.1f%%RH\r\n", humi_threshold);
      HAL_UART_Transmit_DMA(&huart1, uart_send_buf, strlen((char*)uart_send_buf));
    }
    memset(uart_recv_buf, 0, sizeof(uart_recv_buf));  // 清空接收缓冲区
  }
}

五、系统测试与调试(30 分钟,关键验证)

1. 基础功能测试
  • 传感器采集:串口每 2 秒收到温湿度数据,数值随环境变化;
  • 按键设置:按下按键 1,温度阈值 + 1℃并串口反馈;按下按键 2,湿度阈值 + 5% RH;
  • 报警功能:用手捂住 AHT10(升温加湿),温湿度超限时,LED 闪烁 + 蜂鸣器鸣叫。
2. 远程控制测试
  • 电脑串口助手发送指令 “T32”→ 温度阈值改为 32℃,串口反馈修改成功;
  • 发送指令 “H65”→ 湿度阈值改为 65% RH,系统按新阈值判断报警。
3. 多任务并行验证
  • 报警时,按键仍可修改阈值,串口仍能上传数据 —— 证明 4 个任务并行不阻塞。

六、第十天总结:嵌入式开发的完整流程(10 分钟)

通过这个实战项目,你已掌握嵌入式开发的核心流程:

  1. 需求分析:明确系统要实现什么功能;
  2. 硬件选型与接线:根据需求选外设,设计电路连接;
  3. 软件架构设计:拆分任务,分配资源(如 FreeRTOS 任务优先级);
  4. 模块化开发:分外设驱动(传感器、按键、串口)、业务逻辑(采集、报警)编写代码;
  5. 测试与调试:逐步验证功能,解决硬件接线错误、逻辑漏洞等问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值