如何写一个状态指示灯?

工作时,我们常常会有这样的需求:

用一个 LED 灯指示机器的工作状态:正常或故障。

这样一个需求,对于我们入门就写点灯程序的点灯小能手来说,根本就是小意思。

因为这只需要控制IO输出高电平或者低电平就可以达到要求。尽管如此简单,如果用的不好,那也是存在风险的:《引脚输出的隐藏BUG | 深入思考》。

本篇笔记记录的当然不是简单的指示正常和故障这两种状态,而是多种状态。

比如,快闪、慢闪、1秒闪1次,1秒闪3次等。

不过,因精力有限,先介绍一个简单的实现1.5秒闪烁1~5次的方法,并且通过对该方法的详细介绍,你也可以实现更复杂的指示功能(当然也可用于蜂鸣器等)。

该方法有几点优势:

1、代码实现简单;

2、可用于多线程;

3、移植方便;

4、裸机、操作系统均可使用,可不需要定时器。

当然也有缺点,就是只能指示最新的当前状态(也就是说,如果有多个线程同时调用,将指示最后一个调用时的状态),不过对于状态指示来说,这样足够了。

 

为了实现1.5秒内闪烁5次,并且让代码尽可能的简单,我们可以将 1.5 s划分成 10 个等份,每个等份为 150 ms。

 

 

假定,高电平为,低电平为亮。

那么,如果我们要实现1.5 s 闪烁一次的效果,只需要在0 时刻设置为低电平,1时刻设置为高电平即可,其他时刻不需要操作电平,此时电平效果如下:

 

 

这样,通过在指定时刻设置IO电平,即可达到闪烁的效果。

现在的问题是,如何获得稳定的周期时间,这已经是老生常谈的问题,如果不明白,可以参考以下笔记:《延时功能进化论(合集)》。

这里我们需要实现两个周期,一个是 1.5 s,一个是 150 ms,所以需要两个变量保存时间戳,同时为了实现单次延时,再增加一个变量,即关于时间的变量共有三个。

下面贴代码,看看代码实现:

 

 

 

 

代码注释比较详尽,如果看不懂,说明还没有理解以前写的笔记,建议翻翻以前的笔记。

简单说明几点:

1、为了移植方便,使用了一个函数指针设置LED电平,因此可以很方便的修改。

2、可以方便配置多个LED,如果一个LED不够,那就俩。

3、为了减少空间的使用,原本 4 字节的时间戳通过强制转化,使用 2 字节即可实现。

4、单次超时时间实现。

5、时间戳单位为 1 毫秒,同时 led_set_handle 函数为了保证时间精度,调用周期为 10 ms,该函数需要周期性调用,并且只可以在一个地方调用(一个LED情况下)。

6、led_show 函数用于更新闪烁次数,可在闪烁次数变化的时候调用;同时可多线程使用,当然因为没有缓存,始终保存最后一次调用时的显示次数。

7、led 作为共享资源,使用变量 curr_number 控制资源访问,保证指示不会出现混乱。

8、指示更新周期1.5秒,即上层即使更新了 next_number ,最迟需要 1.5 后才会更新,最早更新时间为立刻。

9、使用 C99 的特性,简化初始化过程​。

posted @ 2020-08-03 16:33  欧清辣哨  阅读(466)  评论(0编辑  收藏  举报