单片机C语言函数之中断函数(中断服务程序)
在开始写中断函数之前,我们来一起回顾一下,单片机的中断系统。
中断的意思(学习过微机原理与接口技术的同学,没学过单片机,也应该知道),我们在这里就不讲了,首先来回忆下中断系统涉及到哪些问题。
(1)中断源:中断请求信号的来源。(8051有3个内部中断源T0,T1,串行口,2个外部中断源INT0,INT1(这两个低电平有效,上面的那个横杠不知道怎么加上去))
(2)中断响应与返回:CPU采集到中断请求信号,怎样转向特定的中断服务子程序,并在执行完之后返回被中断程序继续执行。期间涉及到CPU响应中断的条件,现场保护,现场恢复。
(3)优先级控制:中断优先级的控制就形成了中断嵌套(8051允许有两级的中断嵌套,优先权顺序为INT0,T0,INT1,T1,串行口),同一个优先级的中断,还存在优先权的高低。优先级是可以编程的,而优先权是固定的。
80C51的原则是①同优先级,先响应高优先权②低优先级能被高优先级中断③正在进行的中断不能被同一级的中断请求或低优先级的中断请求中断。
80C51的中断系统涉及到的中断控制有中断请求,中断允许,中断优先级控制
(1)3个内部中断源T0,T1,串行口,2个外部中断源INT0,INT1
(2)中断控制寄存器:定时和外中断控制寄存器TCON(包括T0、T1,INT0、INT1),串行控制寄存器SCON,中断允许寄存器IE,中断优先级寄存器IP
具体的是什么,包括哪些标志位,在这里不讲了,所有书上面都会讲。
在这里我们讲下注意的事项
(1)CPU响应中断后,TF0(T0中断标志位)和TF1由硬件自动清0。
(2)CPU响应中断后,在边沿触发方式下,IE0(外部中断INT0请求标志位)和IE1由硬件自动清零;在电平触发方式下,不能自动清楚IE0和IE1。所以在中断返回前必须撤出INT0和INT1引脚的低电平,否则就会出现一次中断被CPU多次响应。
(3)串口中断中,CPU响应中断后,TI(串行口发送中断请求标志位)和RI(接收中断请求标志位)必须由软件清零。
(4)单片机复位后,TCON,SCON给位清零。
C51语言允许用户自己写中断服务子程序(中断函数)
首先来了解程序的格式:
void 函数名() interrupt m [using n]
{}
关键字 interrupt m [using n] 表示这是一个中断函数
m为中断源的编号,有五个中断源,取值为0,1,2,3,4,中断编号会告诉编译器中断程序的入口地址,执行该程序时,这个地址会传个程序计数器PC,于是CPU开始从这里一条一条的执行程序指令。
n为单片机工作寄存器组(又称通用寄存器组)编号,共四组,取值为0,1,2,3
中断号 中断源
0 外部中断0
1 定时器0
2 外部中断1
3 定时器1中断
4 串行口中断
这5个中断源的中断入口地址为:(在上一篇文章中讲到的ROM前43个存储单元就是他们,这40个地址用来存放中断处理程序的地址单元,每一个类中断的存储单元只有8B,显然不是中断处理的程序,而是存放着中断处理程序的真正地址)
INT0:0003H 0
T0: 000BH 1
INT1:0013H 2
T1: 001BH 3
串口: 0023H 4
中断向量(中断入口地址)= 中断号x8 +3
前面m意思很清楚,不同的m值表示这个函数是针对不同的中断源,比如m为1是表示它是定时器0的中断函数,
如void time0() interrupt 1{}
那么后面的using n 又是什么意思呢?在正在执行一个特定任务时,有更紧急的事情需要CPU来处理,涉及到中断优先权。高优先权中断低优先权正在处理的程序,所以最好给每个优先程序分配不同的寄存器组。
CPU正在处理某个事件,突然另外一个事件需要处理,于是进入中断后,而你不想将现在执行的程序的各寄存器状态入栈,那么可以把这个中断程序放入另一个寄存器组,如切换到1组,然后退出中断时,再切回到0组(原来的程序在0组)。
为了更好的了解这里意思,你可以看看工作寄存器组的作用是什么。
下面的注意事项转自网络上其他朋友的文章(整理下,重复的去掉了,写的非常好):
(1)中断函数不能进行参数传递
(2)中断函数没有返回值
(3)在任何情况下都不能直接调用中断函数
(4)中断函数使用浮点运算要保存浮点寄存器的状态。
(5)如果在中断函数中调用了其它函数,则被调用函数所使用的寄存器必须与中断函数相同,被调函数最好设置为可重入的。
(6)C51编译器对中断函数编译时会自动在程序开始和结束处加上相应的内容,具体如下:在程序开始处对ACC、B、DPH、DPL和PSW入栈,结束时出栈。中断函数未加using n修饰符的,开始时还要将R0~R1入栈,结束时出栈。如中断函数加using n修饰符,则在开始将PSW入栈后还要修改PSW中的工作寄存器组选择位。
(7)C51编译器从绝对地址8m+3处产生一个中断向量,其中m为中断号,也即interrupt后面的数字。该向量包含一个到中断函数入口地址的绝对跳转。
(8)中断函数最好写在文件的尾部,并且禁止使用extern存储类型说明。防止其它程序调用。
(9)在设计中断时,要注意的是哪些功能应该放在中断程序中,哪些功能应该放在主程序中。一般来说中断服务程序应该做最少量的工作,这样做有很多好处。首先系统对中断的反应面更宽了,有些系统如果丢失中断或对中断反应太慢将产生十分严重的后果,这时有充足的时间等待中断是十分重要的。其次它可使中断服务程序的结构简单,不容易出错。中断程序中放入的东西越多,他们之间越容易起冲突。简化中断服务程序意味着软件中将有更多的代码段,但可把这些都放入主程序中。中断服务程序的设计对系统的成败有至关重要的作用,要仔细考虑各中断之间的关系和每个中断执行的时间,特别要注意那些对同一个数据进行操作的ISR.
教你玩单片机之定时器(附程序)
80c51的定时器
80c51单片机内有两个可编程的定时/计数器T0、T1。它们是一个16位计数器,分别由一个高8位和一个低8位的寄存器组成的。TMOD是定时/计数器的工作方式寄存器,确定工作方式和功能;TCON是控制寄存器,控制T0、T1的启动和停止及设置溢出标志。
定时/计数器的工作原理
定时/计数器实质上是一个加1计数器。它随着计数器的输入脉冲进行自加1,也就是每来一个脉冲,计数器就自动加1,,当加到计数器为全1时,再输入一个脉冲就使计数器回零,且计数器的溢出使相应的中断标志位置1,向CPU发出中断请求(定时/计数器中断允许时)。如果定时/计数器工作于定时模式,则表示定时时间已到;如果工作于计数模式,则表示计数值已满。可见,由溢出时计数器的值减去计数初值才是加1计数器的计数值。
工作方式寄存器TMOD
GATE:门控制
0时:仅有运行控制位TRx来控制定时/计数器的开启
1时:由TRx和外部中断脉冲计数(用于计算外部中断负跳变 的次数)
C/T:计数器模式和定时器模式选择
0时:选择定时器模式
1时:选择为计数器模式
M1和M0:选择定时/计数器的工作方式
定时器/计数器控制寄存器TCON
IT0和IT1是设置外部中断的触发方式
当其为0时,为低电平触发方式
当其为1时,为负跳变触发方式
IE0和IE1是外部中断标志位
TF0和TF1是定时器的中断标志
TR1和TR0是打开相应的定时器
其他的是定时/计数器的控制
定时/计数器的工作方式
方式1
方式1为13位计数,由TL0的低5位(高3位未用)和TH0的8位组成。TL0的低5位溢出时向TH0进位,TH0溢出时,置位TCON中的TF0标志,向CPU发出中断请求。
方式2
方式2的计数位数是16位,由TL0作为低8位、TH0作为高8位,组成了16位加1计数器 。
方式3
方式3为自动重装初值的8位计数方式。
方式4
方式4只适用于定时/计数器T0,定时器T1处于方式3时相当于TR1=0,停止计数。
定时器操作步骤:
选择工作方式(设置M1,M0)
选择控制方式(设置GATE)
选择定时器还是计数器模式(设置C/T)
给定时/计数器赋初值(设置THx和TLx)
开启定时器中断(设置ET0或ET1)
开启总中断(设置EA)
打开计数器(设置TR1或TR0)
定时器小程序
void TimerConfiguration()
{
TMOD = 0x01; //定时器0选择工作方式1
TH0 = 0x3C; //设置初始值
TL0 = 0xB0;
EA = 1; //打开总中断
ET0 = 1; //打开定时器0中断
TR0 = 1; //启动定时器0
}
单片机之定时器LED程序
实验效果 :LED每隔500ms左移一次
void main(void)
{
Time=0;
GPIO_LED=0XFE;
TimerConfiguration();
while(1)
{
if(Time==10)
{
GPIO_LED=_crol_(GPIO_LED,1);
Time=0;
}
}
}
void TimerConfiguration()
{
TMOD = 0x01; //选择工作方式1
TH0 = 0x3C; //设置初始值,定时50MS
TL0 = 0xB0;
EA = 1; //打开总中断
ET0 = 1; //打开定时器0中断
TR0 = 1; //启动定时器0
}
void Timer0() interrupt 1
{
TH0 = 0x3C; //设置初始值
TL0 = 0xB0;
Time++;
}
相关问答
利用51 单片机定时器 编写一个 C语言 程序,实现一个发光二极管定时亮、灭,要求亮一秒、灭一秒交替闪烁不?初始值为0,只只要启动定时器,定时器就开始工作,当计数溢出后,TF被置1,此时在程序中查询TF的状态,做相应的程序处理。一般建议用中断来做,查询方式会占用c...
单片机 是89 c 51采用 定时器 T0的方式1的定时中断方式初始状态...[最佳回答]是要汇编呀,早不说,做了C的.
c语言 中怎么编写一个 定时器 中断程序来实现定时功能?首先,单片机的定时器和计数器不构成因果关系。但是,TMOD(工作方式寄存器)决定着单片机是定时还是计数的工作方式而我自己的理解是:定时功能:单片机设定...
单片机 中用 C语言 怎么设置TOMD,模式0,1,2,3,对应的 定时 ...那得看你用什么单片机,51单片机的话有两定时器T0和T1;TMOD是一个八位的寄存器,分别对应两个定时器的一些状态,如工作方式、启动方式的设置,设置TMOD...
单片机 定时的时间怎么改变?定时器实质是计数器。当计数脉冲周期一定时,就有定时功能。雅帆用水桶给你打个比方吧!一、向上计定时数器举例当一个255毫升的烧杯,提前放入155毫升水后,...
51 单片机 定时闹铃( c语言 ) - 懂得我来发一个C语言51单片机2113时钟程序,希望5261能帮到你/*程序功能:带定时闹4102铃时钟*//*-----------------------------------------我来21...
单片机 定时/计数器和中断到底有什么用?定时器用来计算时间,固定时间触发中断。计数器用来对引脚输入的信号下降沿进行计数。和中断相关,但不一定要开中断。可以单独用。定时器用来计算时间,固定...
单片机 1秒钟定时汇编 语言 怎么编?可以有两种方法,设晶振为12M,则第一种方法:用延时的方法实现DELAY:MOVR3,#10;延时子程序,延时1秒D1:MOVR4,#200D2:MOVR5,#250D3:DJ...
51 单片机 MCS-51,如果采用的晶振的频率为3MHz, 定时器 /计数器...[最佳回答]方式0:2^13/3M*12=0.032768s;方式1:2^16/3M*12=0.262144s;方式2:2^8/3M*12=0.001024s;方式0:2^13...
单片机 定时计数器最大定时时间怎么算?单片机定时计数器最大定时时间取决于所用时钟周期T和定时器位长,比如T=10mS,定时器位长8位(也就是数字最大设置为255),每个时钟到来时,定时计数器采用减1操...