前言:
在讲解十三届的题目之前,强烈建议去看我上一篇《蓝桥杯嵌入式总结和考前冲刺》,涵盖了各个模块的初始化以及基础配置,相关的思路则在我这一篇,如有某个模块不熟悉,请前往查看。
真题题目:
CubeMX初始化配置:
在我上一篇博客中已经将蓝桥杯需要用到的每个模块以及如何初始化详细的写了出来,如果想知道哪个模块如果使用CubeMX初始化,请跳转到我上一篇博客:http://t.csdnimg.cn/TvogK
LCD模块:
在比赛当中,首先为了保证看的到明显的现象,首先操作的应该是LCD。
LCD_Init();
LCD_Clear(Black);
LCD_SetTextColor(White);
LCD_SetBackColor(Black);
这里初始化LCD,以及设置背景色和文本色。
void lcd_disp(void)
{
if(view==0)//密码输入界面
{
char text[20];
sprintf(text," PSD");
LCD_DisplayStringLine(Line1,(uint8_t *)text);
sprintf(text," B1:%c ",B1);
LCD_DisplayStringLine(Line3,(uint8_t *)text);
sprintf(text," B2:%c ",B2);
LCD_DisplayStringLine(Line4,(uint8_t *)text);
sprintf(text," B3:%c ",B3);
LCD_DisplayStringLine(Line5,(uint8_t *)text);
sprintf(text,"duty_text:%2d%%",duty_text);
LCD_DisplayStringLine(Line8,(uint8_t *)text);
sprintf(text,"f_text:%5dHz",f_text);
LCD_DisplayStringLine(Line9,(uint8_t *)text);
}
if(view==1)//状态输出界面
{
char text[20];
sprintf(text," STA");
LCD_DisplayStringLine(Line1,(uint8_t *)text);
sprintf(text," F:%4dHz",F);
LCD_DisplayStringLine(Line3,(uint8_t *)text);
sprintf(text," D:%2d%%",duty);
LCD_DisplayStringLine(Line4,(uint8_t *)text);
sprintf(text,"duty_text:%2d%%",duty_text);
LCD_DisplayStringLine(Line8,(uint8_t *)text);
sprintf(text,"f_text:%5dHz",f_text);
LCD_DisplayStringLine(Line9,(uint8_t *)text);
}
}
代码解析:
1、uint8_t view;//切换lcd界面,通过按键改变view值实现各个界面的切换。
2、剩下的就是老生常谈的模板了。
Key(按键模块):
这里按键的难点不单单只是识别出哪个按键按下了,这里需要实现每个按键的功能,由于我上过博客已经详细讲解了按键基本模块如何搭建,这里就直接进入实现功能模式。
void key_scan(void)
{
if(key[0].single_sta==1)
{
if(view==0)
{
if(B1=='@')
{
B1='0';
}
else
{
B1++;
if(B1>'9')
{
B1='0';
}
}
}
key[0].single_sta=0;
}
if(key[1].single_sta==1)
{
if(view==0)
{
if(B2=='@')
{
B2='0';
}
else
{
B2++;
if(B2>'9')
{
B2='0';
}
}
}
key[1].single_sta=0;
}
if(key[2].single_sta==1)
{
if(view==0)
{
if(B3=='@')
{
B3='0';
}
else
{
B3++;
if(B3>'9')
{
B3='0';
}
}
}
key[2].single_sta=0;
}
if(key[3].single_sta==1)
{
if(view==0)
{
if(B1==password[0]&&B2==password[1]&&B3==password[2])
{
LCD_Clear(Black);
B1='@';
B2='@';
B3='@';
view=1;
F=2000;
duty=10;
__HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_2,duty);
__HAL_TIM_SET_PRESCALER(&htim2,400);
led_mark=led_mark|0x01;
password_error_mark=0;
}
else
{
B1='@';
B2='@';
B3='@';
password_error_mark++;
}
}
key[3].single_sta=0;
}
}
代码解析:
1、按键1、2、3就不用多说了,按一下就加1,超过9就给它跳回去0。
2、要记得,要在view==0的条件成立下,才进行参数的改变。
3、我们设置了passwor的数组,来存放密码,当三个设置的密码与我们输入密码相等的时候,我们就让view=1,去到另一个界面,并且改变频率以及占空比来实现题目的要求。、
4、注意按键3,里面有几个标志位,led_mark是led全局变量,这里改变来影响led1,password_error_mark是密码输入错误次数的标志,由于这里密码正确,故将他清0。
脉冲输出功能:
pwm输出可调频率和占空比的基本模板在我上一篇博客里面,想知道具体配置过程请跳转到http://t.csdnimg.cn/TvogK。
if(B1==password[0]&&B2==password[1]&&B3==password[2])
{
LCD_Clear(Black);
B1='@';
B2='@';
B3='@';
view=1;
F=2000;
duty=10;
__HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_2,duty);
__HAL_TIM_SET_PRESCALER(&htim2,400);
}
这个是当密码输入正确时,PA1输出1KHZ的方波信号(占空比为50%)
if(view==1)
{
time_out++;
if(time_out>500)
{
time_out=0;
view=0;
duty=50;
__HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_2,duty);
F=1000;
__HAL_TIM_SET_PRESCALER(&htim2,800);
//LCD_Clear(Black);
led_mark=led_mark&0xfe;
}
}
这里是在定时器中断里面,当密码输入正确之后,在5s内,PA1输出2KHz 10%占空比的脉冲信号。注意:这个定时器中断与按键复用在一起,也可以再开一个定时器,我这里定时器是每10ms进来一次。
串口通信功能:
void uart_handle(void)
{
if(pointer==7)
{
if(receive_dat[3]=='-')
{
sscanf(receive_dat,"%3s-%3s",receive_temp1,receive_temp2);
if(receive_temp1[0]==password[0]&&receive_temp1[1]==password[1]&&receive_temp1[2]==password[2])
{
password[0]=receive_temp2[0];
password[1]=receive_temp2[1];
password[2]=receive_temp2[2];
}
}
}
pointer=0;
memset(receive_dat,0,7);
}
说白了,就是接收到题目要求的七个字符,且前三个字符等于我原来的密码,这样子,密码就改变完成,还是很模板和公式化的。
LED模块:
led的显示,说白了,就是根据目前运行的状态来不断改变全局变量led_mark,然后在主循环中不断的调用led_disp()函数,实现led所要求的显示功能。
if(password_error_mark==3)
{
password_time_out++;
if(password_time_out%10==0)
{
led_change++;
if(led_change%2==0)
{
led_mark=led_mark|0x02;
}
else
{
led_mark=led_mark&0xfd;
}
}
if(password_time_out>500)
{
password_error_mark=0;
password_time_out=0;
led_change=0;
led_mark=led_mark&0xfd;
}
}
当密码输入正确的时候,led1连续点亮5s。注意:这里的函数在定时器中断回调函数里面。定时器中断为10ms进入一次。
当密码输入错误的时候,led2每0.1s闪烁一次,5s之后熄灭。
结束语:
这就是十三届全部讲解。