您的位置 首页 电路

STM32的Cortex-M3中止反常处理

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

前段时刻用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的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时钟架构这幅图,如下:

STM32的Cortex-M3中止反常处理

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

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/fangan/dianlu/346824.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部