STM32中断系统

学习来源:哔哩哔哩大学   UP主:江科大自化协

一. 中断系统 

(1)中断 :在主程序运行过程中,出现特定的中断触发条件,使得CPU暂停当前正在运行的程序,而去处理中断程序,完成后,又返回原来被暂停的位置继续工作

(2)中断优先 :当有多个中断开始时,CPU会根据事情的轻重响应更加紧急的中断

中断嵌套 :一个中断正常进行,又来一个更高级的中断,会先去做刚来的高级的中断,然后依次返回

(3)一般中断函数都是在一个子函数里的,这个函数不需要我们调用,当中断来临时,自动由硬件调用这个函数

  

二. STM32的中断

(1)68个可屏蔽中断通道,包含EXTI,TIM,ADC,USART,SPI,IIC,RTC等多个外设

(2) 使用NVIC统一管理中断,每个中断有16个可编程的优先等级,可对优先级分组

三 .  EXTI简介

(1)EXTI外部中断

(2)EXTI可监测指定GPIO口的电平信号,当GPIO口的电平变化时,EXTI就立刻向NVIC发出中断申请,经过NVIC裁决后,让CPU执行中断程序

(3)触发方式 :上升沿(低变高),下降沿(高变低),双边沿(前两个都可以),软件出发(写代码出发,和GPIO没关系)

(4)GPIO :支持所有GPIO口,但是相同的Pin不能触发中断

(5)通道数 :16个Pin,(外加PVD输出,RTC闹钟,USB唤醒,以太网唤醒)

(6)触发响应方式: 中断响应,事件响应 

 所以PA0 PB0 PC0只能有一个触发,不能同时触发(因为数据选择器只能选择一根线)

四. AFIO复用IO口

在STM32中,AFIO口主要完成两个任务:复用功能引脚重映射,中断引脚选择


 外部中断(EXTI)基本结构 

 

 五.代码部分

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "coder.h"
 
int16_t Num;//给了Num赋值
 
int main(void)
{
    //OLED ENCODER初始化,初始化完才能用
    OLED_Init();
    coder_Init();
    
    OLED_ShowString(1, 1, "Num:");
    
    while (1)
    {
        Num += Encoder_Get();
        OLED_ShowSignedNum(1, 5, Num, 5);
    }
}
code.c

#include "stm32f10x.h"     // Device header
 

int16_t coder_Count;//定义一个带符号变量
 
void coder_Init(void)
{
    //两个中断的初始化代码,初始化时钟,GPIOB,AFIO
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    
    //AFIO的部分
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource1);
    
    //指定的中断线为EXTI_LINE1和EXTI_LINE0
    EXTI_InitTypeDef EXTI_InitStructure;
    EXTI_InitStructure.EXTI_Line = EXTI_Line0 | EXTI_Line1;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
    EXTI_Init(&EXTI_InitStructure);
    
    //中断分组
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    
    //中断优先级,对两个通道分别设置优先级
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_Init(&NVIC_InitStructure);
 
    NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
    NVIC_Init(&NVIC_InitStructure);
}
 
//把变量返回回去,返回变化值,所以返回count(这里是用了一个技巧,间接返回了count(把值付给temp让temp回去))
int16_t coder_Get(void)
{
    int16_t Temp;
    Temp = coder_Count;
    coder_Count = 0;
    return Temp;
}
 
//接下来是中断的中断函数
void EXTI0_IRQHandler(void)
{
    //检查一下中断标志位
    if (EXTI_GetITStatus(EXTI_Line0) == SET)
    {
        //判断一下另一个引脚的电平
        if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)
        {
            //如果是就反转
            coder_Count --;
        }
        //清除中断标志位
        EXTI_ClearITPendingBit(EXTI_Line0);
    }
}
//下面这个也是一样的,只是换了线,如果是9——15就把两个放一起,用一个中断就行
void EXTI1_IRQHandler(void)
{
    if (EXTI_GetITStatus(EXTI_Line1) == SET)
    {
        if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0)
        {
            
            coder_Count ++;//正转
        }
        EXTI_ClearITPendingBit(EXTI_Line1);
    }
}
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值