*外中断INT0--------void intsvr0(void) interrupt 0 using 1
*定时/计数器T0-----void timer0(void) interrupt 1 using 1
*外中断INT1--------void intsvr0(void) interrupt 2 using 1
*定时/计数器T1-----void timer0(void) interrupt 3 using 1
*串口中断----------void serial0 interrupt 4 using 1
P3口的代替功能 寄存器地址B0H,位寻址B7H~B0H。 引脚P3.0P3.1P3.2P3.3P3.4P3.5P3.6P3.7代替功能RXDTXD/INT0/INT1T0T1/WR/RD 1、IE:中断允许控制寄存器 寄存器地址A8H,可按位寻址,位寻址AFH~A8H。复位IE全部清零 位地址AFAEADACABAAA9A8位符号EA/ET2ESET1EX1ET0EX0位序号D7D6 D5D4D3D2D1D0 EA:中断允许总控制位 当EA=0时,中断总禁止。 当EA=1时,中断总允许后中断的禁止与允许由各中断源的中断允许控制位进行设置。 EX0(EX1):外部中断允许控制位 当EX0(EX1)=0禁止外中断 当EX0(EX1)=1允许外中断 ET0(EX1):定时/计数中断允许控制位 当ET0(ET1)=0 禁止定时(或计数)中断 当ET0(ET1)=1 允许定时(或计数)中断 ET2:定时器2中断允许控制位 ES:串行中断允许控制位 当ES=0 禁止串行中断 当ES=1 允许串行中断 2、IP:中断优先级控制寄存器 寄存器地址B8H,位寻址BFH~B8H。 位序号D7D6 D5D4D3D2D1D0位地址BFHBEHBDHBCHBBHBAHB9HB8H位符号//PT2PSPT1PX1PT0PX0 PX0——外部中断0优先级设定位,1为高优先级中断,0为低优先级中断 PT0——定时中断0优先级设定位 PX1——外部中断1优先级设定位 PT1——定时中断1优先级设定位 PS——串口中断优先级设定位 PT2——定时器2优先级设定位 3、TCON:定时器控制寄存器 寄存器地址88H,位寻址8FH~88H。 位地址8FH8EH8DH8CH8BH8AH89H88H位符号TF1TR1TF0TR0IE1IT1IE0IT0 TR0(TR1)——定时器运行控制位 当TR0(TR1)=0 停止定时器/计数器工作 当TR0(TR1)=1 启动定时器/计数器工作 IE0(IE1)——外中断请求标志位 当CPU采样到P3.2(P3.3)[INT0或INT1]出现有效中断请求时,此位由硬件置1。在中断响应完成后转向中断服务时,再由硬件自动清0。 IT0(IT1)——外中断请求信号方式控制位 当IT0(IT1)=1脉冲方式(后沿负跳有效)下降沿触发有效 当IT0(IT1)=0电平方式(低电平有效)此位由软件置1或清0。 TF0(TF1)——计数溢出标志位 当计数器产生计数溢出时,此位由硬件置1。当转向中断服务时,再有硬件自动清0。计数溢出的标志位的使用有两种情况:采用中断方式时,作中断请求标志位来使用;采用查询方式时,作查询状态位来使用。 |
4、TMOD:工作方式控制寄存器
寄存器地址89H,不可位寻址。
位序 |
B7 |
B6 |
B5 |
B4 |
B3 |
B2 |
B1 |
B0 |
位符号 |
GATE |
C/T |
M1 |
M0 |
GATE |
C/T |
M1 |
M0 |
GATE——门控位
当=0时,以运行TR0(或TR1)启动或禁止定时器、计数器
当=1时,以TR0*/INT0(或TR1*/INT1)启动或禁止定时器、计数器
GATE=0 以TCON寄存器中的TR0(TR1)启动定时器/计数器
GATE=1 TCON寄存器中的TR0(TR1)和外部中断引脚INT0(INT1)启动定时器,高电位有效
C/T=1由外引脚T0或T1做计数脉冲,C/T=0由TH和TL做定时数。 M1M0——工作方式选择位
M1,M0:用来选择计时计数器工作模式
M1 |
M0 |
工作模式 |
说明 |
0 |
0 |
0 |
13位计时计数器 (8192) |
0 |
1 |
1 |
16位计时计数器 (65536) |
1 |
0 |
2 |
8位计时计数器,可自动重新载入计数值 (256) |
1 |
1 |
3 |
当成两组独立的8位计时器(256,T0和T1不能同时用) |
5、T2MOD:工作方式控制寄存器
寄存器地址0C9H,不可位寻址,用来设定定时器2自动重装模式递增或递减模式
- |
- |
- |
- |
- |
- |
T2OE |
DCEN |
T2OE:定时器2输出允许位,当=1时,P1.0/T2引脚输出连续脉冲信号
DCEN:当=1时,T2配置成向上向下计数器
6、T2CON:定时器控制寄存器,可进行位寻址
寄存器地址0C8H,位寻址0C8H~0CFH。
位地址 |
CF |
CE |
CD |
CC |
CB |
CA |
C9 |
C8 |
位符号 |
TF2 |
EXF2 |
RCLK |
TCLK |
EXEN2 |
TR2 |
C/T2 |
CP/RL2 |
TF2:T2溢出标记;方式2,3置TF2,方式3不置。
当T2溢出时TF2=1,TD2只能用软件清0
当RCLK=1或TCLK=1时,TF2将不置位
EXF2:T2外部标记
当EXEN2=1时,T2EX/P1.1引脚上的负跳变引起T2的捕捉/重装操作,此时EXF2=1。在T2中断允许时,EXF2=1将引起中断,EXF2只能用软件清除。在T2的递增、递减计数模式下(DCEN=1)EXF2的置位将不引起中断。
RCLK:接收时钟允许
当RCLK=1时,T2的溢出脉冲可用作串行口的接收时钟信号,适于串行口模式1、3当RCLK=0时,T1的溢出脉冲用作串行口接收时钟信号
TCLK:发送时钟允许
当RCLK=1时,T2的溢出脉冲可用作串行口的接收时钟信号,适于串行口模式1、3当RCLK=0时,T1的溢出脉冲用作串行口发送时钟信号
EXEN2:T2外部事件(引起捕捉/重装的外部信号)允许,即外部使能标志
当EXEN2=1时,如果T2没有作串行时钟输出(即RCLK+TCLK=0),则在T2EX/P1.1引脚跳变将引起T2的捕捉/重装操作;
当EXEN2=0时,在T2EX引脚的负跳变将不起作用
TR2:T2计数控制位;TR2=1时允许计数/定时。
C/T2:外部计数器/定时器选择位;C/T2=1时为计数器,计数脉冲来自T2(P1.0);下降沿触发
C/T2=0时为内部定时器,以震荡脉冲的十二分频信号为计数信号。
CP/RL2:捕捉/重装选择
当CP/RL2=1且EXEN2=1时,T2EX/P1.1引脚的负跳变将引起捕捉操作
当CP/RL2=0且EXEN2=1时,T2EX/P1.1引脚的负跳变将引起重装操作
当CP/RL2=0且EXEN2=0时,T2的溢出将引起T2的自动重装操作
当RCLK+TCLK=1时,CP/RL2控制位不起作用,T2被强制工作于重装方式。重装方式发生于T2溢出时,常用来作波特率发生器。
7、SCON:串行口控制寄存器
寄存器地址98H,位寻址9FH~98H。
位地址 |
9F |
9E |
9D |
9C |
9B |
9A |
99 |
98 |
位符号 |
SM0 |
SM1 |
SM2 |
REN |
TB8 |
RB8 |
TI |
RI |
SM0、SM1:串行口工作方式选择位
SM2:多机通信控制位
对于方式0:SM2=0。
对于方式1:SM2=1,只有接到有效的停止位才激活RI。
对于方式2和3为多机通信控制位;SM2=1,则接收的第9位数据为0时不激活RI
REN:允许/禁止串行口接收的控制位,REN=1允许接收数据
TB8:在方式2和方式3中,是被发送的第9位数据,可根据需要由软件置1或清零,也可以作为奇偶校验位,在方式1中是停止位。
RB8:在方式2和方式3中,是被接收的第9位数据(来自第TB8位);在方式1中,RB8收到的是停止位,在方式0中不用。
TI:串行口发送中断请求标志位
当发送完一帧串行数据后,由硬件置1;在转向中断服务程序后,用软件清0。
RI:串行口接收中断请求标志位
当接收完一帧串行数据后,由硬件置1;在转向中断服务程序后,用软件清0。
8、PSW:程序状态字
寄存器地址D0H,位寻址D7H~D0H。
位地址 |
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
位符号 |
CY |
AC |
F0 |
RS1 |
RS0 |
OV |
- |
P |
CY——进位标记。CY=1表示运算时有进位产生。
AC——半进位标记。补助进位位;AC=1表示运算时较低4位有进位产生。
F0——用户设定标记
RS1 、RS0——4个工作寄存器区的选择位。
RS1 |
RS0 |
选择的寄存器组 |
0 |
0 |
寄存器组0 |
0 |
1 |
寄存器组1 |
1 |
0 |
寄存器组2 |
1 |
1 |
寄存器组3 |
OV——溢出标记. OV=1表示运算时有益出产生
P——奇偶校验标记. 奇偶位;P=0表示A中1的个数是偶数,P=1表示A中1的个数是奇数。
9、PCON:电源控制器及波特率选择寄存器
字节地址=87H,不可位寻址
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D |
D0 |
SMOD |
(SMOD0) |
(LVDF) |
(POF) |
GF1 |
GF0 |
PD |
IDL |
SMOD——波特率倍增位
SMOD=1:串口方式1,2,3时,波特率正常
SMOD=0:串口方式1,2,3时,波特率加倍
(SMOD0) |
(LVDF) |
(POF) |
是STC单片机特有的功能
GF1、GF0——用户通用标记,用户课*使用
PD——掉电模式控制位,PD=1时进入掉电模式,在硬件复位或外中断低电平触发或由下降沿触发恢复。进入掉电模式,外部晶振,cpu,定时器,串行口全部停止工作,只有外部中断工作
IDL——空闲模式控制位,IDL=1时进入空闲模式,除cpu外,其余继续工作。
在AT89S51中PCON.4是电源断电标记位POF,上电是为1
进入空闲模式:PCON=0x01; 之前执行AUXR=0xFF;定义空闲模式下看门狗WDT不计数。
定时器
1)对TMOD赋值,以确定T0和T1的工作方式
2)计算初值,并将初值写入TH0,TL0或TH1,TL1
3)中断方式时,对IE赋值,开放中断
4)使TR0或TR1置位,启动定时器计数器定时或计数
能在主程序完成的功能就不在中断函数中些,否则一定要高效简洁
方式0和方式3很少用,方式1 用作16位的计数器,方式2用在串口波特率发生器
1、发光二极管以一秒亮灭,11.0592M晶振
l定时器0工作方式1
#include <reg52.h> //52系列单片机头文件
#define uchar unsigned char
#define uint unsigned int
sbit led1=P1^0;
uchar num;
void main()
{
TMOD=0x01; //设置定时器0为工作方式1(M1M0为01)
TH0=(65536-45872)/256; //装初值11.0592M晶振定时50ms为45872
TL0=(65536-45872)%256;
EA=1; //开总中断
ET0=1; //开定时器0中断
TR0=1; //启动定时器0
while(1) //程序停止在这里等待中断发生
{
if(num==200) //如果到了200次,说明1秒时间到
{
num=0; //然后把num清0重新再计200次
led1=~led1; //让发光管状态取反
}
}
}
void T0_time() interrupt 1
{
TH0=(65536-45872)/256; //重装初值
TL0=(65536-45872)%256;
num++;
}
l定时器0工作方式0
1、定时器方式0为13位计数器,最多能装载的数2^=8192个,所以最多经过8192个机器周期该计数器就会溢出一次,向cpu申请中断
2、计算机器周期T,晶振为11.0592MHz,那么机器周期为12*(1/11059200)=1.0851微s,若t=5ms,则N=5000/1.0851=4607
3、TH0=(8192-4607)/32;中,对32求模是因为定时器方式0为13位计数器,计数支使用了TL0的低5位,这5位最多装载32个数,再加1进位。16位计数器装载256个数
void main()
{
TMOD=0x00;//设置定时器0为工作方式0(0000 0000)
TH0=(8192-4607)/32; //装初值
TL0=(8192-4607)%32;
EA=1; //开总中断
ET0=1; //开定时器0中断
TR0=1; //启动定时器0
l定时器T0的定时方式2
1、定时器2被称为8位初值自动装载的8位定时器/计数器,THX被作为常数缓冲器,TLX计数溢出时,在溢出标志TFX置1的同时,还自动将THX中的常数重新装入TLX中,使TLX从初值开始重新计数,提高定时的精度。
2、定时器2特别适合做较精确的脉冲信号发生器,此时晶振频率一定要是12 的整数倍。
方式2为8位计数器,最多装2^8=256个,即使用12MHz晶振,最多只有256微秒
3、机器周期为12*(1/11059200)=1.0851微s,计时1s,当计250个数,需1.0851*250=271.275微秒。需要溢出1000000/271.275=3686,若为12MHz晶振,则溢出4000次
4、主要应用在串口波特率发生器。
#include <reg52.h> //52系列单片机头文件
#define uchar unsigned char
#define uint unsigned int
sbit led1=P1^0;
uint num; //3686远远超过了uchar的范围
void main()
{
TMOD=0x02; //设置定时器0为工作方式2(0000 0010)
TH0=6; //装初值
TL0=6;
EA=1; //开总中断
ET0=1; //开定时器0中断
TR0=1; //启动定时器0
while(1) //程序停止在这里等待中断发生
{
if(num==3686) //如果到了3686次,说明1秒时间到
{
num=0; //然后把num清0重新再计3686次
led1=~led1; //让发光管状态取反
}
}
}
l定时方式3
1、方式3只适用于定时器/计数器T0,当设定定时器T1为方式3,定时器T1不计数,T0分成两个独立的8位计数器TL0和TH0。
2、其中TL0为正常8位计数器,计数溢出后置位TF0,并向CPU申请中断,之后重新装初值。TH0将占用定时器T1的。
3、在工作方式3时,T1一定不要用在有中断的场合,不过可以用来当做串行口的波特率发生器。
TL0计数器对应的8位定时器
#include <reg52.h> //52系列单片机头文件
#define uchar unsigned char
#define uint unsigned int
sbit led1=P1^0;
sbit led2=P1^1;
uint num1,num2;
void main()
{
TMOD=0x03; //设置定时器0为工作方式3(0000 0011)
TH0=6; //装初值
TL0=6;
EA=1; //开总中断
ET0=1; //开定时器0中断
ET1=1; //开定时器1中断
TR0=1; //启动定时器0
TR1=1; //启动定时器0的高8位计数器
while(1) //程序停止在这里等待中断发生
{
if(num1>=3686) //如果到了3686次,说明1秒时间到
{
num1=0; //然后把num1清0重新再计3686次
led1=~led1; //让发光管状态取反
}
if(num2>=1843) //如果到了1843次,说明半秒时间到
{
num2=0; //然后把num2清0重新再计1843次
led2=~led2; //让发光管状态取反
}
}
}
void TL0_time() interrupt 1
{
TL0=6; //重装初值
num1++;
}void TH0_time() interrupt 3
{
TH0=6; //重装初值
num2++;
}
1、定时器0的方式1实现第一个发光二极管以200ms间隔闪烁,定时器1的方式1实现数码管前两位59s循环计时
#include <reg52.h> //52系列单片机头文件
#define uchar unsigned char
#define uint unsigned int
sbit led1=P1^0;
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
void delayms(uint);
void display(uchar,uchar) ;
uchar num, num1,num2,shi,ge;
void main()
{
TMOD=0x01; //设置定时器0为工作方式1(M1M001)
TH0=(65536-45872)/256; //装初值11.0592M晶振定时50ms为45872
TL0=(65536-45872)%256;
TH1=(65536-45872)/256; //装初值11.0592M晶振定时50ms为45872
TL1=(65536-45872)%256;
EA=1; //开总中断
ET0=1; //开定时器0中断
ET1=1; //开定时器1中断
TR0=1; //启动定时器0
TR1=1; //启动定时器1
while(1) //程序在这里不停地对数码管动态扫描同时等待中断
{
display(shi,ge);
}
}
void display(uchar shi,uchar ge) //显示子函数
{
P0=table[shi]; //送十位段选数据
P0=0xfe; //送位选数据
delayms(5); //延时
P0=table[ge]; //送个位段选数据
P0=0xfd;
delayms(5);
}
void delayms(uint xms)
{
uint i,j;
for(i=xms;i>0;i--) //i=xms即延时约xms毫秒
for(j=110;j>0;j--);
}
void T0_time() interrupt 1
{
TH0=(65536-45872)/256; //重装初值
TL0=(65536-45872)%256;
num1++;
if(num1==4) //如果到了4次,说明200ms时间到了
{
num1=0; //清零,重新再计
led1=~led1;
}
}
void T1_time() interrupt 3
{
TH1=(65536-45872)/256; //重装初值
TL1=(65536-45872)%256;
num++;
if(num2==20) //说明一秒到
{
num2=0;
num++;
if(num==60) //这个数送数码管显示,到60归零
num=0;
shi=num/10;
ge=num%10; //把一个2位数分离后分别送数码管显示各位和十位
}
}
2、不按键时,P1口的led呈流水灯显示,按下K1(P3.2),P1口左右4个LED交替闪烁,按下K2(P3.3),P1口LED闪亮,外中断优先级相同。
#include <reg52.h> //52系列单片机头文件
#define uchar unsigned char
#define uint unsigned int
void delayms(uint xms)
{
uint i,j;
for(i=xms;i>0;i--) //i=xms即延时约xms毫秒
for(j=110;j>0;j--);
}
void main()
{
uchar design[9]={0xFF,0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};
uchar a;
for(;;)
{
for(a=0;a<9;a++)
{
delayms(500);
P1=design[a];
}
EA=1; //开放总开关
EX0=1; //允许外部中断0中断
EX1=1; //允许外部中断1中断
IT0=1; //设置外部中断0为边沿中断方式
IT1=1; //设置外部中断1为边沿中断方式
IP=0; //设置中断优先级
}
}
void intsvr0(void) interrupt 0
{
for(;;)
{
P1=0x0F; //左4个灯亮
delayms(500);
P1=0xF0; //右4个灯亮
delayms(500);
}
}
void intsvr1(void) interrupt 2
{
for(;;)
{
P1=0xFF; //全灭
delayms(500);
P1=0; //全亮
delayms(500);
}
}