> 文档中心 > STM32LED--基于HAL库(LCD与LED冲突?一文看懂如何精准劝架)

STM32LED--基于HAL库(LCD与LED冲突?一文看懂如何精准劝架)

文章目录

  • 前言
  • 一、LED和LCD的矛盾在哪
  • 二、部分真题要求解析
    • 综合分析
    • 为什么还要讲
    • 真题涉及矛盾
  • 三、解决方法
    • 第十届省赛真题(数组法)
      • 数组
      • 函数
    • 第九届省赛真题(秒中断+数组法)
    • 第八届省赛真题
  • 四、源码(转载请注明出处)
  • 总结

前言

相关说明:

开发板:CT117E-M4(STM32G431RB 蓝桥杯嵌入式比赛板)
开发环境: CubeMX+Keil5
在历年真题中,几乎每题都会遇到LED与LCD显示冲突的情况,虽然第十二届省赛没有涉及这一矛盾,但第十三届考的概率仍然很大。


心得分享:

一、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便不能以固定频率进行闪烁

二、部分真题要求解析

(按照从易到难的顺序展示、解析,下同)
在这里插入图片描述
STM32LED--基于HAL库(LCD与LED冲突?一文看懂如何精准劝架)
在这里插入图片描述

综合分析

从以上三图+第十二届题目(无需解决冲突)综合分析,似乎官方对于解决冲突的考察力度有所降低,从第八届(实时时钟显示+流水灯)到第十届(实时时钟显示+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了

四、源码(转载请注明出处)

写了个测试用例供大家测试使用,只有多动手测试,才能熟练掌握!
STM32LED--基于HAL库(LCD与LED冲突?一文看懂如何精准劝架)


总结

以上就是全部内容,如有错误请批评指正。