【EXTI】旋转编码器

编写外部中断EXTI代码:以【旋转编码器计次】为例
配置外部中断时从左至右参考该图流程
1、完成驱动文件导入操作和编写驱动程序基本代码(参考之前文章)
2、在Encoder.c中初始化函数Encoder_Init
void Encoder_Init(void)
{
/*第一步:配置RCC,把涉及到的外设时钟打开*/
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//打开GPIOB的时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//打开AFIO的时钟(AFIO也是APB2的外设)
/*还有EXTI和NVIC两个外设的时钟需要打开,但因为这两个外设的时钟一直都是打开的,所以不需要配置开启*/
/*第二步:配置GPIO,选择端口各种模式*/
    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);//初始化GPIOB
/*第三步:配置AFIO,选择使用的中断引脚*/
/*ST公司并未分配专门的库函数文件给AFIO,AFIO的库函数存放在GPIO中*/
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource0);//配置AFIO的数据选择器,选中需要的中断引脚
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource1);//配置AFIO的数据选择器,选中需要的中断引脚
/*第四步:配置EXTI,选择中断配置各种模式*/
    EXTI_InitTypeDef EXTI_InitStructure;
    EXTI_InitStructure.EXTI_Line = EXTI_Line0 | EXTI_Line1;//指定要配置的中断线
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//指定外部中断线的模式
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//指定触发信号的有效边沿
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;//指定选择的中断线的新状态
    EXTI_Init(&EXTI_InitStructure);//初始化EXTI
/*第五步:配置NVIC,选择中断配置各种模式*/
/*NVIC是内核外设,库函数被ST公司分配到杂项mics.h文件中*/
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//在配置中断之前先指定NVIC中断分组
//有两个中断通道,对其分别设置优先级
    NVIC_InitTypeDef NVIC_InitStructure;//定义结构体变量(通道可以重复使用)
//通道1
    NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//指定中断通道来开启或关闭
                                                        //IRQn_Type的定义在stm32f10x.h文件中
                                                        //选择使用芯片的中断通道列表(STM32F10X_MD)
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//指定中断通道是使能还是失能
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//指定所选通道的抢占优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//指定所选通道的响应优先级
    NVIC_Init(&NVIC_InitStructure);//初始化NVIC
//通道2
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;//指定中断通道来开启或关闭
                                                        //IRQn_Type的定义在stm32f10x.h文件中
                                                        //选择使用芯片的中断通道列表(STM32F10X_MD)
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//指定中断通道是使能还是失能
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//指定所选通道的抢占优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;//指定所选通道的响应优先级(较通道1响应优先级低)
    NVIC_Init(&NVIC_InitStructure);//初始化NVIC    
}
3、在Encoder.c中编写中断服务程序函数EXTI0_IRQHandler、EXTI1_IRQHandler
在STM32中,中断函数的名字都是固定的,每个中断通道都对应一个中断函数(名字参考启动文件startup_stm32f10x_md.s)
文件中以IRQHandler结尾的字符串就是中断函数的名字
中断函数都是无参无返回值的
void EXTI0_IRQHandler(void)
{
    if(EXTI_GetITStatus(EXTI_Line0) == SET)//中断标志位判断,确定由哪个中断源触发
                                                                   //看看EXTI0的中断标志位是不是1
    {
        if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)
        {
            CountSensor_Count --;
        }
        EXTI_ClearITPendingBit(EXTI_Line0);//中断程序结束后,清除中断标志位
    }
}
void EXTI1_IRQHandler(void)
{
    if(EXTI_GetITStatus(EXTI_Line1) == SET)//中断标志位判断,确定由哪个中断源触发
                                              看看EXTI1的中断标志位是不是1
    {
        if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0)
        {
            CountSensor_Count ++;
        }
        EXTI_ClearITPendingBit(EXTI_Line1);//中断程序结束后,清除中断标志位
    }
}
//如果用的是9~5或15~10的多个中断通道,只能用一个中断服务程序函数,那么把多个if并列放在一个函数里就行
4、在Encoder.c中编写旋转变量返回函数Encoder_Get
//旋转编码器需要正反转,先定义一个带符号的全局变量int16_t Encoder_Count;
int16_t Encoder_Get(void)
{
    int16_t Temp;//设置一个局部变量来表示Count的变化程度
    Temp = Encoder_Count;
    Encoder_Count = 0;
    return Temp;
}
5、在Encoder.h中声明初始化函数Encoder_Init和返回端口值获取函数Encoder_Get
void Encoder_Init(void);
uint16_t Encoder_Get(void);
//中断函数不用声明,因为中断函数不需要调用,会自动执行
6、在主程序main.c中#include "Encoder.h"
#include "Encoder.h"
7、在主循环之前先初始化外部中断

8、在主循环中编写程序主体

int16_t Num;

int main(void)
{
    Encoder_Init();
    
    OLED_Init();
    OLED_ShowString(1,1,"Num:");
    while(1)
    {
        Num += Encoder_Get();
        OLED_ShowSignedNum(1,5,Num,5);
    }
}
实现功能:OLED显示屏默认显示Num:+00000,向左转数字减小,向右转数字增加

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值