stm32中nvic的中端过程具体是怎么一步一步实现的?哪位高人浅显的解释一下?比如,第一步标志位出现,

stm32中nvic的中端过程具体是怎么一步一步实现的?哪位高人浅显的解释一下?比如,第一步标志位出现,,第1张

我也比如一下

比如说按键中断

1.要使能时钟和相关GPIO口(按键口)

2.使能中断嵌套程序NVIC,里面的关键是中断类型(在本例子中就是外部中断啦,所有的中断都要使能NVIC,否则不能中断),如果就一个中断,优先级可忽略

3.使能外部中断EXTI,其实就是按键中断了

4.主程序中一般是循环啦

举个例子,最简单的

mian()

{

RCC_config()

GPIO_config()

NVIC_config()

EXTI_Config()

while(1)

}

5.中断函数程序中,注意这个是在另一个文件下stm32f10x_it.c,而上面的所有步骤都是在main.c文件中的

编写中断程序

void EXTI9_5_IRQHandler(void)

{

delay()//延时函数

}

因为我用的是第8道,所以函数名是

EXTI9_5_IRQHandler

6.开始运行程序啦,从上往坦樱下走,配置完了时钟,GPIO,NVIC,EXTI后就进入while(1)死循环中,这时候当你按下按键后,会产生一个电平的变换1变0或0变1,对应的GPIO口接受到这个变换后就会发生中断,进入中断函数

EXTI9_5_IRQHandler,中断函数中是个延时函数,等延时完就会结束中断函数返回主函数啦。

贴一个我写的小例子,就是按键中断的。主函数中为橘孝点亮灯,中断函数为熄灭灯

#include "stm32f10x.h"

#include "stm32f10x_gpio.h"

#include "圆信稿stm32f10x_rcc.h"

#include "stm32f10x_exti.h"

void RCC_Configuration(void) //时钟配置函数

{

ErrorStatus HSEStartUpStatus

//使能外部晶振

RCC_HSEConfig(RCC_HSE_ON)

//等待外部晶振稳定

HSEStartUpStatus = RCC_WaitForHSEStartUp()

//如果外部晶振启动成功,则进行下一步 *** 作

if(HSEStartUpStatus==SUCCESS)

{

//设置HCLK(AHB时钟)=SYSCLK 将系统时钟进行分频后,作为AHB总线时钟

RCC_HCLKConfig(RCC_SYSCLK_Div1)

//PCLK1(APB1) = HCLK/2 将HCLK时钟2分频后给低速外部总线

RCC_PCLK1Config(RCC_HCLK_Div2)

//PCLK2(APB2) = HCLK HCLK时钟配置给高速外部总线

RCC_PCLK2Config(RCC_HCLK_Div1)

//外部高速时钟HSE 4倍频

RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_4)

//启动PLL

RCC_PLLCmd(ENABLE)

//等待PLL稳定

while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)

//系统时钟SYSCLK来自PLL输出

RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK)

//切换时钟后等待系统时钟稳定

while(RCC_GetSYSCLKSource()!=0x08)

}

// RCC system reset(for debug purpose) 下面这些都是外设总线上所挂的外部设备时钟的配置

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE)

}

extern void Delay(int cnt) //延时函数

{

int i,j

for (i=0i<cnti++)

{ for (j=0j<1000j++)

{

}

}

}

void GPIO_Configuration(void) //GPIO配置函数

{

//GPIO_DeInit(GPIOA)

GPIO_InitTypeDef GPIO_InitStructure

//RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE)

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4

GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz

GPIO_InitStructure.GPIO_Mode= GPIO_Mode_Out_PP

GPIO_Init(GPIOA,&GPIO_InitStructure)

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_12

GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz

GPIO_InitStructure.GPIO_Mode= GPIO_Mode_Out_PP

GPIO_Init(GPIOB,&GPIO_InitStructure)

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8|GPIO_Pin_9

GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz

GPIO_InitStructure.GPIO_Mode= GPIO_Mode_IPU

GPIO_Init(GPIOB,&GPIO_InitStructure)

}

void EXTI_Config(void)

{

EXTI_InitTypeDef EXTI_InitStructure

// 管脚选择

GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource8)

GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource9)

// 清除 EXTI线路挂起位

EXTI_ClearITPendingBit(EXTI_Line8|EXTI_Line9)

//

EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt

EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling

EXTI_InitStructure.EXTI_Line = EXTI_Line8

EXTI_InitStructure.EXTI_LineCmd = ENABLE

EXTI_Init(&EXTI_InitStructure)

}

void NVIC_Config(void)

{

NVIC_InitTypeDef NVIC_InitStructure

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0)

NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn// 注意名称是“_IRQn”,不是“_IRQChannel”

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0//

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0//

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE

NVIC_Init(&NVIC_InitStructure)

}

int main(void)

{

RCC_Configuration()

GPIO_Configuration()

EXTI_Config()

NVIC_Config()

while(1)

{

GPIO_ResetBits(GPIOB,GPIO_Pin_12)

GPIO_ResetBits(GPIOA,GPIO_Pin_4)

}

}

IT中的函数

void Delay()

void EXTI9_5_IRQHandler(void)

{

if ( EXTI_GetITStatus(EXTI_Line8) != RESET )

{

EXTI_ClearITPendingBit(EXTI_Line8)

GPIO_SetBits(GPIOA,GPIO_Pin_4)

//Delay(100)

while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_8)==0)

}

if ( EXTI_GetITStatus(EXTI_Line9) != RESET )

{

EXTI_ClearITPendingBit(EXTI_Line9)

//Delay(1000)

GPIO_SetBits(GPIOB,GPIO_Pin_12)

while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_9)==0)

}

}

GPIO引脚复用和映射:IO口通过一个复用器连接到内置外设和模块;复用器一次只允许一个外设的复用功能(AF)连接到对应的IO口。这样可以确保共用同一个IO引脚的外设之间不会发生冲突;每个IO引脚都有一个复用器

端口复用为复用功能配置过程:

①GPIO端口时钟使能。

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE)

②复用外设时钟使能。

比如你要将端口PA9,PA10复用为串口,所以要使能孝宏毕串口时钟。

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE)

③端口模式配置为复用功能。 GPIO_Init()函数。

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF//复用功能

④配置GPIOx_AFRL或者GPIOx_AFRH寄存器,将IO连接到所需的AFx。

IO口作为复用功能时查表寻找对应功能

NVIC中断优先级分组

中断管理方法:首先分组,设置抢占优先级,响应优先级

抢占优先级 &响应优先级区别:

1.高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的。

2.抢占优先级相同的中断,高响应优先级不可以打断低响应优先级的中断。

3.抢占优先级相同的中断,当两个中断同时发生的情况下,哪个响应优先级高,哪个先绝冲执行。

4.如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行;

中断分组在程序中只设置一次!!!

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2)

中断优先级设置步骤

系统巧芹运行后先设置中断优先级分组。调用函数:

void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)

整个系统执行过程中,只设置一次中断分组。

②针对每个中断,设置对应的抢占优先级和响应优先级:

void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)

③ 如果需要挂起/解挂,查看中断当前激活状态,分别调用相关函数即可。

外部中断

STM32F4的每个IO都可以作为外部中断输入。

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

中断服务函数列表:

EXTI0_IRQHandler

EXTI1_IRQHandler

EXTI2_IRQHandler

EXTI3_IRQHandler

EXTI4_IRQHandler

EXTI9_5_IRQHandler

EXTI15_10_IRQHandler

外部中断常用库函数

①void SYSCFG_EXTILineConfig(uint8_t EXTI_PortSourceGPIOx, uint8_t EXTI_PinSourcex)

//设置IO口与中断线的映射关系

②void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct)

//初始化中断线:触发方式等

③ITStatus EXTI_GetITStatus(uint32_t EXTI_Line)

//判断中断线中断状态,是否发生

④void EXTI_ClearITPendingBit(uint32_t EXTI_Line)

//清除中断线上的中断标志位

⑤RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE)//使能SYSCFG时钟

//这个函数非常重要,在使用外部中断的时候一定要先使能SYSCFG时钟

外部中断的一般配置步骤:

1使能SYSCFG时钟: RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE)

2初始化IO口为输入 GPIO_Init()

3设置IO口与中断线的映射关系 void SYSCFG_EXTILineConfig()

4初始化线上中断,设置触发条件等 EXTI_Init()

5配置中断分组(NVIC),并使能中断 NVIC_Init()

6编写中断服务函数。EXTIx_IRQHandler()

7清除中断标志位EXTI_ClearITPendingBit()

利用外部中断,我写了一个按键控制流水灯速度的程序:

#include"delay.h"

#include"led.h"

#include"key.h"

#include"exit.h"

#include"sys.h"

#include"fmq.h"

void EXITX_Init(void)

{

NVIC_InitTypeDef NVIC_InitStructure

EXTI_InitTypeDef EXTI_InitStructure

RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG ,ENABLE)

KEY_Init()

SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE,EXTI_PinSource2)

SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE,EXTI_PinSource3)

EXTI_InitStructure.EXTI_Line=EXTI_Line2|EXTI_Line3

EXTI_InitStructure.EXTI_LineCmd=ENABLE

EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt

EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling

EXTI_Init(&EXTI_InitStructure)

NVIC_InitStructure.NVIC_IRQChannel=EXTI2_IRQn

NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1

NVIC_InitStructure.NVIC_IRQChannelSubPriority=1

NVIC_Init(&NVIC_InitStructure)

NVIC_InitStructure.NVIC_IRQChannel=EXTI3_IRQn

NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2

NVIC_InitStructure.NVIC_IRQChannelSubPriority=1

NVIC_Init(&NVIC_InitStructure)

}

void EXTI2_IRQHandler(void)

{

delay_ms(10)

if(KEY0==0)

{

while(1)

{

GPIO_SetBits(GPIOF,GPIO_Pin_9)

delay_ms(500)

GPIO_ResetBits(GPIOF,GPIO_Pin_9)

delay_ms(500)

GPIO_SetBits(GPIOF,GPIO_Pin_10)

delay_ms(500)

GPIO_ResetBits(GPIOF,GPIO_Pin_10)

delay_ms(500)

}

}

EXTI_ClearITPendingBit(EXTI_Line2)

}

void EXTI3_IRQHandler(void)

{

delay_ms(10)

if(KEY1==0)

{

while(1)

{

GPIO_SetBits(GPIOF,GPIO_Pin_9)

delay_ms(20)

GPIO_ResetBits(GPIOF,GPIO_Pin_9)

delay_ms(20)

GPIO_SetBits(GPIOF,GPIO_Pin_10)

delay_ms(20)

GPIO_ResetBits(GPIOF,GPIO_Pin_10)

delay_ms(20)

}

}

EXTI_ClearITPendingBit(EXTI_Line2)

}


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12267362.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-24
下一篇 2023-05-24

发表评论

登录后才能评论

评论列表(0条)

保存