微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 《手把手教你学51单片机-C语言》之六 中断与数码管动态显示

《手把手教你学51单片机-C语言》之六 中断与数码管动态显示

时间:11-19 来源:互联网 点击:

些增强型51单片机的问世,可能会有增加的寄存器,大家理解了我们这里所讲的,其它的通过自己研读数据手册就可以理解明白并且用起来了。

本帖子中包含更多资源

您需要登录才可以下载或查看,没有帐号?立即注册

x

我要点赞0

收藏1举报

这个家伙好懒,什么都没留下回复编辑

金沙滩工作室

  • 发消息

发表于 2014-6-9 08:47:22

2#

表6-1IE——中断使能寄存器的位分配(地址0xA8、可位寻址)

7

6

5

4

3

2

1

0

符号

EA

--

ET2

ES

ET1

EX1

ET0

EX0

复位值

0

--

0

0

0

0

0

0

表6-2IE——中断使能寄存器的位描述

符号

描述

7

EA

总中断使能位,相当于总开关

6

--

--

5

ET2

定时器2中断使能

4

ES

串口中断使能

3

ET1

定时器1中断使能

2

EX1

外部中断1使能

1

ET0

定时器0中断使能

0

EX0

外部中断0使能

中断使能寄存器IE的位0~5控制了6个中断使能,而第6位没有用到,第7位是总开关。总开关就相当于我们家里或者学生宿舍里的那个电源总闸门,而0~5位这6个位相当于每个分开关。那么也就是说,我们只要用到中断,就要写EA=1这一句,打开中断总开关,然后用到哪个分中断,再打开相对应的控制位就可以了。

我们现在就把前面的数码管动态显示的程序改用中断再实现出来,同时数码管显示抖动和“鬼影”也一并处理掉了。程序运行的流程跟图6-1所示的流程图是基本一致的,但因为加入了中断,所以整个流程被分成了两部分,秒计数和转换为数码管显示字符的部分还留在主循环内,而动态扫描部分则移到了中断函数内,并加入了消隐的处理。下面来看程序:

#include

sbitADDR0=P1^0;

sbitADDR1=P1^1;

sbitADDR2=P1^2;

sbitADDR3=P1^3;

sbitENLED=P1^4;

unsignedcharcodeLedChar[]={//数码管显示字符转换表

0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,

0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E

};

unsignedcharLedBuff[6]={//数码管显示缓冲区,初值0xFF确保启动时都不亮

0xFF,0xFF,0xFF,0xFF,0xFF,0xFF

};

unsignedchari=0;//动态扫描的索引

unsignedintcnt=0;//记录T0中断次数

voidmain()

{

unsignedlongsec=0;//记录经过的秒数

EA=1;//使能总中断

ENLED=0;//使能U3,选择控制数码管

ADDR3=1;//因为需要动态改变ADDR0-2的值,所以不需要再初始化了

TMOD=0x01;//设置T0为模式1

TH0=0xFC;//为T0赋初值0xFC67,定时1ms

TL0=0x67;

ET0=1;//使能T0中断

TR0=1;//启动T0

while(1)

{

if(cnt>=1000)//判断T0溢出是否达到1000次

{

cnt=0;//达到1000次后计数值清零

sec++;//秒计数自加1

//以下代码将sec按十进制位从低到高依次提取并转为数码管显示字符

LedBuff[0]=LedChar[sec%10];

LedBuff[1]=LedChar[sec/10%10];

LedBuff[2]=LedChar[sec/100%10];

LedBuff[3]=LedChar[sec/1000%10];

LedBuff[4]=LedChar[sec/10000%10];

LedBuff[5]=LedChar[sec/100000%10];

}

}

}

/*定时器0中断服务函数*/

voidInterruptTimer0()interrupt1

{

TH0=0xFC;//重新加载初值

TL0=0x67;

cnt++;//中断次数计数值加1

//以下代码完成数码管动态扫描刷新

P0=0xFF;//显示消隐

switch(i)

{

case0:ADDR2=0;ADDR1=0;ADDR0=0;i++;P0=LedBuff[0];break;

case1:ADDR2=0;ADDR1=0;ADDR0=1;i++;P0=LedBuff[1];break;

case2:ADDR2=0;ADDR1=1;ADDR0=0;i++;P0=LedBuff[2];break;

case3:ADDR2=0;ADDR1=1;ADDR0=1;i++;P0=LedBuff[3];break;

case4:ADDR2=1;ADDR1=0;ADDR0=0;i++;P0=LedBuff[4];break;

case5:ADDR2=1;ADDR1=0;ADDR0=1;i=0;P0=LedBuff[5];break;

default:break;

}

}

大家可以先把程序抄下来,编译下载到单片机里运行,看看实际效果。是否可以看到,近乎完美的显示效果经过我们的努力终于做成功了。下面我们还要再来解析一下这个程序。

在这个程序中,有两个函数,一个是主函数,一个是中断服务函数。主函数main()我们就不用说了,重点强调一下中断服务函数,它的书写格式是固定的,首先中断函数前边void表示函数返回空,即中断函数不返回任何值,函数名是InterruptTimer0(),这个函数名在符合函数命名规则的前提下可以随便取,我们取这个名字是为了方便区分和记忆,而后是interrupt这个关键字,一定不能错,这是中断特有的关键字,另外后边还有个数字1,这个数字1怎么来的呢?我们先来看表6-3。

表6-3中断查询序列

中断

函数编号

中断名称

中断

标志位

中断

使能位

中断

向量地址

默认

优先级

0

外部中断0

IE0

EX0

0x0003

1(最高)

1

T0中断

TF0

ET0

0x000B

2

2

外部中断1

IE1

EX1

0x0013

3

3

T1中断

TF1

ET1

0x001B

4

4

UART中断

TI/RI

ES

0x0023

5

5

T2中断

TF2/EXF2

ET2

0x002B

6

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top