相关说明:
开发板:CT117E-M4(STM32G431RB 蓝桥杯嵌入式比赛板)
开发环境: CubeMX+Keil5
在历年真题中,几乎每题都会遇到LED与LCD显示冲突的情况,虽然第十二届省赛没有涉及这一矛盾,但第十三届考的概率仍然很大。
心得分享:
上面是官方提供控制LED的原理图。控制LED状态用到的芯片是SN74HC573ADWR,我们可以控制PC8~ PC15引脚输出高低电平到D端。当LE脚(PD2)输入为高电平时,D端输入的电平传输到Q端输出;当LE脚输入为低电平时,Q端输出被锁存。那点亮LED1的步骤就是PC8输出低电平,PD2输出高电平再输出低电平,这样LED1就可以被点亮了。
这张是LCD的原理图,从两图中可以看出控制LED和LCD的引脚都有PC8 ~ PC15,这八个引脚对应的正好就是LED1 ~ LED8。
那么当需要实时更新数据就会出现D端数据被修改的情况,LED1就无法正常闪烁。比如LED1要以0.5s的频率闪烁(若使用Toggle函数实现),当前状态为灭,那下一状态应该为亮,这时LCD更新显示,PC8引脚电平就无法确定了,那Toggle后的结果自然也无法确定,这时LED1便不能以固定频率进行闪烁。
从以上三图+第十二届题目(无需解决冲突)综合分析,似乎官方对于解决冲突的考察力度有所降低,从第八届(实时时钟显示+流水灯)到第十届(实时时钟显示+LED闪烁)到第十届(电压检测+LED闪烁)再到十二届(……),难度都在下降。
虽然对于解决冲突的考察力度有所降低,但考察概率仍然很大,所以需掌握解决冲突最基本的方法(LED状态数组+定时器),这里会将上面设计到的三种情况都做详细说明,最基本的掌握LED状态数组+定时器即可。
1.第十届省赛真题
虽然难度有所降低,但题目的要求比往年都更加具体:
a.一状态LED以固定频率闪烁,另一状态LED熄灭。
b.除提醒功能的指示灯外,其他指示灯均处于熄灭状态。
c.实时获取电压值的情况下保持LED以固定频率闪烁。
2.第九届省赛真题
a.在实时时钟显示情况下保持LED以固定频率闪烁。
3.第八届省赛真题
a.在实时时钟显示的情况下展示流水灯效果。
既然LCD更新显示会使D端数据无法确定,那便造一个数组用于存储LED1~LED8的当前状态,我将其命名为LED_Close(随意,开心就好……),这样命名是为了和原理图逻辑相同,数组元素为1则下标对应LED灯灭,为0则亮,如LED_Close[1]=0,那LED1当前状态就是亮。数组长度根据题目使用LED灯数量决定,第零号元素不用。
uint8_t LED_Close[2]={1,1};//如果只用LED1 那我长这样
有了当前状态的存储数组,那怎么使LED闪烁呢?请看下面两个函数。
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM6)//定时器6中断
{
LED_Close[1]=!LED_Close[1];//状态反转
}
}
void LED_AllClose(uint8_t *LED_Close)//LED状态改变函数
{
uint8_t i;
LED1(ON);//默认开启
for(i=1;i<=1;i++)
{
if(LED_Close[i])//如果值为1
{
switch(i)//则下标对应LED灯关闭
{
case 1:
LED1(OFF);//为1关闭
break;
}
}
}
LED2(OFF);//不使用的默认关闭 使用就像LED1一样操作即可(默认开启,增加case)
LED3(OFF);
LED4(OFF);
LED5(OFF);
LED6(OFF);
LED7(OFF);
LED8(OFF);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
LED_AllClose函数中,默认认为LED1为亮,一旦LED_Close[1]的值为1,则将LED1状态更改为灭,最后再用锁存器锁存。
当只使用LED1进行闪烁时,可以使用定时器控制LED1闪烁频率,即每次定时器中断时将当前存储的状态反转一次,再调用LED_AllClose函数对LED1进行更新显示即可实现闪烁效果。
第九届省赛题仍然沿用上面讲的数组法对LED闪烁频率进行精准把控。
Q:那还要秒中断干嘛?
A:秒中断存在的目的是让时钟精确地显示。
Q:用定时器一秒显示一次不可以吗?
A:可以,但误差相对较大,有时计数到一个数时会停留较长时间(秒中断可以完美解决此问题)。
秒中断详细实现可参考STM32RTC秒中断–基于HAL库(一文看懂如何配置并使用)
第八届省赛题涉及LED闪烁,实时时钟,还涉及到流水灯(……)。
LED闪烁仍然可以使用数组法解决,实时时钟用秒中断解决,那流水灯呢?
将流水灯放在数循环中跑时,会出现一个现象:流水灯跑着的时候,时钟更新显示了,根据原理可知D端数据被改变了,这就会直接导致流水灯显示错误(断水灯?)。
Q:那如何解决?
A:解决的方法其实很简单,就是在D端数据不变时再跑流水灯,简单讲就是时钟更新后,再跑流水灯,这样LCD就不会影响到LED了。
写了个测试用例供大家测试使用,只有多动手测试,才能熟练掌握!
以上就是全部内容,如有错误请批评指正。