对于这次已经是第二次参加蓝桥杯了,对于一些经验想在这里分享给一些参加蓝桥杯嵌入式的学弟。对于每次蓝桥杯虽然是有点水,但是可以打下STM32的基础,对于一些外设都可以进行尝试,为后面的电赛打下基础。对于蓝桥杯官方还是推荐使用CubeMax这个软件,但是我个人并不是非常推荐,即使当时我也是非常的喜欢这个软件,后面就不太喜欢了。因为有个学弟发现生成的代码非常不匹配,对于这个问题在比赛假如碰见是一个非常大的隐患。
那应该如何不使用CubeMax软件就能进行一个工程的搭建?比赛官方还是提供了STM32的官方资料和数据手册,在没有CubeMax的那个时代,我们都是使用这个进行代码参考和工程搭建的。
所以在这个幸运的时代,我们都是幸运的人。
对于打开第十三届蓝桥杯嵌入式的题目,我们可以看见一些基本要求和备注。这些我们都是要仔细的阅读。对于我们有一个优质选手就是因为准考证号没有弄对,就错失了省奖。也是一个非常严重的问题。
从硬件框图就可以看见,我们要做的就是LCD显示,串口通信,控制信号的输出,按键输入,LED显示。还是比较简单的。
首先我们可以先搞好LCD显示,LCD显示正确就可以打入省三的样子,因为这是可以人眼看见的一个现象,非常重要,与人的交互功能比较差的话,我都会气的砸板子。
对于如何控制两个界面进行翻转的话,我们可以定义一个标志位,可以是Bool类型。
if(!B4){
uint8_t buf[20]={0};
sprintf((char*)buf," PSD ");
LCD_DisplayStringLine(Line1,buf);
sprintf((char*)buf," B1:%c ",B1);
LCD_DisplayStringLine(Line3,buf);
sprintf((char*)buf," B2:%c ",B2);
LCD_DisplayStringLine(Line4,buf);
sprintf((char*)buf," B3:%c ",B3);
LCD_DisplayStringLine(Line5,buf);
}else if(B4){
uint8_t buf[20]={0};
sprintf((char*)buf," STA ");
LCD_DisplayStringLine(Line1,buf);
sprintf((char*)buf," F:%dHz ",2000);
LCD_DisplayStringLine(Line3,buf);
sprintf((char*)buf," D:%d%% ",10);
LCD_DisplayStringLine(Line4,buf);
sprintf((char*)buf," ");
LCD_DisplayStringLine(Line5,buf);
}
LCD界面搞好的话就搞按键功能,我们要干什么呢?
首先它是一个非连续按键的功能,我们只需要读取他的引脚电平,或者可以开外部中断,对于这种简单功能我一般会直接选择简单的轮询系统,能简单就简单,后面我也会继续保持这种风格。
switch(KEY_Scan(0)){
case KEY1_PRES:
if(B1=='@'){
B1=48;
}else if(B1==57){
B1=48;
}else{
B1++;
}
break;
case KEY2_PRES:
if(B2=='@'){
B2=48;
}else if(B2==57){
B2=48;
}else{
B2++;
}
break;
case KEY3_PRES:
if(B3=='@'){
B3=48;
}else if(B3==57){
B3=48;
}else{
B3++;
}
break;
case KEY4_PRES:
if(B1==B1_S&&B2==B2_S&&B3==B3_S){
B4=1;
error=0;
B1='@';
B2='@';
B3='@';
TIM2->PSC=(42-1);
TIM2->CCR2=200-1;
LED(0xfeff);
HAL_TIM_Base_Start_IT(&htim16);
}else{
B1='@';
B2='@';
B3='@';
error++;
if(error>=3){
HAL_TIM_Base_Start_IT(&htim17);
}
}
break;
}
}
脉冲输出功能也是非常简单,我们只要简单配置一下PWM波就可以了,想要改一下频率和占空比直接使用PSK 、CCR(大概名字叫这个,具体情况自己看一下数据手册)这两个寄存器就可以了。所以还是没有难度。
对于串口通信也是简单配置就行了,我们可以通过一位一位读,也可以牺牲一个位的时间设置空闲中断,个人感觉空闲中断还是比较好用的,因为题目的要求是没有换行和回车的,所以无法判断是否接收完成。而且不用频繁进入中断。
对于LED灯指示功能需要注意的是LED使用的GPIO与LCD的GPIO有冲突,我们需要在进行锁存的时候保存LCD的每个GPIO状态。
void LED(uint16_t port)
{
uint16_t port_value;
port_value = GPIOC ->IDR;
GPIOD ->ODR =((GPIOD->IDR)|0x0004);
GPIOC ->ODR =(port);
GPIOD ->ODR =((GPIOD->IDR)&0xfffb);
GPIOC->ODR = port_value;
}
我个人是使用这种方式进行点灯的,感觉还是比较好的,可能有更好的解决办法,但是只不过我的时间不多,草草解决吧。
对于有5秒和0.秒的的周期我可以使用定时器中断(开两个基本定时器),配置一个5秒中断一次和0.1秒中断一次的定时器,解决起来还是非常的轻松。
总体来说还是非常的简单,简单的配置,简单的状态。
对于STM32G431RBT6的配置中有这么几段话,我感觉可以理解在TIM6和TIM7的中断下面运行错误的中断,因为根本无法进入中断,既然你都说了,我就只能默认你的这两个中断开不起。