STM32旋转编码器计次

你的糖来啦
2024-06-19 / 0 评论 / 19 阅读 / 正在检测是否收录...

使用外部中断方式在oled屏幕上显示计次

步骤:

-打开GPIO、AFIO外设并配置
-配置EXTI、NVIC(EXTI、NVIC这些模块已经自动准备就绪,无需额外的启动步骤)

-配置中断函数

不断获取被中断函数操作的变量,把变量信息显示在oled屏幕上

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Encoder.h"
int16_t Count;
int main(void)
{
    /*模块初始化*/
    OLED_Init();        //OLED初始化
    Encoder_Init();        //旋转编码器初始化
    
    /*OLED显示*/
    OLED_ShowString(1, 1, "Count:");    //1行3列显示字符串HelloWorld!
    
    
    while (1)
    {
        Count += Count_Get();
        OLED_ShowSignedNum(2,1,Count,5);
    }
}

配置外部中断 Encoder.c

#include "stm32f10x.h"                  // Device header

int16_t Count_num;
void Encoder_Init(void)
{
    //开启GPIO、AFIO的外设
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2ENR_AFIOEN,ENABLE);
    
    GPIO_InitTypeDef GPIO_InitStrcuture;
    //上拉输入方式
    GPIO_InitStrcuture.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStrcuture.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
    GPIO_Init(GPIOB, &GPIO_InitStrcuture);
    
    //配置AFIO 不同GPIO组也不能使用相同的GPIO_PinSourceX
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource0);
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource1);
    
    //配置EXTI
    EXTI_InitTypeDef EXTI_InitStructuer;
    EXTI_InitStructuer.EXTI_Line = EXTI_Line0 | EXTI_Line1;
    EXTI_InitStructuer.EXTI_LineCmd = ENABLE;
    //这里设置的是外部中断
    EXTI_InitStructuer.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructuer.EXTI_Trigger = EXTI_Trigger_Falling;
    EXTI_Init(&EXTI_InitStructuer);
    
    //配置NVIC
    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);
    
}

int16_t Count_Get(void)
{
    int16_t temp = Count_num;
    Count_num = 0;
    return temp;
}

void EXTI0_IRQHandler(void)
{
    if(EXTI_GetITStatus(EXTI_Line0) == SET)
    {
        if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0) == 0)
        {
            while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0) == 0);
            if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)        //PB0的下降沿触发中断,此时检测另一相PB1的电平,目的是判断旋转方向
            {
                Count_num --;                    //此方向定义为反转,计数变量自减
            }
        }
        EXTI_ClearITPendingBit(EXTI_Line0);
    }
}

void EXTI1_IRQHandler(void)
{
    if(EXTI_GetITStatus(EXTI_Line1) == SET)
    {
        if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == 0)
        {
            while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == 0);
            if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0)        //PB0的下降沿触发中断,此时检测另一相PB1的电平,目的是判断旋转方向
            {
                Count_num ++;                    //此方向定义为反转,计数变量自减
            }
        }
        EXTI_ClearITPendingBit(EXTI_Line1);
    }
}

0

评论 (0)

取消