二、预备知识
外部中断建立过程 启动代码文件
建立中断向量表 startup_stm32f10x yy. s 分配栈空间并初始化 GPIO初始化 用户应用主程序文件
main. C
EXTI中断线引脚映射 EXTI中断初始化 中断服务程序文件 stm32f10x it.c
NVIC初始化,中断使能 编写对应的中断服务程序 STM32F10x的NVIC相关库函数: 函数NVIC_Init: 函数名 函数原形 功能描述 输入参数 输出参数 返回值 先决条件 NVIC_Init void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct) 根据 NVIC_InitStruct 中指定的参数初始化外设 NVIC 寄存器 NVIC_InitStruct:指向结构 NVIC_InitTypeDef 的指针,包含了外设 GPIO 的配置信息 无 无 无 被调用函数 无 typedef struct {
uint8_t NVIC_IRQChannel;
uint8_t NVIC_IRQChannelPreemptionPriority; uint8_t NVIC_IRQChannelSubPriority; FunctionalState NVIC_IRQChannelCmd; } NVIC_InitTypeDef;
参数NVIC_IRQChannel用以使能或失能指定的IRQ通道。
WWDG_IRQn PVD_IRQn RTC_ IRQn RCC_IRQn
TAMPER_ IRQn Flashltf_IRQn
窗口看门狗中断
PVD通过EXTI探测中断 篡改中断 RTC全局中断 FLASH全局中断 RCC全局中断
EXTI0_IRQn EXTI1_IRQn EXTI2_IRQn EXTI3_IRQn EXTI4_IRQn
外部中断线0中断 外部中断线1中断 外部中断线2中断 外部中断线3中断 外部中断线4中断 DMA通道1中断 DMA通道2中断 DMA通道3中断 DMA通道4中断 DMA通道5中断 DMA通道6中断 DMA通道7中断 ADC全局中断
USB高优先级或者CAN发送中断 USB低优先级或者CAN接收0中断 CAN接收1中断 CAN SCE中断 外部中断线9~5中断 TIM1暂停中断 TIM1刷新中断 TIM1触发和通信中断 TIM1捕获比较中断 TIM2全局中断 TIM3全局中断 TIM4全局中断 I2C1事件中断 I2C1错误中断 I2C2事件中断 I2C2错误中断 SPI1全局中断 SPI2全局中断 USART1全局中断 USART2全局中断 USART3全局中断 外部中断线15~10中断 RTC闹钟通过EXTI线中断 USB通过EXTI线从悬挂唤醒中断
DMAChannel1_IRQn DMAChannel2_IRQn DMAChannel3_IRQn DMAChannel4_IRQn DMAChannel5_IRQn DMAChannel6_IRQn DMAChannel7_IRQn ADC_IRQn
USB_HP_CANTX_IRQn CAN_RXI_IRQn CAN_SCE_IRQn EXTI9_5_IRQn TIM1_BRK_IRQn TIM1_UP_IRQn TIM1_CC_IRQn TIM2_IRQn TIM3_IRQn TIM4_IRQn
USB_LP_CAN_RX0_IRQn
TIM1_TRG_COM_IRQn
I2C1_EV_IRQn I2C1_ER_IRQn I2C2_EV_IRQn I2C2_ER_IRQn SPI1_IRQn SPI2_IRQn
USART1_IRQn USART2_IRQn USART3_IRQn EXTI15_10_IRQn RTCAlarm_IRQn USBWakeup_IRQn
函数NVIC_PriorityGroupConfig: 函数名 函数原形 功能描述 输入参数 输出参数 NVIC_PriorityGroupConfig void NVIC_PriorityGroupConfig(u32 NVIC_PriorityGroup) 设置优先级分组:先占优先级和从优先级 NVIC_PriorityGroup:优先级分组位长度 参阅 Section: NVIC_PriorityGroup 查阅更多该参数允许取值范围 无 返回值 先决条件 被调用函数 无 优先级分组只能设置一次 无 STM32F10x的EXTI相关库函数: 函数EXTI_Init: 函数名 函数原形 功能描述 输入参数 输出参数 返回值 先决条件 被调用函数 EXTI_Init void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct) 根据 EXTI_InitStruct 中指定的参数初始化外设 EXTI 寄存器 EXTI_InitStruct:指向结构 EXTI_InitTypeDef 的指针,包含了外设 EXTI 的配置信息,参阅 Section: EXTI_InitTypeDef 查阅更多该参数允许取值范围 无 无 无 无 EXTI_InitTypeDef定义于头文件“stm32f103x_exit.h”: typedef struct {
uint32_t EXTI_Line; EXTIMode_TypeDef EXTI_Mode; EXTITrigger_TypeDef EXTI_Trigger; FunctionalState EXTI_LineCmd; }EXTI_InitTypeDef;
函数EXTI_GetITStatus: 函数名 函数原形 功能描述 输入参数 输出参数 返回值 先决条件 被调用函数 函数名 函数原形 功能描述 输入参数 输出参数 返回值 先决条件 EXTI_GetITStatus ITStatus EXTI_GetITStatus(u32 EXTI_Line) 检查指定的 EXTI 线路触发请求发生与否 EXTI_Line:待检查 EXTI 线路的挂起位 参阅 Section: EXTI_Line 查阅更多该参数允许取值范围 无 EXTI_Line 的新状态(SET 或者 RESET) 无 无 EXTI_ClearFlag void EXTI_ClearFlag(u32 EXTI_Line) 清除 EXTI 线路挂起标志位 EXTI_Line:待清除标志位的 EXTI 线路 无 无 无 函数EXTI_ClearFlag: 被调用函数 函数名 函数原形 功能描述 输入参数 1 无 GPIO_EXTILineConfig void GPIO_EXTILineConfig(u8 GPIO_PinSource) 选择 GPIO 管脚用作外部中断线路 GPIO_PortSource: 选择用作外部中断线源的 GPIO 端口 参阅 Section: GPIO_PortSource 查阅更多该参数允许取值范围 GPIO_PinSource:待设置的外部中断线路 该参数可以取 GPIO_PinSourcex(x 可以是 0-15) 无 无 无 无 GPIO_PortSource, u8 EXTI中断线GPIO引脚映射库函数: 输入参数 2 输出参数 返回值 先决条件 被调用函数 三、实验步骤: 功能描述:程序运行后背光灯亮,按下左键背光灯灭,按下右键背光灯亮,按键是通过外部中断实现的。
1、设置相应的时钟
打开PA 、PB端口时钟,并且打开复用时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO,ENABLE);
STM32 的所有 GPIO 都引入到 EXTI 外部中断线上,使得所有的GPIO 都
能作为外部中断的输入源,所以如果把 GPIO 用作 EXTI 外部中断时,还需要开启 AFIO 时钟。 2、设置好相应的中断
设置相应的中断实际上就是设置NVIC,在STM32的固件库中有一个结构体NVIC_InitTypeDef,里面有相应的标志位设置,然后再用NVIC_Init()函数进行初始化。详细代码如下:
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //选择中断分组2 NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn; //选择中断通道号
//抢占式中断优先级设置为1
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //响应式中断优先级设置为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中断 NVIC_Init(&NVIC_InitStructure); //中断初始化
由于有2个中断,需要有2个bit来指定抢占优先级,所以选择第2组。又由于EXTI15-10共用一个中断响应函数,所以EXTI14,EXTI15选择的中断通道是EXTI15_10_IRQn,详细信息可以在头文件中查询得到。用到的NVIC相关的库函数在stm32f10x_nivc.c中,需要将此文件复制并添加到工程中。 3、IO口初始化
连接外部中断的引脚需要设置为输入状态 GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14 | GPIO_Pin_15; //选择引脚14,15 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //输出最大50MHz GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //内部上拉输入 GPIO_Init(GPIOB,&GPIO_InitStructure); //设置PB.14/PB.15 4、把相应的IO口设置为中断线路
由于GPIO并不是专用的中断引脚,因此在用GPIO来触发外部中断的时候需要设置将GPIO相应的引脚和中断线连接起来。 EXTI_InitTypeDef EXTI_InitStructure; //清空中断标志 EXTI_ClearITPendingBit(EXTI_Line14); EXTI_ClearITPendingBit(EXTI_Line15);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14); GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource15);
EXTI_InitStructure.EXTI_Line = EXTI_Line14|EXTI_Line15;//中断线路14,15
//设置为中断请求,非事件请求
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //设置中断触发方式为下降沿触发
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE; //外部中断使能 EXTI_Init(&EXTI_InitStructure);
至此,中断的配置完毕。不过,现在只能够说该中断已经配置完毕,但还不能使用它。我们还缺少一个中断的执行函数,当中断被触发后,程序要马上跳转到中断函数去执行中断操作,这个函数在工程创建时默认时没有的。需要去添加,而且需要注意的是,中断函数的名称必须是由标准库提供的,否则无法识别。 5、创建中断响应函数
EXTI15_10_IRQHandler 就是中断线EXTI_Line14, EXTI_Line15的中断函数,所以,我们把这个函数添加到工程中即可。最好添加到stm32f10x_it.c 这个文件中,方便管理。
可以在这个函数中添加你想要的功能,代码如下: /************************************************ 函数名称 : EXTI15_10_IRQHandler 功 能 : GPIO中断
*************************************************/ void EXTI15_10_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line14)!=RESET) //中断IO判断
{if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==0)
{
Delay_Ms(10); //按键消抖 if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==0) {Led_On; //右键背光灯亮
}
} } EXTI_ClearITPendingBit(EXTI_Line14); //别忘记清除中断标志位 if(EXTI_GetITStatus(EXTI_Line15)!=RESET)//中断IO判断
{if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15)==0)
{
Delay_Ms(10); //按键消抖 if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15)==0)
{Led_Off; //左键背光灯灭 }
} } EXTI_ClearITPendingBit(EXTI_Line15); //别忘记清除中断标志位 }
6、创建主函数
//例程名称:按键实现外部中断
#include \"stm32f10x.h\" #include \"led.h\"
#include \"systick.h\" #include \"exti.h\"
int main(void) { Delay_Init(); Led_Init(); Exti_Init(); while(1) { } }
因篇幅问题不能全部显示,请点此查看更多更全内容