搜档网
当前位置:搜档网 › STM32中断程序

STM32中断程序

STM32中断程序
STM32中断程序

STM32中断程序

前段时间用STM32F103VBT6写了一个中断的函数,借此机会想了解下STM32的中断机制,用过之后发现STM32的中断配置相当灵活,稳定行很高,测试发现几乎没出过什么差错。我在程序里开了三个中断,一个计数器用于精确延时用,另外两个为外部事件处理中断,下面一一详细介绍,方便初学者入门。

在进行STM32中断配置之前首先需要了解下它的中断部分:

一、Cortex-M3中断机制

在STM32处理器中有43个可屏蔽中断通道(?包含16个Cortex?-M3的中断线)。共设置了16个可编程的优先等级(使用? 4位中断优先级);它的嵌套向?中断控制器(NVIC)和处?器核的接口紧密相连,可以实现低延迟的中断处?和有效处?地处?晚到的中断。嵌套向?中断控制器管?着包括核异常等中断。

Cortex—M3是一个32位的核,在传统的单片机领域中,有一些不同于通用32位CPU应用的要求。比如在工控领域,用户要求具有更快的中断速度,Cortex-M3采用了Tail-Chaining中断技术,完全基于硬件进行中断处理,最多可减少12个时钟周期数,在实际应用中可减少70%中断。

异常或者中断是处理器响应系统中突发事件的一种机制。当异常发生时,Cortex—M3通过硬件自动将编程计数器(PC)、编程状态寄存器(XPSR)、链接寄存器(LR)和R0~R3、R12等寄存器压进堆栈。在Dbus(数据总线)保存处理器状态的同时,处理器通过Ibus(指令总线)从一个可以重新定位的向量表中识别出异常向量,并获取ISR函数的地址,也就是保护现场与取异常向量是并行处理的。一旦压栈和取指令完成,中断服务程序或故障处理程序就开始执行。执行完ISR,硬件进行出栈操作,中断前的程序恢复正常执行。图1为Cortex—M3处理器的异常处理流程。

二、STM32 SysTick 介绍

Cortex-M3的内核中包含一个SysTick时钟。SysTick为一个24位递减计数器,SysTick设定初值并使能后,每经过1个系统时钟周期,计数值就减1 。计数到0时SysTick计数器自动重装初值并继续计数,同时内部的COUNTFLAG 标志会置位,触发中断( 如果中断使能情况下) 。

对于STM32系列微处理器来说,执行一条指令只有几十个ns ,进行for 循环时,要实现N毫秒的x值非大,而且由于系统频率的宽广,很难计算出延时N毫秒的精确值。针对STM32微处理器,需要重新设计一个新的方法去实现该功能,因此,在STM32的应用中,使用Cortex-M3内核的SysTick 作为定时时钟,设定每一毫秒产生一次中断,在中断处理函数里对N减一,在Delay(N)函数中循环检测N是否为0,不为0则进行循环等待;若为0 则关闭SysTick 时钟,退出函数,这种延时函数的做法能很高效地实现精确定时。

三、SysTick编程实现Delay(N)函数

思路:利用systick定时器为递减计数器,设定初值并使能它后,它会每个系统时钟周期计数器减 1 ,计数到0 时,SysTick 计数器自动重装初值并继续计数,同时触发中断。那么每次计数器减到0 ,

时间经过了:

T = 系统时钟周期x计数器初值

比如使用72M 作为系统时钟,那么每次计数器减1 所用的时间是1/72M ,计数器的初值如果是72000 ,那么每次计数器减到0 ,时间经过(1/72M) * 72000 =0.001s ,即1ms.

有了以上思路做铺垫后,为了实现首先我们需要一个72MHz的SysTick时钟。

第一步配置RCC寄存器和SysTick寄存器

由于系统时钟(SysTick)可选择为PLL输出、HSI或者HSE,在这里选择9倍频的PLL作为SysTick的时钟源,同时HCLK(AHB Clock)时钟也相应的配置成72MHz了,因为最终SysTick是需要通过AHB后输出的,所以在配置的同时也需要选择AHB 时钟,这里选择为RCC_SYSCLK_Div1(咖啡色部分)表示AHB 时钟= 系统时钟,相关配置见下面函数(RCC_Configuration)红色字体部分。这里需要特别强调一点,有关书籍里常提到"SysTick的最高频率为9MHz (最大为HCLK/ 8),在这个条件下,把SysTick重装载值设置为9000,将SysTick时钟设置为9MHz,就能够产生1ms 的时间基值"刚开始对这句话感到很迷惑,因为,有的地方介绍SysTick没有说最大频率智能9MHz,这里却指出会被8分频,两者出现了矛盾!相信有过我这种疑惑的人不在少数!究其原因我猜想是原文作者没有说明这点,转载的人见到有相关的知识便直接转载了,自己也没去想,估计也没弄明白过,这样便一个个都转开了,所以我建议在吸取别人精华时要多多思考,只有注入了自己的新元素知识才是被真正吸收了,否则即使涉猎的再多,也只是收藏!现在再来分析下上面的那个矛盾点,其实应该这么理解的,在STM32中,SysTick的架构其实是这么回事的:首先选择时钟源

-->AHB-->这里便分走两路,其一被8分频,也便出现了最高频率9MHz的结果;其二作为FCLK(CM3上的自由运行时钟)直接从AHB输出,这里却是没有再分频的,其频率就是AHB时钟频率,最大可以达到72MHz,下面程序对其设置也是在72MHz的的情况下的,具体可以参考STM32时钟架构这幅图,如下:

void RCC_Configuration(void)

{

RCC_DeInit();

RCC_HSEConfig(RCC_HSE_ON);

HSEStartUpStatus=RCC_WaitForHSEStartUp(); if(HSEStartUpStatus==SUCCESS)

{

RCC_HCLKConfig(RCC_SYSCLK_Div1);

RCC_PCLK2Config(RCC_HCLK_Div1);

RCC_PCLK1Config(RCC_HCLK_Div2);

FLASH_SetLatency(FLASH_Latency_2);

FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9);

RCC_PLLCmd(ENABLE);

while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET)

{

}

RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

while(RCC_GetSYSCLKSource()!=0x08)

{

}

}

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ GPIOE|

RCC_APB2Periph_AFIO,ENABLE);

}

配置完了RCC后,接下来便是需要配置SysTick了,使用ST 的函数库使用systick 的方法一般步骤如下所示:

1 、调用SysTick_CounterCmd() -- 失能SysTick 计数器

2 、调用SysTick_ITConfig () -- 失能SysTick 中断

3 、调用SysTick_CLKSourceConfig() -- 设置SysTick 时钟源。

4 、调用SysTick_SetReload() -- 设置SysTick 重装载值。

5 、调用SysTick_ITConfig () -- 使能SysTick 中断

6 、调用SysTick_CounterCmd() -- 开启SysTick 计数器

SysTick_Configuration: 配置SysTick

void SysTick_Configuration(void)

{

SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);

NVIC_SystemHandlerPriorityConfig(SystemHandler_SysT

SysTick_ITConfig(ENABLE);

}

编写响应的中断服务子函数,这个先对比较简单,直接在stm32f10x_it.h的void SysTickHandler(void)函数里填充计数值便可:

vu32 TimingDelay = 0;

void SysTickHandler(void)

{

TimingDelay--;

}

记住,在调用它的.C文件里记得申明TimingDelay这个变量为全局变量,否则无法使用这个计数值:

extern vu32 TimingDelay;

上面函数只是完成了前5步,接下来需要开启SysTick计数器以便让其工作,前面已经说过在SysTick一般多用于做精确延时用,故而对于这个延时函数它的生命周期便在调用开始到调用结束,所以第6部一般放在被调用的这个函数中(Delay(N)):

void Delay(u32 nTime)

{

SysTick_CounterCmd(SysTick_Counter_Enable);

TimingDelay = nTime;

while(TimingDelay != 0);

SysTick_CounterCmd(SysTick_Counter_Disable);

SysTick_CounterCmd(SysTick_Counter_Clear);

}

至此,一个小的时钟便算配置好了,接下来配置其他两个中断,道理是一样的,这两个为按键输入,作为外部中断事件,分为两个部分,其一为端口配置在

GPIO_Configration函数中,选择工作模式为上拉输入,用作外部中断线路,下降沿触发

void GPIO_Configration(void)

{

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_11;

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;

GPIO_Init(GPIOA,&GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_12;

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;

GPIO_Init(GPIOA,&GPIO_InitStructure);

GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource11);

GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource12);

EXTI_InitStructure.EXTI_Line=EXTI_Line11|EXTI_Line12;

EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;

EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;

EXTI_InitStructure.EXTI_LineCmd=ENABLE;

EXTI_Init(&EXTI_InitStructure);

}

其二是NVIC嵌入式中断配置,包括中断源(中断向量)、优先级、使能等常规设置,具体在前一篇STM32中断机制中介绍得很详细了,这里就不多说了,具体配置在void NVIC_Configuration(void)函数里

void NVIC_Configuration(void)

{

NVIC_InitTypeDef NVIC_InitStructure;

#ifdef VECT_TAB_RAM

NVIC_SetVectorTable(NVIC_VectTab_RAM,0X0);//向量表位于RAM区

#else

NVIC_SetVectorTable(NVIC_VectTab_FLASH,0X0);//向量表位于FLASH区 #endif

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);//选择第一组

//使能EXTI15_10中断,按键PA11

NVIC_InitStructure.NVIC_IRQChannel=EXTI15_10_IRQChannel;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;// 指定抢占式优先级别0

NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;// 指定响应优先级别0 NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//

NVIC_Init(&NVIC_InitStructure);

//使能EXTI15_10中断,按键PA12

NVIC_InitStructure.NVIC_IRQChannel=EXTI15_10_IRQChannel;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;// 指定抢占式优先级别0

NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;// 指定响应优先级别0 NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//

NVIC_Init(&NVIC_InitStructure);

}

最后是相应的中断服务子函数,还是在stm32f10x_it.h中,该中断为EXTI15_10中断,故而其中断服务子函数在void EXTI15_10_IRQHandler(void)中惊醒执行,具体格式如下:

void EXTI15_10_IRQHandler(void)

{

if(EXTI_GetITStatus(EXTI_Line11)!=RESET)//判断标志,中断是否发生

{

...

EXTI_ClearITPendingBit(EXTI_Line11); //清标志位

}

if(EXTI_GetITStatus(EXTI_Line12)!=RESET)//判断标志,中断是否发生

{

...

EXTI_ClearITPendingBit(EXTI_Line12); //清标志位

}

}

最后下载运行,主函数中让一个LED闪烁,按键1让其他四个LED连续闪烁三次,按键2让另外4个LED依次流水,下载运行,测试通过!详细代码可以直接下载如下压缩文件,编译环境为MDK350PRC,固件库在安装目录下的子文件夹中,版本差别不大

STM32外部中断配置例程

STM32 外部中断配 NVIC_Configuration 函数实现配置嵌套向量中断中断优先级并使能中断。其中的NVIC_PriorityGroupConfig 函数配置中断优先级的组织方式,STM32 的嵌套向量中断控制器可以配置16 个可编程的优先等级,使用了4 位表示中断优先级(2 的4 此方就是16),16 个可编程的优先等级又可以分为主优先级和次优先级,例如参数NVIC_PriorityGroup_1表示1bit 主优先级(pre-emption priority)3 bits 次优先级(subpriority )。 一、配置中断 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.NVIC_IRQChannel = EXTI4_IRQChannel; //中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= PreemptionPriorityValue; //占先优先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //响应(次级)优先级NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //通道中断使能 NVIC_Init(&NVIC_InitStructure); //初始化中断 注意:如果我们配置的外部针脚为PA4,或PB4,或PC4,PD4等,那么采用的外部 中断也必须是EXTI4,同样,如果外部中断针脚是PA1,PB1,PC1,PD1 那么中断就要用EXTI1,其他类推。 二、配置GPIO针脚作为外部中断的触发事件 1、选择IO针脚 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; 注意,如果的针脚是端口的4号针脚,配置的中断一定是EXTI4 2、配置针脚为输入 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 3、初始化针脚 GPIO_Init(GPIOD,&GPIO_InitStructure); 3配置EXTI线,使中断线和IO针脚线连接上 1、将EXTI线连接到IO端口上 将EXTI线4连接到端口GPIOD的第4个针脚上 GPIO_EXTILineConfig(GPIO_PortSourceGPIOD,GPIO_PinSource4);

STM32的基本概念及中断应用

STM32的基本概念及中断应用 1、基本概念 ARMCoetex-M3内核共支持256个中断,其中16个内部中断,240个外部中断和可编程的256级中断优先级的设置。STM32目前支持的中断共84个(16个内部+68个外部),还有16级可编程的中断优先级的设置,仅使用中断优先级设置8bit中的高4位。 STM32可支持68个中断通道,已经固定分配给相应的外部设备,每个中断通道都具备自己的中断优先级控制字节PRI_n(8位,但是STM32中只使用4位,高4位有效),每4个通道的8位中断优先级控制字构成一个32位的优先级寄存器。68个通道的优先级控制字至少构成17个32位的优先级寄存器。 4bit的中断优先级可以分成2组,从高位看,前面定义的是抢占式优先级,后面是响应优先级。按照这种分组,4bit一共可以分成5组 第0组:所有4bit用于指定响应优先级; 第1组:最高1位用于指定抢占式优先级,后面3位用于指定响应优先级; 第2组:最高2位用于指定抢占式优先级,后面2位用于指定响应优先级; 第3组:最高3位用于指定抢占式优先级,后面1位用于指定响应优先级; 第4组:所有4位用于指定抢占式优先级。 所谓抢占式优先级和响应优先级,他们之间的关系是:具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断嵌套。 当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之后才能被处理。如果这两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先处理哪一个;如果他们的抢占式优先级和响应优先级都相等,则根据他们在中断表中的排位顺序决定先处理哪一个。每一个中断源都必须定义2个优先级。 有几点需要注意的是:

STM32中断

STM32外部中断详解 2012-07-02 21:59:24| 分类:嵌入式相关| 标签:|举报|字号大中小订阅 一、基本概念 ARM Coetex-M3内核共支持256个中断,其中16个内部中断,240个外部中断和可编程的256级中断优先级的设置。STM32目前支持的中断共84个(16个内部+68个外部),还有16级可编程的中断优先级的设置,仅使用中断优先级设置8bit中的高4位。 STM32可支持68个中断通道,已经固定分配给相应的外部设备,每个中断通道都具备自己的中断优先级控制字节PRI_n(8位,但是STM32中只使用4位,高4位有效),每4个通道的8位中断优先级控制字构成一个32位的优先级寄存器。68个通道的优先级控制字至少构成17个32位的优先级寄存器。 4bit的中断优先级可以分成2组,从高位看,前面定义的是抢占式优先级,后面是响应优先级。按照这种分组,4bit一共可以分成5组 第0组:所有4bit用于指定响应优先级; 第1组:最高1位用于指定抢占式优先级,后面3位用于指定响应优先级; 第2组:最高2位用于指定抢占式优先级,后面2位用于指定响应优先级; 第3组:最高3位用于指定抢占式优先级,后面1位用于指定响应优先级; 第4组:所有4位用于指定抢占式优先级。 所谓抢占式优先级和响应优先级,他们之间的关系是:具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断嵌套。 当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之后才能被处理。如果这两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先处理哪一个;如果他们的抢占式优先级和响应优先级都相等,则根据他们在中断表中的排位顺序决定先处理哪一个。每一个中断源都必须定义2个优先级。 有几点需要注意的是: 1)如果指定的抢占式优先级别或响应优先级别超出了选定的优先级分组所限定的范围,将可能得到意想不到的结果; 2)抢占式优先级别相同的中断源之间没有嵌套关系; 3)如果某个中断源被指定为某个抢占式优先级别,又没有其它中断源处于同一个抢占式优先级别,则可以为这个中断源指定任意有效的响应优先级别。 二、 GPIO外部中断 STM32中,每一个GPIO都可以触发一个外部中断,但是,GPIO的中断是以组位一个单位的,同组间的外部中断同一时间只能使用一个。比如说,PA0,PB0,PC0,PD0,PE0,PF0,PG0这些为1组,如果我们使用PA0作为外部中断源,那么别的就不能够再使用了,在此情况下,我们智能使用类似于PB1,PC2这种末端序号不同的外部中断源。每一组使用一个中断标志EXTIx。EXTI0 –EXTI4这5个外部中断有着自己的单独的中断响应函数,EXTI5-9共用一个中断响应函数,EXTI10-15共用一个中断响应函数。对于中断的控制,STM32有一个专用的管理机构:NVIC。 三、程序实现

STM32各模块学习之中断

STM32系统及各模块配置 一、STM32中断优先级和开关总中断 (1)中断优先级: STM32(Cortex-M3)中的优先级概念 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位用于指定响应优先级

stm32中断和事件

STM32中断和事件 库函数: void EXTI_DeInit(void) { EXTI->IMR = 0x00000000;//屏蔽所有中断 EXTI->EMR = 0x00000000;//屏蔽所有事件 EXTI->RTSR = 0x00000000; //禁止所有上升沿触发 EXTI->FTSR = 0x00000000; //禁止所有下降沿触发 EXTI->PR = 0x000FFFFF;//挂起位全部清空 } void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct) { 该函数接收一个结构体,按照下面的结构体配置EXTI 寄存器 typedef struct { uint32_t EXTI_Line; /*!< Specifies the EXTI lines to be enabled or disabled. This parameter can be any combination of @ref EXTI_Lines */ EXTI_IMR EXTI_EMR EXTI_RTSR EXTI_FTSR EXTI_SWIER EXTI_PR 写“1”清除 读到“1”有请求 读到“0”无请求 写“0” 屏蔽中断 写“1” 开放中断 写“0” 屏蔽事件 写“1” 开放事件 写“0” 禁止 写“1” 允许上升 写“0” 禁止下降沿触发 写“1” 允许下降沿触发 SWIER 写“1”PR 挂起

EXTIMode_TypeDef EXTI_Mode; /*!< Specifies the mode for the EXTI lines. This parameter can be a value of @ref EXTIMode_TypeDef */ EXTITrigger_TypeDef EXTI_Trigger; /*!< Specifies the trigger signal active edge for the EXTI lines. This parameter can be a value of @ref EXTIMode_TypeDef */ FunctionalState EXTI_LineCmd; /*!< Specifies the new state of the selected EXTI lines. This parameter can be set either to ENABLE or DISABLE */ }EXTI_InitTypeDef; uint32_t tmp = 0; tmp = (uint32_t)EXTI_BASE; if (EXTI_InitStruct->EXTI_LineCmd != DISABLE) { /* Clear EXTI line configuration 屏蔽中断和事件*/ EXTI->IMR &= ~EXTI_InitStruct->EXTI_Line; EXTI->EMR &= ~EXTI_InitStruct->EXTI_Line; tmp += EXTI_InitStruct->EXTI_Mode; *(__IO uint32_t *) tmp |= EXTI_InitStruct->EXTI_Line; //开放中断或事件 /* Clear Rising Falling edge configuration 禁止上升沿触发和下降沿触发*/ EXTI->RTSR &= ~EXTI_InitStruct->EXTI_Line; EXTI->FTSR &= ~EXTI_InitStruct->EXTI_Line; /* Select the trigger for the selected external interrupts */ if (EXTI_InitStruct->EXTI_Trigger == EXTI_Trigger_Rising_Falling) //允许上升沿触发和下降沿触发 {

Stm32 IO端口及其中断

弟4章I/O端口及中断 I/O口(GPIO) 一、GPIO的概述: GPI/O,通用型之输入输出(General Purpose I/O)的简称,对于stm32的学习,应该从最基本的GPIO开始学习:首先看看STM32的datasheet上对GPIO口的简单介绍:每个GPI/O端口有两个32位配置寄存器(GPIOx_CRL,GPIOx_CRH),两个32位数据寄存器(GPIOx_IDR,GPIOx_ODR),一个32位置位/复位寄存器(GPIOx_BSRR),一个16位复位寄存器(GPIOx_BRR)和一个32位锁定寄存器(GPIOx_LCKR)。共7组寄存器。GPIO端口的每个位可以由软件分别配置成多种模式。每个I/O端口位可以自由编程,然而I/0端口寄存器必须按32位字被访问(不允许半字或字节访问)。GPIOx_BSRR和GPIOx_BRR寄存器允许对任何GPIO寄存器的读/更改的独立访问;这样,在读和更改访问之间产生IRQ时不会发生危险。我们常用的IO端口寄存器只有4个:CRL、CRH、IDR、ODR。CRL和CRH控制着每个IO口的模式及输出速率。二、GPIO的配置: 当使用GPIO时,需要两步。一是:配置模式,二是配置时钟。对于模式配置共有8种,可以通过编程选择: 1.浮空输入:GPIO_Mode_IN_FLOATING

2.带上拉输入:GPIO_Mode_IPU 3.带下拉输入:GPIO_Mode_IPD 4.模拟输入:GPIO_Mode_AIN 5.开漏输出:GPIO_Mode_Out_OD 6.推挽输出:GPIO_Mode_Out_PP 7.复用功能的推挽输出:GPIO_Mode_AF 8.复用功能的开漏输出:GPIO_Mode_AF_OD 模式7和模式8需根据具体的复用功能决定。时钟配置将会在后续课程中一一介绍。 I/O口的输出模式下,有3种输出速度可选(2MHz、10MHz 和50MHz),这有利于噪声控制。这个速度是指I/O口驱动电路的响应速度而不是输出信号的速度,输出信号的速度与程序有关(芯片内部在I/O口的输出部分安排了多个响应速度不同的输出驱动电路,用户可以根据自己的需要选择合适的驱动电路)。通过选择速度来选择不同的输出驱动模块,达到最佳的噪声控制和降低功耗的目的。高频的驱动电路,噪声也高,当不需要高的输出频率时,请选用低频驱动电路,这样非常有利于提高系统的EMI性能。当然如果要输出较高频率的信号,但却选用了较低频率的驱动模块,很可能会得到失真的输出信号。 三、GPIO的功能: 1.通用I/O(GPIO):最最基本的功能,可以驱动LED、可以产生PWM、可以驱动蜂鸣器等等;

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.NVIC_IRQChannel = EXTI4_IRQChannel; //中断通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = PreemptionPriorityValue;//强占优先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //次优先级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //通道中断使能 NVIC_Init(&NVIC_InitStructure); //初始化中断 注意:如果我们配置的外部针脚为PA4,或PB4,或PC4,PD4等,那么采用的外部中断也必须是EXTI4,同样,如果外部中断针脚是PA1,PB1,PC1,PD1 那么中断就要用EXTI1,其他类推。 2配置GPIO针脚作为外部中断的触发事件 1、 选择IO针脚 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; 注意,如果的针脚是端口的4号针脚,配置的中断一定是EXTI4 2、 配置针脚为输入 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 3、 初始化针脚 GPIO_Init(GPIOD,&GPIO_InitStructure);

STM32F103中断和定时器程序

STM32中断程序 /*======================================================================================== *名称: main.c *功能: *入口参数: *说明:去掉stm32f10x_conf.h里#include "stm32f10x_tim.h" 注释 *范例: *编者时间: Ye.FuYao 2012-9-23 *========================================================================================*/ #include "stm32f10x.h" #include "12864.h" ErrorStatus HSEStartUpStatus; //等待时钟的稳定 u8 count=0; u8 d; void SYS_Configuration(void); /* //ms延时函数 void delayms(unsigned int nValue) //delay 1ms at 8M { unsigned int nCount; unsigned int ii; unsigned int jj; nCount = 1980; for(ii = nValue;ii > 0;ii--) { for(jj = nCount;jj > 0;jj--) Delay(1); } } */ //GPIO管脚初始化配置 void GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; //GPIO状态恢复默认参数 /*GPIO口配置每四行一组,每组GPIO属性相同,默认情况:ALL,2MHZ,FLATING*/ /*PA-2-3配置为输出*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_7; //管脚位置定义 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //设置输出模式 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //输出速度为50MHZ GPIO_Init(GPIOA, &GPIO_InitStructure); //A组GPIO初始化 /*PB-2配置为输出*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //管脚位置定义 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //设置输出模式

STM32中断15—10的设置

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( ) {

stm32中断(NVIC与EXTI)说课讲解

s t m32中断(N V I C与 E X T I)

一、本章大纲 一、嵌套向量中断控制器—NVIC CM3内核搭载了一个异常响应系统,通过NVIC(嵌套向量中断控制器)来管理和配置。NVIC是一个总的控制器,相当于51的IE,不论是来自CM3内部的异常还是来自外设的中断,都进入该控制器进行处理和逻辑控制。并且NVIC还通过优先级系统,来控制中断的嵌套。 1.中断优先级 ①优先级的数值越小,则优先级越高。②NVIC支持中断嵌套,使得高优先级异常会抢占低优先级异常。 ③有3个系统异常:复位、NMI(不可屏蔽中断)以及硬件失效(Hard fault),它们有固定的优先级,并且它们的优先级号是负数,从而高于所有其他异常。 原则上,NVIC支持3个固定的高优先级和多达256级的可设置优先级,用一个字节的8个比特位来表示。 STM32F107采用最高有效位对齐,在设计时裁掉表达优先级的4个低端有效位,所以只支持16级优先级。 2.抢占优先级与从优先级 NVIC中有一个寄存器是“应用程序中断及复位控制寄存器”,它里面有一个位段名为“优先级组”。它把优先级分为2个位段:

MSB所在的位段对应抢占优先级,抢占优先级决定了抢占行为。 LSB所在的位段对应从优先级,从优先级则处理“内务”。 在STM32F107中,只使用4个位来表达优先级([7:4]),如果抢占优先级组从比特5处分,则得到4级抢占优先级,且在每个抢占优先级的内部有4个从优先级(00 01 10 11)。 3.中断输入与悬起 当中断输入脚被置为有效后,该中断就被“悬起”。所谓“悬起”,也就是等待、就绪的意思。即使后来中断源撤消了中断请求,已经被标记成悬起的中断也被记录下来。 当某中断的服务程序开始执行时,就称此中断进入了“活跃”状态,并且其悬起位会被硬件自动清除。在一个中断活跃后,直到其服务例程执行完毕,并且返回后,才能对该中断的新请求予以响应。 当NVIC响应一个中断时,会自动完成以下三项工作,以便安全、准确地跳转到相应的中断服务程序: 入栈:把8个寄存器的值压入栈。当响应中断时,如果当前的代码正在使用PSP,则压入PSP(进程堆栈),否则就压入MSP(主堆栈)。一旦进入了服务例程,就一直使用主堆栈。在自动入栈的过程中,将寄存器写入堆栈的顺序与时间顺序无关,CM3会保证正确的寄存器被保存到正确的位置。 取向量:当数据总线(系统总线)进行入栈操作时,指令总线(I-Code总线)正在从向量表中找出正确的中断向量与对应的服务程序入口地址。 更新寄存器。

STM32中断管理函数

STM32中断管理函数 CM3 内核支持256 个中断,其中包含了16 个内核中断和240 个外部中断,并且具有256 级的可编程中断设置。但STM32 并没有使用CM3 内核的全部东西,而是只用了它的一部分。 STM32 有76 个中断,包括16 个内核中断和60 个可屏蔽中断,具有16 级可编程的中断优先级。 而我们常用的就是这60 个可屏蔽中断,所以我们就只针对这60 个可屏蔽中断进行介绍。在MDK 内,与NVIC 相关的寄存器,MDK 为其定义了如下的结构体: typedef struct { vu32 ISER[2]; u32 RESERVED0[30]; vu32 ICER[2]; u32 RSERVED1[30]; vu32 ISPR[2]; u32 RESERVED2[30]; vu32 ICPR[2]; u32 RESERVED3[30]; vu32 IABR[2]; u32 RESERVED4[62]; vu32 IPR[15]; } NVIC_TypeDef; STM32 的中断在这些寄存器的控制下有序的执行的。了解这些中断寄存器,你才能方便的使用STM32 的中断。下面重点介绍这几个寄存器: ISER[2]:ISER 全称是:Interrupt Set-Enable Registers,这是一个中断使能寄存器组。上面 说了STM32 的可屏蔽中断只有60 个,这里用了2 个32 位的寄存器,总共可以表示64 个中断。 而STM32 只用了其中的前60 位。ISER[0]的bit0~bit31 分别对应中断0~31。ISER[1]的bit0~27 对应中断32~59;这样总共60 个中断就分别对应上了。你要使能某个中断,必须设置相应的ISER 位为1,使该中断被使能(这里仅仅是使能,还要配合中断分组、屏蔽、IO 口映射等设置才算是 一个完整的中断设置)。具体每一位对应哪个中断,请参考stm32f10x_nvic..h 里面的第36 行处。 ICER[2]:全称是:Interrupt Clear-Enable Registers,是一个中断除能寄存器组。该寄存器组与ISER 的作用恰好相反,是用来清除某个中断的使能的。其对应位的功能,也和ICER 一样。 这里要专门设置一个ICER 来清除中断位,而不是向ISER 写0 来清除,是因为NVIC 的这些寄 存器都是写1 有效的,写0 是无效的。具体为什么这么设计,请看《CM3 权威指南》第125 页, NVIC 概览一章。

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.NVIC_IRQChannel = EXTI4_IRQChannel; //中断通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = PreemptionPriorityValue;//强占优先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //次优先级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //通道中断使能 NVIC_Init(&NVIC_InitStructure); //初始化中断 注意:如果我们配置的外部针脚为PA4,或PB4,或PC4,PD4等,那么采用的外部中断也必须是EXTI4,同样,如果外部中断针脚是PA1,PB1,PC1,PD1 那么中断就要用EXTI1,其他类推。 2配置GPIO针脚作为外部中断的触发事件 1、选择IO针脚 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; 注意,如果的针脚是端口的4号针脚,配置的中断一定是EXTI4 2、配置针脚为输入 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 3、初始化针脚 GPIO_Init(GPIOD,&GPIO_InitStructure);

STM32中断过程详解

STM32中断过程详解 对于 STM32 讲(还是以Timer2例),外部中断通道位置 28(35 号优先级)是给外部设备 TIME2 的,但 TIME2本身能够引起中断的中断源或事件有好多个,比如更新事件(上溢/下溢)、输入捕获、输出匹配、DMA 申请等。所有TIME2 的中断事件都是通过一个 TIME2 的中断通道向 STM32 内核提出中断申请,那么 STM32 中如何处理和控制 TIME2 和它众多的、不同的、中断申请呢? 1.因为cortex_m3 内核对于每一个外部中断通道都有相应的控制字和控制位,用于单独的和总的控制该中断通道。它们包括有: 中断优先级控制字:PRI_n(前面有提到过) 中断允许设置位:在 ISER 寄存器中 中断允许清除位:在 ICER 寄存器中 中断悬挂 Pending(排队等待)位置位:在 ISPR 寄存器中(类似于置中断通道标志位)中断悬挂 Pending(排队等待)位清除:在 ICPR 寄存器中(用于清除中断通道标志位)正在被服务(活动)的中断(Active)标志位:在 IABR 寄存器中,(只读,可以知道当前内核正在处理哪个中断通道) 2.作为外围设备 TIME2 本身也包括更具体的,管理自己不同中断的中断控制器(位),它们主要是自身各个不同类型中断的允许控制位,和各自相应的中断标志位(STM32 的手册中有详细的说明)。 理解上面两点之后,我们可以全程、全面和综合的来了解 TIME2 的中断过程,以及如何控制的。 ①初始化过程 首先要设置寄存器 AIRC 中 PRIGROUP 的值,规定系统中的抢先优先级和子优先级的个数(在 4 个 bits 中占用的位数); 设置 TIME2 本身的寄存器,允许相应的中断,如允许 UIE(TIME2_DIER 的第[0]位)

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位用于指定响应优先级 这就是优先级分组的概念。 Cortex-M3允许具有较少中断源时使用较少的寄存器位指定中断源的优先级,因此STM32把指定中断优先级的寄存器位减少到4位(AIRCR高四位),这4个寄存器位的分组方式如下:

stm32-串口中断总结

本文以USART1为例,叙述串口中断的编程过程。 1、先来讲述一下在应用串口中断时涉及到的一些库文件。 首先对于STM32外设库文件的应用编程,misc.c和stm32f10x_rcc.c是肯定要添加到。 接下来就是我们要用到的相关外设了。毫无疑问,串口文件stm32f10x_usart.c是必须的。串口通信是对通用GPIO端口引脚的功能复用,所以还需要stm32f10x_gpio.c文件。另外,因为有中断的产生,所以中断文件stm32f10x_it.c也是必要的,当然这个文件一般和main.c 放在一个文件夹下(一般习惯为User文件夹),因为我们的中断响应函数是要在里面自己编写的。 当然还有其他的基本必须文件如系统配置文件等在这地方就不说了,这个是创建一个工程应该知道的。 2、初始化 对于串口通信的初始化,不仅仅只是对串口的初始化(这个地方是比较烦人的,不像别的芯片那样简洁明了)。 ●?首先时钟使能配置。STM32内部的时钟有很多,感兴趣的自己看看参考手册。此处 以USART1为例说明。有USART1时钟、GPIOA时钟、GPIO复用(AFIO)时钟。由于 此处USART1和GPIOA、AFIO均在APB2上,所以可以一次配置完成。如下: RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO|RCC_APB 2Periph_USART1 ,ENABLE); ●?其次中断配置。主要有优先级组设定、USART1中断使能、该中断的优先级,中断初 始化。程序如下: void NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);//选择分组方式0 /* 使能 USART1中断 */ NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } ●?然后GPIO复用功能配置。一般情况下我们使用原始的外设和GPIO端口引脚的映射 关系,如果要改变其映射的话,请另外查看参考手册上关于GPIO重映射部分。对 于GPIO的复用,其引脚的输入与输出模式都有要求,在参考手册上有详细说明。 void GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; /* 配置 USART1 Rx 作为浮空输入 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(USARTy_GPIO, &GPIO_InitStructure); /* 配置 USART1 Tx 作为推挽输出 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

STM32中断向量表

/** *@brief STM32F10x Interrupt Number Definition,according to the selected device *in@ref Library_configuration_section */ typedef enum IRQn { /******Cortex-M3Processor Exceptions Numbers***************************************************/ NonMaskableInt_IRQn=-14,/*!<2Non Maskable Interrupt*/ MemoryManagement_IRQn=-12,/*!<4Cortex-M3Memory Management Interrupt*/ BusFault_IRQn=-11,/*!<5Cortex-M3Bus Fault Interrupt*/ UsageFault_IRQn=-10,/*!<6Cortex-M3Usage Fault Interrupt*/ SVCall_IRQn=-5,/*!<11Cortex-M3SV Call Interrupt*/ DebugMonitor_IRQn=-4,/*!<12Cortex-M3Debug Monitor Interrupt*/ PendSV_IRQn=-2,/*!<14Cortex-M3Pend SV Interrupt*/ SysTick_IRQn=-1,/*!<15Cortex-M3System Tick Interrupt*/ /******STM32specific Interrupt Numbers*********************************************************/ WWDG_IRQn=0,/*!

相关主题