《最新STM32中断以及各模块学习资料.doc》由会员分享,可在线阅读,更多相关《最新STM32中断以及各模块学习资料.doc(250页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、Four short words sum up what has lifted most successful individuals above the crowd: a little bit more.-author-dateSTM32中断以及各模块学习资料STM32中断优先级和开关总中断STM32中断优先级一,中断优先级STM32(Cortex-M3)中的优先级概念STM32(Cortex-M3)中有两个优先级的概念抢占式优先级和响应优先级,有人把响应优先级称作亚优先级或副优先级,每个中断源都需要被指定这两种优先级。具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,
2、即中断嵌套,或者说高抢占式优先级的中断可以嵌套低抢占式优先级的中断。当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之后才能被处理。如果这两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先处理哪一个;如果他们的抢占式优先级和响应优先级都相等,则根据他们在中断表中的排位顺序决定先处理哪一个。既然每个中断源都需要被指定这两种优先级,就需要有相应的寄存器位记录每个中断的优先级;在Cortex-M3中定义了8个比特位用于设置中断源的优先级,这8个比特位可以有8种分配方式,如下:所有8位用于指定响应
3、优先级最高1位用于指定抢占式优先级,最低7位用于指定响应优先级最高2位用于指定抢占式优先级,最低6位用于指定响应优先级最高3位用于指定抢占式优先级,最低5位用于指定响应优先级最高4位用于指定抢占式优先级,最低4位用于指定响应优先级最高5位用于指定抢占式优先级,最低3位用于指定响应优先级最高6位用于指定抢占式优先级,最低2位用于指定响应优先级最高7位用于指定抢占式优先级,最低1位用于指定响应优先级这就是优先级分组的概念。-Cortex-M3允许具有较少中断源时使用较少的寄存器位指定中断源的优先级,因此STM32把指定中断优先级的寄存器位减少到4位,这4个寄存器位的分组方式如下: 第0组:所有4位
4、用于指定响应优先级第1组:最高1位用于指定抢占式优先级,最低3位用于指定响应优先级第2组:最高2位用于指定抢占式优先级,最低2位用于指定响应优先级第3组:最高3位用于指定抢占式优先级,最低1位用于指定响应优先级第4组:所有4位用于指定抢占式优先级可以通过调用STM32的固件库中的函数NVIC_PriorityGroupConfig()选择使用哪种优先级分组方式,这个函数的参数有下列5种:NVIC_PriorityGroup_0 = 选择第0组NVIC_PriorityGroup_1 = 选择第1组NVIC_PriorityGroup_2 = 选择第2组NVIC_PriorityGroup_3
5、= 选择第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.
6、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_IRQChannelSubPr
7、iority = 1; / 指定响应优先级别1NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);要注意的几点是:1)如果指定的抢占式优先级别或响应优先级别超出了选定的优先级分组所限定的范围,将可能得到意想不到的结果;2)抢占式优先级别相同的中断源之间没有嵌套关系;3)如果某个中断源被指定为某个抢占式优先级别,又没有其它中断源处于同一个抢占式优先级别,则可以为这个中断源指定任意有效的响应优先级别。二,开关总中断:在STM32/Cortex-M3中是通过改变CPU的当前优先级来允许或禁止中断。
8、PRIMASK位:只允许NMI和hard fault异常,其他中断/异常都被屏蔽(当前CPU优先级=0)。FAULTMASK位:只允许NMI,其他所有中断/异常都被屏蔽(当前CPU优先级=-1)。在STM32固件库中(stm32f10x_nvic.c和stm32f10x_nvic.h) 定义了四个函数操作PRIMASK位和FAULTMASK位,改变CPU的当前优先级,从而达到控制所有中断的目的。下面两个函数等效于关闭总中断:void NVIC_SETPRIMASK(void);void NVIC_SETFAULTMASK(void);下面两个函数等效于开放总中断:void NVIC_RESET
9、PRIMASK(void);void NVIC_RESETFAULTMASK(void);上面两组函数要成对使用,不能交叉使用。例如:第一种方法:NVIC_SETPRIMASK(); /关闭总中断NVIC_RESETPRIMASK();/开放总中断第二种方法:NVIC_SETFAULTMASK(); /关闭总中断NVIC_RESETFAULTMASK();/开放总中断常常使用NVIC_SETPRIMASK(); / Disable InterruptsNVIC_RESETPRIMASK(); / Enable Interrupts STM32时钟系统STM32资料 2009-09-23 14:
10、53 阅读72 评论0 字号: 大大 中中 小小 在STM32中,有五个时钟源,为HSI、HSE、LSI、LSE、PLL。、HSI是高速内部时钟,RC振荡器,频率为8MHz。、HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz16MHz。、LSI是低速内部时钟,RC振荡器,频率为40kHz。、LSE是低速外部时钟,接频率为32.768kHz的石英晶体。、PLL为锁相环倍频输出,其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频可选择为216倍,但是其输出频率最大不得超过72MHz。图1 HSE/LSE时钟源其中40kHz的LSI供独立看门狗IWDG使用,另
11、外它还可以被选择为实时时钟RTC的时钟源。另外,实时时钟RTC的时钟源还可以选择LSE,或者是HSE的128分频。RTC的时钟源通过RTCSEL1:0来选择。STM32中有一个全速功能的USB模块,其串行接口引擎需要一个频率为48MHz的时钟源。该时钟源只能从PLL输出端获取,可以选择为1.5分频或者1分频,也就是,当需要使用USB模块时,PLL必须使能,并且时钟频率配置为48MHz或72MHz。另外,STM32还可以选择一个时钟信号输出到MCO脚(PA8)上,可以选择为PLL输出的2分频、HSI、HSE、或者系统时钟。系统时钟SYSCLK,它是供STM32中绝大部分部件工作的时钟源。系统时钟
12、可选择为PLL输出、HSI或者HSE。系统时钟最大频率为72MHz,它通过AHB分频器分频后送给各模块使用,AHB分频器可选择1、2、4、8、16、64、128、256、512分频。其中AHB分频器输出的时钟送给5大模块使用:、送给AHB总线、内核、内存和DMA使用的HCLK时钟。、通过8分频后送给Cortex的系统定时器时钟。、直接送给Cortex的空闲运行时钟FCLK。、送给APB1分频器。APB1分频器可选择1、2、4、8、16分频,其输出一路供APB1外设使用(PCLK1,最大频率36MHz),另一路送给定时器(Timer)2、3、4倍频器使用。该倍频器可选择1或者2倍频,时钟输出供定
13、时器2、3、4使用。、送给APB2分频器。APB2分频器可选择1、2、4、8、16分频,其输出一路供APB2外设使用(PCLK2,最大频率72MHz),另一路送给定时器(Timer)1倍频器使用。该倍频器可选择1或者2倍频,时钟输出供定时器1使用。另外,APB2分频器还有一路输出供ADC分频器使用,分频后送给ADC模块使用。ADC分频器可选择为2、4、6、8分频。在以上的时钟输出中,有很多是带使能控制的,例如AHB总线时钟、内核时钟、各种APB1外设、APB2外设等等。当需要使用某模块时,记得一定要先使能对应的时钟。需要注意的是定时器的倍频器,当APB的分频为1时,它的倍频值为1,否则它的倍频
14、值就为2。连接在APB1(低速外设)上的设备有:电源接口、备份接口、CAN、USB、I2C1、I2C2、UART2、UART3、SPI2、窗口看门狗、Timer2、Timer3、Timer4。注意USB模块虽然需要一个单独的48MHz时钟信号,但它应该不是供USB模块工作的时钟,而只是提供给串行接口引擎(SIE)使用的时钟。USB模块工作的时钟应该是由APB1提供的。连接在APB2(高速外设)上的设备有:UART1、SPI1、Timer1、ADC1、ADC2、所有普通IO口(PAPE)、第二功能IO口。下图是STM32用户手册中的时钟系统结构图,通过该图可以从总体上掌握STM32的时钟系统。
15、STM32外部中断之二STM32资料 2009-09-10 21:18 阅读243 评论0 字号: 大大 中中 小小 STM32 外部中断配置1配置中断1、 分配中断向量表:/* Set the Vector Table base location at 0x20000000 */ NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);2、 设置中断优先级:NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); /设置中断优先级3、 初始化外部中断:/*允许EXTI4中断 */ NVIC_InitStructure.NVI
16、C_IRQChannel = EXTI4_IRQChannel; /中断通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = PreemptionPriorityValue;/强占优先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; /次优先级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; /通道中断使能 NVIC_Init(&NVIC_InitStructure); /初始化中断注意:如果我们配置的外部针脚为PA4,或PB4,
17、或PC4,PD4等,那么采用的外部中断也必须是EXTI4,同样,如果外部中断针脚是PA1,PB1,PC1,PD1 那么中断就要用EXTI1,其他类推。2配置GPIO针脚作为外部中断的触发事件 1、 选择IO针脚GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;注意,如果的针脚是端口的4号针脚,配置的中断一定是EXTI42、 配置针脚为输入GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;3、 初始化针脚GPIO_Init(GPIOD,&GPIO_InitStructure);3配置EXTI线,使中断线和IO
18、针脚线连接上1、 将EXTI线连接到IO端口上将EXTI线4连接到端口GPIOD的第4个针脚上 GPIO_EXTILineConfig(GPIO_PortSourceGPIOD,GPIO_PinSource4); 注意:如果配置的针脚是4号,那么参数必须是GPIO_PinSource4 如果配置的针脚是3号,那么参数必须是GPIO_PinSource32、配置中断边沿 /*配置EXTI线0上出现下降沿,则产生中断*/ EXTI_InitStructure.EXTI_Line = EXTI_Line4; 注意:如果配置的4号针脚,那么EXTI_Line4是必须的 EXTI_InitStructu
19、re.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; /下降沿触发 EXTI_InitStructure.EXTI_LineCmd = ENABLE; /中断线使能 EXTI_Init(&EXTI_InitStructure); /初始化中断 EXTI_GenerateSWInterrupt(EXTI_Line4); /EXTI_Line4中断允许到此中断配置完成,可以写中断处理函数。举例:配置函数/* 函数名 NVIC_Configration* 描述 配置各个中
20、断寄存器* 输入 无 * 输出 无* 返回值 无*/void NVIC_Configration(void) NVIC_InitTypeDef NVIC_InitStructure; /#ifdef VECT_TAB_RAM /* Set the Vector Table base location at 0x20000000 */ NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); /#else /* VECT_TAB_FLASH */ /* Set the Vector Table base location at 0x08000000 */ /NVIC
21、_SetVectorTable(NVIC_VectTab_FLASH, 0x0); /#endif NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); /设置中断优先级 /*允许EXTI4中断 */ NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQChannel; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = PreemptionPriorityValue; NVIC_InitStructure.NVIC_IRQChannelSubPriori
22、ty = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /*允许EXTI9中断*/ NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQChannel; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChann
23、elCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /*配置SysTick处理优先级:优先级以及子优先级*/ /* 函数名 :GPIO_Configuration(void)* 描述 :配置TIM2阵脚* 输入 :无* 输出 :无* 返回 :无*/void GPIO_Configuration(void)/* GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3; GPIO_InitS
24、tructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStructure); */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOC,&GPIO_InitStr
25、ucture); /*配置GPIOD的第一个管角为浮动输入*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOD,&GPIO_InitStructure); /*配置GPIOB的第9个管脚为浮动输入*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOB
26、,&GPIO_InitStructure); /* 函数 SysTick_Configuration* 描述 设置SysTick* 输入 无* 输出 无* 返回值 无*/void SysTick_Configuration(void) /*配置 HCLK 时钟做为SysTick 时钟源*/ SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); /系统时钟8分频 72MHz NVIC_SystemHandlerPriorityConfig(SystemHandler_SysTick, 8,2); /*SysTick Interrupt eac
27、h 1000Hz with HCLK equal to 72MHz*/ SysTick_SetReload(9000);/中断周期1ms /*Enable the SysTick Interrupt */ SysTick_ITConfig(ENABLE);/打开中断 SysTick_CounterCmd(SysTick_Counter_Enable); SysTick_CounterCmd(SysTick_Counter_Clear); /* 函数名 EXTI_Configuration* 描述 配置EXTI线* 输入 无 * 输出 无* 返回值 无*/void EXTI_Configurat
28、ion(void) /*将EXTI线0连接到PA0*/ GPIO_EXTILineConfig(GPIO_PortSourceGPIOD,GPIO_PinSource4); /*配置EXTI线0上出现下降沿,则产生中断*/ EXTI_InitStructure.EXTI_Line = EXTI_Line4; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; EXTI_InitStructure.EXTI_LineCmd = ENA
29、BLE; EXTI_Init(&EXTI_InitStructure); EXTI_GenerateSWInterrupt(EXTI_Line4); /*将EXTI线9连接到PB9上*/ GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource9); /*将EXTI线9上出现下降沿产生中断*/ EXTI_InitStructure.EXTI_Line = EXTI_Line9; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigge
30、r = EXTI_Trigger_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); EXTI_GenerateSWInterrupt(EXTI_Line9); 中断函数:void EXTI4_IRQHandler(void) if(EXTI_GetITStatus(EXTI_Line4)!= RESET) EXTI_ClearITPendingBit(EXTI_Line4); if(Ledflag = 0) Ledflag = 1; GPIOC-ODR |= 0X00000080
31、; else Ledflag = 0; GPIOC-ODR &= 0XFFFFFF7F; 注:时钟设置的时候最好加上这句: RCCRCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); / 使能AFIO时钟 STM32中定时器的时钟源STM32资料 2009-07-24 21:34 阅读277 评论0 字号: 大大 中中 小小 STM32中有多达8个定时器,其中TIM1和TIM8是能够产生三对PWM互补输出的高级定时器,常用于三相电机的驱动,它们的时钟由APB2的输出产生。其它6个为普通定时器,时钟由APB1的输出产生。下图是STM32参考手册
32、上时钟分配图中,有关定时器时钟部分的截图:从图中可以看出,定时器的时钟不是直接来自APB1或APB2,而是来自于输入为APB1或APB2的一个倍频器,图中的蓝色部分。下面以定时器27的时钟说明这个倍频器的作用:当APB1的预分频系数为1时,这个倍频器不起作用,定时器的时钟频率等于APB1的频率;当APB1的预分频系数为其它数值(即预分频系数为2、4、8或16)时,这个倍频器起作用,定时器的时钟频率等于APB1的频率两倍。假定AHB=36MHz,因为APB1允许的最大频率为36MHz,所以APB1的预分频系数可以取任意数值;当预分频系数=1时,APB1=36MHz,TIM27的时钟频率=36MH
33、z(倍频器不起作用);当预分频系数=2时,APB1=18MHz,在倍频器的作用下,TIM27的时钟频率=36MHz。有人会问,既然需要TIM27的时钟频率=36MHz,为什么不直接取APB1的预分频系数=1?答案是:APB1不但要为TIM27提供时钟,而且还要为其它外设提供时钟;设置这个倍频器可以在保证其它外设使用较低时钟频率时,TIM27仍能得到较高的时钟频率。再举个例子:当AHB=72MHz时,APB1的预分频系数必须大于2,因为APB1的最大频率只能为36MHz。如果APB1的预分频系数=2,则因为这个倍频器,TIM27仍然能够得到72MHz的时钟频率。能够使用更高的时钟频率,无疑提高了
34、定时器的分辨率,这也正是设计这个倍频器的初衷。STM32笔记之外部中断GPIOSTM32资料 2009-07-14 13:35 阅读331 评论0 字号: 大大 中中 小小 b) 初始化函数定义:void EXTI_Configuration(void); /定义IO中断初始化函数c) 初始化函数调用:EXTI_Configuration();/IO中断初始化函数调用简单应用:d) 初始化函数:void EXTI_Configuration(void) EXTI_InitTypeDef EXTI_InitStructure; /EXTI初始化结构定义EXTI_ClearITPendingBit
35、(EXTI_LINE_KEY_BUTTON);/清除中断标志 GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource3);/管脚选择 GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource4); GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource5); GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource6); EXTI_InitStructure.EXTI_
36、Mode = EXTI_Mode_Interrupt;/事件选择 EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;/触发模式 EXTI_InitStructure.EXTI_Line = EXTI_Line3 | EXTI_Line4; /线路选择 EXTI_InitStructure.EXTI_LineCmd = ENABLE;/启动中断 EXTI_Init(&EXTI_InitStructure);/初始化e) RCC初始化函数中开启I/O时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA
37、 , ENABLE);GPIO初始化函数中定义输入I/O管脚。/IO输入,GPIOA的4脚输入 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; /上拉输入 GPIO_Init(GPIOA, &GPIO_InitStructure); /初始化f) 在NVIC的初始化函数里面增加以下代码打开相关中断: NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQChannel; /通道 NVIC_InitStructure.NVIC_
38、IRQChannelPreemptionPriority = 0;/占先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; /响应级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; /启动 NVIC_Init(&NVIC_InitStructure); /初始化g) 在stm32f10x_it.c文件中找到void USART1_IRQHandler函数,在其中添入执行代码。一般最少三个步骤:先使用if语句判断是发生那个中断,然后清除中断标志位,最后给字符串赋值,或做其他事情。 if(EXTI_GetITStatus(EXTI_Line3) != RESET) /判断中断发生来源 EXTI_ClearITPendingBit(EXTI_Line3); /清除中断标志 USART_SendData(USART1, 0x41); /发送字符“a” GPIO_WriteBit(GPIOB, GPIO_Pin_2, (BitAction)(1-GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_2);/LED发生明暗交替h) 中断注意事项:中断发生后必须清除中