[stm32]用定时器编码模式解码EC11旋转编码器

1.客官,要不先康康内脏

  • 左调右调没调出来,那就拆开看看,到底吃了几碗粉
    在这里插入图片描述
  • 再做个搭桥手术吧
    在这里插入图片描述

2.怎么驱动呢

先看看EC11旋钮旋转时的波形吧
在这里插入图片描述

1. 首先想到的是用IO中断咯

在中断中判断哪路IO先来就可以确定是正旋还是反旋咯

2. stm32不是有定时器编码模式么,正好可以用来解码EC11

直接上代码吧!

//定义一下IO口
#define KEY_Port    GPIOA
#define KEY_A       GPIO_PIN_0
#define KEY_B       GPIO_PIN_1
#define KEY_C       GPIO_PIN_3

typedef struct encode_t_{
    uint8_t Key_num;    //0:left 1:right  2:key_C
    uint8_t Key_val;    //[AB]:0~255  [C]1:pressed
}Encode_TypeDef;
/**
  *************************************************************************************************
  * @file    : slim_encode.c
  * @author  : slim 
  * @version : V1.0.0
  * @date    : 2021.04.10
  * @brief   : encode driver
  *************************************************************************************************
  */
#include "slim_encode.h"
#include "slim_event_task.h"
#include "slim_drv.h"
#include "main.h"

uint8_t Rotary = 0;

TIM_HandleTypeDef htim2;
Encode_TypeDef Encode;

extern rt_event_t slim_event;
/*===============================================================================================*
*					
*===============================================================================================*/
void slim_encode_init(void){
    GPIO_InitTypeDef GPIO_InitStruct;
    TIM_Encoder_InitTypeDef sConfig = {0};
    TIM_MasterConfigTypeDef sMasterConfig = {0};
	
	__HAL_RCC_GPIOA_CLK_ENABLE();
    
    GPIO_InitStruct.Pin = KEY_C;
	GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
	GPIO_InitStruct.Pull = GPIO_PULLDOWN;
	HAL_GPIO_Init(KEY_Port, &GPIO_InitStruct);

	HAL_NVIC_SetPriority(EXTI2_3_IRQn, 0, 3);
    HAL_NVIC_EnableIRQ(EXTI2_3_IRQn);

    htim2.Instance = TIM2;
    htim2.Init.Prescaler = 3;
    htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim2.Init.Period = 20;
    htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
    sConfig.EncoderMode = TIM_ENCODERMODE_TI12;
    sConfig.IC1Polarity = TIM_ICPOLARITY_RISING;
    sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
    sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
    sConfig.IC1Filter = 1;
    sConfig.IC2Polarity = TIM_ICPOLARITY_FALLING; //TIM_ICPOLARITY_RISING
    sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
    sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
    sConfig.IC2Filter = 1;
    if (HAL_TIM_Encoder_Init(&htim2, &sConfig) != HAL_OK){
        Error_Handler();
    }
    sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
    sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
    if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK){
        Error_Handler();
    }
    
    HAL_TIM_Encoder_Start(&htim2,TIM_CHANNEL_ALL);
    HAL_TIM_Encoder_Start_IT(&htim2,TIM_CHANNEL_ALL);
}
//重构虚函数
void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef* htim_encoder){
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    if(htim_encoder->Instance==TIM2){
        /* Peripheral clock enable */
        __HAL_RCC_TIM2_CLK_ENABLE();

        __HAL_RCC_GPIOA_CLK_ENABLE();

        // PA0 ------> TIM2_CH1
        // PA1 ------> TIM2_CH2
        GPIO_InitStruct.Pin = KEY_A | KEY_B;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_PULLUP;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
        GPIO_InitStruct.Alternate = GPIO_AF2_TIM2;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

        HAL_NVIC_SetPriority(TIM2_IRQn, 1, 3);
        HAL_NVIC_EnableIRQ(TIM2_IRQn);
    }
}

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim){
    if(htim->Instance->CR1==0x01){//顺时针
        Encode.Key_num = 'L';
        Rotary++;
    }
    if(htim->Instance->CR1==0x11){//逆时针
        Encode.Key_num = 'R';
        Rotary++;
    }
//    rt_kprintf(">> %d <<\n",Rotary);
    Encode.Key_val = Rotary;
    rt_event_send(slim_event, KEY_FALG);
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
    if(KEY_C == GPIO_Pin){	
//        rt_kprintf("key-C\n");
        Encode.Key_num = 'C';
        Encode.Key_val = 1;
        rt_event_send(slim_event, KEY_FALG);
	}
}
//key处理线程
static void Event_thread_entry(void *arg){
    rt_err_t ret = RT_EOK;
    rt_uint32_t recved = 0;
    char tmp[UART_RCV_LEN] = {0};
    while(1){
        rt_event_recv(slim_event, 0xFFFFFFFF, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER, &recved);
        if(KEY_FALG == recved){
            rt_kprintf("key event\n");
            sprintf(tmp, "{\"key\":\"%c\",\"Kval\":%d}\n", Encode.Key_num, Encode.Key_val);   //格式: [key:value@]
            Rotary = 0;
            ret = rt_mq_send(uart_mq, tmp, sizeof(tmp));
            if(RT_EOK != ret){
                rt_kprintf("[tMQ errNo]:%x\n",ret);
            }
        }
        rt_thread_delay(200);
    }
}

3.效果挺好

在这里插入图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值