完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
1、STM32F40x外部中断介绍
中断按键:响应及时 扫描按键:需要不断的扫描,响应不及时,耗费CPU。 2、STM32F40x外部中断框图
以独立地配置输出类型(脉冲或挂起)以及对应的触发事件(上升沿或下降沿触发或者双边沿触发),每个输入线都 可以独立地被屏蔽。挂起寄存器保持着状态线的中断请求。外部中断 0~4 有单独的中断入口,外部中断 5~9 共用一个中断入口,外部中断 10~15 共用一个中断入口。 EXTI 线 0~15:对应的外部 IO 口的输入中断 EXTI 线 16:连接到 PVD 输出 EXTI 线 17:连接到 RTC 闹钟事件 EXTI 线 18:连接到 USB OTG FS 唤醒事件 EXTI 线 19:连接到以太网唤醒事件 EXTI 线 20:连接到 USB OTG HS 唤醒事件 EXTI 线 21:连接到 RTC 入侵和时间戳事件 EXTI 线 22:连接到 RTC 唤醒事件 3、外部中断线路映象 (1)中断线0的输入信号只能所有IO0口中的一个。 (2)如何选择中断线的输入? 通过寄存器SYSCFG_EXTICRx (x:1~4),来进行选择
4.1、上升沿触发选择寄存器 (EXTI_RTSR) 每一位对应一条中断线。 0:禁止上升沿触发 1:允许上升沿触发 TR0~TR22是对应EXTI0~EXTI22 举例中断线3的触发信号配置为上升沿触发:EXTI->RTSR |= 1<<3; 4.2、下降沿触发选择寄存器 (EXTI_FTSR) 每一位对应一条中断线。 0:禁止下降沿触发 1:允许下降沿触发 TR0~TR22是对应EXTI0~EXTI22 举例中断线9的触发信号配置为下降沿触发,EXTI->FTST |= 1<<9; 4.3、中断屏蔽寄存器 (EXTI_IMR) 每一位对应一条中断线。 0:屏蔽来自 x 线的中断请求 1:开放来自 x 线的中断请求 MR0~MR22是对应EXTI0~EXTI22 举例:开放中断线5的中断请求·:EXTI->IMR |= 1<<5; 4.4、挂起寄存器 (EXTI_PR) 每一位对应一条中断线。 0:没有发生触发请求 1:发生了选择的触发的请求。即:产生了中断请求,中断请求是有相应的边沿信号来触发的。 PR0~PR22是对应EXTI0~EXTI22 当在外部中断线上发生了选择的边沿事件,该位被置“ 1”。 如何清零?答:在此位中写入“ 1”可以清零。 举例: void EXTI0_IRQHandler(void) //中断线0的中断函数 { if(EXTI->PR &(1<<0)) //判断挂起寄存器的位0是否为1 { EXTI->PR |=(1<<0); //写入1,将相应的位清零 } } 4.5、SYSCFG 外部中断配置寄存器 1 (SYSCFG_EXTICR1) 例如:位3~0,EXTI0[3:0] 用于选择外部中断线0的中断源输入管脚 0000: PA0 引脚 0001: PB0引脚 0010: PC0引脚 0011: PD0引脚 0100: PE0引脚 0101: PF0 引脚 0110: PG0 引脚 0111: PH0引脚 1000: PI0 引脚 举例:将GPIOB2配置为外部中断线2的中断源输入管脚,SYSCFG->EXTICR[0] |= 1<<8; 注意:写代码是,没有SYSCFG->EXTICR1,而是写成SYSCFG->EXTICR[0]。 4.6、SYSCFG 外部中断配置寄存器 2 (SYSCFG_EXTICR2) 4.7、SYSCFG 外部中断配置寄存器 4 (SYSCFG_EXTICR3) 4.8、SYSCFG 外部中断配置寄存器 4 (SYSCFG_EXTICR4) 作用和SYSCFG 外部中断配置寄存器 1 (SYSCFG_EXTICR1)一样,只是作用的管脚不一样 4.9、RCC APB2 外设时钟使能寄存器 (RCC_APB2ENR) 位14: 0:禁止系统配置控制器时钟 1:使能系统配置控制器时钟 注意:在配置SYSCFG_EXTICRx (x:1~4)之前,必须使能系统配置控制器的时钟 即:RCC->APB2ENR |= 1<<14; 5、外部中断线和中断函数 外部中断线有16条,但是并不会每条中断线都会对应有一个中断函数。请参考: 提问:配置GPIOD8是外部中断线8的中断输入管脚,配置GPIOE7是外部中断线7的中断输入管脚,如果产生了一次中断,并且进入了中断函数EXTI9_5_IRQHandler ,如何判断是哪个中断源管脚的边沿信号导致芯片产生中断? 答:每个中断线都有独立的挂起标志位,判断PR寄存器中的挂起标志位可以辨别导致产生进入EXTI9_5_IRQHandler的因素是什么。或者你也可以判断当前GPIO9-5的输入引脚电平 6、原理图 PA0:按下为高电平,所以设置上升沿触发 PE2~4:按下为低电平,选择为下降沿触发
外部中断2:中断源输入管脚配置为PE2 外部中断3:中断源输入管脚配置为PE3 外部中断4:中断源输入管脚配置为PE4 8、软件设计 寄存器版 void delay(u32 i) { while(i--); } void LED_Init(void) { RCC->AHB1ENR |= 1 << 5;//使能GPIOF的时钟 RCC->AHB1ENR |= 1 << 2;//使能GPIOC的时钟 //LED1->PF6 GPIOF->MODER |= 1 << 12;//输出模式 GPIOF->OTYPER &=~(1<<6);//推挽模式 //LED2->PF9 GPIOF->MODER |= 1 << 18; GPIOF->OTYPER &=~(1<<9); //LED3->PF10 GPIOF->MODER |= 1 << 20; GPIOF->OTYPER &=~(1<<10); //LED4->PC0 GPIOC->MODER |= 1 << 0; GPIOC->OTYPER &=~(1<<0); } void key_Init(void) { RCC->AHB1ENR |= 1 << 0;//使能GPIOA的时钟 RCC->AHB1ENR |= 1 << 4;//使能GPIOE的时钟 //KEY1->PA0 GPIOA->MODER &= ~(3 << 0);//输出模式 GPIOA->PUPDR &= 2 << 0;//PA0设置为下拉,平时为低电平 //KEY2->PE2 GPIOE->MODER &= ~(3 << 4);//PE2,3,4设置为上拉,平时为高电平 GPIOE->PUPDR |= 1 << 4; //KEY3->PE3 GPIOE->MODER &= ~(3 << 6); GPIOE->PUPDR |= 1 << 6; //KEY4->PE4 GPIOE->MODER &= ~(3 << 8); GPIOE->PUPDR |= 1 << 8; } void EXTI0_IRQHandler(void) { if(EXTI->PR &(1<<0)) //判断挂起寄存器的位0是否为1 { GPIOF->ODR ^= 1 << 6;//led1状态翻转 EXTI->PR=1<<0; //清除 LINE0 上的中断标志位 } } //外部中断 2 服务程序 void EXTI2_IRQHandler(void) { if(EXTI->PR &(1<<2)) //判断挂起寄存器的位0是否为1 { GPIOF->ODR ^= 1 << 9;//led2状态翻转 EXTI->PR=1<<2; //清除 LINE2 上的中断标志位 } } //外部中断 3 服务程序 void EXTI3_IRQHandler(void) { if(EXTI->PR &(1<<3)) //判断挂起寄存器的位0是否为1 { GPIOF->ODR ^= 1 << 10;//led3状态翻转 EXTI->PR=1<<3; //清除 LINE3 上的中断标志位 } } //外部中断 4 服务程序 void EXTI4_IRQHandler(void) { if(EXTI->PR &(1<<4)) //判断挂起寄存器的位0是否为1 { GPIOC->ODR ^= 1 << 0;//led4状态翻转 EXTI->PR=1<<4; //清除 LINE0 上的中断标志位 } } void ExitX_Init(void) { EXTI->RTSR |= 1<<0;//中断线0设置为上升沿触发 EXTI->IMR |= 1<<0;//开放来自exit0的请求 SYSCFG->EXTICR[0] |= 1<<0;//将GPIOA0配置为Exit0的中断源输入管脚 RCC->APB2ENR |= 1<<14;//使能系统配置控制器时钟,必须设置 NVIC_EnableIRQ(EXTI0_IRQn); //使能中断函数 EXTI->FTSR |= 1<<2; EXTI->IMR |= 1<<2; SYSCFG->EXTICR[0] |= 4<<8; NVIC_EnableIRQ(EXTI2_IRQn); EXTI->FTSR |= 1<<3; EXTI->IMR |= 1<<3; SYSCFG->EXTICR[0] |= 4<<12; NVIC_EnableIRQ(EXTI3_IRQn); EXTI->FTSR |= 1<<4; EXTI->IMR |= 1<<4; SYSCFG->EXTICR[1] |= 4<<0; NVIC_EnableIRQ(EXTI4_IRQn); } int main(void) { LED_Init(); key_Init(); ExitX_Init(); while(1) { } } 库函数版 void LED_Init(void) { GPIO_InitTypeDef LED_InitTypeDef; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE); //使能 F 端口 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE); //使能 C 端口 LED_InitTypeDef.GPIO_Mode =GPIO_Mode_OUT; //配置为输出模式 LED_InitTypeDef.GPIO_OType =GPIO_OType_PP; //配置为推挽输出 LED_InitTypeDef.GPIO_Pin =GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_6; //初始化GPIOF6/9/10; LED_InitTypeDef.GPIO_PuPd =GPIO_PuPd_NOPULL; //配置为无上下拉状态 LED_InitTypeDef.GPIO_Speed =GPIO_Speed_50MHz; //速度设置为 50MHz GPIO_Init(GPIOF,&LED_InitTypeDef); LED_InitTypeDef.GPIO_Mode =GPIO_Mode_OUT; //配置为输出模式 LED_InitTypeDef.GPIO_OType =GPIO_OType_PP; //配置为推挽输出 LED_InitTypeDef.GPIO_Pin =GPIO_Pin_0; //初始化 GPIOC0; LED_InitTypeDef.GPIO_PuPd =GPIO_PuPd_NOPULL; //配置为无上下拉状态 LED_InitTypeDef.GPIO_Speed =GPIO_Speed_50MHz; //速度设置为 50MHz GPIO_Init(GPIOC,&LED_InitTypeDef); //初始化 GPIOC0; } void key_Init(void) { GPIO_InitTypeDef LED_InitTypeDef; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA|RCC_AHB1Periph_GPIOE,ENABLE); //使能GPIOA 和 GPIOE 时钟 LED_InitTypeDef.GPIO_Mode =GPIO_Mode_IN; //配置为输入模式 LED_InitTypeDef.GPIO_Pin =GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4; //初始化 GPIOE2/3/4; LED_InitTypeDef.GPIO_PuPd =GPIO_PuPd_UP; //上拉 GPIO_Init(GPIOE,&LED_InitTypeDef); LED_InitTypeDef.GPIO_Mode =GPIO_Mode_IN; //配置为输入模式 LED_InitTypeDef.GPIO_Pin =GPIO_Pin_0; //初始化 GPIOA0; LED_InitTypeDef.GPIO_PuPd =GPIO_PuPd_DOWN; //下拉 GPIO_Init(GPIOA,&LED_InitTypeDef); //初始化 GPIOA0; } void EXTI0_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line0)) //判断挂起寄存器的位0是否为1 { GPIO_ToggleBits(GPIOF,GPIO_Pin_6); //led1状态翻转 EXTI_ClearITPendingBit(EXTI_Line0); //清除 LINE0上的中断标志位 } } //外部中断 2 服务程序 void EXTI2_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line2)) //判断挂起寄存器的位0是否为1 { GPIO_ToggleBits(GPIOF,GPIO_Pin_9);//led2状态翻转 EXTI_ClearITPendingBit(EXTI_Line2); //清除 LINE2 上的中断标志位 } } //外部中断 3 服务程序 void EXTI3_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line3)) //判断挂起寄存器的位0是否为1 { GPIO_ToggleBits(GPIOF,GPIO_Pin_10);//led3状态翻转 EXTI_ClearITPendingBit(EXTI_Line3); //清除 LINE3 上的中断标志位 } } //外部中断 4 服务程序 void EXTI4_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line4)) //判断挂起寄存器的位0是否为1 { GPIO_ToggleBits(GPIOC,GPIO_Pin_0);//led4状态翻转 EXTI_ClearITPendingBit(EXTI_Line4); //清除 LINE4 上的中断标志位 } } void ExitX_Init(void) { EXTI_InitTypeDef EXTI_InitTypeSter; NVIC_InitTypeDef NVIC_InitTypeSter; RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE); //使能中断时钟 SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource2); SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource3); SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource4); SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0); EXTI_InitTypeSter.EXTI_Line =EXTI_Line2|EXTI_Line3|EXTI_Line4; //外部中断线 2,3,4 EXTI_InitTypeSter.EXTI_LineCmd =ENABLE; //使能 EXTI_InitTypeSter.EXTI_Mode =EXTI_Mode_Interrupt; //外部中断模式 EXTI_InitTypeSter.EXTI_Trigger =EXTI_Trigger_Falling; //下降沿触发 EXTI_Init(&EXTI_InitTypeSter); EXTI_InitTypeSter.EXTI_Line =EXTI_Line0; //外部中断线 0 EXTI_InitTypeSter.EXTI_LineCmd =ENABLE; //使能 EXTI_InitTypeSter.EXTI_Mode =EXTI_Mode_Interrupt; //外部中断模式 EXTI_InitTypeSter.EXTI_Trigger =EXTI_Trigger_Rising; //上升沿触发 EXTI_Init(&EXTI_InitTypeSter); NVIC_InitTypeSter.NVIC_IRQChannel =EXTI2_IRQn; //外部中断 2 NVIC_InitTypeSter.NVIC_IRQChannelCmd =ENABLE; //使能外部中断 2 //在不需要优先级的情况下可以不设置,寄存器版我就懒得设置 // NVIC_InitTypeSter.NVIC_IRQChannelPreemptionPriority =1; //抢占优先级 1 // NVIC_InitTypeSter.NVIC_IRQChannelSubPriority =0; //子优先级 0 NVIC_Init(&NVIC_InitTypeSter); NVIC_InitTypeSter.NVIC_IRQChannel =EXTI3_IRQn; //外部中断 3 // NVIC_InitTypeSter.NVIC_IRQChannelCmd =ENABLE; //使能外部中断 3 // NVIC_InitTypeSter.NVIC_IRQChannelPreemptionPriority =2; //抢占优先级 2 // NVIC_InitTypeSter.NVIC_IRQChannelSubPriority =0; //子优先级 0 NVIC_Init(&NVIC_InitTypeSter); NVIC_InitTypeSter.NVIC_IRQChannel =EXTI4_IRQn; //外部中断 4 NVIC_InitTypeSter.NVIC_IRQChannelCmd =ENABLE; //使能外部中断 4 // NVIC_InitTypeSter.NVIC_IRQChannelPreemptionPriority =3; //抢占优先级 3 // NVIC_InitTypeSter.NVIC_IRQChannelSubPriority =0; //子优先级 0 NVIC_Init(&NVIC_InitTypeSter); NVIC_InitTypeSter.NVIC_IRQChannel =EXTI0_IRQn; //外部中断 0 NVIC_InitTypeSter.NVIC_IRQChannelCmd =ENABLE; //使能外部中断 0 // NVIC_InitTypeSter.NVIC_IRQChannelPreemptionPriority =0; //抢占优先级 1 // NVIC_InitTypeSter.NVIC_IRQChannelSubPriority =0; //子优先级 0 NVIC_Init(&NVIC_InitTypeSter); } int main(void) { LED_Init(); key_Init(); ExitX_Init(); while(1) { } } |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1927 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1697 浏览 1 评论
1180 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
779 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1745 浏览 2 评论
1984浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
818浏览 4评论
stm32f4下spi+dma读取数据不对是什么原因导致的?
268浏览 3评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
633浏览 3评论
637浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-31 10:24 , Processed in 0.596454 second(s), Total 42, Slave 37 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号