STM32中断15—10的设置

合集下载

STM32 不断进入串口中断问题 解决方法

STM32 不断进入串口中断问题 解决方法

STM32 不断进入串口中断问题解决方法STM32 有时候会不断进入中断,解决方法如下1.串口初始化配置时,需要打开ORE 溢出中断,如下红色代码所示 [cpp] view plain copy1.void Usart_Init(void)2.{3.4.5. GPIO_InitTypeDef GPIO_InitStructure;6. NVIC_InitTypeDef NVIC_InitStructure;7. USART_InitTypeDef USART_InitStructure;8.9. RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); // 开启串口时钟10.11. GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_1);12. GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_1);13.14. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;15. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;16. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;17. GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;18. GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;19. GPIO_Init(GPIOA,&GPIO_InitStructure);20.21.22.23. USART_ART_BaudRate = 57600; // 配置波特率为11520024. USART_ART_StopBits = USART_WordLength_8b; // 配置数据长度为825. USART_ART_StopBits = USART_StopBits_1; //设置停止位26. USART_ART_Parity = USART_Parity_No; // 配置奇偶校验为NONE27. USART_ART_HardwareFlowControl = USART_HardwareFlowControl_None; // 配置硬件流为NONE 28. USART_ART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 打开Rx接收和Tx发送功能29.30. USART_Init(USART1,&USART_InitStructure); // 配置31.32.33. USART_Cmd(USART1,ENABLE);34.35. NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; // 选择中断通道36. NVIC_InitStructure.NVIC_IRQChannelPriority = 2; // 抢断优先137. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 使能中断38.39. NVIC_Init(&NVIC_InitStructure);40.41.<span style="color:#ff0000;"> USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // 打开中断42. USART_ITConfig(USART1, USART_IT_ORE, ENABLE);</span> // 打开中断43.44.45.}2.在中断中,检测溢出中断并作处理,代码如下所示[cpp] view plain copy1.void USART1_IRQHandler(void)2.{3. u8 dat;4.5.<span style="color:#ff0000;"> if (USART_GetITStatus(USART1, USART_IT_ORE) == SET)6. {7. USART_ClearITPendingBit(USART1,USART_IT_ORE);8. USART_ReceiveData( USART1 );9.10. }</span>11.if( USART_GetITStatus(USART1,USART_IT_RXNE) != RESET ) // 等价于if( !RI ) 检查串口数据是否已就位12. {13. USART_ClearITPendingBit(USART1,USART_IT_RXNE);14. dat = USART_ReceiveData( USART1 );15. uart_rec_buf[uart_len++]=dat;16. RX_TIM=UART_INIT_TIM;17.18. }19.20.}这样就可以解决,串口不断进入中断的问题。

STM32中断中设置的先占式优先级与从优先级

STM32中断中设置的先占式优先级与从优先级

STM32中断中设置的先占式优先级与从优先级STM32(Cortex-M3)中有两个优先级的概念——抢占式优先级和响应优先级,有人把响应优先级称作'亚优先级'或'副优先级',每个中断源都需要被指定这两种优先级。

具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断嵌套,或者说高抢占式优先级的中断可以嵌套低抢占式优先级的中断。

当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之后才能被处理。

如果这两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先处理哪一个;如果他们的抢占式优先级和响应优先级都相等,则根据他们在中断表中的排位顺序决定先处理哪一个。

既然每个中断源都需要被指定这两种优先级,就需要有相应的寄存器位记录每个中断的优先级;在Cortex-M3中定义了8个比特位用于设置中断源的优先级,这8个比特位可以有8种分配方式,如下:所有8位用于指定响应优先级最高1位用于指定抢占式优先级,最低7位用于指定响应优先级最高2位用于指定抢占式优先级,最低6位用于指定响应优先级最高3位用于指定抢占式优先级,最低5位用于指定响应优先级最高4位用于指定抢占式优先级,最低4位用于指定响应优先级最高5位用于指定抢占式优先级,最低3位用于指定响应优先级最高6位用于指定抢占式优先级,最低2位用于指定响应优先级最高7位用于指定抢占式优先级,最低1位用于指定响应优先级这就是优先级分组的概念。

--------------------------------------------------------------------------------Cortex-M3允许具有较少中断源时使用较少的寄存器位指定中断源的优先级,因此STM32把指定中断优先级的寄存器位减少到4位,这4个寄存器位的分组方式如下:第0组:所有4位用于指定响应优先级第1组:最高1位用于指定抢占式优先级,最低3位用于指定响应优先级第2组:最高2位用于指定抢占式优先级,最低2位用于指定响应优先级第3组:最高3位用于指定抢占式优先级,最低1位用于指定响应优先级第4组:所有4位用于指定抢占式优先级可以通过调用STM32的固件库中的函数选择使用哪种优先级分组方式,这个函数的参数有下列5种: NVIC_PriorityGroup_0 => 选择第0组NVIC_PriorityGroup_1 => 选择第1组NVIC_PriorityGroup_2 => 选择第2组NVIC_PriorityGroup_3 => 选择第3组NVIC_PriorityGroup_4 => 选择第4组接下来就是指定中断源的优先级,下面以一个简单的例子说明如何指定中断源的抢占式优先级和响应优先级:// 选择使用优先级分组第1组NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);// 使能EXTI0中断NVIC_InitStructure.NVIC_IRQChannel=EXTI0_IRQChannel;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 指定抢占式优先级别1NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 指定响应优先级别0NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);// 使能EXTI9_5中断NVIC_InitStructure.NVIC_IRQChannel=EXTI9_5_IRQChannel;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 指定抢占式优先级别0NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 指定响应优先级别1NVIC_InitStructure.NVIC_IRQChannelCmd =ENABLE;NVIC_Init(&NVIC_InitStructure);--------------------------------------------------------------------------------要注意的几点是:1)如果指定的抢占式优先级别或响应优先级别超出了选定的优先级分组所限定的范围,将可能得到意想不到的结果;2)抢占式优先级别相同的中断源之间没有嵌套关系;3)如果某个中断源被指定为某个抢占式优先级别,又没有其它中断源处于同一个抢占式优先级别,则可以为这个中断源指定任意有效的响应优先级别。

STM32中断优先级彻底讲解

STM32中断优先级彻底讲解

STM32中断优先级彻底讲解一:综述STM32 目前支持的中断共为 84 个(16 个内核+68 个外部), 16 级可编程中断优先级的设置(仅使用中断优先级设置 8bit 中的高 4 位)和16个抢占优先级(因为抢占优先级最多可以有四位数)。

二:优先级判断STM32(Cortex-M3)中有两个优先级的概念——抢占式优先级和响应优先级,有人把响应优先级称作'亚优先级'或'副优先级',每个中断源都需要被指定这两种优先级。

具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断嵌套,或者说高抢占式优先级的中断可以嵌套低抢占式优先级的中断。

当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之后才能被处理。

如果这两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先处理哪一个;如果他们的抢占式优先级和响应优先级都相等,则根据他们在中断表中的排位顺序决定先处理哪一个。

三:优先级分组既然每个中断源都需要被指定这两种优先级,就需要有相应的寄存器位记录每个中断的优先级;在Cortex-M3中定义了8个比特位用于设置中断源的优先级,这8个比特位在NVIC应用中断与复位控制寄丛器(AIRCR)的中断优先级分组域中,可以有8种分配方式,如下:所有8位用于指定响应优先级最高1位用于指定抢占式优先级,最低7位用于指定响应优先级最高2位用于指定抢占式优先级,最低6位用于指定响应优先级最高3位用于指定抢占式优先级,最低5位用于指定响应优先级最高4位用于指定抢占式优先级,最低4位用于指定响应优先级最高5位用于指定抢占式优先级,最低3位用于指定响应优先级最高6位用于指定抢占式优先级,最低2位用于指定响应优先级最高7位用于指定抢占式优先级,最低1位用于指定响应优先级这就是优先级分组的概念。

Stm32中断优先级相关概念与使用笔记

Stm32中断优先级相关概念与使用笔记

Stm32中断优先级相关概念与使用笔记一、基本概念1.ARM cortex_m3内核支持256个中断(16个内核+240外部)和可编程256级中断优先级的设置,与中断控制核中断优先级控制的寄存器(NVIC、SYSTICK等)属于cortex_m3内核的部分。

STM32采用了cortex_m3内核,所以这些部分仍旧保留使用,但并不是完全使用的,只是使用了一部分。

2.STM32目前支持的中断共为84个(16个内核+68个外部),和16级可编程中断优先级的设置(仅使用中断优先级设置8bit中的高4位,见后面解释)。

《参考最新101xx-107xx STM32 Reference manual, RM0008》。

以下主要对外部中断进行说明。

3.68个外部中断(通道)在STM32中已经固定的分配给相应的外部设备,每个中断通道都具备自己的中断优先级控制字节PRI_n(8位,但在STM32中只有高4位有效),每4个通道的8位中断优先级控制字(PRI_n)构成一个32位的优先级寄存器(Priority Register)。

68个通道的优先级寄存器至少有是17个32位的寄存器,它们是NVIC寄存器的一部分。

4.这4bit的中断优先级控制位还要分成2组看,从高位开始,前面的定义抢先式优先级,后面为子优先级。

4bit的组合可以有以下几种形式:5.在一个系统中,通常只使用上面5种分配情况的一种,具体采用哪一种,需要在初始化时写入到一个32位寄存器AIRC(Application Interrupt and Reset Control Register)的第[10:8]这2个位中。

这3个bit位有专门的称呼:PRIGROUP(具体写操作后面介绍)。

比如你将0x05(上表的编号)写到AIRC的[10:8]中,那么也就规定了你的系统中只有4个抢先式优先级,相同的抢先式优先级下还可以有4个不同级别的子优先级。

6.AIRC中PRIGROUP的值规定了设置和确定每个外部中断通道优先级的格式。

STM32外部中断以及中断优先级

STM32外部中断以及中断优先级

外部中断(zhōngduàn)的初始化过程:1.初始化IO为输入(shūrù)(可以设置上拉,下拉,浮空)2.开启(kāiqǐ)IO复用(fù yònɡ)时钟3.开启(kāiqǐ)与该IO相对的线上(详解下)4.配置NVIC,使能中断5.编写中断服务函数外部中断:Stm32中总共有19个外部中断包括:线0-15:IO输入中断(每条线上最多有7个IO,如GPIOA~GPIOG,但是每一条线每次只允许同时连接到一个IO)线16:PVD线17:RTC线18:USB关于(guānyú)优先级:CM3中内核(nèi hé)支持256个中断(zhōngduàn)(16个内核(nèi hé)+240外部(wàibù))和可编程256级中断优先级的设置Stm32目前(mùqián)支持84个中断(zhōngduàn)(16个内核(nèi hé)+68个外部(wàibù),注:不是(bù shi)指68个外部中断),16级可编程优先级(优先级设置寄存器中使用了4位)注意:其中(qízhōng)外部中断5-9和中断(zhōngduàn)10-15向量存放(cúnfàng)在一起优先级:数值(shùzí)低的优先级要高于数值高的!!!!!!上电复位后,系统默认(mòrèn)使用的是组0;一个系统只能使用一组优先级组,不可使用多个,优先级的设置不能超过组的范围,否则会产生不可预计的错误1.高抢先级的中断可以打断低优先级的中断响应,构成中断嵌套2.相同抢先级的中断不可以构成嵌套,系统会优先响应子优先级高的3.当2(n)个相同抢先优先级和相同子优先级的中断(zhōngduàn)出现,STM32首先响应中断通道所对应的中断向量地址(dìzhǐ)低的那个中断4.0号抢先优先级的中断,可以(kěyǐ)打断任何中断抢先优先级为非0号的中断(zhōngduàn);1号抢先优先级的中断(zhōngduàn),可以打断任何中断抢先优先级为2、3、4号的中断;……;构成中断嵌套。

STM32Cube学习之五:定时器中断

STM32Cube学习之五:定时器中断

STM32Cube学习之五:定时器中断假设已经安装好STM32CubeMX和STM32CubeF4支持包。

Step1.打开STM32CubeMX,点击“New Project”,选择芯片型号,STM32F407ZETx。

Step2.在Pinout界面下配置PF9,PF10为输出模式,并输入用户标签LED0,LED1。

Step3.配置TIM1,使用内部时钟源。

Step4.配置时钟树,在此使用默认值,16MHz。

Step5.配置TIM1参数和GPIO的参数。

在configuration界面中点击TIM1按钮,可以进入参数配置界面。

在Parameter Settings页配置预分频系数为15999,计数周期(自动加载值)为999,定时器溢出频率就是16MHz/(15999+1)/(999+1) = 1Hz。

在NVIC页面使能TIM1的更新中断。

在configuration界面中点击GPIO按钮,配置GPIO的上拉电阻。

在此GPIO配置默认即可。

Step6.生成源代码。

点击生成源代码按钮。

在设置界面中输入工程名,保存路径,工程IDE类型,点OK即可。

生成代码完成后可直接打开工程。

弹出如下对话框时,如果已经安装了F4的支持包,则点击OK关闭。

如果没有安装,则点击界面中的/...链接,找到芯片的支持包,然后安装。

关闭后面的界面。

点击“是”,然后选择芯片型号。

可以在搜索框中输入关键字,加快选择速度。

Step7.添加功能代码。

在main文件/* USER CODE BEGIN 4 */和/* USER CODE END 4 */注释之间加入下面代码。

在main函数的while(1)之前启动TIM1并使能其中断功能。

至此,完成整个工程。

编译下载,现象就是LED0和LED1同步循环闪烁,亮1秒灭1秒。

特别说明:CubeMX生成的MDK工程已经包含了配置中用到的外设相关文件,如下图:打开stm32f4xx_hal_tim.c,并点击右键,选择相应条目即可打开stm32f4xx_hal_tim.h文件,在HAL_开头的函数中,找到使能定时器中断的函数,如下图:定时器周期中断回调函数,在1304行。

stm32解决中断冲突的方法

stm32解决中断冲突的方法

stm32解决中断冲突的方法如何解决STM32中的中断冲突第一步:了解STM32中断机制STM32微控制器系列是STMicroelectronics开发的一系列32位ARM Cortex-M内核的微控制器。

STM32使用向量中断控制器(NVIC)来管理中断。

每个可中断源都有一个特定的中断优先级,并且可以通过调整优先级来控制中断的触发和处理顺序。

中断是STM32系统中非常重要的一部分,它允许微控制器在处理其他任务时根据需要对外部事件作出响应。

但是,在STM32中使用多个中断时可能会出现冲突的问题。

这可能导致一些中断无法触发或中断优先级错误。

为了解决这个问题,可以采取以下方法。

第二步:了解中断冲突的原因中断冲突可能是由于中断优先级设置错误、中断嵌套问题或中断间共享资源引起的。

中断优先级设置错误是指中断的优先级设置不正确,导致某些中断会被覆盖或延迟触发。

中断嵌套问题是指当一个中断正在处理时,另一个中断发生,导致中断无法正确触发。

中断间共享资源引起的冲突是指多个中断同时访问共享资源,导致数据错误或冲突。

第三步:调整中断优先级首先,调整中断的优先级是解决中断冲突的关键。

在STM32中,每个中断源都有一个特定的优先级,范围从0到15。

较低的数值表示更高的优先级,而较高的数值表示较低的优先级。

为了更好地控制中断触发和处理顺序,可以根据系统需求适当调整中断的优先级。

调整中断优先级可通过在NVIC中设置相关的中断控制器寄存器来实现。

有两个关键的寄存器需要设置:中断优先级寄存器(IPR)和中断使能寄存器(IER)。

中断优先级寄存器用于设置中断的优先级,而中断使能寄存器用于使能或禁用中断。

为了防止冲突,可以将高优先级的中断设置为较低的值(例如0或1),而将低优先级的中断设置为较高的值(例如14或15)。

这样可以确保高优先级的中断首先得到处理,从而避免了中断冲突。

第四步:正确处理中断嵌套另一个常见的中断冲突问题是中断嵌套。

STM32-NVIC中断优先级分组-中断优先级设置

STM32-NVIC中断优先级分组-中断优先级设置

STM32-NVIC中断优先级分组-中断优先级设置STM32-中断优先级管理NVIC1.NVIC中断优先级分组NVIC的全称是Nested vectoredinterrupt controller,即嵌套向量中断控制器。

STM32F中⽂参考⼿册中搜索向量表可以找到相应的中断说明。

CM4/CM7 内核⽀持256个中断,其中包含了16个内核中断和240个外部中断,并且具有256级的可编程中断设置。

STM32F4/F7并没有使⽤CM4内核的全部东西,⽽是只⽤了它的⼀部分。

STM32F40xx/STM32F41xx总共有92个中断。

10个内核中断,82个可屏蔽中断。

STM32F42xx/STM32F43xx则总共有97个中断。

10个内核中断,87个可屏蔽中断。

STM32F76x总共118个中断,10个内核中断,108个可屏蔽中断。

STM32具有16级可编程的中断优先级,⽽我们常⽤的就是这些可屏蔽中断。

⼏⼗个中断,怎么管理?⾸先,对STM32中断进⾏分组,组0~4。

同时,对每个中断设置⼀个抢占优先级和⼀个响应优先级值。

分组配置是在寄存器SCB->AIRCR中配置: IP bit[7:4]有4位,2^4=16,所以说它们的优先级可以有16个值,这时候如果是2位抢占优先级,那么它的值可能为0、1、2、3。

也就是抢占优先级可以取0到3 。

⾸先进⾏分组来决定⼏位抢占优先级、⼏位响应优先级。

数越⼩它的优先级越⾼。

组AIRCR[10:8]IP bit[7:4]分配情况分配结果01110:40位抢占优先级,4位响应优先级11101:31位抢占优先级,3位响应优先级21012:22位抢占优先级,2位响应优先级31003:13位抢占优先级,1位响应优先级40114:04位抢占优先级,0位响应优先级抢占优先级 & 响应优先级区别:⾼优先级的抢占优先级是可以打断正在进⾏的低抢占优先级中断的。

抢占决定了是否能打断别⼈。

stm32中断学习总结

stm32中断学习总结

stm32中断学习总结经过了两天,终于差不多能看懂32的中断了,由于是⽤的库函数操作的,所以有些内部知识并没有求甚解,只是理解知道是这样的。

但对于要做简单开发的我来说这些已经够了。

我学习喜欢从⼀个例程来看,下⾯的程序是我粘贴但是改编的,⼤部分都做了注释。

其实主要步骤就是:1、将GPIO⼝配置成中断输⼊模式。

void Init_LED(void){GPIO_InitTypeDef GPIO_InitStructure; //定义⼀个GPIO结构体变量RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE |RCC_APB2Periph_GPIOG, ENABLE);//使能各个端⼝时钟,GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14; //板上LED编号 D2GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOG, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; //板上LED编号 D5GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOD, &GPIO_InitStructure);}2、这个例程是做的按键,就是你要哪个地⽅产⽣中断,然后将其所在的总线配置成中断源,然后照猫画虎,填写中断结构体成员,就是配置外部事件的模式、触发条件、使能外部触发,但是别忘了打开复⽤功能(现在我还不理解)void Init_TI_KEY(void){EXTI_InitTypeDef EXTI_InitStructure; //定义⼀个EXTI结构体变量RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //使能IO复⽤功能,使⽤中断功能重要/* 引脚选择 */GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource13);//配置端⼝C的13引脚为中断源重要!!板上标号INT2GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource0); //配置端⼝E的0引脚为中断源重要!!板上标号INT1/* 设置外部中断结构体的成员*/EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式为中断模式EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发EXTI_InitStructure.EXTI_Line = EXTI_Line0 | EXTI_Line13;EXTI_InitStructure.EXTI_LineCmd = ENABLE; //使能中断线EXTI_Init(&EXTI_InitStructure); //根据参数初始化中断寄存器}3、现在就该配置中断了。

STM32中断优先级彻底讲解

STM32中断优先级彻底讲解

STM32中断优先级彻底讲解一:综述STM32 目前支持的中断共为 84 个(16 个内核+68 个外部), 16 级可编程中断优先级的设置(仅使用中断优先级设置 8bit 中的高 4 位)和16个抢占优先级(因为抢占优先级最多可以有四位数)。

二:优先级判断STM32(Cortex-M3)中有两个优先级的概念——抢占式优先级和响应优先级,有人把响应优先级称作'亚优先级'或'副优先级',每个中断源都需要被指定这两种优先级。

具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断嵌套,或者说高抢占式优先级的中断可以嵌套低抢占式优先级的中断。

当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之后才能被处理。

如果这两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先处理哪一个;如果他们的抢占式优先级和响应优先级都相等,则根据他们在中断表中的排位顺序决定先处理哪一个。

三:优先级分组既然每个中断源都需要被指定这两种优先级,就需要有相应的寄存器位记录每个中断的优先级;在Cortex-M3中定义了8个比特位用于设置中断源的优先级,这8个比特位在NVIC应用中断与复位控制寄丛器(AIRCR)的中断优先级分组域中,可以有8种分配方式,如下:所有8位用于指定响应优先级最高1位用于指定抢占式优先级,最低7位用于指定响应优先级最高2位用于指定抢占式优先级,最低6位用于指定响应优先级最高3位用于指定抢占式优先级,最低5位用于指定响应优先级最高4位用于指定抢占式优先级,最低4位用于指定响应优先级最高5位用于指定抢占式优先级,最低3位用于指定响应优先级最高6位用于指定抢占式优先级,最低2位用于指定响应优先级最高7位用于指定抢占式优先级,最低1位用于指定响应优先级这就是优先级分组的概念。

STM32外部中断5-9,10-15的应用解析

STM32外部中断5-9,10-15的应用解析
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE7
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//普通输入模式
EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能LINE0
EXTI_Init(&EXTI_InitStructure);//配置
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource9);//PE9连接到中断线9
/*配置EXTI_Line5 */
EXTI_InitStructure.EXTI_Line = EXTI_Line5;//LINE5
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断事件
EXTI_InitStructure.EXTI_Trigger =EXTI_Trigger_Rising; //上升沿触发
STM32外部中断5-9,10-15的应用解析
STM32有些系列(比如STM32F407)的外部中断5-9是共用一个中断处理函数EXTI9_5_IRQHandler(),外部中断10-15共用中断函数EXTI15_10_IRQHandler(),所以很多人(包括我自己)刚开始时对于这些外部中断线的设置以及判断都不是弄得很清楚,下面就直接贴出中断引脚的配置、中断配置以及进入中断之后的判断处理程序。

STM32外部中断原理与配置

STM32外部中断原理与配置

STM32外部中断原理与配置STM32-外部中断原理与配置IO⼝外部中断原理概述STM32控制器⽀持的外部中断/事件请求中断线M3M4M7EXTI线0~15:对应外部IO⼝的输⼊中断。

√√√EXTI线16:连接到PVD输出。

√√√EXTI线17:连接到RTC闹钟事件。

√√√EXTI线18:连接到USB OTG FS唤醒事件。

√√√EXTI线19:连接到以太⽹唤醒事件。

√√EXTI线20:连接到USB OTG HS(在FS中配置)唤醒事件√√EXTI线21:连接到RTC⼊侵和时间戳事件。

√√EXTI线22:连接到RTC唤醒事件。

√√EXSTI线23:连接到LPTIM1异步事件√IO⼝外部中断STM32的每个IO都可以作为外部中断输⼊。

每个外部中断线可以独⽴的配置触发⽅式(上升沿,下降沿或者双边沿触发),触发/屏蔽,专⽤的状态位。

STM32供IO使⽤的中断线只有16个,但是STM32F系列的IO⼝多达上百个,STM32F103ZGT6(112),那么中断线怎么跟io⼝对应呢?GPIO和中断线映射关系GPIOx.0映射到EXTI0GPIOx.1映射到EXTI1……GPIOx.14映射到EXTI14GPIOx.15映射到EXTI15对于M4/M7,配置寄存器为SYSCFG_EXTIRx对于M3,配置寄存器为AFIO_EXTICRx如下图所⽰,EXTI0[3:0]有4个位,可以配置16个,所以可以从PA0选择到PI0。

也就是说16个中断线,最多可以处理16*16个外部引脚的中断。

可以在⼿册中找到SYSCFG 外部中断配置寄存器:16个中断线就分配16个中断服务函数?IO⼝外部中断在中断向量表中只分配了7个中断向量,也就是只能使⽤7个中断服务函数。

从表中可以看出,外部中断线5~ 9分配⼀个中断向量,共⽤⼀个服务函数外部中断线10~15分配⼀个中断向量,共⽤⼀个中断服务函数。

中断服务函数列表:EXTI0_IRQHandlerEXTI1_IRQHandlerEXTI2_IRQHandlerEXTI3_IRQHandlerEXTI4_IRQHandlerEXTI9_5_IRQHandlerEXTI15_10_IRQHandlerIO⼝外部中断HAL库配置⽅法外部中断操作使⽤到的函数分布⽂件stm32fxxx_hal_gpio.hstm32fxxx_hal_gpio.c外部中断配置:外部中断的中断线映射配置和触发⽅式都是在GPIO初始化函数中完成:GPIO_InitTypeDef GPIO_Initure;GPIO_Initure.Pin=GPIO_PIN_0; //PA0GPIO_Initure.Mode=GPIO_MODE_IT_RISING; //上升沿触发GPIO_Initure.Pull=GPIO_PULLDOWN;HAL_GPIO_Init(GPIOA,&GPIO_Initure);void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init){uint32_t position;uint32_t ioposition = 0x00;uint32_t iocurrent = 0x00;uint32_t temp = 0x00;/* Check the parameters */assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));assert_param(IS_GPIO_PIN(GPIO_Init->Pin));assert_param(IS_GPIO_MODE(GPIO_Init->Mode));assert_param(IS_GPIO_PULL(GPIO_Init->Pull));/* Configure the port pins */for(position = 0; position < GPIO_NUMBER; position++){/* Get the IO position */ioposition = ((uint32_t)0x01) << position;/* Get the current IO position */iocurrent = (uint32_t)(GPIO_Init->Pin) & ioposition;if(iocurrent == ioposition){/*--------------------- GPIO Mode Configuration ------------------------*//* In case of Alternate function mode selection */if((GPIO_Init->Mode == GPIO_MODE_AF_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_OD)){/* Check the Alternate function parameter */assert_param(IS_GPIO_AF(GPIO_Init->Alternate));/* Configure Alternate function mapped with the current IO */temp = GPIOx->AFR[position >> 3];temp &= ~((uint32_t)0xF << ((uint32_t)(position & (uint32_t)0x07) * 4)) ;temp |= ((uint32_t)(GPIO_Init->Alternate) << (((uint32_t)position & (uint32_t)0x07) * 4));GPIOx->AFR[position >> 3] = temp;}/* Configure IO Direction mode (Input, Output, Alternate or Analog) */temp = GPIOx->MODER;temp &= ~(GPIO_MODER_MODER0 << (position * 2));temp |= ((GPIO_Init->Mode & GPIO_MODE) << (position * 2));GPIOx->MODER = temp;/* In case of Output or Alternate function mode selection */if((GPIO_Init->Mode == GPIO_MODE_OUTPUT_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_PP) || (GPIO_Init->Mode == GPIO_MODE_OUTPUT_OD) || (GPIO_Init->Mode == GPIO_MODE_AF_OD)) {/* Check the Speed parameter */assert_param(IS_GPIO_SPEED(GPIO_Init->Speed));/* Configure the IO Speed */temp = GPIOx->OSPEEDR;temp &= ~(GPIO_OSPEEDER_OSPEEDR0 << (position * 2));temp |= (GPIO_Init->Speed << (position * 2));GPIOx->OSPEEDR = temp;/* Configure the IO Output Type */temp = GPIOx->OTYPER;temp &= ~(GPIO_OTYPER_OT_0 << position) ;temp |= (((GPIO_Init->Mode & GPIO_OUTPUT_TYPE) >> 4) << position);GPIOx->OTYPER = temp;}/* Activate the Pull-up or Pull down resistor for the current IO */temp = GPIOx->PUPDR;temp &= ~(GPIO_PUPDR_PUPDR0 << (position * 2));temp |= ((GPIO_Init->Pull) << (position * 2));GPIOx->PUPDR = temp;/*--------------------- EXTI Mode Configuration ------------------------*//* Configure the External Interrupt or event for the current IO */if((GPIO_Init->Mode & EXTI_MODE) == EXTI_MODE){/* Enable SYSCFG Clock */__HAL_RCC_SYSCFG_CLK_ENABLE();temp = SYSCFG->EXTICR[position >> 2];temp &= ~(((uint32_t)0x0F) << (4 * (position & 0x03)));temp |= ((uint32_t)(GPIO_GET_INDEX(GPIOx)) << (4 * (position & 0x03)));SYSCFG->EXTICR[position >> 2] = temp;/* Clear EXTI line configuration */temp = EXTI->IMR;temp &= ~((uint32_t)iocurrent);if((GPIO_Init->Mode & GPIO_MODE_IT) == GPIO_MODE_IT){temp |= iocurrent;}EXTI->IMR = temp;temp = EXTI->EMR;temp &= ~((uint32_t)iocurrent);if((GPIO_Init->Mode & GPIO_MODE_EVT) == GPIO_MODE_EVT){temp |= iocurrent;}EXTI->EMR = temp;/* Clear Rising Falling edge configuration */temp = EXTI->RTSR;temp &= ~((uint32_t)iocurrent);if((GPIO_Init->Mode & RISING_EDGE) == RISING_EDGE){temp |= iocurrent;}EXTI->RTSR = temp;temp = EXTI->FTSR;temp &= ~((uint32_t)iocurrent);if((GPIO_Init->Mode & FALLING_EDGE) == FALLING_EDGE){temp |= iocurrent;}EXTI->FTSR = temp;}}}}和串⼝中断⼀样,HAL库同样提供了外部中断通⽤处理函数HAL_GPIO_EXTI_IRQHandler,我们在外部中断服务函数中会调⽤该函数处理中断。

stm32中断(NVIC与EXTI)

stm32中断(NVIC与EXTI)

stm32中断(NVIC与EXTI) D部有4个从优先级(00 01 10 11)。

1.中断输入与悬起当中断输入脚被置为有效后,该中断就被“悬起”。

所谓“悬起”,也就是等待、就绪的意思。

即使后来中断源撤消了中断请求,已经被标记成悬起的中断也被记录下来。

当某中断的服务程序开始执行时,就称此中断进入了“活跃”状态,并且其悬起位会被硬件自动清除。

在一个中断活跃后,直到其服务例程执行完毕,并且返回后,才能对该中断的新请求予以响应。

当NVIC响应一个中断时,会自动完成以下三项工作,以便安全、准确地跳转到相应的中断服务程序:入栈:把8个寄存器的值压入栈。

当响应中断时,如果当前的代码正在使用PSP,则压入PSP(进程堆栈),否则就压入MSP(主堆栈)。

一旦进入了服务例程,就一直使用主堆栈。

在自动入栈的过程中,将寄存器写入堆栈的顺序与时间顺序无关,CM3会保证正确的寄存器被保存到正确的位置。

取向量:当数据总线(系统总线)进行入栈操作时,指令总线(I-Code总线)正在从向量表中找出正确的中断向量与对应的服务程序入口地址。

更新寄存器。

注意:①如果在某个中断得到响应之前,其悬起状态被清除了,则中断被取消。

②新请求在得到响应时,由硬件自动清零其悬起标志位。

③如果中断源咬住请求信号不放,该中断就会在其上次服务例程返回后再次被置为悬起状态。

④如果某个中断在得到响应之前,其请求信号以若干的脉冲的方式呈现,则被视为只有一次中断请求⑤如果在服务例程执行时,中断请求释放了,但是在服务例程返回前又重新被置为有效,则NVIC会记住此动作,重新悬起该中断。

2.中断返回当中断完成,返回主程序时,NVIC自动完成以下两步:①出栈:先前压入栈中的寄存器在这里恢复。

内部的出栈顺序与入栈时的相对应,堆栈指针的值也改回先前的值。

②更新NVIC 寄存器:伴随着中断的返回,它的活动位也被硬件清除。

对于外部中断,倘若中断输入再次被置为有效,则悬起位也将再次置位,新一次的中断响应序列也会再次开始。

stm32 之 中断按键初始化(注意事项)

stm32 之 中断按键初始化(注意事项)

stm32 之中断按键初始化(注意事项)之前做终端按键的时候都是只做了一个,没有做多个,昨天在把所有按键都设置成中断模式的时候遇到问题,于是乎还跟一个网上的哥们进行了热议,后来还是我发现了问题!最终把问题给解决了!我的按键的GPIO连接有点奇葩,他不是连续的,这可能就是竞赛板故意设置的难度吧!首先管脚初始化:[cpp]view plaincopyprint?1. GPIO_InitTypeDef key;2.3. RCC->APB2ENR |= ((1<<0)|(1<<2)|(1<<3));4.5. key.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_8;6. key.GPIO_Mode = GPIO_Mode_IPD;7. GPIO_Init(GPIOA, &key);8.9. key.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2;10. key.GPIO_Mode = GPIO_Mode_IPD;11. GPIO_Init(GPIOB, &key);全部设置成输入模式,AFIO再时钟使能的时候不要忘记了!这里我就不多说了!然后就是中断组设置:NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC初始化:[cpp]view plaincopyprint?1. key_nvic.NVIC_IRQChannel = EXTI0_IRQn;2. key_nvic.NVIC_IRQChannelCmd = ENABLE;3. key_nvic.NVIC_IRQChannelPreemptionPriority = 0;4. key_nvic.NVIC_IRQChannelSubPriority = 1;5. NVIC_Init(&key_nvic);重点都不在这,值得注意的是下面:我第一次在配置EXTI Line的时候这样配置!GPIO_EXTILineConfig(GPIO_PortSourceGPIOA|GPIO_PortSourceGPIOB,\ GPIO_PinSource0|GPIO_PinSource1|GPIO_PinSource2|GPIO_PinSource8); 大致一看,貌似很正常啊!但是问题就出在这!我们跳转到GPIO_PinSourcex和GPIO_PortSourceGPIOx哪里看看:[cpp]view plaincopyprint?1. #define GPIO_PortSourceGPIOA ((uint8_t)0x00)2. #define GPIO_PortSourceGPIOB ((uint8_t)0x01)3. #define GPIO_PortSourceGPIOC ((uint8_t)0x02)4. #define GPIO_PortSourceGPIOD ((uint8_t)0x03)5. #define GPIO_PortSourceGPIOE ((uint8_t)0x04)6. #define GPIO_PortSourceGPIOF ((uint8_t)0x05)7. #define GPIO_PortSourceGPIOG ((uint8_t)0x06)[cpp]view plaincopyprint?1. #define GPIO_PinSource0 ((uint8_t)0x00)2. #define GPIO_PinSource1 ((uint8_t)0x01)3. #define GPIO_PinSource2 ((uint8_t)0x02)4. #define GPIO_PinSource3 ((uint8_t)0x03)5. #define GPIO_PinSource4 ((uint8_t)0x04)6. #define GPIO_PinSource5 ((uint8_t)0x05)7. #define GPIO_PinSource6 ((uint8_t)0x06)8. #define GPIO_PinSource7 ((uint8_t)0x07)9. #define GPIO_PinSource8 ((uint8_t)0x08)10. #define GPIO_PinSource9 ((uint8_t)0x09)11. #define GPIO_PinSource10 ((uint8_t)0x0A)12. #define GPIO_PinSource11 ((uint8_t)0x0B)13. #define GPIO_PinSource12 ((uint8_t)0x0C)14. #define GPIO_PinSource13 ((uint8_t)0x0D)15. #define GPIO_PinSource14 ((uint8_t)0x0E)16. #define GPIO_PinSource15 ((uint8_t)0x0F)我们来计算下:GPIO_PortSourceGPIOA | GPIO_PortSourceGPIOB = 0x00 | 0x01 = 0x01 =GPIO_PortSourceGPIOBGPIO_PinSource0 | GPIO_PinSource1 | GPIO_PinSource2 | GPIO_PinSource8 = 0x00 | 0x01 | 0x02 | 0x08 = 0x0b = GPIO_PinSource11所以我最后初始化后的中断就成为:GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource11);最终让我事与愿违了。

STM32外部中断总结

STM32外部中断总结

STM32 外部中断配置总结一:触发方式STM32 的外部中断是通过边沿来触发的,不支持电平触发;二:外部中断分组STM32 的每一个GPIO 都能配置成一个外部中断触发源,STM32 通过根据引脚的序号不同将众多中断触发源分成不同的组,比如:PA0,PB0,PC0,PD0,PE0,PF0,PG0为第一组,那么依此类推,我们能得出一共有16 组,STM32 规定,每一组中同时只能有一个中断触发源工作,那么,最多工作的也就是16个外部中断。

STM32 分组和对应中断处理函数分配:三:外部中断的配置过程配置触发源 -GPIO触发源为通过GPIO 端口输入,所以,要配置GPIO 的模式,输入方式,输入方式有以下几种:1.GPIO_Mode_AIN ,模拟输入(ADC 模拟输入,或者低功耗下省电)2.GPIO_Mode_IN_FLOATING ,浮空输入3.GPIO_Mode_IPD = 0x28,带下拉输入4.GPIO_Mode_IPU = 0x48,带上拉输入管脚 中断标志 中断处理函数分配PA0~PG0 EXTI0 EXTI0_IRQHandlerPA1~PG1 EXTI1 EXTI1_IRQHandlerPA2~PG2 EXTI2 EXTI2_IRQHandlerPA3~PG3 EXTI3 EXTI3_IRQHandler PA4~PG4 EXTI4 EXTI4_IRQHandler PA5~PG5 EXTI5 EXTI9_5_IRQHandler PA6~PG6 EXTI6 PA7~PG7 EXTI7 PA8~PG8 EXTI8 PA9~PG9 EXTI9 PA10~PG10 EXTI10 EXTI15_10_IRQHandler PA11~PG11 EXTI11 PA12~PG12 EXTI12 PA13~PG13 EXTI13 PA14~PG14 EXTI14 PA15~PG15 EXTI15●引脚与外部中断关联●外部中断AFIO时钟开启●外部中断配置这个主要是中断线路选择,中断触发方式,中断使能。

STM32 串口中断处理方法

STM32 串口中断处理方法
现串口会出现频繁跳中断,导致无法执行主循环的问题!
调试发现是串口中断硬件 BUG:
1. USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);使能了接收中断,那么 ORE 中断也同 时被开启了。
2. ORE 中断只能使用 USART_GetFlagStatus(USART1, USART_FLAG_ORE) 读到(没有使 能 USART_IT_ERR 中断时) 解决办法:
4.找资料 STM32F10x 微控制器参考手册(2009 年 12 月第 10 版)P541 发现如下说明:
也就是说只要接收中断打开,即 RXNEIE 设置为 1,那么 ORE 中断也自动打开了。 可是 USART_GetITStatus(USART1, USART_IT_ORE )== RESET!!!! 找到 USART_GetITStatus(USART1, USART_IT_RXNE)函数,发现只有当 USART_IT_ERR 中断使 能时,才能读到 ORE 中断。 在这里要指出这个 BUG:产生 ORE 中断了,但使用 USART_GetITStatus()函数却无法读到这个中断被 SET 起来!

2.为什么会一直跑到接收中断? 断点之后发现(USART_GetITStatus(USART1, USART_IT_RXNE)==RESET 的,也就是说没有数据 接收到也进了中断,而且在 USART 配置中我也只打开了接收中断!没有数据送过来应该是不可能进入中断 的!
3.响应了什么中断? 我想通过函数(USART_GetITStatus()把所有中断状态都读出来,但失败了,USART_IT_XXX 所有中断 状态都是 RESET!也就是说没有中断也进入到这个中断服务程序来了!?

STM32F103ZET6的中断管理

STM32F103ZET6的中断管理

STM32F103ZET6的中断管理1、STM32的中断 STM32的中断管理是属于内核部分的,所以中断管理的寄存器也是属于内核组,不属于芯⽚外设,在查看相关资料的时候,需要查看相对应的内核⼿册。

STM32F103ZET6是Cortex-M3内核的IC。

Cortex-M3内核⽀持256个中断,其中包含了16个内核中断和240个外部中断,并且具有256级的可编程中断设置。

但是STM32并没有完全使⽤Cortex-M3内核的全部中断,只是⽤了其中的⼀部分。

在STM32中,有时候中断也称为异常、系统异常,把它们统⼀理解为中断就可以了。

2、中断编号 STM32不同类型的芯⽚IC所具有的中断个数是不⼀样的,在HAL库中,可以通过查找IRQn_Type这个结构体来查看该IC所具有的中断。

IRQn_Tyepe对该芯⽚的中断进⾏了编号。

STM32F103ZET6的IRQn_Type结构体定义在stm32f103xe.h头⽂件中,如下:typedef enum{ /****** Cortex-M3 Processor Exceptions Numbers ***************************************************/ NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ HardFault_IRQn = -13, /*!< 3 Cortex-M3 Hard Fault Interrupt */ MemoryManagement_IRQn = -12, /*!< 4 Cortex-M3 Memory Management Interrupt */ BusFault_IRQn = -11, /*!< 5 Cortex-M3 Bus Fault Interrupt */ UsageFault_IRQn = -10, /*!< 6 Cortex-M3 Usage Fault Interrupt */ SVCall_IRQn = -5, /*!< 11 Cortex-M3 SV Call Interrupt */ DebugMonitor_IRQn = -4, /*!< 12 Cortex-M3 Debug Monitor Interrupt */ PendSV_IRQn = -2, /*!< 14 Cortex-M3 Pend SV Interrupt */ SysTick_IRQn = -1, /*!< 15 Cortex-M3 System Tick Interrupt */ /****** STM32 specific Interrupt Numbers *********************************************************/ WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */ PVD_IRQn = 1, /*!< PVD through EXTI Line detection Interrupt */ TAMPER_IRQn = 2, /*!< Tamper Interrupt */ RTC_IRQn = 3, /*!< RTC global Interrupt */ FLASH_IRQn = 4, /*!< FLASH global Interrupt */ RCC_IRQn = 5, /*!< RCC global Interrupt */ EXTI0_IRQn = 6, /*!< EXTI Line0 Interrupt */ EXTI1_IRQn = 7, /*!< EXTI Line1 Interrupt */ EXTI2_IRQn = 8, /*!< EXTI Line2 Interrupt */ EXTI3_IRQn = 9, /*!< EXTI Line3 Interrupt */ EXTI4_IRQn = 10, /*!< EXTI Line4 Interrupt */ DMA1_Channel1_IRQn = 11, /*!< DMA1 Channel 1 global Interrupt */ DMA1_Channel2_IRQn = 12, /*!< DMA1 Channel 2 global Interrupt */ DMA1_Channel3_IRQn = 13, /*!< DMA1 Channel 3 global Interrupt */ DMA1_Channel4_IRQn = 14, /*!< DMA1 Channel 4 global Interrupt */ DMA1_Channel5_IRQn = 15, /*!< DMA1 Channel 5 global Interrupt */ DMA1_Channel6_IRQn = 16, /*!< DMA1 Channel 6 global Interrupt */ DMA1_Channel7_IRQn = 17, /*!< DMA1 Channel 7 global Interrupt */ ADC1_2_IRQn = 18, /*!< ADC1 and ADC2 global Interrupt */ USB_HP_CAN1_TX_IRQn = 19, /*!< USB Device High Priority or CAN1 TX Interrupts */ USB_LP_CAN1_RX0_IRQn = 20, /*!< USB Device Low Priority or CAN1 RX0 Interrupts */ CAN1_RX1_IRQn = 21, /*!< CAN1 RX1 Interrupt */ CAN1_SCE_IRQn = 22, /*!< CAN1 SCE Interrupt */ EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */ TIM1_BRK_IRQn = 24, /*!< TIM1 Break Interrupt */ TIM1_UP_IRQn = 25, /*!< TIM1 Update Interrupt */ TIM1_TRG_COM_IRQn = 26, /*!< TIM1 Trigger and Commutation Interrupt */ TIM1_CC_IRQn = 27, /*!< TIM1 Capture Compare Interrupt */ TIM2_IRQn = 28, /*!< TIM2 global Interrupt */ TIM3_IRQn = 29, /*!< TIM3 global Interrupt */ TIM4_IRQn = 30, /*!< TIM4 global Interrupt */ I2C1_EV_IRQn = 31, /*!< I2C1 Event Interrupt */ I2C1_ER_IRQn = 32, /*!< I2C1 Error Interrupt */ I2C2_EV_IRQn = 33, /*!< I2C2 Event Interrupt */ I2C2_ER_IRQn = 34, /*!< I2C2 Error Interrupt */ SPI1_IRQn = 35, /*!< SPI1 global Interrupt */ SPI2_IRQn = 36, /*!< SPI2 global Interrupt */ USART1_IRQn = 37, /*!< USART1 global Interrupt */ USART2_IRQn = 38, /*!< USART2 global Interrupt */ USART3_IRQn = 39, /*!< USART3 global Interrupt */ EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */ RTC_Alarm_IRQn = 41, /*!< RTC Alarm through EXTI Line Interrupt */ USBWakeUp_IRQn = 42, /*!< USB Device WakeUp from suspend through EXTI Line Interrupt */ TIM8_BRK_IRQn = 43, /*!< TIM8 Break Interrupt */ TIM8_UP_IRQn = 44, /*!< TIM8 Update Interrupt */ TIM8_TRG_COM_IRQn = 45, /*!< TIM8 Trigger and Commutation Interrupt */ TIM8_CC_IRQn = 46, /*!< TIM8 Capture Compare Interrupt */ ADC3_IRQn = 47, /*!< ADC3 global Interrupt */ FSMC_IRQn = 48, /*!< FSMC global Interrupt */ SDIO_IRQn = 49, /*!< SDIO global Interrupt */ TIM5_IRQn = 50, /*!< TIM5 global Interrupt */ SPI3_IRQn = 51, /*!< SPI3 global Interrupt */ UART4_IRQn = 52, /*!< UART4 global Interrupt */ UART5_IRQn = 53, /*!< UART5 global Interrupt */ TIM6_IRQn = 54, /*!< TIM6 global Interrupt */ TIM7_IRQn = 55, /*!< TIM7 global Interrupt */ DMA2_Channel1_IRQn = 56, /*!< DMA2 Channel 1 global Interrupt */ DMA2_Channel2_IRQn = 57, /*!< DMA2 Channel 2 global Interrupt */ DMA2_Channel3_IRQn = 58, /*!< DMA2 Channel 3 global Interrupt */ DMA2_Channel4_5_IRQn = 59, /*!< DMA2 Channel 4 and Channel 5 global Interrupt */} IRQn_Type;3、NVIC NVIC的简称是嵌套中断向量控制器,它控制着整个芯⽚中断相关的功能。

STM32 硬件IIC中断使用方法

STM32 硬件IIC中断使用方法

STM32 硬件IIC中断使用方法--中北大学:马政贵本文详细描述了STM32硬件IIC的中断使用方法,包含流程图和对应代码,以及调试过程中的问题记录和分析解决。

之前,一直听说STM32的硬件IIC有问题,加之以前写好的模拟IIC模块用着一直没问题,就没有去使用STM32的硬件IIC。

后面项目中需要实时读取三个传感器的数据,三个传感器并在一起共用一个IIC口,通过地址进行区分通信,一个传感器要读取8字节数据。

采用模拟IIC方式,很多时间都浪费在高低电平的等待时间上,导致其他任务时间很紧迫。

于是想到使用硬件IIC的中断方式,来提升效率。

查看了下库自带的例程,使用的是查询方式,使用了大量的while来等待状态标志完成。

移植过来,虽然可以跑通,但使用的是查询方式,效率本质上和模拟IIC是一样的。

于是自己便把手册里的IIC模块看了一遍,自己根据手册来写硬件IIC的中断模式。

上图是传感器的通讯时序,属于标准的IIC通信,这里不做进一步展开,详细可以参看IIC总线规范。

应用中,MCU做主机,传感器做从机。

MCU先工作在主发送器模式,然后工作在主接收器模式。

在默认状态下,MCU接口工作于从模式。

接口在生成起始条件后自动地从从模式切换到主模式;当仲裁丢失或产生停止信号时,则从主模式切换到从模式。

在应用手册中,详细给出了IIC主模式的操作要求及顺序:这里需要注意的是怎样结束通信,然后重启通信,以便获取下一个传感器的数据。

应用手册根据情况分为了三种,我这里使用的是第一种方式,也就是把IIC的中断优先级设置为最高。

下面我以流程图的方式,把整个过程表示出来,然后再据此给出相应的代码,代码在中断中以状态机的方式进行。

先进行IIC管脚GPIO的配置:接着进行IIC的配置(中断先不使能,在初始化完传感器之后再使能。

我这里把IIC的事件中断优先级设置为最高,若不是,IIC的结束操作需参照应用手册中相应的情况进行):中断中的状态机如下:void I2C2_EV_IRQHandler(void){switch(IIC2_State){case 0:if(I2C_GetINTStatus(I2C2, I2C_INT_STARTF)){I2C_ClearITPendingBit(I2C2, I2C_INT_STARTF);(void)(I2C2->STS1);I2C_Send7bitAddress(I2C2, ALS31300_ADR[IIC_Device], I2C_Direction_Transmit);IIC2_State++;}else{I2C2->STS1 = 0;}break;case 1:if(I2C_GetINTStatus(I2C2, I2C_INT_ADDRF)){I2C_ClearITPendingBit(I2C2, I2C_INT_ADDRF);(void)(I2C2->STS1);(void)(I2C2->STS2);I2C_SendData(I2C2, 0x28);IIC2_State++;}else{I2C2->STS1 = 0;}break;case 2:if(I2C_GetINTStatus(I2C2, I2C_INT_TDE)){I2C_ClearITPendingBit(I2C2, I2C_INT_TDE);I2C_ClearITPendingBit(I2C2, I2C_INT_BTFF);(void)(I2C2->STS1);I2C_GenerateSTART(I2C2, ENABLE); /* Send STRAT condition a second time */IIC2_State++;}else{I2C2->STS1 = 0;}break;case 3:if(I2C_GetINTStatus(I2C2, I2C_INT_STARTF)){I2C_ClearITPendingBit(I2C2, I2C_INT_STARTF);(void)(I2C2->STS1);I2C_Send7bitAddress(I2C2, ALS31300_ADR[IIC_Device],I2C_Direction_Receive);IIC2_State++;}else{I2C2->STS1 = 0;}break;case 4:if(I2C_GetINTStatus(I2C2, I2C_INT_ADDRF)){I2C_ClearITPendingBit(I2C2, I2C_INT_ADDRF);(void)(I2C2->STS1);(void)(I2C2->STS2);IIC2_State++;}else{I2C2->STS1 = 0;}break;case 5:if(I2C_GetINTStatus(I2C2, I2C_INT_RDNE)){I2C_ClearITPendingBit(I2C2, I2C_INT_RDNE);(void)(I2C2->STS1);ALS31300_Reg_Data[IIC_Device][IIC_Rec_Num] = I2C_ReceiveData(I2C2);IIC_Rec_Num++;if(IIC_Rec_Num >= 6){IIC2_State++;}}else{I2C2->STS1 = 0;}break;case 6:if(I2C_GetINTStatus(I2C2, I2C_INT_RDNE)){I2C_ClearITPendingBit(I2C2, I2C_INT_RDNE);(void)(I2C2->STS1);ALS31300_Reg_Data[IIC_Device][IIC_Rec_Num] = I2C_ReceiveData(I2C2);I2C_AcknowledgeConfig(I2C2, DISABLE);I2C_GenerateSTOP(I2C2, ENABLE);IIC_Rec_Num++;IIC2_State++;}else{I2C2->STS1 = 0;}break;case 7:if(I2C_GetINTStatus(I2C2, I2C_INT_RDNE)){I2C_ClearITPendingBit(I2C2, I2C_INT_RDNE);(void)(I2C2->STS1);ALS31300_Reg_Data[IIC_Device][IIC_Rec_Num] =I2C_ReceiveData(I2C2);IIC_Device++;if(IIC_Device >= 3){IIC_Device = 0;IIC_Rec_OK = 1;}I2C_AcknowledgeConfig(I2C2, ENABLE);I2C_GenerateSTART(I2C2, ENABLE);IIC_Rec_Num = 0;IIC2_State = 0;}else{I2C2->STS1 = 0;}break;default:I2C2->STS1 = 0;break;}}初始化之后,产生开始信号之后,使能中断,此后就一直在中断的状态机中往复进行了:#define IIC_TIMEOUT 1000IIC2_GPIO_Config();IIC2_Config();time_count = IIC_TIMEOUT;while(I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSYF)){time_count--;if(0 == time_count){IIC_Wrong_Count++;return;}}I2C_AcknowledgeConfig(I2C2, ENABLE);I2C_GenerateSTART(I2C2, ENABLE);//初始化之后再开中断,只在读操作中使用中断I2C_INTConfig(I2C2, I2C_INT_EVT | I2C_INT_BUF | I2C_INT_ERR, ENABLE);编译调试,咦,状态机一直停留在0状态,也就是卡在总线一直BUSY。

学习6__STM32--SPI外设之中断收发---

学习6__STM32--SPI外设之中断收发---

学习6__STM32--SPI外设之中断收发---<⽬标> STM32双机 SPI中断收发通信<描述> # STM32双机配置为⼀主⼀从模式 # 采⽤主机中断发送,从机中断接收 # 收发机制采⽤不间断收发(发送为空就发送,接收⾮空就接收,中间⽆其他操作打断) # 就是单字节发送与接收<问题> 从机接收端会出现,接收到的数据可能是原始发送数据也会是错误数据,出现这种现象的条件是发送主机复位、发送主机重新上电、随时间变化(物理碰触等)都会产⽣错误数据,⽽复位接收从机、重新上电接收从机会纠正数据<分析> # STM32双机未共地导致 共地后问题依旧 # STM32未使⽤NSS引脚导致 使⽤后问题依旧 # ⼯作模式改变尝试(发送与接收⼯作模式配置为不匹配) 问题依旧 # 主机发送太过频繁导致,导致接收来不及接收导致 拉⼤发送数据周期问题依旧 # 从数据结果上分析,应该是发送主机与接收从机未同步导致,接收总线的数据先由移位寄存器接收,再copy⾄数据寄存器,所以分析数据错位现象是出现在移位寄存器中,⽐如正在传输中由复位操作或断电操作等,致使移位寄存器只接收了3bit数据,⽽SPI数据的接收机制是,移位寄存器收满8bit数据后copy⾄数据寄存器,这⼀切都是硬件完成,注意数据的搬移是copy,所以移位寄存器中的数据还在即数据残留特性,就像刚刚的这种中断操作⾏为导致移位寄存器残留了当前字节的3bit数据,未满8bit数据故不会copy⾄数据寄存器,所以等待恢复⼯作后,需要再接收5bit数据,这样满8bit数据后copy⾄spi->DR,但是这1byte数据中的前3bit与后5bit数据本不是⼀个有效byte数据,就导致读到1byte⽆效数据,产⽣了接收错误数据的现象<解决> # 拉⼤发送数据周期&在进⼊接收中断后先关闭SPI外设,然后再读取数据,出中断前开始SPI外设 > 在进⼊中断服务程序后关闭spi外设,将导致在关闭外设期间发⽣的中断⽽被忽视,尤其是多数据连续发送,⽐如DMA数据发送,实测将导致丢数据,即其中的部分中断未作出响应⽽丢弃。

stm32hal库uart中断接收修改步骤(适合GPS数据处理)

stm32hal库uart中断接收修改步骤(适合GPS数据处理)

实际使用中gsp数据解析是单个字符操作,串口接收中断需要一直打开,而hal库的中断接收配置(指定接收长度,和接收数据区域,数据区域满,会关闭接收中断,触发接收回调函数,需要人工再次打开接收中断(HAL_UART_Receive_IT函数)),而处理gps数据无法事先确定接收的长度,因此这种使用方式不合适。

因此有如下文处理办法(串口数据发送我用的是普通发送(非中断,非DMA));
定义全局的接收缓存区,数据区域满,自动复写而不停止接收中断。

1. 定义全局空间存储串口中断接收的数据(建议配置一个结构体,有读写指针,我的操作如“段二”)
2. 串口中断功能已经打开
3. 初始化调用一次HAL_UART_Receive_IT函数(打开接收中断);
4. 在如下图一函数中修改为如图二;
图一
图二
段二:
缓存区写指针指向的缓存区内的位置 = DEBUGPORTRECVBUFFLEN - *pWriteCount;写已经做好了(在中断中进行),下面是关于读的:
如下是在主循环中查询缓存区是否有数据,和一个字节一个字节读取数据;。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

STM32----4----EXTI
文章发表于:2011-05-09 10:33
外部中断配置的目标是:PA15、PA13为按键,PA8,PD0为LED,按键进入中断,相应的LED亮灭。

void EXTI_Configuration()
{
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
//清空中断标志
EXTI_ClearITPendingBit(EXTI_Line13);
EXTI_ClearITPendingBit(EXTI_Line15);
//(1)管脚配置
LED_Init();
KEY_Init();
//(2)外部中断线配置,选择中断线管脚PA13、PA15、PA0
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource13);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource15);
//(3)对中断线进行中断设置
EXTI_InitStructure.EXTI_Line = EXTI_Line13 | EXTI_Line15 ; //选择中断线路PA13/15
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //设置为中断请求,非事件请求
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling ; //设置中断触发方式为上下降沿触发EXTI_InitStructure.EXTI_LineCmd = ENABLE; //外部中断使能
EXTI_Init(&EXTI_InitStructure); //初始化中断
//EXTI_GenerateSWInterrupt(EXTI_Line0| EXTI_Line13 | EXTI_Line15 ); //中断线使能、中断结构体初始化、以及设置软中断综合起来才启用了中断
//(4)NVIC配置
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); //选择中断分组2
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQChannel; //选择中断通道2
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占式中断优先级设置为0 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //响应式中断优先级设置为0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中断
NVIC_Init(&NVIC_InitStructure);
}
void LED_Init( )
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;//选择PA.8
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //管脚频率为50MHZ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //模式为推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA寄存器
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;//选择PX.2
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//管脚频率为50MHZ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//设置推挽输出
GPIO_Init(GPIOD , &GPIO_InitStructure);//初始化GPIOD寄存器
GPIO_WriteBit(GPIOA,GPIO_Pin_8,Bit_SET);
GPIO_WriteBit(GPIOD,GPIO_Pin_2,Bit_SET);
}
void KEY_Init()
{
/*PA13、PA15管口引脚的配置**下拉输入******************************/ GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13|GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void EXTI15_10_IRQHandler(void)
{
delay_ms(10);
if(EXTI_GetITStatus(EXTI_Line15)==RESET)
{
if((GPIO_ReadOutputDataBit(GPIOD,GPIO_Pin_2)==0) )
LED1_Off();
else
LED1_On();
else if(EXTI_GetITStatus(EXTI_Line13)==RESET)
{
if((GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_8)==0) ) LED0_Off();
else
LED0_On();
}
EXTI_ClearITPendingBit(EXTI_Line13);
EXTI_ClearITPendingBit(EXTI_Line15);
}
void EXTI0_IRQHandler(void)
{
delay_ms(10);
if(EXTI_GetITStatus(EXTI_Line0)!=RESET)
{
if((GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_8)==0) ) LED0_Off();
else
LED0_On();
if((GPIO_ReadOutputDataBit(GPIOD,GPIO_Pin_2)==0) ) LED1_Off();
else
LED1_On();
}
EXTI_ClearITPendingBit(EXTI_Line0);
最后中断了,在中断里。

相关文档
最新文档