Skip to content

MrW1027/Weather-Clock

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Weather-Clock

Weather Clock

基于 STM32F407、FreeRTOS 与 ESP32-C3的嵌入式天气时钟。

MCU RTOS Language IDE Version

项目简介

Weather Clock 是一套运行在 STM32F407VET6 上的嵌入式天气时钟系统。

项目以 FreeRTOS 为运行基础,通过 ESP32-C3 AT 固件接入 Wi-Fi,使用 SNTP 同步网络时间,通过 HTTP 请求获取心知天气数据,同时采集 AHT20 温湿度传感器数据,最终在 240 × 320 分辨率的 ST7789 LCD 上集中显示时间、日期、室内温湿度、室外温度、天气图标及网络状态。

项目重点不只是完成多个外设功能,而是围绕以下问题进行设计:

  • 如何划分系统任务并控制不同业务的刷新周期;
  • 如何避免网络请求、传感器采集阻塞 FreeRTOS 软件定时器;
  • 如何解决多个业务模块同时访问 LCD 时的资源竞争;
  • 如何利用 DMA、中断和信号量降低 CPU 轮询开销;
  • 如何通过分层日志、超时退出和错误页面定位软硬件问题;
  • 如何在资源有限的 MCU 上完成图片、中文字体和天气数据解析。

天气时钟主界面

主要功能

  • 基于 FreeRTOS 实现多任务调度、软件定时器、消息队列和信号量同步;
  • 通过 ESP32-C3 AT 指令接入 Wi-Fi;
  • 获取并监测 SSID、BSSID、信道及 RSSI 等网络状态;
  • 通过 SNTP 获取网络时间,并同步至 STM32 内部 RTC;
  • 使用 LSE 作为 RTC 时钟源,实现本地时间持续运行;
  • 通过 HTTP 请求获取心知天气实时天气数据;
  • 解析城市、天气现象、天气代码和室外温度;
  • 根据天气代码映射晴、阴、多云、雨、雪、雷阵雨等图标;
  • 通过 AHT20 采集室内温度和湿度;
  • 使用 ST7789 显示时间、日期、室内环境及室外天气;
  • 支持中文点阵字库和 RGB565 图片资源;
  • 通过 USART 调试串口输出系统运行过程和错误信息;
  • 对 Wi-Fi、SNTP、HTTP、I2C 和内存异常设置分阶段诊断信息。

UI 效果

欢迎页面 Wi-Fi 连接页面
天气主页面 Wi-Fi 错误页面

当前仓库中展示的是 UI 设计稿。后续将补充实物运行照片、上电演示视频和串口调试截图。

技术栈

类型 技术
MCU STM32F407VET6,ARM Cortex-M4F
编程语言 C
RTOS FreeRTOS
固件库 STM32F4 Standard Peripheral Library
开发环境 Keil MDK5、ARM Compiler 5
调试工具 ST-Link、串口助手、逻辑分析仪
网络模块 ESP32-C3,AT 固件
显示模块 ST7789,240 × 320,RGB565
环境传感器 AHT20
网络协议 Wi-Fi、HTTP、SNTP
数据接口 USART、SPI、I2C
系统机制 Task、Queue、Software Timer、Semaphore、DMA、Interrupt
天气服务 心知天气 API

系统架构

项目按照应用层、系统服务层、驱动层和硬件层进行组织。

 flowchart TB
    subgraph APP["应用层"]
        INIT["启动流程<br/>main_init"]
        CLOCK["时间与日期更新"]
        INDOOR["室内温湿度采集"]
        WEATHER["室外天气更新"]
        WIFI["Wi-Fi 状态监测"]
        PAGE["页面与局部刷新"]
    end

    subgraph SERVICE["FreeRTOS 系统服务层"]
        TIMER["软件定时器"]
        WORKQ["工作队列<br/>Queue + Worker Task"]
        UIQ["UI 消息队列"]
        SYNC["二值信号量"]
    end

    subgraph DRIVER["驱动层"]
        ESPAT["ESP32-C3 AT 驱动"]
        LCD["ST7789 驱动"]
        SENSOR["AHT20 驱动"]
        RTC["RTC 驱动"]
        CONSOLE["Console 调试串口"]
        DELAY["TIM6 微秒时基"]
    end

    subgraph HARDWARE["硬件层"]
        ESP32-C3["ESP32-C3"]
        ST7789["ST7789 LCD"]
        AHT20["AHT20"]
        LSE["LSE + 内部 RTC"]
        UART["USB-TTL / 串口工具"]
    end

    INIT --> TIMER
    TIMER --> CLOCK
    TIMER --> WORKQ
    WORKQ --> WIFI
    WORKQ --> INDOOR
    WORKQ --> WEATHER

    CLOCK --> PAGE
    WIFI --> PAGE
    INDOOR --> PAGE
    WEATHER --> PAGE
    PAGE --> UIQ
    UIQ --> LCD

    WIFI --> ESPAT
    WEATHER --> ESPAT
    CLOCK --> RTC
    INDOOR --> SENSOR

    ESPAT --> SYNC
    LCD --> SYNC
    CONSOLE --> SYNC

    ESPAT --> ESP32-C3
    LCD --> ST7789
    SENSOR --> AHT20
    RTC --> LSE
    CONSOLE --> UART
Loading

启动流程

系统启动后按照以下顺序完成初始化:

flowchart LR
    RESET["系统复位"] --> LOW["底层时钟初始化"]
    LOW --> WQ["创建 Workqueue"]
    WQ --> INIT["创建 Init Task"]
    INIT --> BOARD["RTC / AHT20 / Console 初始化"]
    BOARD --> UI["创建 UI Task"]
    UI --> WELCOME["显示欢迎页面"]
    WELCOME --> AT["初始化 ESP32-C3AT 驱动"]
    AT --> WIFI["连接 Wi-Fi"]
    WIFI --> MAIN["显示天气主页面"]
    MAIN --> APP["创建周期任务与软件定时器"]
    APP --> DELETE["删除 Init Task"]
Loading

初始化任务优先级较高,用于确保系统按照确定顺序完成硬件、显示和网络初始化。初始化完成后主动调用 vTaskDelete(NULL) 删除自身,释放任务资源。

FreeRTOS 任务设计

项目主要创建三个应用任务,并使用 FreeRTOS 内部 Timer Service Task 处理软件定时器。

任务 优先级 主要职责
Init Task 9 完成板级初始化、页面初始化、ESP32-C3初始化和 Wi-Fi 连接
UI Task 8 串行处理文字、图片和区域填充请求
Workqueue Task 5 执行网络、传感器和状态检查等周期工作
Timer Service Task 9 管理软件定时器并触发回调

FreeRTOS 关键配置:

  • 抢占式调度;
  • 系统节拍频率为 1000 Hz;
  • 最大优先级数量为 10;
  • 动态内存管理采用 heap_4
  • FreeRTOS 堆空间设置为 92 KB;
  • 启用软件定时器;
  • 启用队列、互斥量和信号量;
  • 启用栈溢出检测;
  • 启用动态内存申请失败钩子;
  • 使用 configASSERT 捕获非法状态。

周期调度设计

不同业务具有不同实时性要求,因此使用独立软件定时器控制刷新周期。

业务 更新周期 执行方式
时间显示 1 秒 软件定时器回调直接读取 RTC
室内温湿度 3 秒 定时器触发后投递至 Workqueue
Wi-Fi 状态 5 秒 定时器触发后投递至 Workqueue
室外天气 1 分钟 定时器触发后投递至 Workqueue
SNTP 校时 正常 1 小时 定时器触发后投递至 Workqueue
SNTP 失败重试 1 秒 动态修改下一次定时周期

软件定时器只负责产生调度事件。HTTP 请求、ESP32-C3 AT 交互和 AHT20 采集等可能发生等待的操作,被转移到 Workqueue Task 中执行。

这样可以避免耗时操作长时间占用 Timer Service Task,降低其他软件定时器被连带延迟的风险。

Workqueue 工作队列

项目实现了一个轻量级工作队列:

Software Timer
      │
      │ 生成 work_message_t
      ▼
FreeRTOS Queue(长度 16)
      │
      ▼
Workqueue Task
      │
      ├── time_sync
      ├── wifi_update
      ├── inner_update
      └── outdoor_update

工作项由函数指针和参数组成:

typedef void (*work_t)(void *param);

typedef struct
{
    work_t work;
    void *param;
} work_message_t;

Workqueue 的作用:

  • 将定时触发和具体业务执行解耦;
  • 避免在软件定时器回调中执行阻塞操作;
  • 对网络访问和传感器访问进行串行化;
  • 统一记录工作项开始执行的调试日志;
  • 减少为每个周期业务单独创建任务带来的栈空间开销。

当前设计使用单工作线程,因此结构简单、内存开销较低,但某个 HTTP 请求耗时较长时,会延迟队列中的其他工作。后续可以将网络任务和传感器任务拆分为不同工作队列。

UI 消息队列

所有 LCD 操作统一由 UI Task 执行。其他任务不能直接并发操作 ST7789,而是向 UI Queue 投递消息。

UI 支持三类操作:

UI_ACTION_FILL_COLOR
UI_ACTION_WRITE_STRING
UI_ACTION_DRAW_IMAGE

数据流如下:

业务任务
   │
   │ ui_fill_color / ui_write_string / ui_draw_image
   ▼
UI Queue(长度 16)
   │
   ▼
UI Task
   │
   ▼
ST7789 Driver
   │
   ▼
SPI2 + DMA

采用单独 UI Task 的原因:

  • 防止多个任务同时访问 SPI 和 LCD;
  • 避免显示命令与像素数据交叉;
  • 将业务逻辑与具体屏幕驱动解耦;
  • 便于后续扩展动画、页面切换和刷新合并;
  • 保证界面绘制顺序与消息入队顺序一致。

对于字符串消息,调用方使用 pvPortMalloc 创建字符串副本,UI Task 完成显示后再调用 vPortFree 释放,避免调用方局部变量失效造成悬空指针。

天气数据链路

室外天气更新链路如下:

sequenceDiagram
    participant T as Outdoor Timer
    participant W as Workqueue
    participant E as ESP AT Driver
    participant S as 心知天气 API
    participant P as Weather Parser
    participant U as UI Queue
    participant L as ST7789

    T->>W: 投递 outdoor_update
    W->>E: esp_at_http_get(url)
    E->>S: AT+HTTPCLIENT / HTTPS 请求
    S-->>E: HTTP 响应与 JSON 数据
    E-->>W: 返回响应缓冲区
    W->>P: parse_seniverse_response()
    P-->>W: 城市、天气、代码、温度
    W->>W: 与上一次天气数据比较
    W->>U: 温度和图标刷新消息
    U->>L: SPI2 + DMA 刷新指定区域
Loading

天气解析没有引入完整 JSON 库,而是通过字符串搜索和受长度限制的 sscanf 提取所需字段,包括:

  • 城市名称;
  • 城市路径;
  • 天气现象;
  • 天气代码;
  • 室外温度。

这种方式依赖少、代码量小,适合当前固定格式的响应,但对服务器字段格式变化的兼容性有限。后续可替换为轻量级 JSON 解析器。

ESP32-C3 AT 驱动

ESP32-C3通过 USART2 与 STM32 通信:

  • 波特率:115200;
  • 数据格式:8N1;
  • 发送:USART2 TX + DMA1 Stream6;
  • 接收:USART2 RXNE 中断;
  • 同步:FreeRTOS 二值信号量;
  • 接收缓冲区:1024 字节。

驱动支持的主要 AT 功能:

功能 AT 指令
模块在线检测 AT
恢复默认配置 AT+RESTORE
设置 Station 模式 AT+CWMODE=1
连接 Wi-Fi AT+CWJAP
查询连接状态 AT+CWSTATE?
查询 AP 信息 AT+CWJAP?
配置 SNTP AT+CIPSNTPCFG
获取网络时间 AT+CIPSNTPTIME?
发起 HTTP 请求 AT+HTTPCLIENT

接收中断按行累积响应,并识别以下关键应答:

OK
ERROR
busy
ready

中断识别到完整应答后,通过 xSemaphoreGiveFromISR 唤醒等待任务,并调用 portYIELD_FROM_ISR 请求必要的任务切换。

每条 AT 命令均设置独立超时时间,避免 ESP32-C3异常或串口断线后任务永久阻塞。

SNTP 与 RTC 校时

系统通过 ESP32-C3获取 SNTP 时间,再同步到 STM32 内部 RTC。

时间链路:

ESP32-C3SNTP
      │
      ▼
解析星期、月份、日期和时间
      │
      ▼
写入 STM32 RTC
      │
      ▼
RTC 使用 LSE 持续计时
      │
      ▼
每秒刷新 LCD 时间和日期

RTC 驱动采用以下一致性处理:

  • 写入 RTC 后重新读取并验证秒字段;
  • 读取 RTC 时连续读取两次;
  • 两次结果一致后才返回数据;
  • 避免日期和时间寄存器跨秒更新时读取到不一致数据。

SNTP 获取失败或时间数据非法时,系统将下一次校时间隔缩短为 1 秒;成功后恢复为 1 小时。

AHT20 温湿度驱动

AHT20 使用 I2C2 与 STM32 通信:

  • I2C 频率:100 kHz;
  • SCL:PB10;
  • SDA:PB11;
  • 7 位设备地址:0x38
  • STM32 标准库发送地址参数:0x70

驱动流程:

发送初始化/校准命令
        │
        ▼
检查设备状态
        │
        ▼
发送测量命令 0xAC 0x33 0x00
        │
        ▼
轮询 Busy 状态
        │
        ▼
读取 6 字节原始数据
        │
        ▼
提取 20 位温度和湿度数据
        │
        ▼
转换为实际温度和相对湿度

转换公式:

Humidity    = RawHumidity × 100 / 2²⁰
Temperature = RawTemperature × 200 / 2²⁰ - 50

I2C 的 START、地址发送、字节发送和字节接收均设置微秒级超时。总线异常或设备无应答时,函数返回错误,而不是无限等待。

ST7789 显示驱动

ST7789 使用 SPI2 与 STM32 通信:

信号 STM32 引脚
SCK PB13
MOSI PC3
MISO PC2
CS PE2
RESET PE3
DC PE4
BL PE5

显示参数:

  • 分辨率:240 × 320;
  • 像素格式:RGB565;
  • SPI 模式:Mode 0;
  • 发送顺序:MSB First;
  • SPI 分频:4;
  • 像素数据传输:DMA1 Stream4 Channel 0。

寄存器命令使用 8 位 SPI 发送,像素数据切换为 16 位 SPI 发送。

大块像素数据通过 DMA 传输。DMA 完成中断释放二值信号量,等待任务被唤醒后继续下一段数据发送。

单次 DMA 传输长度受 NDTR 寄存器限制,因此驱动会将大块图像拆分为不超过 65535 个半字的数据块。

对于纯色填充,关闭 DMA 内存地址递增,使 DMA 重复读取同一个 RGB565 颜色值,减少额外颜色缓冲区占用。

局部刷新策略

系统只在数据发生变化时刷新对应区域。

例如:

  • Wi-Fi 连接状态与上一次状态一致时不刷新;
  • RTC 时间与上次读取结果一致时不刷新;
  • 室内温湿度未变化时不刷新;
  • 室外天气结构体与上一次结果一致时不刷新。

这样可以减少:

  • SPI 总线传输量;
  • DMA 传输次数;
  • LCD 重复绘制;
  • 界面闪烁;
  • 无意义的 CPU 和内存访问。

天气代码会被映射为晴天、夜晚、阴天、多云、雨、雷阵雨、雪等图标。

调试与问题定位

项目通过“分阶段日志 + 超时退出 + 硬件信号验证”的方式定位问题。

1. ESP32-C3与 Wi-Fi 调试

AT 驱动可打印发送命令和完整响应:

[DEBUG] Send: AT
[DEBUG] Response:
OK

Wi-Fi 初始化被拆分为多个阶段:

[AT] init failed
[WIFI] init failed
[SNTP] init failed
[WIFI] Connection Timeout

通过日志可以判断问题位于:

  • ESP32-C3未启动;
  • USART 波特率或接线错误;
  • AT 固件没有正确响应;
  • Station 模式设置失败;
  • Wi-Fi 名称或密码错误;
  • AP 无法连接;
  • SNTP 初始化失败。

硬件侧可使用串口工具或逻辑分析仪检查 PA2、PA3 上的 115200 波特率数据,确认 STM32 是否发出 AT 指令,以及 ESP32-C3是否返回响应。

2. AHT20 调试

温湿度采集分为三个阶段:

[AHT20] start measurement failed
[AHT20] wait for measurement failed
[AHT20] read measurement failed

定位顺序:

  1. 检查 PB10/PB11 是否存在上拉;
  2. 检查 START 和设备地址;
  3. 检查 AHT20 是否返回 ACK;
  4. 检查 Busy 位是否按预期清除;
  5. 检查是否读取到完整 6 字节数据;
  6. 检查原始值拼接和转换公式。

I2C 事件检查包含超时机制,因此传感器掉线不会使整个系统永久卡死。

3. LCD 与 DMA 调试

当屏幕不显示或刷新异常时,可按以下顺序定位:

  1. 检查 RESET、DC、CS 和背光引脚电平;
  2. 检查 SPI2 的 SCK 和 MOSI 波形;
  3. 检查 SPI 数据位宽是否在寄存器和像素数据之间正确切换;
  4. 检查 DMA1 Stream4 Channel 0 配置;
  5. 检查 DMA 完成中断是否进入;
  6. 检查二值信号量是否正确释放;
  7. 检查 UI Queue 中的消息类型和坐标范围。

所有屏幕操作由 UI Task 串行执行,降低并发写屏导致花屏和命令错位的可能性。

4. SNTP 与 RTC 调试

系统分别输出:

[SNTP] get time failed
[SNTP] invalid date formate
[SNTP] sync time: ...
[RTC] ...

如果网络时间获取成功但屏幕时间异常,可以继续检查:

  • 月份英文缩写转换;
  • 星期转换;
  • RTC 年份偏移;
  • LSE 是否起振;
  • RTC 写入后读取验证;
  • 日期与时间是否跨秒读取。

5. HTTP 与天气解析调试

天气更新区分两类错误:

[WEATHER] http error
[WEATHER] parse failed

http error 表示 AT 请求或网络通信失败;parse failed 表示收到了响应,但数据格式不符合解析器预期。

这种区分可以避免把所有问题都归因于“网络错误”。

6. RTOS 异常诊断

FreeRTOS 配置了以下开发期保护:

Assert Called
Stack Overflowed
Malloc Failed

对应机制:

  • configASSERT:捕获队列、信号量、任务参数等非法状态;
  • vApplicationStackOverflowHook:检测任务栈溢出;
  • vApplicationMallocFailedHook:检测动态内存申请失败。

这些异常会通过调试串口打印文件、行号或任务名称,便于进一步定位。

硬件连接

模块 外设 引脚/配置
ESP32-C3 TX/RX USART2 PA2 / PA3,115200 8N1
调试串口 USART1 PA9 / PA10,115200 8N1
AHT20 I2C2 PB10 / PB11,100 kHz
ST7789 SCK SPI2 PB13
ST7789 MOSI SPI2 PC3
ST7789 MISO SPI2 PC2
ST7789 CS GPIO PE2
ST7789 RESET GPIO PE3
ST7789 DC GPIO PE4
ST7789 BL GPIO PE5
RTC STM32 内部 RTC LSE 外部低速晶振
微秒时基 TIM6 1 MHz 计数时基

实际接线前请确认显示模块和 ESP32-C3模块的供电要求,并确保模块与 STM32 共地。

工程目录

Weather-Clock/
├── app/
│   ├── main.c                 # 程序入口与启动流程
│   ├── board.c                # 板级时钟及基础外设初始化
│   ├── app.c                  # 周期业务与软件定时器
│   ├── workqueue.c            # 工作队列
│   ├── ui.c                   # UI 消息队列与 UI Task
│   ├── wifi.c                 # Wi-Fi 初始化与连接流程
│   ├── weather.c              # 天气响应解析
│   ├── font/                  # 中文和数字点阵字库
│   ├── image/                 # LCD 图片及天气图标
│   └── page/                  # 欢迎、连接、错误和主页面
├── driver/
│   ├── aht20/                 # AHT20 I2C 驱动
│   ├── console/               # USART 调试串口驱动
│   ├── esp_at/                # ESP32-C3 AT 驱动
│   ├── rtc/                   # STM32 RTC 驱动
│   ├── st7789/                # ST7789 SPI/DMA 驱动
│   └── tim_delay/             # TIM6 微秒时基
├── firmware/
│   ├── cmsis/                 # CMSIS 与启动文件
│   └── driver/                # STM32F4 标准外设库
├── third_lib/
│   └── freertos/              # FreeRTOS 内核与移植层
├── resources/
│   ├── design/                # UI 设计图
│   └── images/                # 原始图片资源
├── tools/
│   └── convert_chinese_font.py # 中文点阵字库转换工具
└── mdk/
    └── stm32f407.uvprojx      # Keil MDK 工程文件

编译与运行

1. 克隆仓库

git clone https://github.com/MrW1027/Weather-Clock.git
cd Weather-Clock

2. 配置 Wi-Fi

打开:

app/wifi.h

将占位符替换为测试网络信息:

#define WIFI_SSID   "YOUR_WIFI_SSID"
#define WIFI_PASSWD "YOUR_WIFI_PASSWORD"

3. 配置天气 API

在心知天气平台注册并获取 API Key,然后在:

app/app.c

中找到天气请求地址,将:

YOUR_SENIVERSE_API_KEY

替换为自己的 API Key,并根据需要修改 location 参数。

请勿将真实 Wi-Fi 密码、API Key、Token 或其他敏感信息提交到公开仓库。

4. 打开 Keil 工程

使用 Keil MDK5 打开:

mdk/stm32f407.uvprojx

推荐环境:

  • Keil MDK5;
  • STM32F4 Device Family Pack;
  • ARM Compiler 5;
  • ST-Link 下载器。

当前工程使用 ARM Compiler 5 配置。若使用 ARM Compiler 6,需要检查汇编启动文件、编译选项和标准库兼容性。

5. 编译和下载

在 Keil 中执行:

Build → Download

下载完成后复位开发板。

6. 查看调试日志

使用 USB-TTL 或板载调试串口连接 USART1:

Baud Rate : 115200
Data Bits : 8
Stop Bits : 1
Parity    : None
Flow Ctrl : None

正常启动时可以观察到类似日志:

[SYS] Build Date: ...
[DEBUG] Workqueue task started
[AT] inited
[WIFI] inited
[SNTP] inited
[WIFI] connecting
[WIFI] Connected
[SNTP] sync time: ...
[AHT20] Temperature: ...
[WEATHER] ...

设计取舍

为什么使用 Workqueue,而不是为每项业务创建任务?

室内采集、天气请求、Wi-Fi 检查和 SNTP 同步都属于低频业务。如果分别创建任务,需要为每个任务分配独立栈空间。

使用统一 Workqueue 可以减少任务数量和 RAM 占用,同时将耗时操作从软件定时器回调中移出。

为什么 LCD 使用独立 UI Task?

ST7789 驱动及其 DMA 传输不是可重入资源。由多个任务直接调用可能导致寄存器命令、坐标数据和像素数据交叉。

使用 UI Queue 将所有显示请求串行化,可以从架构上规避并发写屏问题。

为什么使用 DMA 和中断?

LCD 图片、颜色填充和串口输出包含较多连续数据。DMA 可以减少 CPU 逐字节搬运的开销,中断与信号量用于在传输完成后唤醒任务,使任务不需要持续轮询 DMA 状态。

为什么不直接引入完整 JSON 库?

当前天气接口只需要少量固定字段,字符串搜索方式占用空间较小,也便于理解数据解析过程。

代价是对响应格式变化的适应能力有限,因此后续计划替换为轻量级 JSON 解析器。

当前限制

  • Wi-Fi 和天气服务配置仍通过源码中的编译期宏或字符串设置;
  • Wi-Fi 启动连接失败后会显示错误页面并停止初始化流程;
  • 运行过程中可以检测 Wi-Fi 断开,但尚未实现完整自动重连状态机;
  • ESP32-C3 AT 层使用固定大小的响应缓冲区;
  • AT 驱动当前采用单请求串行处理,不支持多个并发请求;
  • 天气响应解析依赖固定字段格式;
  • 城市参数在源码中配置,暂不支持屏幕端动态选择;
  • Workqueue 为单工作线程,长时间网络请求可能延迟其他工作;
  • 当前缺少主机端单元测试和硬件在环自动化测试;
  • 仓库暂未提供预编译固件。

后续计划

  • 将 Wi-Fi、API Key 和城市信息移入独立配置层;
  • 实现 Wi-Fi 自动重连状态机和退避重试;
  • 拆分网络工作队列与传感器工作队列;
  • 分离 ESP32-C3 TX/RX 缓冲区并增强异常响应解析;
  • 引入轻量级 JSON 解析器;
  • 增加天气接口失败缓存和离线显示;
  • 增加按键配置及参数持久化;
  • 增加任务栈余量和运行状态统计;
  • 增加实物照片、运行视频和逻辑分析仪波形;
  • 增加天气解析器的主机端单元测试;
  • 提供可直接烧录的 Release 固件。

项目总结

本项目完成了从板级外设驱动、FreeRTOS 任务设计、网络通信、传感器采集到图形界面显示的完整嵌入式应用链路。

相比简单地将各个外设功能依次组合,项目重点处理了周期业务调度、阻塞操作隔离、LCD 并发访问、DMA 完成同步、网络异常检测和分阶段问题定位等工程问题。

通过该项目,实践了以下能力:

  • STM32 外设寄存器和标准外设库开发;
  • FreeRTOS 任务、队列、软件定时器和信号量;
  • USART、SPI、I2C、DMA、中断和 RTC;
  • ESP32-C3 AT 指令交互与网络状态解析;
  • HTTP 天气数据获取和轻量级数据解析;
  • 嵌入式 GUI 资源转换与局部刷新;
  • 串口日志、超时机制和软硬件联合调试;
  • 嵌入式系统模块划分与资源权衡。

作者

无滞

GitHub:@MrW1027

项目地址:Weather-Clock

About

STM32F407 + FreeRTOS weather clock with ESP8266, AHT20 and ST7789

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages