1. 项目概述
作为一名参加过多次蓝桥杯嵌入式竞赛的选手,我深知省赛真题对备赛同学的重要性。本文将详细解析第16届蓝桥杯嵌入式省赛真题,提供完整的工程源码和超详细代码级注释,帮助大家快速掌握竞赛要点。
这个项目基于STM32G431微控制器,实现了以下核心功能:
- 两路ADC模拟信号采集(R37/R38电位器)
- PWM波形输出(PA7引脚)
- LCD多界面显示(监控/统计/参数)
- 四按键交互(界面切换/参数调整)
- 频率异常检测与记录
2. 硬件环境搭建
2.1 开发板配置
竞赛使用的开发板通常为官方指定的STM32G431系列开发板,核心配置如下:
- 主控芯片:STM32G431CBU6(Cortex-M4内核,主频80MHz)
- ADC:12位分辨率,0-3.3V输入范围
- 定时器:TIM3用于PWM输出,TIM6触发ADC采样
- GPIO:PA15用于脉冲捕获,PB0-PB2/PA0用于按键输入
2.2 外设连接
根据题目要求,需要连接以下外设:
code复制R37电位器 -> ADC2_IN12 (模拟输入A)
R38电位器 -> ADC1_IN5 (模拟输入B)
PA7 -> PWM输出(连接示波器检测)
PA15 -> 外部脉冲输入(用于频率检测)
B1-B4 -> 四个功能按键
提示:实际接线时务必对照开发板原理图,确认引脚分配与题目要求一致。我曾遇到过因引脚接错导致整个下午调试无果的情况。
3. 软件架构设计
3.1 工程目录结构
完整的工程包含以下关键文件:
code复制├── Core
│ ├── Src
│ │ ├── main.c // 主程序
│ │ ├── fun.c // 功能函数
│ │ ├── key.c // 按键处理
│ │ └── handler.c // 中断处理
│ └── Inc
│ └── headfile.h // 全局定义
├── Drivers
└── STM32CubeMX配置文件
3.2 核心模块划分
- ADC采样模块:定时采集两路模拟信号
- PWM生成模块:根据输入信号调节频率/占空比
- LCD显示模块:三界面动态刷新
- 按键处理模块:支持短按/长按操作
- 异常检测模块:频率偏差超过1kHz触发报警
4. CubeMX关键配置
4.1 时钟树配置
系统时钟必须严格配置为80MHz,这是题目明确要求:
code复制HCLK = 80MHz
PCLK1 = 80MHz
PCLK2 = 80MHz
4.2 ADC配置
双ADC独立模式配置要点:
- ADC1:通道5,规则转换,TIM6触发
- ADC2:通道12,规则转换,TIM6触发
- 12位分辨率,右对齐
- 不开启连续转换模式
4.3 定时器配置
三个定时器各司其职:
- TIM3:PWM生成
- 通道2(PA7)
- PWM模式1
- 初始ARR=999
- TIM6:ADC触发
- 100ms周期(PSC=7999,ARR=999)
- 触发输出使能
- TIM2:输入捕获
- 通道1(PA15)
- 上升沿捕获
5. 核心代码解析
5.1 ADC采样与滤波处理
c复制// 获取ADC电压值(滑动平均滤波)
double get_vol(ADC_HandleTypeDef *hadc) {
static uint16_t adc_buf[10], index = 0;
uint32_t sum = 0;
// 采集10次进行滤波
for(int i=0; i<10; i++){
HAL_ADC_Start(hadc);
adc_buf[index] = HAL_ADC_GetValue(hadc);
index = (index + 1) % 10;
}
// 计算平均值
for(int i=0; i<10; i++) sum += adc_buf[i];
return 3.3 * sum / 10 / 4096;
}
经验:滤波次数不宜过多,否则会导致响应迟缓。经过实测,10次滑动平均既能平滑波形,又能保证实时性。
5.2 PWM参数计算
根据题目要求,PWM参数需按档位调节:
c复制// 计算占空比档位
VA = 3.3f / ((g_param_DR - 10)/g_param_DS + 1);
// 确定当前档位
for(g_param_n_duty = 0; g_param_n_duty < ((g_param_DR - 10)/g_param_DS + 1); g_param_n_duty++) {
if(R37_vol >= (g_param_n_duty * VA) && R37_vol < ((g_param_n_duty+1) * VA)) {
TIM3->CCR2 = 10 + (g_param_n_duty * g_param_DS);
}
}
5.3 频率异常检测
通过比较输出频率(CF)与参考频率(DF)的差值:
c复制int delta = abs(g_pa15_freq - pa7_freq);
if(delta > 1000) {
abnormal_flag = 1;
// 记录异常参数...
}
6. 关键调试技巧
6.1 PWM输出校准
常见问题及解决方法:
-
频率偏差大:
- 检查TIM3时钟源是否为80MHz
- 确认PSC和ARR计算正确
- 使用公式:频率 = 80MHz / (PSC+1) / (ARR+1)
-
占空比不准确:
- 确认CCR2值在10-100范围内
- 检查是否为PWM模式1
- 示波器测量实际输出
6.2 LCD显示优化
为避免屏幕闪烁,采用以下策略:
- 仅刷新变化部分,不重复绘制静态内容
- 使用
LCD_DisplayStringLine局部刷新 - 控制刷新率在10Hz左右(题目要求)
6.3 按键防抖处理
c复制// 按键扫描函数中的防抖逻辑
uint32_t current_tick = HAL_GetTick();
if(current_tick - last_tick < 20) return; // 20ms防抖
last_tick = current_tick;
7. 完整工程源码
工程已上传至百度网盘,包含:
- 完整STM32CubeMX工程
- 所有模块源代码
- 竞赛题目文档
- 测试用例
下载链接:
code复制https://pan.baidu.com/s/1qzvEbgAE6wTdRKC5uCU2ug
提取码:thsi
8. 参赛建议
根据多次参赛经验,总结以下要点:
-
时间分配:
- CubeMX配置:≤15分钟
- 模块开发:≤30分钟/模块
- 联调测试:≥30分钟
-
得分重点:
- ADC采样精度(无噪点)
- PWM参数准确性(频率偏差<3%)
- LCD显示规范(严格按题目格式)
-
常见失误:
- 未按要求命名提交文件
- 压缩包超过30MB
- 参数校验不完整
最后提醒:比赛时先通读所有题目要求,用笔标记得分点,确保不遗漏任何细节。我在第一次参赛时就因忽略"长按2秒重置"的要求而失分。
