while (1) {
GPIOPinWrite(GPIO_PORTB_BASE, LED3, ~GPIOPinRead(GPIO_PORTB_BASE, LED3));
delay(200000);
}
}
/*********************************************************************************************************
END FILE
*********************************************************************************************************/
/****************************************Copyright (c)****************************************************
** Guangzhou ZHIYUAN electronics Co.,LTD.
**
** http://www.embedtools.com
**
**--------------File Info---------------------------------------------------------------------------------
** File name: IntDome1.c
** Latest modified Date: 2007.11.23
** Latest Version: V1.0
** Descriptions: 中断优先级实验
**
**--------------------------------------------------------------------------------------------------------
** Created by: Kang qinhua
** Created date: 2007.11.23
** Version: V1.0
** Descriptions: The original version
**
**--------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
** Version:
** Descriptions:
**
*********************************************************************************************************/
#include "hw_types.h"
#include "hw_memmap.h"
#include "hw_ints.h"
#include "hw_nvic.h"
#include "interrupt.h"
#include "sysctl.h"
#include "gpio.h"
#define KEY1 GPIO_PIN_4 /* 设置PA4口为KEY1 */
#define KEY2 GPIO_PIN_4 /* 设置PB4口为KEY2 */
#define KEY3 GPIO_PIN_4 /* 设置PC4口为KEY3 */
#define LED3 GPIO_PIN_6 /* 设置PB6口为LED3 */
#define LED4 GPIO_PIN_5 /* 设置PA5口为LED4 */
#define LED5 GPIO_PIN_5 /* 设置PB5口为LED5 */
#define LED6 GPIO_PIN_5 /* 设置PC5口为LED6 */
/*********************************************************************************************************
** Function name: delay
** Descriptions: 延时函数
** input parameters: t,延时时间常数
** output parameters: 无
** Returned value: 无
*********************************************************************************************************/
void delay (int t)
{
for ( ; t; --t);
}
/*********************************************************************************************************
** Function name: GPIO_Port_A_ISR
** Descriptions: GPIOA中断函数
** 用KEIL软件时,在Startup.S中添加该中断函数名
** input parameters: 无
** output parameters: 无
** Returned value: 无
*********************************************************************************************************/
void GPIO_Port_A_ISR (void)
{
unsigned long i = 0;
GPIOPinIntClear(GPIO_PORTA_BASE, KEY1); /* 清除中断标志 */
for ( i = 100; i > 0; i--) {
GPIOPinWrite(GPIO_PORTA_BASE, LED4, ~GPIOPinRead(GPIO_PORTA_BASE, LED4));
delay(200000);
}
}
/*********************************************************************************************************
** Function name: GPIO_Port_B_ISR
** Descriptions: GPIOB中断函数
** 用KEIL软件时,在Startup.S中添加该中断函数名
** input parameters: 无
** output parameters: 无
** Returned value: 无
*********************************************************************************************************/
void GPIO_Port_B_ISR (void)
{
unsigned long i = 0;
GPIOPinIntClear(GPIO_PORTB_BASE, KEY2); /* 清除中断标志 */
for ( i = 100; i > 0; i--) {
GPIOPinWrite(GPIO_PORTB_BASE, LED5, ~GPIOPinRead(GPIO_PORTB_BASE, LED5));
delay(200000);
}
}
/*********************************************************************************************************
** Function name: GPIO_Port_C_ISR
** Descriptions: GPIOC中断函数
** 用KEIL软件时,在Startup.S中添加该中断函数名
** input parameters: 无
** output parameters: 无
** Returned value: 无
*********************************************************************************************************/
void GPIO_Port_C_ISR (void)
{
unsigned long i = 0;
GPIOPinIntClear(GPIO_PORTC_BASE, KEY3); /* 清除中断标志 */
for ( i = 100; i > 0; i--) {
GPIOPinWrite(GPIO_PORTC_BASE, LED6, ~GPIOPinRead(GPIO_PORTC_BASE, LED6));
delay(200000);
}
}
/*********************************************************************************************************
** Function name: main
** Descriptions: 主函数
** 运行时LED3闪烁
** KEY1--GPIOA中断 ,对应于LED4,设置成组优先级为2,次优先级为0
** KEY2--GPIOB中断 ,对应于LED5,设置成组优先级为2,次优先级为1
** KEY3--GPIOC中断 ,对应于LED6,设置成组优先级为1,次优先级为1
** 按下KEY1,LED4闪烁;按下KEY2,LED5闪烁;按下KEY3,LED6闪烁;
** KEY1与KEY2产生末尾连锁,KEY3可抢断KEY1、KEY2,通过LED可以观测结果
** input parameters: 无
** output parameters: 无
** Returned value: 无
*********************************************************************************************************/
int main (void)
{
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); /* 使能GPIO PA口 */
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); /* 使能GPIO PB口 */
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC); /* 使能GPIO PC口 */
/*********************************************************************************************************
设置KEY1、KEY2、KEY3为输入
*********************************************************************************************************/
/* GPIOPinTypeGPIOInput(GPIO_PORTA_BASE, KEY1);
GPIOPinTypeGPIOInput(GPIO_PORTB_BASE, KEY2);
GPIOPinTypeGPIOInput(GPIO_PORTC_BASE, KEY3); */
GPIODirModeSet(GPIO_PORTA_BASE, KEY1, GPIO_DIR_MODE_IN);
GPIODirModeSet(GPIO_PORTB_BASE, KEY2, GPIO_DIR_MODE_IN);
GPIODirModeSet(GPIO_PORTC_BASE, KEY3, GPIO_DIR_MODE_IN);
/*********************************************************************************************************
设置LED3、LED4、LED5、LED6为输出
*********************************************************************************************************/
/* GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE, LED3);
GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, LED4);
GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE, LED5);
GPIOPinTypeGPIOOutput(GPIO_PORTC_BASE, LED6); */
GPIODirModeSet(GPIO_PORTB_BASE, LED3, GPIO_DIR_MODE_OUT);
GPIODirModeSet(GPIO_PORTA_BASE, LED4, GPIO_DIR_MODE_OUT);
GPIODirModeSet(GPIO_PORTB_BASE, LED5, GPIO_DIR_MODE_OUT);
GPIODirModeSet(GPIO_PORTC_BASE, LED6, GPIO_DIR_MODE_OUT);
GPIOPadConfigSet(GPIO_PORTA_BASE, KEY1 | LED4, /* 设置KEY1的驱动强度和类型 */
GPIO_STRENGTH_4MA, /* 4mA的输出驱动强度 */
GPIO_PIN_TYPE_STD); /* 设置为推挽管脚 */
GPIOPadConfigSet(GPIO_PORTB_BASE, KEY2 | LED5 | LED3, /* 设置KEY2的驱动强度和类型 */
GPIO_STRENGTH_4MA, /* 4mA的输出驱动强度 */
GPIO_PIN_TYPE_STD); /* 设置为推挽管脚 */
GPIOPadConfigSet(GPIO_PORTC_BASE, KEY3 | LED6, /* 设置KEY3的驱动强度和类型 */
GPIO_STRENGTH_4MA, /* 4mA的输出驱动强度 */
GPIO_PIN_TYPE_STD); /* 设置为推挽管脚 */
GPIOIntTypeSet(GPIO_PORTA_BASE, KEY1, GPIO_RISING_EDGE); /* 设置KEY1中断的触发方式为
上升沿触发 */
GPIOIntTypeSet(GPIO_PORTB_BASE, KEY2, GPIO_RISING_EDGE); /* 设置KEY2中断的触发方式为
上升沿触发 */
GPIOIntTypeSet(GPIO_PORTC_BASE, KEY3, GPIO_RISING_EDGE); /* 设置KEY3中断的触发方式为
上升沿触发 */
IntMasterEnable(); /* 使能总中断 */
GPIOPinIntEnable(GPIO_PORTA_BASE, KEY1); /* 使能KEY1中断 */
GPIOPinIntEnable(GPIO_PORTB_BASE, KEY2); /* 使能KEY2中断 */
GPIOPinIntEnable(GPIO_PORTC_BASE, KEY3); /* 使能KEY3中断 */
IntEnable(INT_GPIOA); /* 使能GPIOA中断 */
IntEnable(INT_GPIOB); /* 使能GPIOB中断 */
IntEnable(INT_GPIOC); /* 使能GPIOC中断 */
IntPrioritySet(INT_GPIOA, 2 << 6 | 0 << 5); /* GPIOA组优先级为2,
次优先级为0 */
IntPrioritySet(INT_GPIOB, 2 << 6 | 1 << 5); /* GPIOB组优先级为2,
次优先级为1 */
IntPrioritySet(INT_GPIOC, 1 << 6 | 1 << 5); /* GPIOA组优先级为1,
次优先级为1 */
IntPriorityGroupingSet(2); /* 组优先级为4位,次优先级2位 */
while (1) {
GPIOPinWrite(GPIO_PORTB_BASE, LED3, ~GPIOPinRead(GPIO_PORTB_BASE, LED3));
delay(200000);
}
}
/*********************************************************************************************************
END FILE
*********************************************************************************************************/
GPIOPinIntEnable(GPIO_PORTA_BASE, KEY1); /* 使能KEY1中断 */
GPIOPinIntEnable(GPIO_PORTB_BASE, KEY2); /* 使能KEY2中断 */
GPIOPinIntEnable(GPIO_PORTC_BASE, KEY3); /* 使能KEY3中断 */
IntEnable(INT_GPIOA); /* 使能GPIOA中断 */
IntEnable(INT_GPIOB); /* 使能GPIOB中断 */
IntEnable(INT_GPIOC); /* 使能GPIOC中断 */
IntPrioritySet(INT_GPIOA, 2 << 6 | 0 << 5); /* GPIOA组优先级为2,
次优先级为0 */
IntPrioritySet(INT_GPIOB, 2 << 6 | 1 << 5); /* GPIOB组优先级为2,
次优先级为1 */
IntPrioritySet(INT_GPIOC, 1 << 6 | 1 << 5); /* GPIOA组优先级为1,
次优先级为1 */
IntPriorityGroupingSet(2); /* 组优先级为4位
楼主的问题实际上是两个问题,
1. 尾链是什么用的?
2. M3的中断优先级机制?
3. 我先回答第一个问题
1) 在M3之前的MCU在处理中断时一般都采用如下的过程:
中断1发生 -> 现场保护1 -> 中断1处理 -> 现场恢复
2) 如果在中断1发生之后,未处理结束之前,和中断1优先级相同的中断2也发生了,这个时候的处理过程如下:
中断1发生 -> 现场保护1 -> 中断1处理 -> 现场恢复
中断2发生.................................................................-> 现场保护2 -> 中断2处理 -> 现场恢复
从上面的过程我们可以看出,实际上我们进行了2次同样的现场保护,即现场保护1和现场保护2, 也进行了2次同样的现场恢复。
M3的内核对这个过程进行了优化,在中断1处理完后,并不急于恢复现场,而是判断是否由另外的中断2发生,如果有则不退出中断处理,而是直接进入中断2处理程序。
处理流程如下:
中断1发生 -> 现场保护1 -> 中断1处理 ->
中断2发生...........................................中断2处理 -> 现场恢复
3) 总结一下,由上描述可知,尾链技术是为了简化两个相同优先级的中断的切换过程。
注意: 这里讲的相同优先级是指两个中断不能互相打断,而不是绝对的相等。M3采用中断优先级编号和组号来管理中断的优先级。使用者需要了解这个机制才能正确的设置各个中断源的处理流程。
4. 关于第二个问题,请参见我对M3中断优先级的描述: http://bbs.eeworld.com.cn/viewthread.php?tid=301771&highlight=
[ 本帖最后由 Triton.zhang 于 2011-10-1 00:33 编辑 ]一周热门 更多>