这个实验是老师布置的课后作业,当时老师只教了外部中断,但是经过我课后学习,发现这个实验用外部中断和定时器中断结合挺好的。先来简单介绍以下该实验。
实验简介与原理
1.实验功能
数码管显示计时,独立按键按下时,计时暂停,再次按下时,继续计时。
2.实验原理
这次实验的重点是中断系统的运用,,所以重点讲一下中断系统的原理。
中断程序是和主程序配合享用的。主程序即为当前程序一直在做的事,而中断程序是突发事件(即中断源)到来,先中止当前事件,转而去处理突发事件,待处理完成后,再返回原先被终止的工作处,继续进行随后的工作。
51单片机提供了5个中断源,本次实验我用到了外部中断INT0和定时器INT1
图片第二列简而言之就是中断允许的开关,如果想使用某个中断,一定要将该开关置为1;;第三列是触发中断的要求;
一旦需要中断响应,那么cpu会保存当前中断的语句位置,然后跳转到中断服务程序。不同于子程序会根据函数名跳转,cpu会根据中断号来查找对应的中断程序,第五列即是中断号。
中断程序的书写格式是:
void 函数名() interrupt 中断号
{
}
同时在该程序中我运用到了定时器,所以说一下定时器的原理。
定时器的运行包含了启动、机器周期、初值寄存器(TH0和TL0,TH0是高八位,TL0是低八位)、寄存器自动加一(经过一个机器周期后)、溢出。
上图为寄存器的自动加一,每一个机器周期为1us,溢出需要65536个周期,即65536us。对于我程序中定时的1s,65536us是远远不够的,我们可以从15536个周期开始计时,那么一次溢出就只需要50ms,只需要溢出20次就达到一秒了。所以我们需要定义初值:
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
使用定时器的步骤:
1.报备,即给TMOD(工作方式寄存器)赋值:
2.赋初值。
3.启动:TR0=1;
TR0=0;(停止)
4.等待溢出:移除后TF0自动置为1,不过我们需要手动置为0,等待下次溢出。
5.重置初值:我的定时器的中断函数有写。
另外的数码管和独立按键的原理就不赘述了,在之前的实验报告中已经写了很多次了。需要注意的是,当使用中断系统时,独立按键仅K3(P3^2)、K4(P3^3)有效。
代码
注:该代码仅实现了0-9的计时。
如有不足,请各位大佬评论区指正~
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit key=P3^2;
uchar k;
code uchar smg[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
void delay(uint ms)
{
uint i,j;
for(i=ms;i>0;i--)
for(j=114;j>0;j--);
}
void key0() interrupt 0
{
delay(20);
if(!key)
{
TR0=~TR0;//暂停/继续计时
}
}
void timer0() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
k++;
}
void main()
{
uchar i;
k=0;
TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1;
ET0=1;
EX0=1;
IT0=1;
TR0=1;//启动!
while(1)
{
for(i=0;i<10;i++)
{
P0=smg[i];
while(k<20);//每一秒计数一次
k=0;//将k重置,进行下一轮计时
}
}
}