arm在发生中断的时候会固定跳到0x18处执行一段code,所以你需要在0x18处放一段你自己的code,而我们通常的做法就是在这个放一个code使其执行0x38处的中断handler,这个handler是我们自己定义的,一般在这个handler里面会有b code_ISR之类的语句,跳转到c语言中的 code_ISR函数,然后在这个函数里面再判断是那种类型的irq,比如说是timer,那么就跳转到Timer1_ISR这个函数里面。就算是执行啦。
代码如下:
//实现led灯一秒亮灭闪烁
void main()
{
TMOD=0x01;//设置定时器0为工作方式1(M1 M0为01)
TH0=(65536-45872)/256;//装初值110582晶振定时50ms数为45872
TL0=(65536-45872)%256;
EA=1;//开总中断
ET0=1;//开定时器0中断
TR0=1;//启动定时器0
while(1);//程序停止在这里等待中断发生
}
void T0_time() interrupt 1
{
TMOD=0x01;//重装初值
TH0=(65536-45872)/256;
num++;//num每加一次判断一次是否到20次
if(num==20)//如果到了20次,说明1秒时间到
{
num=0;//num清0重新计数
led=~led1;
}
}
扩展资料
定时器有两种工作模式,分别为计数模式和定时模式。对Px,y的输入脉冲进行计数为计数模式。定时模式,则是对MCU的主时钟经过12分频后计数。因为主时钟是相对稳定的,所以可以通过计数值推算出计数所经过的时间。
51单片机计数器的脉冲输入脚。主要的脉冲输入脚有Px,y, 也指对应T0的P34和对应T1的P35,主要用来检测片外来的脉冲。而引脚18和19则对应着晶振的输入脉冲,脉冲的频率和周期为
F = f/12 = 110592M/12 = 09216MHZ T = 1/F = 1085us
51计数器的计数值存放于特殊功能寄存器中。T0(TL0-0x8A, TH0-0x8C), T1(TL1-0x8B, TH1-0x8D)
定时器常用作定时时钟,以实现定时检测,定时响应、定时控制,并且可以产生ms宽的脉冲信号,驱动步进电机。定时和计数的最终功能都是通过计数实现,若计数的事件源是周期固定的脉冲则可实现定时功能,否则只能实现计数功能。因此可以将定时和计数功能全由一个部件实现。
方法1 用关键词interrupt和中断矢量编号定义中断函数
这种方式最简单也最直观。缺点是程序的可移植性稍差。范例如下:
void interrupt 17 sci1_Recv_ISR(void){
}关键词interrupt告诉编译器此函数为中断服务函数,数字17告诉连接器该中断矢量的偏移位置(以复位矢量偏移为0计)。某一个中断响应对应的矢量入口编号可以在该芯片的DataSheet中查到。
方法2 用关键词interrupt定义中断函数,中断矢量入口由prm文件指定,仍以上面的中断服务函数为例,这时函数的定义方式为
void interrupt sci1_Recv_ISR(void){
}然后在项目对应的prm文件中添加一行矢量位置定义:
VECTOR 17 sci1_Recv_ISR //指定的中断服务矢量入口
方法3 用#pragma TRAP_PROC定义中断函数,中断矢量入口由prm文件指定。此类型的函数编译器在将C代码编译成汇编指令时会在代码前后增加必要的现场保护和恢复汇编代码,同时函数的最后返回用汇编指令RTI而不是针对普通函数的RTS。例如
中断定义:由硬件或软件驱动的信号,使DSP将当前的程序挂起,执行另一个称为中断服务子程序(ISR)的任务。
C55x支持32个ISR。有些ISR可以由软件或硬件触发,有些只能由软件触发。
当CPU同时收到多个硬件中断请求时,CPU会按照预先定义的优先级对它们做出响应和处理。
所有的软件中断都是不可屏蔽中断
DSP处理中断的步骤:
(1)接收中断请求。软件和硬件都要求DSP将当前程序挂起。
(2)响应中断请求。CPU必须响应中断。如果是可屏蔽中断,响应必须满足某些条件。如果是不可屏蔽中断,则CPU立即响应。
(3)准备进入中断服务子程序。
CPU要执行的主要任务有:
完成当前指令的执行,并冲掉流水线上还未解码的指令
自动将某些必要的寄存器的值保存到数据堆栈和系统堆栈
从用户实现设置好的向量地址获取中断向量,该中断向量指向中断服务子程序
(4)执行中断服务子程序。
CPU执行用户编写的ISR。ISR以一条中断返回指令结束,自动恢复步骤(3)中自动保存的寄存器值。
☼ 注意:
外部中断只能发生在CPU退出复位后的至少3个周期后,否则无效;
在硬件复位后,不论INTM位的设置和寄存器IER0、IER1的值如何,所有的中断都被禁止,直到通过软件初始化堆栈后才开放中断。
2 可屏蔽中断
所有的可屏蔽中断都是硬件中断。
无论硬件何时请求一个可屏蔽中断,在一个中断标志寄存器里就有相应的中断标志置位。该标志一旦置位,相应的中断还必须使能,否则不会得到处理。
当CPU在实时硬件仿真模式下暂停时,只能处理时间临界中断。
可屏蔽中断标准处理流程:
1 向CPU发送中断请求。
2 设置响应的IFR标志。CPU检测到一个有效的可屏蔽中断请求时,它设置并锁上某个中断标志寄存器的响应标志位,这个位保持锁定,直到该中断得到响应或者复位,才清楚
3 IER中断使能?根据中断使能寄存器是否使能,响应中断。
4 INTM = 0?全局开放中断,才响应
5 跳转到ISR服务程序,
6 执行ISR服务程序
7, 返回。
3 不可屏蔽中断
当CPU接收到一个不可屏蔽中断请求时,立即无条件响应,并很快跳转到相应的中断服务子程序(ISR)
C55x的不可屏蔽中断有:
硬件中断/RESET。如果引脚/RESET为低电平,则触发了一个DSP硬件复位和一个中断(迫使执行复位ISR)。
硬件中断/NMI。如果引脚/NMI为低电平,则CPU必须执行相应的ISR。 /NMI提供了一种通用的无条件中断DSP的硬件方法。
软件中断。
4 按键中断
按键中断,属于可屏蔽中断,用户自定义硬件中断,当CPU响应按键后,检查相关引脚中断标记寄存器,若标志位为1,则响应该中断。同时,清除中断标志寄存器位
5 c_int00
当C环境被初始化时,启动程序禁止中断。 如果系统使用中断,必须处理有关的中断使能或屏蔽。
关于中断的几个要点:
中断程序会执行任何其它函数执行的工作,包括访问全局变量、为局部变量分配地址、调用其它函数。
需要处理任何特殊中断屏蔽(通过IER0寄存器)。通过嵌入汇编语言语句可以使能或禁止中断,也可以修改IER0寄存器而不会破坏C环境或C指针。
中断处理程序不能有参数,即使声明了参数也会被忽略
中断处理程序不能被普通C代码调用。
为了将中断程序和中断联系起来,需要将分支程序放在合适的中断向量中,通过sect指令创建一个简单的分支指令表就可以实现此 *** 作。
在汇编语言中,需要在中断程序名前加下划线,如_c_int00。
分配堆栈到偶地址。
c_int00是系统复位中断。当进入c_int00中断时,运行时间堆栈并没有被建立起来,因此不能为局部变量分配地址,也不能在运行时间堆栈中保存任何信息。
通过interrupt关键字可以用C函数直接处理中断。
interrupt关键字可以和定义为返回void并不含参数的函数一起使用。中断函数体可以有局部变量,可以自由使用堆栈。
c_int00是C程序入口。这个名字被保存为系统重启中断。这个特殊的中断程序初始化系统并调用了主函数。因为没有调用者,所以c_int00不保存任何寄存器。
例,
interrupt void isr()
{
}
中断管理
基于DSP/BIOS管理中的硬件中断,DSP/BIOS为中断提供了一个HWI调度程序,为ISR完成必要的开头和结尾部分。如果不使用,则在调用任何DSP/BIOS对象的API之前,必须调用HWI_enter和HWI_exit汇编宏来完成ISR的开头和结束。实际上,DSP/BIOS提供的调度程序,就包括这两个宏。
为了正确响应硬件中断,同时,也为了DSP/BIOS内核的稳定性,必须注意:
1 在一个硬件中断ISR中,不要调用SWI_disable和SWI_enable。
2 在NMI(不可屏蔽)中断中,不要调用硬件中断使能/禁止函数。
3 当使用DSP/BIOS调度程序时,不要使用HWI_exit和HWI_enter汇编宏
4 中断中,可以打开新中断。
我们可以在中断配置选项卡中,设置Interrupt Mask 来实现在DSP/BIOS调度程序执行前禁止某些中断。
EOI是外部中断的中断结束命令,这个CPU执行\x0d\mov al,20h\x0d\out 20h,al\x0d\就是给8259a芯片发送EOI命令,通知8259A芯片一个中断完成,8259a将负责把ISR中的位清除,以便以后可以继续接受中断。\x0d\\x0d\如果不加的话,8259a永远收不到中断结束命令,那么就认为某一个中断一直在执行,所以如果遇到比这个阻塞的中断级别低或者相等的中断发生时就不会再响应了。
嗯,我猜你问的是PC的,不是单片机
一、汇编语言的中断分以下几种:
1BIOS中断,这是固化到BIOS程序中的,每次开机BIOS会自动加载到指定内存
2186下的DOS中断,在DOS系统被加载后,系统会延用BIOS的中断向量,并向里面添加一些新的向量,这些功能便是DOS系统自带的中断服务程序
3286及以上的系统中断,PC会进入保护模式,在OS被加载后,中断由IDT控制,这一机制类似于中断向量表,只不过中断向量换成了选择子。这样的中断机制对不同型号的CPU有略微的差别,这里不细说了,我自己也没全弄明白。
二、中断实现的方式(8086下的普通中断)
听说过“优先级编码器”没?——如果同时有两个信号被接收,会指定某一个信号的优先级高,先执行它。中断就是类似的处理方法。
当CPU获取到某一高 *** 作优先级的信号时(比如时钟,每固定时间就会触发一次;比如键盘响应,用户希望通过Ctrl+C来退出任何正在执行的DOS程序),CPU会将当前正在执行的程序挂起来,转而去处理该信号(类似于Call,但略有不同,你看的书应该会讲到)。
处理中断时,系统会将其解释为一个标号,比如int 9h、int 21h等等。这个标号是一个序号,在内存某处存放着连续的一个表格,这个标号便是表格中的“行号”,只不过,每一行是两列,包括了该中断的处理程序的段基址和偏移量。中断向量表是从0000:0000开始的,每4字节为一个表项。中断标号x4就是对应的中断向量表项所存的地址,高地址是基地址,低地址是偏移。
这么说不知道你懂不懂。。。
反正总结一下你的问题吧,中断服务程序是加载到内存中的,它在加载前可能是存在BIOS芯片上,也可能是存在硬盘里的;中断向量表里只能写上中断处理程序的入口地址,要知道每个表项只有4字节;具体的中断服务程序,我不信你学汇编的书上不讲,我大概讲一下:CPU的INTR引脚获得了中断信号,得到了标号,比方说是5号,中断向量表项为0000:000A,读取这个内存,得到中断程序入口地址比方说是AAAA:BBBB,那么它会将当前的CS/IP、Flags寄存器入栈,然后转到AAAA:BBBB处去执行一直到iret指令返回原任务(或许该中断结束了这个任务,就不会返回了)。
至于保护模式的中断,相信你暂时还没遇到。到后面还有 *** 控8259A芯片来实现高级中断的,这个就不是一般需要学的了。
以上就是关于ARM中的异常中断是如何实现进入中断程序的,比如如何进入void __irq Timer1_ISR( void )定时器中断全部的内容,包括:ARM中的异常中断是如何实现进入中断程序的,比如如何进入void __irq Timer1_ISR( void )定时器中断、51单片机中的定时器中断是怎么用的 、怎样写中断服务程序等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)