6位7段LED数码管显示

更新时间:2023-05-20 07:30:01 阅读量: 实用文档 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

目录

1. 设计目的与要求 ..................................................... - 1 -

1.1 设计目的 ...................................................... - 1 - 1.2 设计环境 ...................................................... - 1 - 1.3 设计要求 ...................................................... - 1 - 2. 设计的方案与基本原理 ............................................... - 2 -

2.1 6 位 8 段数码管工作原理 ....................................... - 2 - 2.2 实验箱上 SPCE061A控制 6 位 8 段数码管的显示 ................... - 3 - 2.3 动态显示原理 .................................................. - 4 - 2.4 unSP IDE2.0.0 简介 ............................................ - 6 - 2.5 系统硬件连接 .................................................. - 7 - 3. 程序设计 ........................................................... - 8 -

3.1主程序 ......................................................... - 8 - 3.2 中断服务程序 .................................................. - 9 - 4.调试 ............................................................... - 12 -

4.1 实验步骤 ..................................................... - 12 - 4.2 调试结果 ..................................................... - 12 - 5.总结 ............................................................... - 14 - 6.参考资料 ........................................................... - 15 - 附录 设计程序汇总 .................................................... - 16 -

1.设计目的与要求 1.1 设计目的

1. 了解 6 位 7 段 LED数码管的工作原理。 2. 熟悉并进一步掌握定时器和时基信号的使用方法。 3. 掌握 SPCE061A单片机控制 LED数码管显示的方法。

4. 通过本次课程设计使学生对智能仪表与装置系统有更深一步的了解,培养学生

将理论知识综合利用的能力,并与实践紧密结合。

5. 掌握各子系统设计方法、步骤,培养学生创新能力,总结报告的能力。

1.2 设计环境

1. 装有 Windows 系统和μ’nSP(TM) IDE 仿真环境的 PC 机一台,μ’nSP(TM)

十六位单片机实验箱一个。

2. 本实验用到的实验箱硬件模块为:SPCE061A核心及周边电路模块(包含 32 个

I/O口),6位 8 段数码管电路模块。

1.3 设计要求

1. 编程要求:主程序利用 C 语言编写,中断服务程序利用汇编语言编写。 2. 实现功能:SPCE061A单片机控制 6 个 LED数码管的显示。

3. 实验现象:运行开始点亮所有的数码管,6 位 LED 数码管均显示 0 并持续

1s。1s 后,第一位数码管从 0 显示到9,刷新时间为 0.5s,其他数码管全部显示 0。当第一位数码管显示到9 后,第一位数码管保持显示 9,第二位数码管从 0 显示到 9,刷新时间为 0.5s,其他数码管显示 0。依次直到第 6位数码管显示 9,即6 位数码管全部显示 9,6 位数码管全部显示 0,持续 1s,如此循环。(1s 的时间、0.5s 的时间都使用 2Hz 的时基信号(IRQ5)提供)。6 位数码管的显示状态见表1.

表 1 6 位数码管显示状态

注意:①表中序号为 0 和 61 的状态持续 1s;其他状态刷新时间为 0.5s。 ②表中需要类似“1~10”表示有十个状态。

2.设计的方案与基本原理

2.1 6 位 8 段数码管工作原理

实验箱的 6 位 8 段数码管电路采用“共阴”连接,阴极公共端(COM)由晶体管推动。实验箱上的数码管共有两种,如图 1。

图 1 两种数码管图

首先介绍两个基本概念:段码和位码,段码即段选信号 SEG,它负责数码管显示的内容,图 4-1中 a~g、dp组成的数据(a 为最低位,dp 为最高位)就是段码。比如 1的段码“0x06”(b=1,c=1,其他都为 0,即段码为 00000110b),8 的段码为“0x7f”;位码即位选信号 DIG,它决定哪个数码管工作,哪个数码管不工作,比如仅使能 DIG4,那么 6 个 LED 只有 LED4 工作,而其它的五个都不工作。

当需要某一位数码管显示数字时,只需要先选中这位数码管的位信号,再给显示数字的段码。比如当在第一个数码管上显示一个“6”时,如图 2,先选中第一位数码管的位信号(实验箱上标号是“1”),即先给和“1”相连接的 I/O 口送 1;再把段码设置为 0x007d,即在 a、c、d、e、f、g各段引出的端口检测到高电平,就可以显示一个“6”出来。

图 2 数码管显示“6”

2.2 实验箱上 SPCE061A控制 6 位 8 段数码管的显示

实验箱在 6位 8 段数码管的上面有 16 对排针,其中有 7 个“a\b\c\d\e\f\g\”是控制此 6位 8 段数码管的段码选择的,另有 6 个“1\2\3\4\5\6”是控制 6 位8 段数码管位选择的,“DD”控制“点”或“分隔符号”,“DP”控制小数点。把实验箱上 JP4 和 JP5 的引针用跳线全部短接。框图如图 3。

图 3 实验箱上SPCE061A和6位LED显示电路模块的连接

按照上面数码管的显示原理,当要在第四个数码管上显示一个“E”时,先要通过 IOB12 端口给“4”端口送一个 1,选中第四个数码管;由图 4-1 可以看出,显示“E”时,需要 a、d、e、f、g段被点亮,所以给 IOA0、IOA3、IOA4、IOA5、IOA6 端口各送一个 1,则在 a、d、e、f、g 端口各能检测到一个高电平,就可以点亮 a、d、e、f、g 段,显示一个“E”。

2.3 动态显示原理

动态显示是数码管显示比较常用的方式,可以很好的解决端口资源紧张问题。下面以四位数码管为例说明动态显示的原理,如图 4 所示

图 4 4位*7段数码管动态显示原理图

动态显示的过程:以显示“1234”为例说明,首先发送“1”的段码“0x06”至数码管,然后仅使能位信号 DIG4,LED4 就会显示“1”,其余的数码管都是不工作的;延时一定时间之后再发送“2”的段码“0x5b”至数码管,同时仅使能位信号 DIG3,这时“2”就会在 LED3 上显示出来;延时之后再发送“3”的段码并使能位信号 DIG2,LED2 就会显示“3”;延时一定时间之后再发送“4”的段码并使能位信号 DIG1,LED1 就会显示“4”;延时之后再回过头来重新发送“1”的代码,并选中位信号 DIG4,重复循环点亮数码管。由于相邻两次(第一次点亮 LED4 和第二次点亮 LED4)的时间间隔很短(t<10ms),看起来仿佛 LED4 一直在显示“1”,4 各数码管整体看起来就在显示“1234”。

动态显示的延时很重要,延时太短,数码管发光时间过短,数码管的亮度不够;延时太长,回扫间隔过大(超过 11ms),肉眼就会感觉到闪烁。该例程采用 4KHz 中断作为时间基准执行动态扫描,每来一次中断,显示自动移位,回扫时间 t = 0.25ms*6 = 1.5ms。

通过对 I/O口的控制,定时 1s 的时间和 0.5s 的时间都使用 2Hz 的时基信号(IRQ5)。按照基础实验中 IRQ5 中断的工作原理,响应一次 IRQ5_2Hz 中断需要 0.5s 的时间,而响应两次中断的时间刚好是 1s。按照实验要求,当开 IRQ5_2Hz 中断时,6 位数码管全部显示“0”后,响应两次 IRQ5_2Hz中断,再从第一个数码管开始显示;而刷新时间刚好是响应一次 IRQ5_2Hz 中断的时间。

2.4 unSP IDE2.0.0 简介

1. 为什么推出 unSP IDE2.0.0D (R)

为了提高μ’nSP IDE 工具的兼容性,让μ’nSP IDE 工具能支持更多的芯片,并且由于实验箱实验指导书的全面改版,IDE 下的例程全面修改、更新,凌阳科技推出了μ’nSP IDE 工具的最新版本——unSP IDE 2.0.0(以下简称:IDE2.0.0)。

IDE 2.0.0 作为μ’nSP IDE 工具截止现在(2005-11-11)最新的一个版本,它不但继承以前版本 IDE 的特点,同时增加了一些新的功能,集纳了众多用户在使用μ’nSP IDE 过程中提出的一些意见,并包含了一些新的例程。

除增加了一些新的功能外,IDE2.0.0 在编译优化、代码查错定位等方面都有了一定的进步,用户在使用本版 IDE 时,应该可以体会到,其对代码的严谨性有了更高的要求。而在新版 IDE 的各个方面,都有所加强,用户在使用过程当用会有所体会。

新添加功能、加强原有功能等,都没有改变 unSP IDE 一惯的使用方法,所以用户可以参考 unSP IDE184(R) 的用户手册,以学习μ’nSP IDE 的基本操作及相关知识,这在 IDE2.0.0 的使用当中是保持不变的。

2. 从 IDE184 到 IDE2.0.0D的变化

IDE1.8.4 是用户用的最多的一版μ’nSP IDE 工具,实际上在推出 IDE1.8.4 之后,μ’nSP IDE 也在不断的升级,其间也出现了非常多的版本,比如已发布的就有 IDE1.16.1 和 IDE1.18.1;但相比之下,IDE2.0.0的版本有更多细节的完善,更多新功能的添加,为用户的代码编辑、工程调试等提供了更人性化的辅助功能和更便利的工具。

从较大的区别来看,IDE2.0.0 工具由 IDE1.8.4 支持两颗芯片变为支持四颗芯片,增加了许多新的功能,并对一些旧的功能进行了改善,同时对 IDE1.8.4 下包含的例程进行了修改、更新和规范化,走过了很长的路程,是对前面μ’nSP IDE 工具版本的升级。而 IDE 在安装后的文件结构发生了一些变化,为后期加入更多的新芯片提供了统一的平台,也更符合 IDE 版本维护的要求。

从细节上看,IDE2.0.0 在代码编译、优化以及错误、警告定位方面都作了改进,在调试时的增加变量提示、在 Memery观察窗中数据变化以红色提示等等;为用户的软件编辑、调试提供了更加友好的界面。

在网上提供的《IDE User guide》(unSP IDE184 用户手册)中详细地介绍了μ’nSP

IDE 工具的使用方法.

2.5 系统硬件连接

硬件连接图如图 3,IOA0~IOA7 分别接数码管的 7 个段信号 a~g 和小数点信号 dp,IOB15~IOB12 连接数码管的位信号 1~4,IOB2~IOB1 连接数码管的位信号 5~6,IOB0 连接数码管的分隔符号信号 DD,即把 JP4 和 JP5 的引针用跳线全部短接。

硬件电路连接图

3.程序设计

本程序由主程序和中断服务程序组成。

3.1主程序

主程序流程图如图 5。先进行系统初始化;开 2Hz 中断;进入数码管循环显示程序:判断位信号寄存器是否为 0(位信号寄存器由读者自己定义,这个寄存器的内容在中断里会改变),如果为0,6 位数码管显示“000000”;如果不为零,按照位信号和段码显示数据进行显示。

图 4-5 主程序流程图

主程序:

#include "SPCE061A.h" #include "Dig.h"

#define C_IRQ5_2Hz 0x0004

unsigned int g_uiFirst = 0x0000;

unsigned int g_uiFlag;

//用于控制1s延时 //用于控制数码管

unsigned

int

g_Data[11]

=

{0x0000,0x003f,0x0006,0x005b,0x004f,0x0066,0x006d,0x007d,0x0007,0x007f,0x006f}; //0,

1, 2,

3,

4, 5, 6,

7,

8,

9

unsigned int g_uiSeg;

//段码指针

3.2 中断服务程序

由于显示数据的刷新时间为 1s 和 0.5s,因此考虑采用 2Hz(0.5s)时基中断。并且在中断内部完成段码数据更新。具体的流程如图 6 示:

在中断服务程序中会用到三个重要的寄存器:中断计数寄存器、显示数据寄存器、位信号寄存器。其中中断计数寄存器用于记录第几次进入中断(前 3次有效),显示数据寄存器的内容为当前被刷新显示数据的数值(0~9),位信号寄存器用于标识被刷新数据所在位。结合主程序分析中断程序:首先显示“000000”时需要延时 1s,使用 2Hz 中断产生 1s 延时,需要连续响应两次中断,第二次响应中断延时满 1s,设置显示数据寄存器和位信号寄存器,让第一位数码管显示 1,其余各位仍为“0”,即显示“100000”;判断显示数据寄存器显示数据是否大于 9,如果小于,显示数据寄存器数据加 1;如果大于,判断位信号寄存器是否已经指向第六位数码管,否则位信号寄存器设置为指向下一位数码管,显示数据寄存器显示数据设置为 0;如果已经指向第六位数码且显示数据寄存器为 9,寄存器清零,清中断标志,中断返回。

中断服务程序流程图:

图 6 中断服务程序流程图

中断服务程序: int main(void) {

unsigned int Dis1[6] = {0x003f,0x003f,0x003f,0x003f}; unsigned int uiIntStatus;

uiIntStatus = *P_INT_Ctrl_New; uiIntStatus |= C_IRQ5_2Hz;

//开2Hz中断

*P_INT_Ctrl = uiIntStatus; g_uiFlag = 0x0000;

//该变量在2Hz中断当中会被

修改

g_uiSeg = 0;

//该变量在2Hz中断当中会被修

改,以便及时刷新显示 DIG_Init();

IRQ4的4KHz中断 while(1) { if(g_uiFlag == 0x0000) { DIG_SetAll(Dis1);

}

if(g_uiFlag != 0x0000) { DIG_Set(g_uiFlag,g_Data[g_uiSeg]);

}

*P_Watchdog_Clear = 0x0001;

}

}

//显示初始化,同时会打开

//设置数码管全部显示0

//刷新6位数码管显示值

4.调试

4.1 实验步骤

1. 新建一个工程 ex1_Led_Show,新建一个 C 语言文件 main.c,新建一个汇编语言文件 isr.asm。

(根据读者需要可以自己新建文件)

2. 拷贝头文件 SPCE061A.inc 和 SPCE061A.h 到新建工程 ex1_Led_Show,这两个文件在 IDE的安装路径\SPCE061A\include 路径下可以找到。

3. 添加 SPCE061A.h、SPCE061A.inc到工程的“Head Files”;添加后可以直接用这两个头文件中申明的变量或者地址单元。

4. 按照程序流程图编写程序。 5. Rebuild All。

6. 按照硬件连接图连接电路,注意断开 JP3 和 JP7 的所有引针,以免影响输出显示数据。

4.2 调试结果

调试结果如下图: 运行开始时

图7运行开始时

运行到第1位9、第2位1时

图8 运行到第1位9、第2位1时

运行到前两位都为9时

图9 运行到前两位都为9时

运行到6位都为9时

图10 运行到6位都为9时

5.总结

在这为期两周的课程设计中,通过对6位7段LED数码管显示的设计与分析,我清楚地认识到了自己以前仅仅学到的书本上的知识的欠缺与经验的不足,所谓实践出真知,智能仪器本就是一种实践操作环节十分重要的课程,而这次的课设正好弥补了我操作方面的不足,进而更加巩固了这方面的知识。

课程设计过程中,我们不断发现错误,不断改正,不断领悟,不断获取。尤其是硬件方面的知识,我们更为的稀少,以前的课程中学到的基本都是软件方面LabVIEW的使用等等,而硬件却是很少接触到,因此对于硬件我们是知之甚少。然而我们通过不断地查阅6位7段LED数码管和IDE的相关资料,对其有了进一步的认识,还有硬件设备与软件的连接,我们也都出现过问题,但最总都能认真的一一排除予以解决。最终,我们达到了任务书上的要求,完成了本次的智能仪器课程设计。

在今后社会的发展和学习实践过程中,一定要不懈努力,不能遇到问题就想到要退缩,一定要不厌其烦的发现问题所在,然后一一进行解决,只有这样,才能成功的做成

想做的事,才能在今后的道路上劈荆斩棘,而不是知难而退,那样永远不可能收获成功,收获喜悦,也永远不可能得到社会及他人对你的认可!

最后感谢本次课程设计中老师与同学们的帮助与指导,使我获益匪浅!

6.参考资料

【1】朱麟章 蒙建波主编.检测理论及应用. 重庆大学出版社 2007.8(2) 【2】张国雄编著.测控电路 天津大学出版社 2005.1

【3】费业泰编著.误差理论与数据处理 .合肥工业出版社 2005.1

【4】王志刚编著.单片机应用技术及实训.北京:清华大学出版社 2004.5

附录 设计程序汇总

Main.c

#include "SPCE061A.h" #include "Dig.h"

#define C_IRQ5_2Hz 0x0004

unsigned int g_uiFirst = 0x0000; //用于控制1s延时 unsigned int g_uiFlag; //用于控制数码管 unsigned int g_Data[11] = {0x0000,0x003f,0x0006,0x005b,0x004f,0x0066,0x006d,0x007d,0x0007,0x007f,0x006f};

//0, 1, 2, 3, 4, 5, 6, 7, 8, 9

unsigned int g_uiSeg; //段码指针

//======================================================== // 语法格式: int main(void) // 实现功能: 数码管显示 // 参数: 无 // 返回值: 无

//======================================================== int main(void) {

unsigned int Dis1[6] = {0x003f,0x003f,0x003f,0x003f}; unsigned int uiIntStatus;

uiIntStatus = *P_INT_Ctrl_New; //开2Hz中断 uiIntStatus |= C_IRQ5_2Hz; *P_INT_Ctrl = uiIntStatus;

g_uiFlag = 0x0000; //该变量在2Hz中断当中会被修改

g_uiSeg = 0; //该变量在2Hz中断当中会被修改,以便及时刷新显示

DIG_Init(); //显示初始化,同时会打开IRQ4的4KHz中断 while(1) {

if(g_uiFlag == 0x0000) {

DIG_SetAll(Dis1); //设置数码管全部显示0

}

if(g_uiFlag != 0x0000) {

DIG_Set(g_uiFlag,g_Data[g_uiSeg]); //刷新6位数码管显示值 }

*P_Watchdog_Clear = 0x0001; } }

Isr.asm

.INCLUDE SPCE061A.inc .INCLUDE Dig.inc

.EXTERNAL _g_uiFirst .EXTERNAL _g_uiFlag .EXTERNAL _g_uiSeg

.TEXT

//======================================================== // 汇编格式: _IRQ4 // 实现功能: 1KHz中断调用F_DIG_Drive函数 // 参数: 无 // 返回值: 无

//======================================================== .PUBLIC _IRQ4 _IRQ4:

push r1,r5 to [sp] r1 = C_IRQ4_1KHz test r1,[P_INT_Ctrl] jnz ?L_IRQ4_1KHz r1 = C_IRQ4_2KHz test r1,[P_INT_Ctrl] jnz ?L_IRQ4_2KHz ?L_IRQ4_4KHz:

call F_DIG_Drive //F_DIG_Drive函数是数码管显示函数,定义在Dig.asm文件中 r1 = C_IRQ4_4KHz [P_INT_Clear] = r1 pop r1,r5 from [sp] reti

?L_IRQ4_2KHz:

[P_INT_Clear] = r1 pop r1,r5 from [sp] reti

?L_IRQ4_1KHz:

call F_DIG_Drive [P_INT_Clear] = r1 pop r1,r5 from [sp] reti

//======================================================== // 汇编格式: _IRQ5 // 实现功能: 2Hz中断进行显示处理 // 参数: 无 // 返回值: 无

//======================================================== .PUBLIC _IRQ5 _IRQ5:

push r1,r5 to [sp] r1 = C_IRQ5_2Hz

test r1,[P_INT_Ctrl] jnz ?L_IRQ5_2Hz ?L_IRQ5_4Hz:

r1 = C_IRQ5_4Hz [P_INT_Clear] = r1 pop r1,r5 from [sp] reti

?L_IRQ5_2Hz:

r1 = [_g_uiFirst]

cmp r1,0x0001 //第2次进入中断 ja ?Start //时间〉=1s r1 = [_g_uiFirst] //时间小于1s r1 += 1

[_g_uiFirst] = r1 goto ?Exit ?Start:

r1 = [_g_uiFirst]

cmp r1,2 //1s jne ?Next

r1 += 1 //初始化g_uiFlag、g_uiSeg显示"1000"

[_g_uiFirst] = r1 r1 = 1

[_g_uiFlag] = r1 r1 = 2

[_g_uiSeg] = r1 goto ?Exit

?Next:

r1 = [_g_uiSeg]

cmp r1,9 //更改段码指针,显示数值加1 ja ?Next1 r1 += 1

[_g_uiSeg] = r1 goto ?Exit

?Next1:

r1 = [_g_uiFlag] //更改被刷新数码管位 cmp r1,4 je ?Last r1 += 1

[_g_uiFlag] = r1 r1 = 2

[_g_uiSeg] = r1 goto ?Exit ?Last:

r1 = 0x0000 //置标志,重新显示“000000” [_g_uiFirst] = r1 [_g_uiFlag] =r1 goto ?Exit

?Exit:

r1 = C_IRQ5_2Hz [P_INT_Clear] = r1 pop r1,r5 from [sp] Reti Dig.asm

.DEFINE SEG_IO_Port 0 // 若LED段选使用IOA口则采用该行定义 //.DEFINE SEG_IO_Port 1 // 若LED段选使用IOB口则采用该行定义

.DEFINE SEG_IO_HighByte 0 // 若LED段选使用IO口低8位则采用该行定义

//.DEFINE SEG_IO_HighByte 1 // 若LED段选使用IO口高8位则采用该行定义

//================================================ // LED位控制端口设定

//================================================

//.DEFINE DIG_IO_Port 0 // 若LED位选使用IOA口则采用该行定义 .DEFINE DIG_IO_Port 1 // 若LED位选使用IOB口则采用该行定义

/////----- 数码管的位数 -----///// .DEFINE DIG_Count 4

/////----- 数码管每一位的控制脚设定 -----///// .DATA PIN_DIG:

.DW 0x0004,0x0008,0x0010,0x0020;

/////----- 数码管所有位的控制脚设定,应等于PIN_DIG所有数之和 -----///// .DEFINE PIN_DIG_ALL 0x003C

//================================================ // 不必修改下面的定义

//================================================ .IF SEG_IO_Port==0

.DEFINE P_SEG_Data 0x7000 .DEFINE P_SEG_Buf 0x7001 .DEFINE P_SEG_Dir 0x7002 .DEFINE P_SEG_Attrib 0x7003 .ELSE

.DEFINE P_SEG_Data 0x7005 .DEFINE P_SEG_Buf 0x7006 .DEFINE P_SEG_Dir 0x7007 .DEFINE P_SEG_Attrib 0x7008 .ENDIF

.IF SEG_IO_HighByte==0

.DEFINE PIN_SEG_ALL 0x00ff .ELSE

.DEFINE PIN_SEG_ALL 0xff00 .ENDIF .IF DIG_IO_Port==0

.DEFINE P_DIG_Data 0x7000 .DEFINE P_DIG_Buf 0x7001 .DEFINE P_DIG_Dir 0x7002 .DEFINE P_DIG_Attrib 0x7003 .ELSE

.DEFINE P_DIG_Data 0x7005 .DEFINE P_DIG_Buf 0x7006 .DEFINE P_DIG_Dir 0x7007 .DEFINE P_DIG_Attrib 0x7008 .ENDIF

//================================================ // 中断常量定义

本文来源:https://www.bwwdw.com/article/pme4.html

Top