蓝桥杯嵌入式模板创建(STM32 CubeMx简单使用教程)
蓝桥杯嵌入式新板模板创建&简单经验分享补充在最前:
以下原文是22年还未毕业时写的,那时经验不多,现在也由于工作使用的芯片不同已很久没有使用CubeMX了,因此文章可能有很多错漏之处,欢迎在评论区指出。
当时整理的资料,包含22年以前的赛题:
链接:https://pan.baidu.com/s/1I8QjNOwCHjpuWItRn0aYvQ?pwd=1234 提取码:1234 复制这段内容后打开百度网盘手机App,操作更方便哦备注在前: uint8_t 即 unsigned char(总忘
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 时钟树
时钟树如下图红框处设置,最后生成的是80MHZ就对了
输出配置1
输出配置2
1. GPIO
1.1 LED
cubemx配置
配置引脚 PC8~15 输出output - 8LED
输出
需要手打的部分
//gpio.h
void LED_Disp(unsigned char ucLed);
// gpio.c
//函数名: LED_Disp
//函数功能: LD8-LED1对应ucLed的8个位
//传入参数: unsigned char ucLed
//返回值: 无
void LED_Disp(unsigned char ucLed)
{
//将所有的灯熄灭
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);
// 说明:要使用GPIOC控制灯,需要使PD2引脚产生一个下降沿
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
//根据ucLed的数值点亮相应的灯
HAL_GPIO_WritePin(GPIOC, ucLed << 8, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
}6.2.2 测量2路PWM频率和占空比
cubemx配置
这里和测量1路PWM的一样,TIM3的部分不再赘述
配置第二路 TIM2, 引脚为PA15
参数配置
同样需要开中断,修改中断优先级
需要手打的部分
// gpio.h
unsigned char Key_Scan(void);
// gpio.c
unsigned char Key_Scan(void)
{
unsigned char unKey_Val = 0;
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) == GPIO_PIN_RESET){
unKey_Val = 1;
}
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == GPIO_PIN_RESET){
unKey_Val = 2;
}
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2) == GPIO_PIN_RESET){
unKey_Val = 3;
}
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET){
unKey_Val = 4; //PA0对应按键B4
}
return unKey_Val;
}
// main.c
// 减速变量
__IO uint32_t uwTick_KEY = 0;
// 按键扫描专用变量
unsigned char Key_Val, Key_Up, Key_Down, Key_Old;
void Key_Proc(void)
{
// 减速
if((uwTick-uwTick_KEY)<100) return ;
uwTick_KEY = uwTick;
Key_Val = Key_Scan();
Key_Down= Key_Val & (Key_Old ^ Key_Val);
Key_Up = ~Key_Val & (Key_Old ^ Key_Val);
Key_Old = Key_Val;
if (Key_Down == 1){
LED_Disp(0x01);
}
if (Key_Down == 2){
LED_Disp(0x02);
}
if (Key_Down == 3){
LED_Disp(0x04);
}
if (Key_Down == 4){
LED_Disp(0x08);
}
}6.2.3 方波输出
可以使用一个定时器的两个通道输出两个不同频率的方波
cubemx配置
此处使用TIM4的通道1和通道2,引脚对应PA11、PA12
参数配置
需要使能中断,修改中断优先级
需要手打的部分
// main.c 头文件别多加fonts
#include "lcd.h"
// 减速变量
__IO uint32_t uwTick_LCD = 0;
int main(){
LCD_Init();
LCD_Clear(White);
LCD_SetTextColor(Black);
LCD_SetBackColor(White);
while(1){
LCD_Proc();
}
}
void LCD_Proc(void){
// 减速
if((uwTick - uwTick_LCD) < 100) return ;
uwTick_LCD= uwTick;
sprintf((char *)str, "Hello, world!");
LCD_DisplayStringLine(Line0, str);
}6.2.4 输出2路PWM
cubemx配置
第一路PWM输出, 定时器TIM17通道1, 引脚PA7
参数配置
无需使能中断
第二路PWM输出配置, TIM16通道1, 引脚PA6。配置和第一路一致。
参数配置
同样无需使能中断
需要手打的部分
//main.c
__IO uint32_t uwTick_UART1;
int counter = 0;
char str;
u8 rx_buffer;
// uart.c
UART_HandleTypeDef huart1;
// uart.h
#include "main.h"
extern UART_HandleTypeDef huart1;
void UART1_Init(void);其他
// 串口发数据(开发板发送)
void UART1_Proc()
{
//减速
if(uwTick-uwTick_UART1 < 500) return;
uwTick_UART1 = uwTick;
sprintf(str, "%04d : hello\n", counter);
HAL_UART_Transmit(&huart1, (unsigned char *)str, strlen(str), 50);
if(++counter == 10000) counter = 0;
}6.3 高级定时器 TIM1/8
用通用的就够了,一般用不上高级的
7. RTC 时钟
cubemx配置
使能RTC时钟和日历
配置时钟树 时钟来自外部晶振(可以看到分频后为750kHZ, 之后还要分频成1HZ)
配置分频
750k/125/6000 = 1HZ
时分秒的初始值可以在此设置
日期也可初始化(年的数值范围是0-99)
RTC模块的使用(需手打代码)
// stm32g4xx_it.c
extern UART_HandleTypeDef huart1;
void USART1_IRQHandler(void)
{
HAL_UART_IRQHandler(&huart1);
}
// mian.c
int main(){
// ...初始化等等
// 开中断
HAL_UART_Receive_IT(&huart1, &rx_buffer, 1);
while(1){
// ...
}
}
// 串口接收中断回调函数 【重要 需要记住名称】
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
// 功能 ...
HAL_UART_Receive_IT(&huart1, &rx_buffer, 1); // 结尾需要重新开中断
}经验分享
关于是否要买教程这件事
个人觉得,如果之前有stm32开发基础且备赛时间比较多的人可以不买教程完全自学,主要学cubemx的使用,当然买教程也是可以的,买教程相当于是花钱省了自己找资料的时间。
我备赛是买了蚂蚁工厂的教程,只跟了基础部分,模板创建部分快速的略过了。因为今年国赛比较特殊,没考扩展板,所以后面扩展板创建和国赛模板创建的部分我都没看。如果跟蚂蚁的教程走的话,不建议完全参考他使用移植的方法,参考思路就好,直接用cubemx生成的工程就可以了,代码写在begin和end之间就不会被覆盖。
如果要用移植的方法,这里有一些函数比如MspInit之类的,实际也要一起移植(移植真的又慢又麻烦,没必要)
比赛相关
省赛会考的内容就是以上模板创建提到的那些,屏幕+LED+按键这仨是必考,这一块的模板创建必须烂熟于心(其实所有内容都要记下来)。其他要注意的就是PWM输出这一部分,这是省赛最常考的,要熟悉PWM输出的频率和占空比调节,练习的时候没有示波器的人可以网购个逻辑分析仪,不用太贵的能用就行,我用的NanoDLA(30元左右),当然能用示波器的还是用示波器,比逻辑分析仪舒服多了。其他的比如I2C和串口就是死记,用法都大差不差,建议有时间的把往年省赛题都做一遍,多练练模板。
今年国赛没用扩展板,理论上考的内容也是省赛的那些,综合性和难度要强一节,基本上述模板的所有模块都考到了,因为我也没拿好成绩,所以就不多说了。
另外客观题(15分 程序85)我基本都是蒙的所以也不好给出建议。客观考的范围很宽泛,数电、模电、开发板相关的等等,主要靠自己积累,开发板相关的赛时可以看官方发的资料进行查找,争国一的还是最好多做准备。
建议比赛前一天晚上保证良好的睡眠和比较好的精神状态,这一点还挺重要的,好的状态对编程思路有很大的帮助。我省赛和国赛时完全是两个状态,我因为国赛撞了期末就没准备蓝桥杯,当时又焦虑又疲惫,比完还以为白给了,最后混到了国三。如果我以我国赛的状态去比省赛肯定就白给了。
其他要注意的就是如果跟我一样是线上比赛的,比赛要保证网络畅通,前置摄像头对准自己,这样自己偶尔回头能看到自己的手机屏幕,就能知道自己有没有掉线了,偶尔卡顿监考老师不会说什么。比赛要用Chrome浏览器的ACMcoder插件,安装好赛前几天需要上线测试,官网下载的准考证上会有相关注意事项,跟着官方的要求做就行。
调试的时候发现自己的代码写好了屏幕没反应不要着急,先按复位键看看,经常有人忘记设置Keil工程的“Reset and Run”配置项,以为自己代码出问题。实际比赛中是一定要配置好Keil工程的这一项的。
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页:
[1]