单片机毕设选题新:面向新手的低门槛实战项目指南
毕业设计季一到,实验室里总会出现两种人:
一种抱着“高大上”选题,三天后板子冒烟;
另一种抱着“点亮LED”选题,答辩时被老师一句“还有别的创新吗?”问得哑口无言。
如果你刚好是第一次碰单片机,又想把毕设做得“能跑、能讲、能演示”,下面的笔记或许能救急。
1. 新手选题三大痛点,我踩过的坑都写在这儿
- 资料少:一搜“单片机毕设”,结果全是 10 年前的“智能浇花”“红外遥控小车”。原理图只有 JPG,代码只有 HEX,想看寄存器配置?抱歉,没有。
- 调试难:Proteus 里跑得好好的,实物一上电就“鬼闪灯”。没有 J-Link,只能拿串口一句一句打印,调一个中断花两天。
- 功能空洞:为了“创新”硬加蓝牙、Wi-Fi、摄像头,结果 4 月才调通通信,5 月还在移植协议栈,最后主功能——“测温”——都没时间标定。
一句话:选题阶段不把“最小可运行原型”(MRP)想明白,后面就是无底洞。
2. 8 位还是 32 位?一张表看懂 STC89C52 vs STM32F103
| 维度 | STC89C52(8 位) | STM32F103(32 位) |
|---|---|---|
| 主频 | 12 MHz(需外晶振) | 72 MHz(内部 PLL) |
| 片上资源 | 8K Flash、512B RAM、定时器×2 | 64K Flash、20K RAM、ADC×2、PWM×4、USB/CAN |
| 开发环境 | Keil C51、烧录需冷启动 | Keil MDK、ST-Link 一键下载 |
| 低功耗 | 掉电模式 0.1 μA | Stop 模式 20 μA,可 RTC 唤醒 |
| 价格 | 3 元/片 | 7 元/片(C8T6 小封装) |
| 毕设友好度 | 资料多,但性能天花板低;扩展 Wi-Fi/蓝牙需要外挂模块 | 资料新,库函数齐全,答辩演示动画流畅 |
结论:
只想“跑通流程”、老师要求不高→STC 够用;
想加“传感器融合”“低功耗”“实时显示”→直接上 STM32,省得后期换平台。
3. 选题示例:红外+蜂鸣器盲人避障手环
3.1 创意点
把三个 GP2Y0A21 红外测距传感器做成 120° 扇形分布,戴在手腕内侧。
距离 < 60 cm 就驱动蜂鸣器,越近越急促;同时震动马达给触觉反馈。
无无线、无屏幕,纯硬件实现,功耗 1.5 mA,两节 7 号电池能跑 2 周。
3.2 系统框图
3.3 最小可运行原型(MRP)代码
以下代码基于 STM32F103C8T6,HAL 库,注释直接写清“哪里改引脚”“哪里调阈值”,复制即可跑通。
/* main.c 盲人避障手环 MRP */ #include "stm32f1xx_hal.h" /* 宏:传感器阈值 60 cm 对应 ADC 值,实测校准 */ #define DIST_THRESHOLD 1600 /* 全局变量 */ volatile uint16_t adc_val[3]; // 0-左 1-中 2-右 volatile uint8_t alarm_flag = 0; // 1=需要报警 /* 函数声明 */ void SystemClock_Config(void); void GPIO_Init(void); void ADC1_Init(void); void TIM2_Init(void); // 产生 40 kHz 蜂鸣器 PWM void Error_Handler(void); int main(void) { HAL_Init(); SystemClock_Config(); GPIO_Init(); ADC1_Init(); TIM2_Init(); while (1) { /* 启动 ADC 扫描三通道 */ HAL_ADC_Start(&hadc1); for(int i=0;i<3;i++){ adc_val[i] = HAL_ADC_GetValue(&hadc1); if(adc_val[i] > DIST_THRESHOLD) { alarm_flag = 1; } } if(alarm_flag){ __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, 50); // 50% 占空比 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET); // 震动马达开 }else{ __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, 0); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET); } alarm_flag = 0; HAL_Delay(200); // 200 ms 刷新一次,兼顾功耗 } } /* GPIO 初始化:PA0/1/2 接 ADC,PA8 接马达,PA15 接蜂鸣器 */ void GPIO_Init(void) { __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitTypeDef g = {0}; g.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2; g.Mode = GPIO_MODE_ANALOG; HAL_GPIO_Init(GPIOA, &g); g.Pin = GPIO_PIN_8; g.Mode = GPIO_MODE_OUTPUT_PP; g.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOA, &g); } /* ADC1 三通道扫描,DMA 省略,保持代码最少 */ void ADC1_Init(void){ /* 略,详见工程模板 */ } /* TIM2 40 kHz PWM 驱动无源蜂鸣器 */ void TIM2_Init(void){ /* 略 */ } /* 低功耗:进入 Stop 模式,外部中断唤醒 */ void Enter_Stop(void) { HAL_SuspendTick(); HAL_PWR_EnterSTOPMode(PWR_LOWPOWERPO regulator_ON, PWR_STOPENTRY_WFI); SystemClock_Config(); // 唤醒后重配时钟 HAL_ResumeTick(); }3.4 扩展思路
- 把 ADC 阈值做成 EEPROM 可调校准,答辩现场能演示“调远/调近”。
- 加 MPU605的 I²C 接口,检测“手是否摆动”,静止 5 秒自动休眠。
- 用 3D 打印把传感器做成可折叠扇叶,收起来就是普通手环,外观分直接拉满。
4. 工程考量:电源管理与信号抗干扰
电源管理
- 红外传感器峰值 30 mA,蜂鸣器 15 mA,马达 60 mA。
- 采用 TPS79333 LDO,静态电流 1.2 μA,关断脚直接接 MCU,待机时切断传感器供电。
- 电池电压掉到 2.3 V 时,内部 ADC 测电池分压,低于 2.2 V 蜂鸣器长鸣“滴——”提示换电池。
信号抗干扰
- 红外 LED 采用 38 kHz 调制,接收端同步解调,滤除日光灯高频。
- 电机、马达的电源走线单独 0 Ω 电阻回流,防止地弹电压抬高 ADC 参考。
- 板层 2 层即可,但传感器区域铺地网格,减少 50 Hz 工频耦合。
5. 生产环境避坑指南
仿真 vs 实物
Proteus 里红外传感器输出是理想直线,实测 0-5 V 非线性,而且 40 cm 处有个“突变谷”,必须拉拟合曲线重新写阈值。烧录失败
STMtinny 的 BOOT0 引脚如果接 10 k 上拉,下载器识别不到。正确做法:BOOT0 接 100 k 上拉,再加一个按键下地,手动物理切换。引脚复用冲突
PA13/14 默认 SWD 调试口,别拿它去接马达。否则调试一次就得飞线,答辩前夜哭都来不及。中断优先级
蜂鸣器 PWM 用 TIM2,ADC 用 DMA,如果优先级一样,ADC 会抢总线,导致蜂鸣器“破音”。记住:ADC DMA 优先级设低,蜂鸣器 TIM 设高。
6. 结课不等于结束:把传感器融合玩起来
手环跑通后,你可以:
- 把红外换成 ToF 激光测距,做“楼梯落差检测”;
- 加 BMA223 加速度计,识别“上下楼梯”模式,蜂鸣器节奏随步伐变化;
- 用 HC-05蓝牙把距离数据推到手机,让手机朗读“前方 60 cm 有障碍”。
把代码推到 GitHub,README 里放原理图、BOM、3D 打印文件,就是一份能写在简历上的“嵌入式小作品”。
仓库模板已建好,空文件夹等你 PR:
https://github.com/yourname/StickWatch-MRP
别犹豫,fork 一下,下一个提交者可能就是你。