Proteus仿真:C51中断函数实例
原创
©著作权归作者所有:来自51CTO博客作者海轰Pro的原创作品,请联系作者获取转载授权,否则将追究法律责任
实现目标
要求外部中断INT0和INT1为低电平触发,相应引脚分别接一按钮,按钮按下接地输入低电平,产生中断信号;定时器/计数器T0和定时器/计数器T1设置为外部计数输入,相应引脚接1khz的方波信号,T0每满2000个脉冲产生1次中断,T1每满4000产生一次中断
Proteus仿真图
C51代码
#include <REG52.H> /* special function register declarations */
#include <stdio.h> /* prototype declarations for I/O functions */
#define byte unsigned char
#define uchar unsigned char
#define word unsigned int
#define uint unsigned int
#define ulong unsigned long
#define BYTE unsigned char
#define WORD unsigned int
#define TRUE 1
#define FALSE 0
void initUart(void);/*初始化串口*/
void time(unsigned int ucMs);//延时单位:ms
/******** main 函数 *********/
void main (void) {
initUart();/* 初始化串口 */
TMOD=0x55; /* 工作在方式1,外部引脚计数 */
TH0=-2000>>8;TL0=-2000 % 256;/* 定时器0每2000计数脉冲发生1次中断 */
TH1=-4000>>8;TL1=-4000 % 256;/* 定时器1每4000计数脉冲发生1次中断 */
TCON=0x55; /* 电平触发外部中断,开始计数 */
IE=0x8f; /*打开出串口中断外其它所有中断*/
while (TRUE) {
time(1);/* 延时1ms */
}
}
/*********** 中断0服务程序***************/
void exint0(void) interrupt 0
{
EA=0;/* 关总中断 */
/* 可在此处插入外部中断0服务程序 */
printf ("external interrupt 0 happened\n");
EA=1;/* 开总中断 */
}
/*********** 中断1服务程序***************/
void exint1(void) interrupt 2
{
EA=0;/* 关总中断 */
/* 可在此处插入外部中断1服务程序 */
printf ("external interrupt 1 happened\n");
EA=1;/* 开总中断 */
}
/******* 定时器/计数器0中断服务程序 ***/
void timer0int(void) interrupt 1
{
EA=0;/* 关总中断 */
TR0=0;/*停止计数*/
/* 可在此处插入定时器/计数器0中断服务程序 */
TH0=-2000>>8;TL0=-2000 % 256;/* 重置计数初值 */
printf ("timer0 interrupt happened\n");
TR0=1;/*启动计数*/
EA=1;/* 开总中断 */
}
/******* 定时器/计数器1中断服务程序 ***/
void timer1int(void) interrupt 3
{
EA=0;/* 关总中断 */
TR1=0;/*停止计数*/
/* 可在此处插入定时器/计数器1中断服务程序 */
TH1=-4000>>8;TL1=-4000 % 256;/* 重置计数初值 */
printf ("timer1 interrupt happened\n");
TR1=1;/*启动计数*/
EA=1;/* 开总中断 */
}
/********** 初始化串口波特率 ************/
void initUart(void)/*初始化串口波特率,使用定时器2*/
{
/* Setup the serial port for 9600 baud at 11.0592MHz */
SCON = 0x50; //串口工作在方式1
RCAP2H=(65536-(3456/96))>>8;
RCAP2L=(65536-(3456/96))%256;
T2CON=0x34;
TI = 1; /* 置位TI*/
}
/*********** 延时单位:ms *******************/
void time(unsigned int ucMs)//延时单位:ms
{
unsigned char j;
while(ucMs>0){
for(j=0;j<10;j++) delay_100us();
ucMs--;
}
}
笔记
TCON:定时器/计数器控制
TMOD:定时器/计数器方式控制
TH0:定时器/计数器0高字节
TL0:定时器/计数器0低字节
TH1:定时器/计数器1高字节
TL1:定时器/计数器1低字节
IE:中断允许控制
EA:CPU中断允许控制位
注1:
TH0=-2000>>8;TL0=-2000 % 256;/* 定时器0每2000计数脉冲发生1次中断 */
上面代码定义定时器0每2000计数脉冲发生1次中断
-2000>>8 表示 -2000/256,因为定时器/计数是16位,除以256表示取高8位
-2000%256表示取低8位
注2:
每2000计数脉冲,在程序中写的的-2000,而不是2000。 为什么呢?
这是因为计时器是向上计数,为了得到2000个计数脉冲后定时器溢出, 则必须给计时器赋初值为65536-2000(65536=2的16次方)
其实也就是-2000(取反再+1) emm 举个例子就会懂了 假设计数器是4位,最大溢出时为1111(15)
我们需求是7个脉冲产生一个中断
那么计数器初始值就是16-7(9) 9=1001
-7=-(0111)=1001(取反再+1)
==》16-7=-7 所以是-2000/256 和 -2000%256
运行结果
C51中断实例
说明
参考课本:单片机原理与嵌入式系统设计