中断

中断程序在一个子函数中,不需要手动调用,当中断来临时自动调用

几乎所有的外设(EXIT  TIM  ADC USART SPI  I2C RTC等)都能申请中断,使用NVIC内核外设【都不用开启时钟】(叫号系统)统一管理

中断优先级16个

 一个外设可能占用多个中断通道(n)

抢占优先级:可抢占,嵌套

响应优先级:插队到第二个,等第一处理完后

优先级,值越小越高。若是优先级完全一样,则按照中断向量表里面的排序确认优先级

 

 PA0与PB0 或 PB1与PA1不能同时使用

中断响应时到CPU,事件响应时到其他外设(ADC.DMA等)

EXTI与NVIC默认时钟就是打开的 

AFIO复用IO口

 

 外部中断处理那些转瞬即逝的事件,比如红外。 按键的话不推荐(因为不好处理抖动),可以用主循环读取,或者定时器中断读取,

旋转编码器,测位置、速度或旋转方向,

红外对射式的通过光栅格得到高低电平,方波的个数就是转过的角度,方波的频率就是转速,使用外部中断捕获方波的边缘就可以判断位置和速度,但是只有一路输出,就不能判断正转还是反转

旋转编码器,通过金属触点和栅格来产生高低电平,再通过两路的输出波形(相位相差90度的正交波形)来判断正反转    【适合速度慢的场合】

高速的可用霍尔传感器

代码实现

 先开启AFIO与GPIO的时钟,EXTI与NVIC默认时钟就是打开的 

初始化GPIO

复制代码
void CountSensor_Init(void)
{
    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_14;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14); //实际调用AFIO的函数来处理,将GPIOB的14号引脚设置成中断源,进入EXIT处理电路
    
    EXTI_InitTypeDef EXTI_InitStructure;
    EXTI_InitStructure.EXTI_Line = EXTI_Line14; //对应14号引脚
    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 = EXTI15_10_IRQn;  //可以在stm32f10x.h中找到 STM32F10X_MD去查看可用的中断通道
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;    //问:有5-9 10-15 ,0-4的话可以直接EXTI0_IRQn (启动文件中可以查看相关的函数)
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  //抢占优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;  //响应优先级
    NVIC_Init(&NVIC_InitStructure);
}

复制代码

EXTI库函数解析

void EXTI_DeInit(void);
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);
void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct);
void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line);  //软件触发
FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line);
void EXTI_ClearFlag(uint32_t EXTI_Line);//建议主程序中用上面两个,中断程序中用下面两个 
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);
void EXTI_ClearITPendingBit(uint32_t EXTI_Line);
复制代码
void EXTI15_10_IRQHandler(void)  //每个中断通道对应一个中断函数
{
    if (EXTI_GetITStatus(EXTI_Line14) == SET)  //判断是不是我们需要的中断(可以进来很多个中断到这个函数)
    {
        /*如果出现数据乱跳的现象,可再次判断引脚电平,以避免抖动*/
        if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14) == 0)
        {
            CountSensor_Count ++;
        }
        EXTI_ClearITPendingBit(EXTI_Line14);  //每次中断程序处理完毕就清除中断标志位
    }
}
复制代码

使用  EXTI15_10_IRQHandler  是因为之前用的中断线14在这个区间内

pre-emption priority 抢占优先级  subpriority响应优先级

旋转编码器正负判断

 上A下B,  B下降沿触发进入中断,此时判断A低电平就是正转; A下降沿触发进入中断,判断B是低电平就是反转,因为芯片有处理的延迟,可以通过增加(冗余)高低电平判断来达到这个延迟。

 

posted @   磕伴  阅读(28)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决
· 提示词工程——AI应用必不可少的技术
点击右上角即可分享
微信分享提示