您的位置 首页 硬件

stm32 学习笔记: 中止

中断对于开发嵌入式系统来讲的地位绝对是毋庸置疑的,在C51单片机时代,一共只有5个中断,其中2个外部中断,2个定时/计数器中断和一个串口…

中止关于开发嵌入式体系来讲的位置肯定是毋庸置疑的,在C51单片机年代,总共只要5个中止,其间2个外部中止,2个守时/计数器中止和一个串口中止,可是在STM32中,中止数量大大增加,而且中止的设置也愈加杂乱。今日就将来讨论一下关于STM32中的中止体系

1 根本概念

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)假如某个中止源被指定为某个抢占式优先等级,又没有其它中止源处于同一个抢占式优先等级,则能够为这个中止源指定恣意有用的呼应优先等级。

2 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。关于NVIC的详细解说,能够参阅《ARM Cortex-M3威望攻略》,Joseph Yiu著,宋岩译,北京航空航天大学出书社出书,第8章NVIC与中止操控。中止的使能,挂起,优先级,活动等等部都是NVIC在办理的。因为我学习STM32要点在于怎么开发程序,所以内部的一些东西,在此我就不详细说明晰,有感爱好的能够参看上面说到的那本数。

3 程序开发

其实上面那些根本概念和常识仅仅对STM32的中止体系有一个大约的知道,用程序说话将会更能够加深怎么运用中止。运用外部中止的根本过程如下:

1.设置好相应的时钟;

2.设置相应的中止;

3.IO口初始化;

4.把相应的IO口设置为中止线路(要在设置外部中止之前)并初始化;

5.在挑选的中止通道的呼应函数中中止函数。

因为我用的斗争开发板没有引出相应的芯片引脚,所以只能用按键来触发相应的中止。依据原理图,K1/K2/K3衔接的是PC5/PC2/PC3,因而我将用EXTI5/EXTI2/EXTI3三个外部中止。PB5/PD6/PD3别离衔接了三个LED灯。中止的作用是按下按键,相应的LED灯将会被点亮。

1.设置相应的时钟

首要需求翻开GPIOB、GPIOC和GPIOE(因为按键别的一端衔接的是PE口)。然后由所以要用于触发中止,所以还需求翻开GPIO复用的时钟。相应的函数在GPIO的学习笔记中有了详细了解说。详细代码如下:

void RCC_cfg()

{

//翻开PE PD PC PB端口时钟,而且翻开复用时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);

}

设置相应的时钟所需求的RCC函数在stm32f10x_rcc.c中,所以要在工程中增加此文件。

2.设置好相应的中止

设置相应的中止实际上便是设置NVIC,在STM32的固件库中有一个结构体NVIC_InitTypeDef,里边有相应的标志位设置,然后再用NVIC_Init()函数进行初始化。详细代码如下:

void NVIC_cfg()

{

NVIC_InitTypeDef NVIC_InitStructure;

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//挑选中止分组2

NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQChannel;//挑选中止通道2

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占式中止优先级设置为0

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //呼应式中止优先级设置为0

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能中止

NVIC_Init(&NVIC_InitStructure);

NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQChannel;//挑选中止通道3

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //抢占式中止优先级设置为1

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//呼应式中止优先级设置为1

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能中止

NVIC_Init(&NVIC_InitStructure);

NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQChannel;//挑选中止通道5

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //抢占式中止优先级设置为2

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;//呼应式中止优先级设置为2

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能中止

NVIC_Init(&NVIC_InitStructure);

}

因为有3个中止,因而依据前文所述,需求有3个bit来指定抢占优先级,所以挑选第2组。又因为EXTI5-9共用一个中止呼应函数,所以EXTI5挑选的中止通道是EXTI9_5_IRQChannel,详细信息能够在头文件中查询得到。用到的NVIC相关的库函数在stm32f10x_nivc.c中,需求将此文件仿制并增加到工程中。详细位置能够检查关于GPIO的笔记。这段代码编译起来没有任何问题,可是在链接的时分就会报错,需求把STM32F10xR.LIB参加工程中,详细位置在…KeilARMRV31LIBSTSTM32F10xR.LIB。

3.IO口初始化

void IO_cfg()

{

GPIO_InitTypeDef GPIO_InitStructure;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;//挑选引脚2

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//输出频率最大50MHz

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //带上拉电阻输出

GPIO_Init(GPIOE,&GPIO_InitStructure);

GPIO_ResetBits(GPIOE,GPIO_Pin_2);//将PE.2引脚设置为低电平输出

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_5; //挑选引脚2 3 5

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //挑选输入形式为浮空输入

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //输出频率最大50MHz

GPIO_Init(GPIOC,&GPIO_InitStructure);//设置PC.2/PC.3/PC.5

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_6;//挑选引脚3 6

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//输出频率最大50MHz

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//带上拉电阻输出

GPIO_Init(GPIOD,&GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;//挑选引脚5

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//输出频率最大50MHz

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //带上拉电阻输出

GPIO_Init(GPIOB,&GPIO_InitStructure);

}

其间衔接外部中止的引脚需求设置为输入状况,而衔接LED的引脚需求设置为输出状况,初始化PE.2是为了使得按键的别的一端输出低电平。GPIO中的函数在stm32f10x_gpio.c中。

4.把相应的IO口设置为中止线路

因为GPIO并不是专用的中止引脚,因而在用GPIO来触发外部中止的时分需求设置将GPIO相应的引脚和中止线衔接起来,详细代码如下:

void EXTI_cfg()

{

EXTI_InitTypeDef EXTI_InitStructure;

//清空中止标志

EXTI_ClearITPendingBit(EXTI_Line2);

EXTI_ClearITPendingBit(EXTI_Line3);

EXTI_ClearITPendingBit(EXTI_Line5);

//挑选中止管脚PC.2 PC.3 PC.5

GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource2);

GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource3);

GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource5);

EXTI_InitStructure.EXTI_Line = EXTI_Line2 | EXTI_Line3 | EXTI_Line5; //挑选中止线路2 3 5

EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //设置为中止恳求,非事情恳求

EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; //设置中止触发方法为上下降沿触发

EXTI_InitStructure.EXTI_LineCmd = ENABLE;//外部中止使能

EXTI_Init(&EXTI_InitStructure);

}

EXTI_cfg中需求调用到的函数都在stm32f10x_exti.c。

5.写中止呼应函数

STM32不像C51单片机那样,能够用过interrupt关键字来界说中止呼应函数,STM32的中止呼应函数接口存在中止向量表中,是由发动代码给出的。默许的中止呼应函数在stm32f10x_it.c中。因而咱们需求把这个文件参加到工程中来。

在这个文件中,咱们发现,许多函数都是只要一个函数名,并没有函数体。咱们找到EXTI2_IRQHandler()这个函数,这便是EXTI2中止呼应的函数。我的方针是将LED灯点亮,所以函数体其实很简单:

void EXTI2_IRQHandler(void)

{

//点亮LED灯

GPIO_SetBits(GPIOD,GPIO_Pin_6);

//清空中止标志位,避免继续进入中止

EXTI_ClearITPendingBit(EXTI_Line2);

}

void EXTI3_IRQHandler(void)

{

GPIO_SetBits(GPIOD,GPIO_Pin_3);

EXTI_ClearITPendingBit(EXTI_Line3);

}

void EXTI9_5_IRQHandler(void)

{

GPIO_SetBits(GPIOB,GPIO_Pin_5);

EXTI_ClearITPendingBit(EXTI_Line5);

}

因为EXTI5-9是共用一个中止呼应函数,因而一切的EXTI5 – EXTI9的呼应函数都写在这个里边。

6.写主函数

#include “stm32f10x_lib.h”

void RCC_cfg();

void IO_cfg();

void EXTI_cfg();

void NVIC_cfg();

int main()

{

RCC_cfg();

IO_cfg();

NVIC_cfg();

EXTI_cfg();

while(1);

}

main函数前是函数声明,main函数函数体中都是调用初始化装备函数,然后进入死循环,等候中止呼应。

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

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

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

微信扫一扫关注我们

返回顶部