找回密码
 立即注册
首页 业界区 安全 蓝桥杯嵌入式模板创建(STM32 CubeMx简单使用教程) ...

蓝桥杯嵌入式模板创建(STM32 CubeMx简单使用教程)

闾丘婉奕 2025-6-9 13:49:33
蓝桥杯嵌入式新板模板创建&简单经验分享

补充在最前:
以下原文是22年还未毕业时写的,那时经验不多,现在也由于工作使用的芯片不同已很久没有使用CubeMX了,因此文章可能有很多错漏之处,欢迎在评论区指出。
当时整理的资料,包含22年以前的赛题:
  1. 链接:https://pan.baidu.com/s/1I8QjNOwCHjpuWItRn0aYvQ?pwd=1234 提取码:1234 复制这段内容后打开百度网盘手机App,操作更方便哦
复制代码
备注在前: uint8_t 即 unsigned char(总忘
  1. typedef unsigned char uint8_t;
复制代码
本模板不保证完全正确
目录

目录

  • 蓝桥杯嵌入式新板模板创建&简单经验分享



      • 0. RCC 时钟树
      • 1. GPIO

        • 1.1 LED
        • 1.2 KEY

      • 2. LCD显示屏
      • 3. UART串口
      • 4. IIC



          • 4.1 EEPROM 24c02
          • 4.2 可编程电阻MCP4017 (扩展板)


      • 5. ADC
      • 6. TIM

        • 6.1 基本定时器 TIM6/7
        • 6.2 通用定时器 TIM2/3/4/15/16/17

          • 6.2.1 测量1路PWM(1路PWM输入)
          • 6.2.2 测量2路PWM频率和占空比
          • 6.2.3 方波输出
          • 6.2.4 输出2路PWM

        • 6.3 高级定时器 TIM1/8

      • 7. RTC 时钟
      • 经验分享



0. RCC 时钟树

1.png

时钟树如下图红框处设置,最后生成的是80MHZ就对了
2.png

输出配置1
3.png

输出配置2
4.png

1. GPIO

1.1 LED

cubemx配置
配置引脚 PC8~15 输出output - 8LED
5.png

输出
6.png

需要手打的部分
  1. //gpio.h
  2. void LED_Disp(unsigned char ucLed);
  3. // gpio.c
  4. //函数名: LED_Disp
  5. //函数功能: LD8-LED1对应ucLed的8个位
  6. //传入参数: unsigned char ucLed
  7. //返回值: 无
  8. void LED_Disp(unsigned char ucLed)
  9. {
  10.     //将所有的灯熄灭
  11.     HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12 , GPIO_PIN_SET);
  12.     // 说明:要使用GPIOC控制灯,需要使PD2引脚产生一个下降沿
  13.     HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
  14.     HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
  15.     //根据ucLed的数值点亮相应的灯
  16.     HAL_GPIO_WritePin(GPIOC, ucLed << 8, GPIO_PIN_RESET);
  17.     HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
  18.     HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
  19. }
复制代码
6.2.2 测量2路PWM频率和占空比

cubemx配置
这里和测量1路PWM的一样,TIM3的部分不再赘述
配置第二路 TIM2, 引脚为PA15
7.png

参数配置
8.png

同样需要开中断,修改中断优先级
9.png

需要手打的部分
  1. // gpio.h
  2. unsigned char Key_Scan(void);
  3. // gpio.c
  4. unsigned char Key_Scan(void)
  5. {
  6.     unsigned char unKey_Val = 0;
  7.     if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) == GPIO_PIN_RESET){
  8.         unKey_Val = 1;
  9.     }
  10.     if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == GPIO_PIN_RESET){
  11.         unKey_Val = 2;
  12.     }
  13.     if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2) == GPIO_PIN_RESET){
  14.         unKey_Val = 3;
  15.     }
  16.     if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET){
  17.         unKey_Val = 4;    //PA0对应按键B4
  18.     }
  19.     return unKey_Val;
  20. }
  21. // main.c
  22. // 减速变量
  23. __IO uint32_t uwTick_KEY = 0;
  24. // 按键扫描专用变量
  25. unsigned char Key_Val, Key_Up, Key_Down, Key_Old;
  26. void Key_Proc(void)
  27. {
  28.     // 减速
  29.     if((uwTick-uwTick_KEY)<100) return ;
  30.     uwTick_KEY = uwTick;
  31.     Key_Val = Key_Scan();
  32.     Key_Down  = Key_Val & (Key_Old ^ Key_Val);
  33.     Key_Up = ~Key_Val & (Key_Old ^ Key_Val);
  34.     Key_Old = Key_Val;
  35.     if (Key_Down == 1){
  36.         LED_Disp(0x01);
  37.     }
  38.     if (Key_Down == 2){
  39.         LED_Disp(0x02);
  40.     }
  41.     if (Key_Down == 3){
  42.         LED_Disp(0x04);
  43.     }
  44.     if (Key_Down == 4){
  45.         LED_Disp(0x08);
  46.     }
  47. }
复制代码
6.2.3 方波输出

可以使用一个定时器的两个通道输出两个不同频率的方波
cubemx配置
此处使用TIM4的通道1和通道2,引脚对应PA11、PA12
10.png

参数配置
11.png

需要使能中断,修改中断优先级
12.png

需要手打的部分
  1. // main.c 头文件别多加fonts
  2. #include "lcd.h"
  3. // 减速变量
  4. __IO uint32_t uwTick_LCD = 0;
  5. int main(){
  6.     LCD_Init();
  7.     LCD_Clear(White);
  8.     LCD_SetTextColor(Black);
  9.     LCD_SetBackColor(White);
  10.     while(1){
  11.         LCD_Proc();
  12.     }
  13. }
  14. void LCD_Proc(void){
  15.     // 减速
  16.     if((uwTick - uwTick_LCD) < 100) return ;
  17.     uwTick_LCD  = uwTick;
  18.     sprintf((char *)str, "Hello, world!");
  19.     LCD_DisplayStringLine(Line0, str);
  20. }
复制代码
6.2.4 输出2路PWM

cubemx配置
第一路PWM输出, 定时器TIM17通道1, 引脚PA7
13.png

参数配置
14.png

无需使能中断
第二路PWM输出配置, TIM16通道1, 引脚PA6。配置和第一路一致。
15.png

参数配置
16.png

同样无需使能中断
需要手打的部分
  1. //main.c
  2. __IO uint32_t uwTick_UART1;
  3. int counter = 0;
  4. char str[40];
  5. u8 rx_buffer;
  6. // uart.c
  7. UART_HandleTypeDef huart1;
  8. // uart.h
  9. #include "main.h"
  10. extern UART_HandleTypeDef huart1;
  11. void UART1_Init(void);
复制代码
其他
  1. // 串口发数据(开发板发送)
  2. void UART1_Proc()
  3. {
  4.     //减速
  5.     if(uwTick-uwTick_UART1 < 500)    return;
  6.     uwTick_UART1 = uwTick;
  7.     sprintf(str, "%04d : hello\n", counter);
  8.     HAL_UART_Transmit(&huart1, (unsigned char *)str, strlen(str), 50);
  9.     if(++counter == 10000)    counter = 0;
  10. }
复制代码
6.3 高级定时器 TIM1/8

用通用的就够了,一般用不上高级的
7. RTC 时钟

cubemx配置
使能RTC时钟和日历
17.png

配置时钟树 时钟来自外部晶振(可以看到分频后为750kHZ, 之后还要分频成1HZ)
18.png

配置分频
750k/125/6000 = 1HZ
时分秒的初始值可以在此设置
19.png

日期也可初始化(年的数值范围是0-99)
20.png

RTC模块的使用(需手打代码)
  1. // stm32g4xx_it.c     
  2. extern UART_HandleTypeDef huart1;
  3. void USART1_IRQHandler(void)
  4. {
  5.   HAL_UART_IRQHandler(&huart1);
  6. }
  7. // mian.c
  8. int main(){
  9.     // ...初始化等等
  10.     // 开中断
  11.     HAL_UART_Receive_IT(&huart1, &rx_buffer, 1);
  12.     while(1){
  13.         // ...
  14.     }
  15. }
  16. // 串口接收中断回调函数 【重要 需要记住名称】
  17. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
  18. {
  19.     // 功能 ...
  20.     HAL_UART_Receive_IT(&huart1, &rx_buffer, 1);    // 结尾需要重新开中断
  21. }
复制代码
经验分享

关于是否要买教程这件事
个人觉得,如果之前有stm32开发基础且备赛时间比较多的人可以不买教程完全自学,主要学cubemx的使用,当然买教程也是可以的,买教程相当于是花钱省了自己找资料的时间。
我备赛是买了蚂蚁工厂的教程,只跟了基础部分,模板创建部分快速的略过了。因为今年国赛比较特殊,没考扩展板,所以后面扩展板创建和国赛模板创建的部分我都没看。如果跟蚂蚁的教程走的话,不建议完全参考他使用移植的方法,参考思路就好,直接用cubemx生成的工程就可以了,代码写在begin和end之间就不会被覆盖。
如果要用移植的方法,这里有一些函数比如MspInit之类的,实际也要一起移植(移植真的又慢又麻烦,没必要)
比赛相关
省赛会考的内容就是以上模板创建提到的那些,屏幕+LED+按键这仨是必考,这一块的模板创建必须烂熟于心(其实所有内容都要记下来)。其他要注意的就是PWM输出这一部分,这是省赛最常考的,要熟悉PWM输出的频率和占空比调节,练习的时候没有示波器的人可以网购个逻辑分析仪,不用太贵的能用就行,我用的NanoDLA(30元左右),当然能用示波器的还是用示波器,比逻辑分析仪舒服多了。其他的比如I2C和串口就是死记,用法都大差不差,建议有时间的把往年省赛题都做一遍,多练练模板。
今年国赛没用扩展板,理论上考的内容也是省赛的那些,综合性和难度要强一节,基本上述模板的所有模块都考到了,因为我也没拿好成绩,所以就不多说了。
另外客观题(15分 程序85)我基本都是蒙的所以也不好给出建议。客观考的范围很宽泛,数电、模电、开发板相关的等等,主要靠自己积累,开发板相关的赛时可以看官方发的资料进行查找,争国一的还是最好多做准备。
建议比赛前一天晚上保证良好的睡眠和比较好的精神状态,这一点还挺重要的,好的状态对编程思路有很大的帮助。我省赛和国赛时完全是两个状态,我因为国赛撞了期末就没准备蓝桥杯,当时又焦虑又疲惫,比完还以为白给了,最后混到了国三。如果我以我国赛的状态去比省赛肯定就白给了。
其他要注意的就是如果跟我一样是线上比赛的,比赛要保证网络畅通,前置摄像头对准自己,这样自己偶尔回头能看到自己的手机屏幕,就能知道自己有没有掉线了,偶尔卡顿监考老师不会说什么。比赛要用Chrome浏览器的ACMcoder插件,安装好赛前几天需要上线测试,官网下载的准考证上会有相关注意事项,跟着官方的要求做就行。
调试的时候发现自己的代码写好了屏幕没反应不要着急,先按复位键看看,经常有人忘记设置Keil工程的“Reset and Run”配置项,以为自己代码出问题。实际比赛中是一定要配置好Keil工程的这一项的。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册