比如说按键中断
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)
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)