0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

深入浅出AMetal之LED 数码管接口

AGk5_ZLG_zhiyua 来源:互联网 作者:佚名 2017-10-30 15:28 次阅读

周立功教授新书《面向AMetal框架与接口编程(上)》,对AMetal框架进行了详细介绍,通过阅读这本书,你可以学到高度复用的软件设计原则和面向接口编程的开发思想,聚焦自己的“核心域”,改变自己的编程思维,实现企业和个人的共同进步。经周立功教授授权,即日起,致远电子公众号将对该书内容进行连载,愿共勉之。

第五章为深入浅出AMetal,本文内容为5.2 LED 数码管接口。

5.2 LED 数码管接口

>>> 5.2.1 静态显示

在这里以图4.10 所示的由2 个共阳极的LN3161BS 组成的LED 数码管电路为例,当输出低电平至com0 端,且同时输出低电平至b、c 段,则点亮LED 得到字符“1”,其相应的代码详见程序清单5.22。

程序清单5.22 数码管静态显示1 范例程序(1)

为了方便访问,不妨将段码存放到一个数组中,段码传送函数详见程序清单5.23。

程序清单5.23 段码传送函数

如果要求输出数字3,可以使用以下代码实现:

如果还需要加上一个小数点呢?“与”上0x7F 就是将最高位清零。即:

如果要求输出段码表中没有的数字呢?则直接传入对应的段码。即:

那到底让那个数码管显示呢?这就是位码传送问题,其相应函数详见程序清单5.24。

程序清单5.24 位码传送函数

有了段码和位码传送函数,则在com0 显示数字1 就非常简单了,详见程序清单5.25。

程序清单5.25 数码管静态显示数字1 范例程序(2)

显然合并上述两个函数,即可同时传送段码和位码信息,详见程序清单5.26。

程序清单5.26 digitron_disp_code()显示函数

在这里主要就是显示数字,为了避免每次重复从段码表中获取相应数字的段码,可以写一个用于在指定位置显示指定数字的函数,详见程序清单5.27。

程序清单5.27 digitron_disp_num()显示函数

由于只支持0~9 的显示,因此需要做判断处理,即当num 值小于等于9 时,才做显示操作。为何不判断大于等于0 的判断呢?由于num 的类型是无符号类型,因此一定大于等于0,显然还需要一个初始化函数,因此将这些管脚的初始化全部放到程序清单5.28。

程序清单5.28 数码管板级初始化函数

此时编程完毕,将相关函数接口声明到digitron0.h 中,详见程序清单5.29。当后续需要调用时,只需要#include "digitron0.h"就可以了。

程序清单5.29 digitron0.h 文件内容

>>> 5.2.2 动态显示

如程序清单5.30 所示的就是此前大家已经熟练掌握的digitron1.h 接口,其相应的实现代码详见程序清单5.31。

程序清单5.30 digitron1.h 文件内容

程序清单5.31 digitron1.c 文件内容

>>> 5.2.3 代码重构

重构是提高代码质量的方法,即在不改变外部接口下优化内部结构的方法。在进行重构时,必须优先编写单元测试代码,只有这样才能确保重构不会破坏原有的功能。C 语言中的对外接口通常是指头文件的内容,即外部调用我们编写的代码时所必须的数据结构、函数、宏的签名(名字、参数和返回值的类型和顺序)、常量的定义和行为等。而静态函数和.c 文件中的宏和结构体的定义,则不属于对外接口。只要对外接口没有改变,则调用者无需修改任何代码。如果调用者与创建者属于同一部门,则没有必要拘泥于形式禁止修改对外接口。

由于人们习惯用1 代表点亮LED,0 代表熄灭LED,所以无论数码管是共阴极还是共阳极,段码表的设计都应该符合人们的日常习惯,即将与之相应的“段码表”中的数据设定为1 来表示点亮相应的段。如果用1 来表示点亮LED,这恰好是共阴极数码管的段码。如果是共阳极的数码管,则直接使用“~”将段码取反,于是段码表也就统一起来了。

接下来开始设计段码表了,当前想到的有:0123456789.-ABCDEFabcdefORPNorpn,除O 和o 之外,大小写显示都相同。由于字符和段码均为一个字节表示,为了保存字符信息和其对应的段码信息,可以将显示的字符与段码数值组合在一起成为一个二维数组,建立与此相应的段码表,详见程序清单5.32。

程序清单5.32 字符段码表

访问段码表的接口函数详见程序清单5.33。

程序清单5.33 段码访问接口函数

在解码函数digitron_char_decode()中,使用了for 循环遍历段码数组,当找到对应的字符时,返回该字符对应的段码。显然这种解码方式简单易懂,但效率较低。

由于字符本质上是一个整数,可以比较大小。如果段码表按照字符大小进行有序排列,则可以使用二分法进行快速查找,即每次将待查找的字符与搜索范围的中间字符进行比较:若小于中间字符,则将搜索范围缩小一半为下半部分,然后继续搜索;若大于中间字符,则将搜索范围缩小一半为上半部分,然后继续搜索;若恰好相等,则查找到相应字符。

为了使用二分法进行查找,需要将断码表按照字符的大小进行有序排列,这就需要知道段码表中各个字符对应的整数值,这些值可以通过查询ASCII 码表得到,ASCII 码表详见表5.7,表中仅列出了可显示字符(32 ~ 126),共计95 个,其它不可显示字符(0 ~ 31 及127)由于不能显示,与数码管无关,因此没有在表中定义。

表5.7 ASCII 表(95 个可显示字符)

基于ASCII 码表中各个字符的对应的整数值,可以重新定义段码表,详见程序清单5.34。

程序清单5.34 字符段码表(升序排列)

字符段码有序排列后,即可使用二分法查找,更新解码函数的实现详见程序清单5.35。

程序清单5.35 基于二分法查找的解码函数

由此可见,相对于顺序遍历查找法,二分法实现的代码略显复杂。当查找的范围较小时,如段码表仅仅33 个查找项,二分法的效率优势并不明显。有没有更好的办法呢?

在前面定义段码表时,使用了二维数组的方式,将字符和对应的段码存储到数组中,一个字符就占用了2 个字节的存储空间,共计占用了66 字节空间。

ASCII 码表有95 个显示字符,对应十进制数的范围为32 ~ 126。如果在建立段码表时,从第一个可显示字符开始,按照字符顺序依次将所有可显示字符的段码编排到一个数组中,则数组的索引就包含了字符信息,比如,0 号元素代表了32 对应的字符,即空格,1 号元素代表了33 对应的字符,即‘!’……如此一来,由于索引与字符存在一一对应关系,通过索引就可以得到相应的字符信息,因此在段码表只需要使用一维数组存储每个字符对应的段码就可以了。此时,在对一个字符解码时,直接将字符转换为数组索引,然后取出对应的段码即可,无需任何查找过程,范例程序详见程序清单5.36。

程序清单5.36 使用一维数组存储段码(1)

由此可见,这种方式使段码查找的时间效率达到了最优。在段码表中,由于很多ASCII码数码管并不能显示,为了保证索引与字符的对应关系,也必须使用0x00 表示其对应的段码。这在一定程度上造成了空间的浪费,95 个字符对应的编码数组占用的存储空间大小为95 字节,相比于使用二维数组的方式,多占用了29 字节。

观察段码数组的定义可以发现,起始和结尾都存在一大段0x00(起始存在连续的13 个0x00,结尾存在连续的12 个0x00),为此在定义段码数组时,可以不以空格作为起始字符,将第一个段码不为0x00 的字符('-',十进制为45,段码为0x40)作为段码的起始字符,同时,将段码表末尾连续的0x00 移出,以节省内存空间,详见程序清单5.37。

程序清单5.37 使用一维数组存储段码(2)

此时,整个一维数组占用的空间为70 个字节,相对于使用二维数组的方式,仅仅多占用了4 个字节。虽然多占用了4 个字节的存储空间,但是效率的提升却是非常明显的。

由于现在是直接使用段码或字符,因此要显示数字3 时,不能再像以前那样直接写数字3,而应写字符3。比如:

比如,显示自定义段码,则使用以下方式编程:

比如,显示'3.',则使用以下方式编程:

由于段码统一使用1 表示点亮LED 段,而实际中,MiniPort-View 使用的是共阳极数码管,因此需要将段码取反后使用,则进一步修改igitron_disp_scan()函数,详见程序清单5.38。

程序清单5.38 动态扫描显示函数

最后,将这些接口全部声明到程序清单5.39 所示的digitron2.h 文件,实现相关代码全部放到程序清单5.40 所示的digitron2.c 文件。

程序清单5.39 digitron2.h 文件内容

程序清单5.40 digitron2.c 文件内容

使用digitron2.h 中的接口函数,同样可以实现0~59 秒的计数器,代码详见程序清单5.41。

程序清单5.41 0~59 秒计数器范例程序(4)

程序清单5.41(17~18)加上'0'的目的是将数字变为字符。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

原文标题:周立功:深入浅出AMetal——LED 数码管接口

文章出处:【微信号:ZLG_zhiyuan,微信公众号:ZLG致远电子】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    深入浅出玩转fpga PDF教程和光盘资源

    深入浅出玩转FPGA,作者吴厚航,由北京航空航天大学出版社出版。本书收集整理了作者在FPGA学习和实践中的经验点滴。书中既有日常的学习笔记,对一些常用设计技巧和方法进行深入探讨;也有很多生动的实例
    发表于 02-27 10:45

    深入浅出AVR(傻孩子)

    本帖最后由 eehome 于 2013-1-5 09:56 编辑 深入浅出AVR(傻孩子)
    发表于 06-29 15:43

    深入浅出AVR

    深入浅出AVR,一本书。
    发表于 07-15 12:02

    深入浅出玩转FPGA

    深入浅出玩转FPGA
    发表于 07-21 09:21

    深入浅出Linux_设备驱动编程

    深入浅出Linux_设备驱动编程
    发表于 08-16 15:57

    深入浅出ARM7

    深入浅出ARM7
    发表于 08-18 10:12

    HDMI技术深入浅出

    HDMI技术深入浅出
    发表于 08-19 10:52

    深入浅出Android

    深入浅出Android
    发表于 08-20 10:14

    深入浅出安防视频监控系统

    深入浅出安防视频监控系统
    发表于 08-20 10:31

    深入浅出Linux_设备驱动编程

    深入浅出Linux_设备驱动编程
    发表于 08-20 14:58

    深入浅出Android

    深入浅出Android
    发表于 04-26 10:48

    深入浅出安防视频监控系统

    深入浅出安防视频监控系统深入浅出安防视频监控系统
    发表于 05-22 19:28

    深入浅出AVR

    深入浅出AVR
    发表于 08-23 10:10

    深入浅出软件加密技术

    深入浅出软件加密技术
    发表于 09-24 17:18

    深入浅出排序学习使用指南

    深入浅出排序学习:写给程序员的算法系统开发实践
    发表于 09-16 11:38