今天学习了第八课,按小宋老师的意思,确实内容不太多,也比较好理解,当然看得出来,小宋老师非常重视这个中断的内容,我想确实是应该引起相当地重视的。
中断有一个特殊寄存器,一共有八位,用于表示不同的中断类型,如果要使用中断,则要对对应的中断类型进行设置为1,才表示程序代码将要对某种类型的中断进行处理,希望单片机能够进入我们开发的中断处理程序中。当然最高位EA表示总使能,在需要使用中需要将其设置为1,在小宋老师的教程中,使用的是定时器1,故在程序里面将ET1设置为了1,表示对定时器1的中断感兴趣,那么一但定时器1的溢出位溢出时,则将会进行我们的中断响应程序中来。另外如何计算中断响应程序的后面那个中断标号的计算方法应该也是很重要的,其是根据中断对应的中断的向量地址进行计算的,这个公式是向量地址-3和差再除以8得出。当然如果响应了计数器的中断事件,则计数器的溢出位会自动归0,以继续进行,而不用像前面那样进行软件清零。
另外关于中断使用寄存器与计数器寄存器的关系,我们可以这么想象,当我们使用读数器时,其会进行计数的自行运行,当达到溢出位时,如果不进行软件清零的话,则将停止。而在设计单片机中,由于人们对这个计数器的溢出那一刻很感兴趣,于是就做了一个中断出来,并在另外一个寄存器中进行了标识,即本课中的这个IE寄存器,其能够全能的前提是设置对应的使能值以表示对某一个事件感兴趣,如本课中的计数器1溢出事件。由于一个程序可能存在着多个中断响应函数,故通过中断标号进行标识,从而使不同的中断事件响应对应不同的中断标号以达到对不同的中断事件进行响应的目的。
在看他的程序时,我想起了在第六课学习中,后面我想自己通过一个数码管显示一个类似于计时的内容,即按10进制累进的方式进行计数。当时最开始想到的是用取余的方式,取得一个数的各个位,后面竟然发现不行,今天看了下小宋教师的内容,发现其实是可以的。再想起之前的程序,考虑了一下,发现了主要问题是在刷新6个数码管显示数字上,我当时将这个过程直接放在while(1)里面,这样就产生了一个很严重的问题,就是由于其运行太快,而所有的数码管都来不急显示的情况下,被程序进行了P0的不断新的设置值,而由于太过的缘故,导致原来显示的还没有来得及消失,就有新的值来了,所以导致显示很乱,而不法发现原因。
后面还是改成每经过一个毫秒改变一个数码管的值,那么经过每6秒就可以刷新一下某个数码管的值,这样就没有问题了。好像人能感受到变化的时间是20毫秒,这里只有6秒内进行更新,所以从视觉上来说是没有太大问题的,当然似乎还可以再延迟一下,估计也没有太大问题,不过我就没有试了,像这样的问题,等我对单片机掌握得差不多了,就能充分地进行试验了,当然这种想法似乎不太好,但暂时不想去想那么多,我现在最需要的是更进一步地学习单片机。
下面是对第六课的计数器程序的修改代码。
#include <reg52.h>
typedef unsigned char uint8;
typedef unsigned int uint16;
typedef unsigned long uint32;
uint8number[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
sbit ENLED = P1^4;
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
main()
{
uint8j;
uint8num6,num5,num4,num3,num2,num1;
uint16counter;
uint32sec;
ENLED= 0; ADDR3=1;
TMOD= 0X01;
TH0=0Xfc;//设置计数器0的初始值,相应的有TH1,TL1。
TL0=0X67;
TR0=1;//计数器一开始计时
counter=0; //counter声明时默认值为0,不过此处明确赋初始值为0会更明白些
j=0;
while(1)
{
if(TF0==1)//表示完成一次溢出
{
TF0=0; //由于本次未响应中断,则要采用软件清0的方式进行
TH0=0Xfc;
TL0=0X67;
counter++;
switch(j++)
{
case0:ADDR0=0;ADDR1=0;ADDR2=0;P0=number[num1];break;
case1:ADDR0=1;ADDR1=0;ADDR2=0;P0=number[num2];break;
case2:ADDR0=0;ADDR1=1;ADDR2=0;P0=number[num3];break;
case3:ADDR0=1;ADDR1=1;ADDR2=0;P0=number[num4];break;
case4:ADDR0=0;ADDR1=0;ADDR2=1;P0=number[num5];break;
case5:ADDR0=1;ADDR1=0;ADDR2=1;P0=number[num6];j=0;break;
default:break;
}
}
if(counter ==1000)//表示完成了20次溢出,花费时间就是一秒。
{
counter=0;
sec++;
if(sec>999999)
{
sec= 0;
}
num1=sec%10;
num2=sec/10%10;
num3=sec/100%10;
num4=sec/1000%10;
num5=sec/1000%10;
num6=sec/10000%10;
}
}
}
此处取模的方式是这样取。