1. 项目概述与核心价值
这个项目展示了如何用一块成本不到20元的STM32F03C8T6开发板,通过AT指令与网络模块交互,实现天气数据的获取功能。对于嵌入式开发者来说,这种低成本物联网方案在实际项目中非常实用——无论是智能家居的温湿度补偿,还是户外设备的天气预警,都需要实时获取气象数据。
我选择STM32F03C8T6作为主控,主要看中它的性价比:72MHz主频的Cortex-M0内核,64KB Flash和8KB RAM,完全能胜任这种网络通信任务。而AT指令则是嵌入式领域最通用的模块控制方式,几乎所有的2G/4G、WiFi模块都支持这种交互模式。
2. 硬件准备与电路设计
2.1 核心器件选型
主控芯片STM32F03C8T6采用LQFP48封装,开发时建议使用带USB转串口的调试板,比如常见的"蓝色药丸"开发板。网络模块方面,根据项目需求可以选择:
- ESP8266:成本约15元,支持WiFi连接,但需要外接天线
- SIM800C:支持2G网络,约30元,适合无WiFi覆盖的场景
- Air724UG:4G Cat1模块,约60元,网络更稳定但功耗较高
提示:初次尝试建议用ESP8266,开发环境搭建简单,且不需要SIM卡
2.2 电路连接要点
以ESP8266为例,硬件连接需要注意:
-
电源处理:
- ESP8266峰值电流可达500mA,必须单独供电
- 建议使用AMS1117-3.3稳压芯片,输入5V输出3.3V
- 在VCC和GND之间并联100μF+0.1μF电容
-
串口连接:
plaintext复制
STM32 USART1_TX(PA9) -> ESP8266 RX STM32 USART1_RX(PA10) -> ESP8266 TX注意不要交叉连接,且需共地
-
控制引脚:
- ESP8266的CH_PD引脚接3.3V使能
- RST引脚可接STM32的GPIO用于硬件复位
3. 开发环境搭建
3.1 工具链配置
推荐使用STM32CubeIDE作为开发环境,具体配置步骤:
- 安装STM32CubeMX并生成初始化代码
- 在Pinout配置中启用USART1,模式选择Asynchronous
- 参数设置:波特率115200,8位数据,无校验,1停止位
- 生成代码时勾选"Generate peripheral initialization as a pair of .c/.h files"
3.2 关键驱动实现
需要实现以下核心功能函数:
c复制// 串口发送函数
void ESP8266_SendCmd(char* cmd) {
HAL_UART_Transmit(&huart1, (uint8_t*)cmd, strlen(cmd), 1000);
HAL_UART_Transmit(&huart1, (uint8_t*)"\r\n", 2, 1000); // 发送回车换行
}
// 带超时的响应接收
uint8_t ESP8266_WaitResponse(char* target, uint32_t timeout) {
uint8_t buffer[256] = {0};
uint32_t start = HAL_GetTick();
while(HAL_GetTick() - start < timeout) {
if(HAL_UART_Receive(&huart1, buffer, sizeof(buffer)-1, 100) == HAL_OK) {
if(strstr((char*)buffer, target) != NULL) {
return 1; // 匹配成功
}
}
HAL_Delay(10);
}
return 0; // 超时
}
4. AT指令交互协议解析
4.1 基础AT指令流程
典型的WiFi连接流程如下:
-
测试模块是否就绪:
at复制AT应返回"OK"
-
设置WiFi模式为Station:
at复制AT+CWMODE=1 -
连接路由器:
at复制AT+CWJAP="SSID","password"连接过程可能需要10-20秒
-
获取IP地址:
at复制AT+CIFSR
4.2 HTTP请求构造
以心知天气API为例,GET请求构造方法:
c复制char api_request[256];
sprintf(api_request,
"AT+CIPSTART=\"TCP\",\"api.seniverse.com\",80\r\n"
"AT+CIPSEND=%d\r\n"
"GET /v3/weather/now.json?key=你的API密钥&location=beijing&language=zh-Hans&unit=c\r\n"
"Host: api.seniverse.com\r\n"
"\r\n",
strlen(request_content));
关键点说明:
- 需要先在心知天气官网申请免费API密钥
- 每个请求长度必须精确计算
- 必须包含Host头部字段
- 最后需要两个回车换行表示结束
5. JSON数据解析方案
5.1 轻量级解析方案
在资源有限的STM32上,推荐使用以下两种解析方式:
-
字符串查找法:
c复制char* find_key(char* json, char* key) { char pattern[32]; sprintf(pattern, "\"%s\":\"", key); char* start = strstr(json, pattern); if(!start) return NULL; start += strlen(pattern); char* end = strchr(start, '"'); if(!end) return NULL; *end = '\0'; return start; } -
cJSON库移植:
- 下载cJSON的compact版本(约3KB)
- 修改内存管理函数为STM32的malloc/free
- 注意堆空间至少需要4KB以上
5.2 典型天气数据结构
心知天气返回的JSON示例:
json复制{
"results": [{
"now": {
"text": "晴",
"temperature": "23",
"humidity": "40"
}
}]
}
对应的解析代码:
c复制char* weather = find_key(response, "text");
char* temp = find_key(response, "temperature");
char* humidity = find_key(response, "humidity");
6. 低功耗优化技巧
6.1 硬件级优化
-
在不需要通信时,将ESP8266切换到深度睡眠模式:
at复制AT+GSLP=300000 // 睡眠5分钟唤醒需要通过RST引脚触发
-
降低STM32主频到32MHz,仍能满足处理需求
-
关闭所有未使用的GPIO时钟
6.2 软件级优化
-
请求间隔优化:
- 晴天时每小时请求一次
- 雨天时每30分钟请求一次
- 根据天气变化动态调整
-
数据缓存策略:
c复制typedef struct { char weather[16]; int8_t temp; uint8_t humidity; uint32_t timestamp; } WeatherCache; -
错误重试机制:
- 第一次失败后延迟30秒重试
- 连续3次失败进入睡眠模式
- 记录错误日志到Flash
7. 常见问题排查指南
7.1 连接问题排查表
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| AT无响应 | 接线错误/波特率不匹配 | 检查TX/RX交叉连接,确认115200波特率 |
| WiFi连接失败 | 密码错误/信号弱 | 用手机测试信号强度,确认SSID大小写 |
| DNS解析失败 | 网络未连接 | 先执行PING测试:AT+PING="www.baidu.com" |
| API请求超时 | 服务器地址错误 | 先用电脑curl测试API可用性 |
7.2 内存问题预防
-
串口接收缓冲区溢出:
- 使用DMA接收模式
- 设置合理的超时时间
- 添加数据长度检查
-
内存泄漏检测:
c复制// 在内存分配/释放时记录 #ifdef DEBUG #define malloc(size) debug_malloc(size, __LINE__) #define free(ptr) debug_free(ptr, __LINE__) #endif -
栈空间监控:
- 在启动文件中调整Stack_Size EQU 0x400
- 使用FreeRTOS时监控任务栈使用量
8. 项目进阶方向
8.1 多城市支持
通过结构体数组管理多个地点:
c复制typedef struct {
char city[32];
WeatherData data;
} MultiCityWeather;
MultiCityWeather cities[5];
8.2 天气预测功能
扩展API请求参数:
c复制"GET /v3/weather/daily.json?key=YOUR_KEY&location=beijing&days=3"
8.3 本地数据显示
连接OLED屏幕显示信息:
c复制void show_weather(WeatherData* w) {
OLED_Printf(0,0,"%s %dC", w->weather, w->temp);
OLED_DrawHumidityBar(w->humidity);
}
这个项目最让我惊喜的是STM32F03C8T6的处理能力——即使解析复杂的JSON数据,CPU占用率也不到30%。实际部署时,建议在ESP8266的RX线上加10K上拉电阻,能显著提高通信稳定性。下篇我们将探讨如何接入MQTT协议实现双向通信。