文章目录
一、外部中断
中断初始化(3步)
1、打开总
中断;
2、打开外部中断开关
;
3、设置中断的触发方式
。
直接在主函数中搞吧 简单粗暴一点
main()
{
LED=0xff; //P1口初始值 关闭led灯
EA=1; //全局中断开 打开总中断
EX0=1; //外部中断0开
IT0=0; //设置外部中断的触发方式:电平触发
while(1)
{
//在此添加其他程序,中断程序可以跟此处的程序同步执行
}
}
外部中断程序
void Key_INT(void) interrupt 0 using 1
{
LED =~LED; //触发中断后,反转当前LED的状态
}
查看手册
发现外部中断0
的触发引脚(开关)是P32
引脚,所以把P_32接地(图中显示 低电平有效嘛,给0不就对了),即可触发外部中断0
。
二、定时器中断
定时器中断初始化(5步)
1、设置定时器模式
;
2、设置定时器初值
;
3、打开总
中断;
4、打开定时器中断
开关;
5、打开定时器开关
。
定时器中断初始化配置
void Init_Timer0(void) //定时器初始化子程序
{
TMOD |= 0x01; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
TH0=0x0D8; //给定初值,这里使用定时器最大值从0开始计数一直到65535溢出
TL0=0x0F0;
EA=1; //总中断打开
ET0=1; //定时器中断打开
TR0=1; //定时器开关打开
}
定时器中断程序
interrupt 中断号
一定要写 程序是靠识别
这个进入的,using写不写无所谓。
中断号可以在开发手册或百度上找到
void Timer0(void) interrupt 1 using 0
{
TH0=0x0D8; //重新赋值,方式1是16位计数器 最大装载值为65536
TL0=0x0F0; //每次计时10ms
cnt++;
/*用户代码部分*/
if(cnt == 100)//计时 满1s 执行
{
LED=~LED; //指示灯反相,可以看到闪烁
cnt = 0;
}
}
主函数调用定时器初始化函数
main()
{
Init_Timer0();
while(1);
}
要先在
main函数
里先调用定时器0初始化配置
,才能正常使用它。
1.待计时达到我们设置的数值时,程序会自动跳入定时器中断程序
2.进入以后 会重新给TH、TL
重新赋值,以便下一次的计数。(程序会一直以设置的时长为周期反复进入中断
)这便是定时器中断
。
三、串口
涉及寄存器
1、SCON(Serial Control 串口控制)98H
用于设置串行口的工作方式、监视串行口的工作状态、控制发送与接收的状态等。
它是一个既可以字节寻址
又可以位寻址
的8位特殊功能寄存器
。
其格式如下图
其中
SM2
、TB8
、RB8
这几位基本没有用到,不用管。
只要:
——SM0
、SM1
、REN
、TI
、RI
就行啦!
——SerialMode0、ReceiveEnable、TransmitInterrupt、ReceiveInterrupt(展开了记好理解
)!
我的理解是:
1、SM0 SM1的位置是和我们的逻辑相反的(SM0=0 SM1=1 是方式一 );
2、方式0 不算串口,它是 移位寄存器 用来扩展IO口用的;
3、并且用的比较多的是方式一
,我们只要收发数据嘛,一就够了。其它方式的了解一下就行啦;
3、发送完一帧数据后,要用软件把TI
清零,才能再发送下一帧;
4、接收完一帧数据后,要用软件把RI
清零,才能再接收下一帧;
2、PCON
就一位用到了SMOD
,用来设置波特率 加不加倍的。
3、IE -InterruptEnable 中断允许控制寄存器(A8H)
作用:CPU对中断系统所有中断以及某个中断源的开放和屏蔽是由中断 允许寄存器E控制的。
EnableAll Interrupt、EnableSeria lnterrupt、EnableTimer Interrupt、EnableExternal Interrupt
使能所有中断、使能串口中断、使能定时\计数器中断、使能外部中断
串口初始化配置(5步)
1、用定时器设置波特率、工作方式
__a.设置T1的工作方式
;【TMOD寄存器】
__b.设置T1的初值,装载 TH1、TL1
;(波特率)
__c.启动T1;【TCON寄存器中的TR1
】
2、打开串口接收位
;【SCON寄存器REN
】
3、设置串口工作方式SM0 SM1
;【SCON寄存器】
注意SM0 和 SM1的位置 与 我们正常的逻辑相反
如需串行口在中断方式工作时,要进行中断 设置编程IE
寄存器
打开总开关EA
;打开串口使能为ES
。
void main()
{
TMOD=0x20; //用定时器--方式2
TH1=0xfd; //设置串口波特率 9600
TL1=0xfd;
TR1=1; //打开定时器
REN=1; //串口 接收使能
SM0=0; //SM0 SM1 = 0 1 --串口工作方式1
SM1=1;
EA=1; //开启总中断
ES=1; //串口使能
while(1)
{
if(num==1) //判断是否有串口数据的传送
{
ES=0; //禁止串口中断
num=0; //清空串口数据的传送标志位
SBUF=a; //发送数据a到SBUF,即将单片机的数据发送到计算机
while(!TI); //等待串口发送完成
TI=0; //串口发送完成标志位清零
ES=1; //允许 串口进行下一次的中断
}
}
}
串口在接收到一帧有效数据后由于
硬件
置位RI=1
。然后会进入到下面的串口中断中。
进入 串口接收中断
1. 先把标志位RI
清零,方便接收下一条数据帧;
2. 把接收到的数据从SBUF
中取出,赋给a
,再把num=1
;
___explain: 51的SBUF
是串行口数据缓冲寄存器
,具有输入和输出功能(名称相同,但是物理上是独立的,只是占用同一个地址);
—换句话说,SBUF既是接收缓冲器又是发送缓冲器,同一时间只能为一种,要么接收,要么发送。a=SBUF
是把接收缓冲器
中的数据赋给a
。SBUF=a
是把a
中的数据赋给发送缓冲器
。
!!一句话概括:通过读写缓冲器SBUF实现数据收发功能!!!
3. 回到主函数
,此时的串口数据传送标志位num=1
所以 走if分支
,此时把串口接收关闭
了,再把串口数据的传送标志位num=0
清空。在SBUF=a
,这就是把单片机接收到的数据给发出来在电脑屏幕上显示给你看,然后进入while(!IT)
,等待一帧数据发送完成(即发完一帧数据后TI
会被(硬件)置1)。退出while后,把TI
给清零,方便下一次数据的发送
。再ES=1
打开串口使能位。等待下一次串口收发。
void ser() interrupt 4
{
RI=0; //RI由硬件置为1 表示收到,进入中断以后 就用软件清零
a=SBUF; //把接收到的数据赋给`接收缓存区`
num=1; //再把 num置为1
}