1 / 23

第 6 章 中断系统

第 6 章 中断系统. §6.1 中断的一般概念. 中断向量,是中断源提供的处理程序的入口,其入口处,是由系统统一划拨存储空间,给各中断源存放中断处理程序的入口,即中断向量表。 中断响应过程:申请 - 响应( 终止当前程序 - 保护断点 - 转到处理程序。 ) - 中断处理( 保护现场 - 处理 - 清该标志、恢复现场 - 返回。软件 )。. CPU 对突发事件响应方式 中断源及中断申请 开中断与关中断 中断优先级及中断嵌套 中断向量与中断处理. 硬件实现. 一个应用系统,面对处理器众多的中,是根据应用来选取允许中断的事件与不允许中断的事件。. 软件完成.

nakia
Télécharger la présentation

第 6 章 中断系统

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第6章 中断系统

  2. §6.1 中断的一般概念 中断向量,是中断源提供的处理程序的入口,其入口处,是由系统统一划拨存储空间,给各中断源存放中断处理程序的入口,即中断向量表。 中断响应过程:申请-响应(终止当前程序-保护断点-转到处理程序。)-中断处理(保护现场-处理-清该标志、恢复现场-返回。软件)。 • CPU对突发事件响应方式 • 中断源及中断申请 • 开中断与关中断 • 中断优先级及中断嵌套 • 中断向量与中断处理 硬件实现 一个应用系统,面对处理器众多的中,是根据应用来选取允许中断的事件与不允许中断的事件。 软件完成

  3. §6.2 SPCE061A中断系统

  4. 中断类型与中断源 • 异常中断-RESET,向量地址为FFF7H。优先级最高。 • 软中断-执行指令BREAK,向量地址为FFF5H。优先级最低。 • 事件中断-外部与片内I/O事件。快速中断FIQ与中断IRQ。FIQ优先级高于IRQ 。

  5. 事件中断 如果同时有两个以上的IRQ中断时,按此优先级响应。但较“高级别”IRQ中断不能中断“较低级别”IRQ中断。即在IRQ中断中不允许中断嵌套。 中断服务程序以此取名。

  6. 中断控制寄存器 • P_INT_Ctrl(7010H) 读/写 读,中断标志字,用于判别产生中断的源。写,选择允许中断的源。 • P_INT_Clear (7011H) 写 清中断标志。选择的源与中断标志字对应。写“1”清该中断标志。 • P_INT_Ctrl_New(702DH) 读/写 激活与屏蔽中断。读,了解哪些中断源被屏蔽。写,对应0的中断源被屏蔽。对应1的中断源被激活。

  7. 中断控制字 每一位对应一个事件,如果通过[P_INT_Ctrl]向某位写1,则允许该事件向CPU申请中断。 如果通过[P_INT_Ctrl]读,是读中断标志,置1的位,说明该事件已向CPU申请了中断。 [P_INT_Ctrl_New]端口的每一位,也对应表中的事件。 如果通过[P_INT_Clear]向某位写1,则清除该事件的中断标志。

  8. 中断控制指令 注意:只有在P_INT_Ctrl中设置了中断源允许位为“1”, 相应开/关中断指令才有意义。

  9. [P_IOB_ATTRI]=r1 //IOB口设置为同相高电平输出口 • [P_IOB_DIR]=r1 • [P_IOB_DATA]=r1; • R1=0x000C • [P_INT_Ctrl ]=R1 • [P_INT_CTRL_New ]=R1 • R1=0 • [TIME2]=R1 • [TIME4]=R1 • INT IRQ • Loop: • NOP • NOP • JMP Loop • //============================ • .TEXT • .PUBLIC _IRQ5 • _IRQ5:PUSH R1,R5 TO [SP]R1 = 0x0008;TEST R1,[P_INT_Ctrl]; //中断识别JNZ L_IRQ5_4Hz; [例6.1]IRQ5有2个中断源,2Hz和4Hz。TIME2对2Hz中断计数, TIME4对4Hz中断计数。2Hz中断控制A口0~3LED以2S速率闪烁, 4Hz中断控制B口0~3LED以1S速率闪烁。 L_IRQ5_4Hz:R1=0x0008[P_INT_Clear] = R1; //清中断R2=[TIME4] //计数器+1R2+=1[TIME4]=R2CMP R2,2 //是否0.5S? JBE LED4Hz_OFF //否, LED灭 R1=0xFFF0 //是, LED亮 [P_IOB_DATA]=R1 CMP R2,4 //是否1S? JBE LED4Hz_RET //否,中断返回 R2=0 //是, 清TIME4 [TIME4]=R2 JMP LED4Hz_RET LED4Hz_OFF: R1=0xFFFF [P_IOA_DATA]=R1 LED4Hz_RET POP R1,R5 FROM [SP];RETI; L_IRQ5_2Hz:R1=0x0004[P_INT_Clear] = R1; //清中断R2=[TIME2] //计数器+1R2+=1[TIME2]=R2CMP R2,2 //是否1S? JBE LED2Hz_OFF //否, LED灭 R1=0xFFF0 //是, LED亮 [P_IOA_DATA]=R1 CMP R2,4 //是否2S? JBE LED2Hz_RET //否,中断返回 R2=0 //是, 清TIME2 [TIME2]=R2 JMP LED2Hz_RET LED2Hz_OFF: R1=0xFFFF [P_IOA_DATA]=R1 LED2Hz_RET POP R1,R5 FROM [SP];RETI; • .DEFINE P_IOA_DATA 0x7000 • .DEFINE P_IOA_DIR 0x7002 • .DEFINE P_IOA_ATTRI 0x7003 • .DEFINE P_IOB_DATA 0x7005 • .DEFINE P_IOB_DIR 0x7007 • .DEFINE P_IOB_ATTRI 0x7008 • .DEFINE P_INT_Ctrl 0x7010 • .DEFINE P_INT_CLEAR 0x7011 • .DEFINE P_INT_CTRL_New 0x702D • .RAM • .VAR TIME2 //2Hz计数器 • .VAR TIME4 //4Hz计数器 • .CODE • .PUBLIC _main //主程序 • _main: • INT off • R1=0xffff //r1的值为0xffff • [P_IOA_ATTRI]=r1 //IOA口设置为同相高电平输出 • [P_IOA_DIR]=r1 • [P_IOA_DATA]=r1; 否,就是2Hz中断。 Y

  10. [例6.2]键唤醒,A口键盘输入,B口LED输出。 这个循环起什么作用? 低位LED会亮吗?程序如何修改? 交换后,高位LED会亮吗?程序如何修改? R1= 0xFFFE //低位为0 R4=0xFFFF R4=R4 LSL 4 //SR置全1 R2=0xFFFF L_Loopin: R2 - =1 JNZ L_Loopin R1=R1 ROL 1 //循环左移 [P_IOB_Data]=R1 //LED显示 CMP R1,0xFF7F //是否最后一个LED JNE L_Loopin R1=0xFFFE JMP L_Loopin .include Hardwore.inc //硬件资源接口 .define P_IOA_RL 0x7004 // P_IOA_Latch .CODE .PUBLIC _main _main: r1=0 //IOA为带下拉电阻输入。 [P_IOA_Dir]=r1 [P_IOA_Attr]=r1 [P_IOA_Data]=r1 r1=0xFFFF //IOB低电平输出 [P_IOB_Dir]=r1 [P_IOB_Attrib] = r1 r1=0 [P_IOA_Data]=r1 INT OFF Keydown: R1= [P_IOA_Data] CMP R1,0x0001 JNE Keydown Keyup: R1= [P_IOA_Data] CMP R1,0x0000 JNE Keyup R1=0xFFFF [P_IOA_Data]=R1 //LED灭? R1=0x0080 [P_INT_Ctrl]=R1 //开IRQ3_KEY中断 R1=[P_IOA_RL] //激活键唤醒 INT IRQ R1=0x0007 [P_SystemClock]=R1 //CPU入睡 // _IRQ3中断服务程序 .TEXT .PUBLIC _IRQ3 _IRQ3: PUSH R1, R4 TO [SP] R1=0x0080 TEST R1, [P_INT_Ctrl] JZ L_NOTKeyArouse R1=0x0080 [P_INT_Clear]=R1 L_NOTKeyArouse: POP R1, R4 FROM [SP] RETI .END [P_IOB_Data]=R1 //LED显示 R1=R1 ROL 1 //循环左移 CMP R1,0xFEFF

  11. 用C语言编写中断服务程序 函数库SPCE061.LIB提供了相关的底层函数,中断服务程序可以直接用这些函数来描述。

  12. SPCE061.LIB中与中断相关的函数 函数原形: void Set_INT_Ctrl(unsigned int); void Set_INT_Mask(unsigned int); unsigned int Get_INT_Ctrl(void); unsigned int Get_INT_Mask(void); void INT_Clear(unsigned int); void FIQ_ON(void ) void FIQ_OFF(void); void IRQ_ON(void); void IRQ_OFF(void); void INT_FIQ(void); void INT_IRQ(void); void INT_FIQ_IRQ(void); void INT_OFF(void); FIQ_ON(); FIQ ON FIQ_OFF(); FIQ OFF IRQ_ON(); IRQ ON IRQ_OFF(); IRQ OFF INT_FIQ(); INT FIQ INT_IRQ(); INT IRQ INT_FIQ_IRQ(); INT FIQ_IRQ INT_OFF(); INT OFF

  13. [例6.4]A口的LED按1S速率闪烁 #include “SPCE061.H” unsigned int g_uioutput = 0; void IRQ5(void)_attribute_((ISR)) void IRQ5(void) { if (*P_INT_Ctrl & 0x0004) { //IRQ5_2Hz *P_IOA_Data = g_uioutput; g_uioutput ^=0xFFFF; //取反 *P_INT_Clear = 0x0004; // C_IRQ5_2Hz } else { // IRQ5_4Hz *P_INT_Clear = 0x0008; //C_IRQ5_4Hz } } ISR-interrupt service routine #include “SPCE061.H” main() { asm(“INT OFF”); *P_IOA_Dir = 0x00FF; *P_IOA_Attib = 0x00FF; *P_IOA_DATA = 0x0000; //A口为输出,低电平。 *P_INT_Ctrl = C_IRQ5_2Hz; //0004H P_INT_Ctrl asm(“INT IRQ”); while(1) //死循环。 *P_Watchdog_Clear = C_WDTCLR } 如果不喜欢使用SPCE061.H,也不想包含SPCE061.lib,你也可以象下面这样写程序,其实,这里只是将SPCE061.lib中我们用到的部分代码摘出来了。 volatile unsigned int *P_IOA_Data= (unsigned int*)(0x7000); // Data vector for IOA volatile unsigned int *P_IOA_Dir = (unsigned int*)(0x7002); // Direction vector for IOA volatile unsigned int *P_IOA_Attrib = (unsigned int*)(0x7003); // Attribute vector for IOA volatile unsigned int *P_IOB_Data = (unsigned int*)(0x7005); // Data vector for IOB volatile unsigned int *P_IOB_Dir = (unsigned int*)(0x7007); // Direction vector for IOB volatile unsigned int *P_IOB_Attrib = (unsigned int*)(0x7008); // Attribute vector for IOB

  14. [例6.5]不同中断入口的中断源程序举例。LED,A口为1S、B口0.5S闪烁。[例6.5]不同中断入口的中断源程序举例。LED,A口为1S、B口0.5S闪烁。 #include “SPCE061.H” unsigned int g_uiIOA_LED = 0xFF, g_uiIOB_LED = 0xFF; unsigned int g_uiClockCnt = 0; void IRQ2(void)_attribute_((ISR)); void IRQ2(void) //TimerB 中断 { *P_IOB_Data = g_uiIOB_LED ; g_uiIOB_LED ^= 0xFFFF; //取反 *P_INT_Clear = 0x0400; // 清该中断标志 } void IRQ4(void)_attribute_((ISR)); void IRQ4(void) { IF *P_INT_Ctrl & C_IRQ4_1KHz // 如果是IRQ4_1KHz中断 { IF g_uiClockCnt <1024 //且计数器<1024 g_uiClockCnt++ ; // 计数器加1 ELSE { *P_IOA_Data = g_uiIOA_LED ;//显示 g_uiIOA_LED ^= 0xFFFF; //取反,下一个显示状态 g_uiClockCnt = 0 //计数器清0 *P_INT_Clear = C_IRQ4_1KHz; // 清该中断标志 } } IF *P_INT_Ctrl & C_IRQ4_2KHz //如果是IRQ4_2KHz { *P_INT_Clear = C_IRQ4_2KHz; // 清IRQ4_2KHz中断标志 } IF *P_INT_Ctrl & C_IRQ4_4KHz //如果是IRQ4_4KHz { *P_INT_Clear = C_IRQ4_4KHz; // 清IRQ4_4KHz中断标志 } } #include “SPCE061.H” #define TIMER_DATA_FOR_4KHz (65535-2048) //计数器初值 main() { asm(“INT OFF”); *P_IOA_Dir = 0xFFFF; *P_IOA_Attib = 0xFFFF; *P_IOA_Data = 0x00FF; //A口为输出,低8位输出低电平。 *P_IOB_Dir = 0xFFFF; *P_IOB_Attib = 0xFFFF; *P_IOB_Data = 0x00FF; //B口为输出,低8位输出低电平。 *P_Timer_Data = TIMER_DATA_FOR_4KHz; //0.5S,2048次分频 *P_Timer_Ctrl = C_SourceA_4096Hz //0004H  (P_Timer_Ctrl) *P_INT_Ctrl = C_IRQ4_1KHz| C_IRQ2_TMB ; //允许中断 asm(“INT IRQ”); while(1) //死循环。 *P_Watchdog_Clear = C_WDTCLR }

  15. 【实验六】IRQ4中断实验

  16. LED闪亮 1KHz中断控制 2KHz中断控制 4KHz中断控制 1KHz中断,1mS中断。 2KHz中断,0.5mS中断。 4KHz中断,0.25mS中断。

  17. IRQ4中断程序 寄存器组压栈保护 N Y 1KHz中断? 否则,4KHz中断 TIME1+1 2KHz中断? TIME4+1 Y >1S? >0.25S? TIME2+1 Y Y IOA0,1 IOA4,7 LED亮 LED灭 LED亮 LED灭 >0.5S? Y IOA2,3 >2S? >0.5S? LED灭 LED亮 Y Y TIME1清0 TIME4清0 >1S? Y TIME2清0 清1KHz中断标志 清4KHz中断标志 清2KHz中断标志 寄存器组出栈恢复 中断返回

  18. .DEFINE P_IOA_DATA 0x7000 • .DEFINE P_IOA_DIR 0x7002 • .DEFINE P_IOA_ATTRI 0x7003 • .DEFINE P_INT_Ctrl 0x7010 • .DEFINE P_INT_CLEAR 0x7011 • .DEFINE P_WATCHDOG_CLEAR 0x7012 • .RAM • .VAR TIME1 //1KHz计数器 • .VAR TIME2 //2KHz计数器 • .VAR TIME4 //4KHz计数器 • .CODE • .PUBLIC _main //主程序 • _main: • INT off • R1=0xffff //r1的值为0xffff • [P_IOA_ATTRI]=r1 //IOA口设置为同相低电平输出 • [P_IOA_DIR]=r1 ; • R1=0 • [P_IOA_DATA]=r1; • R1=0x0070 • [P_INT_Ctrl ]=R1 • R1=0 • [TIME1]=R1 • [TIME2]=R1 • [TIME4]=R1 • INT on • Loop: • R1=1 • [P_WATCHDOG_CLEAR]=R1 • JMP Loop • //============================ • .TEXT • .PUBLIC _IRQ4 • _IRQ4:PUSH R1,R5 TO [SP]R1 = 0x0010; //中断识别TEST R1,[P_INT_Ctrl]; //是1KHz?JNZ L_IRQ4_1KHz; • R1 = 0x0020;TEST R1,[P_INT_Ctrl]; //是2KHz?JNZ L_IRQ4_2KHz; L_IRQ4_1KHz:R2=[TIME1] //计数器+1R2+=1[TIME1]=R2R1=[P_IOA_DATA] CMP R2,0x0400 //是否1S? JBE LED1KHz_OFF //小于等于, LED灭 R1|=0x0003 //否则,0~1LED [P_IOA_DATA]=R1 CMP R2,0800 //是否2S? JBE LED1KHz_RET //小于等于, 0~1LED继续亮,中断返回 R2=0 //是, 清TIME1 ,在下一次中断灭 [TIME1]=R2 JMP LED2Hz_RET LED1KHz_OFF: R1&=0xFFFC [P_IOA_DATA]=R1 LED1KHz_RET: R1=0x0010[P_INT_Clear] = R1; //清中断POP R1,R5 FROM [SP];RETI; L_IRQ4_4KHz:R2=[TIME4] //TIME4计数器+1R2+=1[TIME4]=R2R1=[P_IOA_DATA] //读A引脚状态 CMP R2,0x0400 //是否≤0.25S? JBE LED4KHz_OFF //是, LED灭 R1|=0x00F0 //否,4~7 LED亮 [P_IOA_DATA]=R1 CMP R2,0x0800 //是否≤0.5S? JBE LED4KHz_RET //是, 4~7 LED继续亮中断返回 R2=0 //否,清TIME4,在下一次中断灭 [TIME4]=R2 JMP LED4KHz_RET LED4Hz_OFF: R1&=0xFF0F // 4~7 LED灭 [P_IOA_DATA]=R1 LED4Hz_RET: R1=0x0040[P_INT_Clear] = R1; //清中断POP R1,R5 FROM [SP];RETI; L_IRQ4_2KHz:R2=[TIME2] //计数器+1R2+=1[TIME2]=R2R1=[P_IOA_DATA] CMP R2,0x0400 //是否≤0.5S? JBE LED2KHz_OFF //小于等于, LED灭 R1|=0x000C //否则,2~3 LED亮 [P_IOA_DATA]=R1 CMP R2,0800 //是否小于等于1S? JBE LED2KHz_RET //小于等于, 2~3 LED继续亮,中断返回 R2=0 //否则,清TIME2 ,在下一次中断灭 [TIME2]=R2 JMP LED2KHz_RET LED2KHz_OFF: R1&=0xFFF3 [P_IOA_DATA]=R1 LED2KHz_RET: R1=0x0010[P_INT_Clear] = R1; //清中断POP R1,R5 FROM [SP];RETI; 程序设计

  19. 本章小结 • 掌握中断系统的一般概念 • CPU对I/O设备管理的方式 • 中断优先级及中断嵌套 • 开中断与关中断 • 中断响应过程 • 掌握µ’nSPTM中断系统的基本特点 • 中断源、中断事件、中断优先级、中断向量、中断响应 • µ’nSPTM系统的中断程序设计 作业: P106 3、6、

  20. IRQ6中断程序 [例6.3] 寄存器组压栈保护 TMB2中断? 计数器+1 计数器+1 >1S? >0.5S? Y Y LED灭 LED亮 LED亮 LED灭 >2S? >1S? Y Y 计数器清0 计数器清0 清Timer2中断标志 清Timer4中断标志 寄存器组出栈恢复 中断返回

  21. [例6.3]程序 .TEXT .PUBLIC _FIQ _FIQ: PUSH R1,R5 TO [SP] R1 = 0x0800; //中断识别 TEST R1,[P_INT_Ctrl]; //是FIQ_TMB?JNZ L_FIQ_TMB; R1 = 0x0200; //否, TEST R1,[P_INT_Ctrl]; //是FIQ_TMA ?JNZ L_FIQ_TMA; L_FIQ_PWM: //否,是FIQ_PWM R1=0x8000 [P_INT_Clear]=R1 POP R1,R5 FROM [SP] RETI .include hardware.inc .DEFINE timea_clk 0x020d ; .DEFINE timeb_clk 0x0004 ; .RAM .VAR TA_Flag .VAR TB_Flag .PUBLIC _main //主程序 _main: INT off R1=0xffff [P_IOA_ATTRI]=r1 //IOA口设置为同相低电平输出 [P_IOA_DIR]=r1 R1=0 [P_IOA_DATA]=r1; R1=0xffff [P_IOB_ATTRI]=r1 //IOB口设置为同相高电平输出 [P_IOB_DIR]=r1 R1=0 [P_IOB_DATA]=r1; L_FIQ_TMA: R1=[TA_Flag] R1^=0xFFFF [P_IOA_Data]=R1 [TA_Flag]=R1 R1=0x0200 [P_INT_Clear]=R1 POP R1,R5 FROM [SP] RETI L_FIQ_TMB: R1=0x0800 [P_INT_Clear]=R1 POP R1,R5 FROM [SP] RETI R1=0xFF9F [P_TimerA_Data]=R1 [P_TimerB_Data]=R1 R1= timea_clk [P_TimerA_Ctrl]=R1 R2=0000000000000100B R1=0010000000000000B R1 | =R2 [P_INT_Ctrl]=R1 INT IRQ,FIQ L_LOOP: NOP NOP NOP JMP L_LOOP

  22. 主程序 设置中断 开中断 初始化A、B口 关中断 系统进入睡眠状态 S1键按下吗? N Y 有键按下吗? N 松开S1键吗? N Y Y LED灯灭 循环点亮LED

  23. IOA0 IOA1 IOA2 R×8 IOA3 IOA4 IOA5 IOA6 IOA7

More Related