搜索

详解led数码管的接口编程技术

gecimao 发表于 2019-05-12 22:00 | 查看: | 回复:

  如图4.10 所示是由2 个共阳极的LN3161BS 组成的LED 数码管电路,R1~R8 为限流电阻,c1 和c2在内部并联连接。如果将段选端a~dp 与位选端com0、com1 连接到AM824-Core 的PIO0_8~PIO0_15 与PIO0_17、PIO0_23,则通过程序即可控制笔段的亮灭。由于数码管的8 个段选端全部都要经过com 口才能得到供电,因此需要增加三极管提高com 口的驱动电流,以弥补LPC824 GPIO 驱动电流的不足。当com 为低电平时三极管导通,则数码管的c1、c2 为高电平,即选通数码管。此时只要数码管的任一段选端为低电平,则点亮数码管相应的笔段。

  “日”形数字显示除了能够显示10 进制数字0~9,有时也用于显示16 进制字母AbCdEF 或其它一些非常简单的符号。按照二进制的计算方法,8 段显示有256 种组合,去掉“点(dp)”的显示,其笔段的组合为128 种(27),而数字0~9 只有10 个符号,因此要想得到我们希望的显示符就必须对显示段进行编码。显然,如果要想点亮数码管的某一个笔段,则只需将对应的笔段置0就可以了。即输出低电平至com0 端,同时输出低电平至b、c 段,点亮LED 得到字符“1”。由此可见,按照数字的笔画排列,则很容易得到10 个数字0~9 共10 个显示字符,七段共阳数码管10 个数字段码表详见表4.2。

  如果以8 位数值表示段码,当其相应位为0 时,则表示对应的段点亮。bit7~0 分别与dp~a 对应,假设bit0 为0,即点亮a。为了方便访问,不妨将段码存放到一个数组中。即:

  AMetal 软件包提供了熄灭所有数码管的板级初始化函数、段码传送函数、位码传送函数和数字显示扫描函数,其函数接口详见程序清单4.10。

  其中,code 为待显示数字0~9 所对应的段码,pos 为com0 或com1 对应的数字下标(0~1),num 为待显示的数字0~9。当后续调用这些函数时,则只需要“#include digitron0.h”就可以了。比如,在com0 数码管上显示数字1,详见程序清单4.11。

  如果让单个数码管循环显示0~9,且循环的时间为1s,显然显示时间也是1s,那么这就是一个简单的秒计数器,详见程序清单4.12。

  当你看到程序清单4.12(9)中的“i = (i + 1) % 10;”代码时,是否有一种似曾相识的感觉呢?这行代码是从LED 流水灯实验中提炼出来的。如果需要倒计时呢?则将其修改为“i= ((i 1) + 10) % 10;”。如果要从9 开始倒计数呢?那就将i 的初始值修改为9。至此已经实现了0~9 的循环显示,能否循环显示0~99 呢?这就是下面将要介绍的数码管动态扫描显示。

  如果要显示多位数字,则需将多个数码管并接在一起使用。此时将会出现一大堆段选端的问题,比如,两位数码管需要2×8=16 个段选信号,而LPC824 一共才16 个I/O,无法满足需求,同时管脚使用越多,连线也会变得越复杂。所以为避免使用过多的管脚而造成资源浪费和连线复杂,人们发明了一种动态扫描方式来实现多个数码管的显示。

  由于数码管的段码是连接在一起的,那么同一时刻两个数码管的段码必然是相同的,如果简单地使2 个公共端(com)均有效来实现2 个数码管的显示,那么必然都会显示相同的内容。怎么办?分时显示,即一段时间数码管0 正常显示(com0 有效,com1 无效,段码为数码管0 需要显示的图形),另外一段时间数码管1 正常显示(com1 有效,com0 无效,段码为数码管1 需要显示的图形)。如要显示一个数值12?即在com0 显示1,在com1 管显示2,详见程序清单4.13。

  虽然在实际的操作过程中数字是轮流显示的,但只要轮流操作的速度达到一定的范围,那么在人眼看起来就能达到和整体显示的效果一样,就像我们经常看的电影技术一样。

  再细心观察一下实验现象可以发现,虽然显示的数字是12,但是数码管显示的1 和2 都会有另外一个数字的影子。com0 显示的是1,但也能看到2 的影子。

  digitron_disp_num()就是digitron_com_sel ()和digitron_segcode_set()的一个简单组合。其显示过程是先传送位码、后传送段码,于是在传送位码和传送段码之间就产生了时间间隙。当新的com 端有效时,仍然还在使用此前的段码,所以出现了短暂的错误现象。怎么办?可以在这段时间内熄灭所有的数码管,避免错误显示。即:

  那如何循环显示0 ~ 59 呢?即将要显示的数值加1,详见程序清单4.14。

  程序还可以继续优化吗?现在的问题是,为了显示一个数据,即便数据没有改变,也必须动态扫描数码管,否则无法显示。首先将待显示的数据存放到缓冲区(存储单元),然后每隔一段时间从缓冲区读取待显示的数据。即:

  由此可见,缓冲区的段码就是当前要显示的数据,当再次切换时,则继续调用该函数,则在下一个位显示数据,以此类推。由于位选变量pos 每次都是在上一次显示的位的基础上变化的,因此必须将其声明为静态变量。显然,只要将显示的内容存放到缓冲区中,同时保证以一定的时间间隔(各个数码管显示后的延时)调用该函数,即可实现动态扫描。

  为了便于复用数码管程序,则将上述代码全部存放到digitron1.c 文件,函数声明放到digitron1.h 文件。其接口如下:

  由于要将待显示内容存放到缓冲区,同时还可能访问段码表,因此不允许调用者直接操作其中的变量、数组等,基于此增加3 个接口函数,其分别为传送段码到显示缓冲区,传送数字0~9 到显示缓冲区与获取待显示数字的段码,其相应的代码详见程序清单4.16。

  在显示过程中,有时为了修改某位数码管的值,需要对数码管进行闪烁处理。在温度采集场合,当温度超过一定的值后,可以将显示的温度值做全闪处理,以引起观察者注意。

  实际上,只要让数码管显示一段时间,熄灭一段时间,就产生了闪烁的效果,显然只要直接操作缓冲区就可以了。假设每秒闪烁2 次,在个位不断闪烁,详见程序清单4.19。

  在程序中,1s 闪烁2 次,每次闪烁占用500ms,即显示250ms,熄灭250ms。每秒结束后,秒计数器加1,显然用同样的方法也可以使秒计数器的十位闪烁,由此可见,实现闪烁仅需交替传送正常显示的段码和熄灭显示的段码即可。由于熄灭显示的段码非常特殊,固定为0xFF。因此,只要在合适的时间传送相应段码即可,段码传送函数digitron_segcode_set()是在digitron_disp_scan()函数中调用的。通过修改该函数,使其在一段时间内传送缓冲区中正常显示的段码,一段时间内传送熄灭显示的段码0xFF,也能实现闪烁,详见程序清单4.20。

  显然,数码管的闪烁状态和显示状态可以用一个标志位来表示,即0 表示显示,1 表示闪烁,bit0 和bit1 分别表示com0 和com1 的状态。定义一个全局变量如下:

  这样一来,即可需要根据该变量的值来获取需要闪烁的位,详见程序清单4.21。显然,只要将g_blink_flag 对应的位置1 就能实现闪烁,否则将其对应位清0。

  为了提高程序的可阅读性,则进一步优化两个if-else 语句,详见程序清单4.22。

  由于g_blink_flag 变量定义在实现代码中,不能直接将该变量提供给用户修改,因此必须提供一个接口函数用于设定闪烁位,其相应的代码详见程序清单4.23。

  有了该接口函数后,实现闪烁就很容易了,程序清单4.25 实现了秒计数器个位闪烁。

  由此可见,与程序清单4.18 相比,仅增加了一行代码就实现了闪烁功能,显然接口的设计非常重要。

本文链接:http://jonnutting.com/dongtaishengchengchengxu/407.html
随机为您推荐歌词

联系我们 | 关于我们 | 网友投稿 | 版权声明 | 广告服务 | 站点统计 | 网站地图

版权声明:本站资源均来自互联网,如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

Copyright @ 2012-2013 织梦猫 版权所有  Powered by Dedecms 5.7
渝ICP备10013703号  

回顶部