用CH32X035做个PD/QC诱骗器,还能当电压表?手把手教你复刻Spectator
2026/6/11 5:04:51
基于STM32毕业设计题目的新手入门实战指南:从选题到固件开发的完整路径
摘要:很多电子/自动化专业的同学第一次做 STM32 毕设时,都会卡在“点灯”和“跑通串口”之间——代码能编译,板子没反应,仿真器连不上,网上例程又各说各话。本文把我自己踩过的坑、帮学弟调过的板子、还有实验室老师反复提醒的细节,打包成一份“新手通关地图”。读完你可以直接上手一个“DHT11 温湿度采集 + UART 上传”的毕设原型,并知道以后往哪个方向继续加功能。
一句话总结:先让板子“喘口气”——时钟、电源、SWD 三线正常,再谈功能。
| 维度 | CubeMX+HAL | 标准外设库 (SPL) | LL 库 |
|---|---|---|---|
| 上手速度 | 最快,图形化配引脚 | 中等,寄存器封装 | 偏慢,接近寄存器 |
| 代码体积 | 最大,易超 64 KB | 中等 | 最小,可 < 32 KB |
| 移植性 | 跨 STM家族最好 | F1 专用,已停止维护 | 与 HAL 并存,需手动 |
| 实时性 | 一般,嵌套抽象层 | 较好 | 最好,可单周期操作 |
| 社区资料 | 最新,官方主推 | 老旧,但例程极多 | 少,需要看手册 |
毕设场景建议:
- 想快速出原型,用 CubeMX+HAL;
- 若导师要求“裸机”或 Flash <64 KB,可 LL 库手写;
- SPL 不建议新课题再用,2025 年后基本找不到官方例程更新。
STM32F103C8TxHSE = 8 MHz,PLL 倍频到72 MHzUSART1全局中断,波特率 115200,长度 8N1PA0为GPIO_Output驱动 DHT11,重命名为DHT11_PINSWD调试口,保持SysTick1 ms 中断STM32CubeIDE(自带 Makefile,后期 CI 方便)/* main.c 节选 */ #include "dht11.h" #include "uart_app.h" static void SystemClock_Config(void); static void MX_GPIO_Init(void); int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_USART1_UART_Init(); DHT11_t sensor = {.port = GPIOA, .pin = GPIO_PIN_0}; char txbuf[64]; while (1) { if (DHT11_Read(&sensor) == DHT11_OK) { int len = snprintf(txbuf, sizeof(txbuf), "{\"T\":%d,\"H\":%d}\r\n", sensor.temp, sensor.rh); UART_Send(txbuf, len); } HAL_Delay(2000); /* 2 s 采样,留足 1 s 稳定 */ } }/* dht11.c 核心时序 */ #define DHT11_DELAY_US(x) delay_us(x) /* 用 TIM2 做 us 定时 */ DHT11_Status DHT11_Read(DHT11_t* d) { uint8_t bits[5] = {0}; /* 主机拉低 18 ms > 启动信号 */ HAL_GPIO_WritePin(d->port, d->pin, GPIO_PIN_RESET); HAL_Delay(18); HAL_GPIO_WritePin(d->port, d->pin, GPIO_PIN_SET); DHT11_DELAY_US(30); /* 切换到输入模式,等待从机响应 80 us 低电平 */ GPIO_InputMode(d->port, d->pin); if (!WAIT_LOW(80)) return DHT11_TIMEOUT; if (!WAIT_HIGH(80)) return DHT11_TIMEOUT; /* 读 40 bit 数据 */ for (int i = 0; i < 40; i++) { if (!WAIT_LOW(50)) return DHT11_TIMEOUT; uint32_t h_time = 0; while (HAL_GPIO_ReadPin(d->port, d->pin) == GPIO_PIN_SET) { h_time++; DHT11_DELAY_US(1); if (h_time > 100) return DHT11_TIMEOUT; } bits[i / 8] |= (h_time > 40) ? (1 << (7 - i % 8)) : 0; } /* 校验 */ if (bits[4] != (bits[0] + bits[1] + bits[2] + bits[3])) return DHT11_CRC_ERR; d->rh = bits[0]; d->temp = bits[2]; return DHT11_OK; }要点注释:
- 单总线对时序敏感,关中断读数最稳;
- 用
snprintf拼 JSON,方便后期直接接 Python 上位机;- 把底层时序与业务逻辑分层,后面换传感器只改
dht11.c。
SysTick关掉,用STOP模式 + RTC 唤醒,电流从 12 mA 降到 120 μA。-Og优化后 38 KB,若导师限定 64 KB 以内,可开-Os并关掉没用到的HAL_XXX_MODULE。结尾碎碎念:
第一次做 STM32 毕设,别急着堆功能,先让板子“稳定呼吸”——时钟对、串口通、调试口随时能打断点。
今晚就找个最小系统,把上面的 DHT11 例程跑一遍,明天你会突然发现:选题报告里那些“高大上”功能,其实就是在今晚的代码里多写几个if和多接几根线。祝你调试顺利,早点睡觉,毕业不熬夜!