历史上的今天
今天是:2024年12月30日(星期一)
2021年12月30日 | STM32F103外部中断实现
2021-12-30 来源:eefocus
中断是单片机中最重要的一个功能了,通过中断可以提高程序的运行效率,可以是单片机及时的响应各种外设的请求。STM32系列单片机的中断主要由嵌套向量中断控制器来管理。
嵌套向量中断控制器特性如下:
68个可屏蔽中断通道(不包含16个Cortex™-M3的中断线);
16个可编程的优先等级(使用了4位中断优先级);
低延迟的异常和中断处理;
电源管理控制;
系统控制寄存器的实现;
嵌套向量中断控制器( NVIC ) 和处理器核的接口紧密相连,可以实现低延迟的中断处理和高效地处理晚到的中断。
外部中断/事件控制器由19个能产生事件/中断请求的边沿检测器。每个输入线可以独立地配置输入类型(脉冲或挂起)和对应的触发事件(上升沿或下降沿或者双边沿都触发)。每个输入线都可以独立地被屏蔽。挂起寄存器保持着状态线的中断请求。
EXTI控制器的主要特性如下:
每个中断/事件都有独立的触发和屏蔽
每个中断线都有专用的状态位
支持多达20个软件的中断/事件请求
检测脉冲宽度低于APB2时钟宽度的外部信号。参见数据手册中电气特性部分的相关参数。
中断控制框图如下:

下面用按键口作为中断检测口,来演示一下中断的使用方法。
//KEY0 PC1 KEY1 PC13 WK_UP PA0
void KEY_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //下拉输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
首先初始化按键所使用的IO口,这里使用了三个按键,其中一个按键默认为低电平,按键按下后为高电平。其余两个按键默认是高电平,按下按键后为低电平。 下面开始初始化中断。
//KEY0 PC1 KEY1 PC13 WK_UP PA0
void EXTIx_Init(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
// 1、初始化IO
KEY_Init(); //按键端口初始化
// 2、开启AFIO时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //使能复用功能时钟
// 3、设置IO口与中断线的映射关系
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0); //PA0
// 4、初始化线上中断,设置触发条件
EXTI_InitStructure.EXTI_Line = EXTI_Line0; //WK_UP 上升沿
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource1); //PC1
EXTI_InitStructure.EXTI_Line = EXTI_Line1; //KEY0 下降沿
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource13);//PC13
EXTI_InitStructure.EXTI_Line = EXTI_Line13; //KEY1 上升沿
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
// 5、配置中断分组,并使能中断
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void EXTI0_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line0) != RESET)
{
delay_ms(10);
if(WK_UP == 1)
{
LED0 = !LED0;
LED1 = !LED1;
}
EXTI_ClearITPendingBit(EXTI_Line0);
}
}
void EXTI1_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line1) != RESET)
{
delay_ms(10);
if(KEY0 == 1)
{
LED0 = !LED0;
}
EXTI_ClearITPendingBit(EXTI_Line1);
}
}
void EXTI15_10_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line13) != RESET)
{
delay_ms(10);
if(KEY1 == 1)
{
LED1 = !LED1;
}
EXTI_ClearITPendingBit(EXTI_Line13);
}
}
初始化中断时需要设置每个IO口对应的中断线,中断线对应关系如下图:

通过上图可以看出所有的P0口对应的都是中断线0,所有的P1口对应的都是中断线1,依次类推。这里使用的三个按键分别是PC1、PC13、PA0,也就是对应的中断线为中断线1、中断线13、中断线0。
中断线设置完成之后,还需要设置中断分组,也就是设置中断的优先级,当中断同时触发的时候,优先级越高的中断优先处理。
中断线设置好之后,还需要提供中断入口函数,因为中断触发后,系统就会自动跳转到中断入口函数中,执行中断函数的代码。每个中断入口的函数名称都是固定的,不能自己定义。中断函数的入口名称可以在startup_stm32f10x_hs.s文件中查看。
; External Interrupts
DCD WWDG_IRQHandler ; Window Watchdog
DCD PVD_IRQHandler ; PVD through EXTI Line detect
DCD TAMPER_IRQHandler ; Tamper
DCD RTC_IRQHandler ; RTC
DCD FLASH_IRQHandler ; Flash
DCD RCC_IRQHandler ; RCC
DCD EXTI0_IRQHandler ; EXTI Line 0
DCD EXTI1_IRQHandler ; EXTI Line 1
DCD EXTI2_IRQHandler ; EXTI Line 2
DCD EXTI3_IRQHandler ; EXTI Line 3
DCD EXTI4_IRQHandler ; EXTI Line 4
DCD DMA1_Channel1_IRQHandler ; DMA1 Channel 1
DCD DMA1_Channel2_IRQHandler ; DMA1 Channel 2
DCD DMA1_Channel3_IRQHandler ; DMA1 Channel 3
DCD DMA1_Channel4_IRQHandler ; DMA1 Channel 4
DCD DMA1_Channel5_IRQHandler ; DMA1 Channel 5
DCD DMA1_Channel6_IRQHandler ; DMA1 Channel 6
DCD DMA1_Channel7_IRQHandler ; DMA1 Channel 7
DCD ADC1_2_IRQHandler ; ADC1 & ADC2
DCD USB_HP_CAN1_TX_IRQHandler ; USB High Priority or CAN1 TX
DCD USB_LP_CAN1_RX0_IRQHandler ; USB Low Priority or CAN1 RX0
DCD CAN1_RX1_IRQHandler ; CAN1 RX1
DCD CAN1_SCE_IRQHandler ; CAN1 SCE
DCD EXTI9_5_IRQHandler ; EXTI Line 9..5
DCD TIM1_BRK_IRQHandler ; TIM1 Break
DCD TIM1_UP_IRQHandler ; TIM1 Update
DCD TIM1_TRG_COM_IRQHandler ; TIM1 Trigger and Commutation
DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare
DCD TIM2_IRQHandler ; TIM2
DCD TIM3_IRQHandler ; TIM3
DCD TIM4_IRQHandler ; TIM4
DCD I2C1_EV_IRQHandler ; I2C1 Event
DCD I2C1_ER_IRQHandler ; I2C1 Error
史海拾趣
|
在我的程序中使用memcpy除了点问题,pBufOut 是一个BYTE的指针,pbuf是局部变量的数组, BYTE pbuf[40]; memcpy( pBufOut, pbuf + 3, 32 ); 执行memcpy后调试信息就出来一大堆: Data Abort: Thread=8fc7e550 Proc=89a8ca60 \'OwireTest.exe\' ...… 查看全部问答> |
|
如题,我想数据量不大的情况下,用.ini文件来保存,所以程序可以实现读写.ini文件。 但是问题出现了,想人工手动修改这个.ini文件的配置信息,直接双击在WinCE里面打不开,然后复制出来到Windows上,打开了,但是中文字信息看不清(是 ...… 查看全部问答> |
|
在调EEPROM(IIC),板子上电后第一次运行程序,可以正常运行,但是,再重新下载一次程序再运行,Serial Bus一直处于忙状态,无法进行正常读写,这是为什么 … 查看全部问答> |
|
main中的raw_memcpy((void *)0, (void *)(exception_vector), 128) 我在main函数中看到这个函数 raw_memcpy((void *)0, (void *)(exception_vector), 128); 有点不理解这个的意思 这里的\"0\"表示的是什么? 最终把什么东西复制到了\"0\"处? 麻烦回答一下啊… 查看全部问答> |




