stm32 中断

中断编程

在配置每个中断的时候一般有三个编程要点:

1、使能外设某个中断,这个具体由每个外设的相关中断使能控制。比如串口发送完成中断接收完成中断,这两个中断都由串口控制寄存器相关中断使能位控制。
2、初始化NVIC_IntTypedef结构体,配置中断优先级分组,设置抢断优先级和子优先级,使能中断请求。NVIC_IntTypeDef结构体在库文件misc.h中定义。

typedef struct {
 uint8_t NVIC_IRQChannel; // 中断源
 uint8_t NVIC_IRQChannelPreemptionPriority; // 抢占优先级
 uint8_t NVIC_IRQChannelSubPriority; // 子优先级
 FunctionalState NVIC_IRQChannelCmd; // 中断使能或者失能
 } NVIC_InitTypeDef;

EXIT初始化结构体

typedef struct{
    uint32_t EXTI_Line;//中断/事件线
    EXTIMode_TypeDef EXTI_Mode;//EXTI模式
    EXTITrigger_TypeDef EXTI_Trigger;//触发类型
    FunctionalState EXTI_LineCmd;//EXTI使能
}EXTI_InitTypeDef;

编程要点
1)初始化用来产生中断的GPIO;
2)初始化EXTI;
3)配置NVIC;
4)编写中断服务函数;

引脚定义

 #define KEY1_INT_GPIO_PORT GPIOA
 #define KEY1_INT_GPIO_CLK (RCC_APB2Periph_GPIOA\
 RCC_APB2Periph_AFIO)
 #define KEY1_INT_GPIO_PIN GPIO_Pin_0
 #define KEY1_INT_EXTI_PORTSOURCE GPIO_PortSourceGPIOA
 #define KEY1_INT_EXTI_PINSOURCE GPIO_PinSource0
 #define KEY1_INT_EXTI_LINE EXTI_Line0
 #define KEY1_INT_EXTI_IRQ EXTI0_IRQn

 #define KEY1_IRQHandler EXTI0_IRQHandler


 #define KEY2_INT_GPIO_PORT GPIOC
 #define KEY2_INT_GPIO_CLK (RCC_APB2Periph_GPIOC\
 RCC_APB2Periph_AFIO)
 #define KEY2_INT_GPIO_PIN GPIO_Pin_13
 #define KEY2_INT_EXTI_PORTSOURCE GPIO_PortSourceGPIOC
 #define KEY2_INT_EXTI_PINSOURCE GPIO_PinSource13
 #define KEY2_INT_EXTI_LINE EXTI_Line13
 #define KEY2_INT_EXTI_IRQ EXTI15_10_IRQn

在上面的宏定义中,我们除了开GPIO的端口时钟外,我们还打开了AFIO的时钟,这是因为等下配置EXTI信号源的时候需要用到AFIO中断控制寄存器AFIO_EXTICRx,
具体见具体见《 STM32F10X-中文参考手册》 8.4 章节 AFIO 寄存器描述。

嵌套向量中断控制寄存器NVIC配置

static void NVIC_Configuration(void)
{
 NVIC_InitTypeDef NVIC_InitStructure;

 /* 配置 NVIC 为优先级组 1 */
 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

 /* 配置中断源:按键 1 */
 NVIC_InitStructure.NVIC_IRQChannel = KEY1_INT_EXTI_IRQ;
 /* 配置抢占优先级: 1 */
 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
 /* 配置子优先级: 1 */
 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
 /* 使能中断通道 */
 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
 NVIC_Init(&NVIC_InitStructure);

 /* 配置中断源:按键 2,其他使用上面相关配置 */
 NVIC_InitStructure.NVIC_IRQChannel = KEY2_INT_EXTI_IRQ;
 NVIC_Init(&NVIC_InitStructure);
 }

EXTI中断配置

 void EXTI_Key_Config(void)
 {
 GPIO_InitTypeDef GPIO_InitStructure;
 EXTI_InitTypeDef EXTI_InitStructure;

/*开启按键 GPIO 口的时钟*/
 RCC_APB2PeriphClockCmd(KEY1_INT_GPIO_CLK,ENABLE);

 /* 配置 NVIC 中断*/
 NVIC_Configuration();

 /*--------------------------KEY1 配置---------------------*/
 /* 选择按键用到的 GPIO */
 GPIO_InitStructure.GPIO_Pin = KEY1_INT_GPIO_PIN;
 /* 配置为浮空输入 */
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
 GPIO_Init(KEY1_INT_GPIO_PORT, &GPIO_InitStructure);

 /* 选择 EXTI 的信号源 */
 GPIO_EXTILineConfig(KEY1_INT_EXTI_PORTSOURCE, \
 KEY1_INT_EXTI_PINSOURCE);
 EXTI_InitStructure.EXTI_Line = KEY1_INT_EXTI_LINE;

 /* EXTI 为中断模式 */ 
 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
 /* 上升沿中断 */
 EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
 /* 使能中断 */
 EXTI_InitStructure.EXTI_LineCmd = ENABLE;
 EXTI_Init(&EXTI_InitStructure);

 /*--------------------------KEY2 配置------------------*/
 /* 选择按键用到的 GPIO */
 GPIO_InitStructure.GPIO_Pin = KEY2_INT_GPIO_PIN;
 /* 配置为浮空输入 */
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
 GPIO_Init(KEY2_INT_GPIO_PORT, &GPIO_InitStructure);

 /* 选择 EXTI 的信号源 */
 GPIO_EXTILineConfig(KEY2_INT_EXTI_PORTSOURCE, \
 KEY2_INT_EXTI_PINSOURCE);
 EXTI_InitStructure.EXTI_Line = KEY2_INT_EXTI_LINE;

 /* EXTI 为中断模式 */
 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
 /* 下降沿中断 */
 EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
 /* 使能中断 */
 EXTI_InitStructure.EXTI_LineCmd = ENABLE;
 EXTI_Init(&EXTI_InitStructure);
 }

EXTI中断服务函数

void KEY1_IRQHandler(void)
 {
 //确保是否产生了 EXTI Line 中断
 if (EXTI_GetITStatus(KEY1_INT_EXTI_LINE) != RESET) {
 // LED1 取反
 LED1_TOGGLE;
 //清除中断标志位
 EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE);
 }
 }

 void KEY2_IRQHandler(void)
 {
//确保是否产生了 EXTI Line 中断
 if (EXTI_GetITStatus(KEY2_INT_EXTI_LINE) != RESET) {
 // LED2 取反
 LED2_TOGGLE;
 //清除中断标志位
 EXTI_ClearITPendingBit(KEY2_INT_EXTI_LINE);
 }
 }

EXTI_GetITStatus 函数用来获取 EXTI 的中断标志位状态,如果 EXTI 线有中断发生函数返回“SET”否则返回“RESET”。实际上, EXTI_GetITStatus 函数是通过读取EXTI_PR 寄存器值来判断 EXTI 线状态的。按键 1 的中断服务函数我们让 LED1 翻转其状态,按键 2 的中断服务函数我们让 LED2翻转其状态。执行任务后需要调用 EXTI_ClearITPendingBit 函数清除 EXTI 线的中断标志位。

主函数

 int main(void)
 {
 /* LED 端口初始化 */
 LED_GPIO_Config();

 /* 初始化 EXTI 中断,按下按键会触发中断,
 * 触发中断会进入 stm32f4xx_it.c 文件中的函数
 * KEY1_IRQHandler 和 KEY2_IRQHandler,处理中断,反转 LED 灯。
 */
 EXTI_Key_Config();

 /* 等待中断,由于使用中断方式, CPU 不用轮询按键 */
 while (1) {
  }
 }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值