STC32G12K128-旋轉編碼器-軟件去抖
- 簡介
- 代碼
簡介
EC11旋轉編碼器是一種可以連續旋轉的器件A,B,C為旋轉編碼引腳,帶按鍵的有D,E引腳。引腳功能:
- A:編碼器A相;
- B:編碼器B相;
- C:公共端-一般接到GND;
- D/E:按鍵,按下時D,E導通,和普通按鍵功能相似;
當旋轉編碼器時:A,B兩個端子的開關相繼導通。 內部機械結構的設計保證了:順時針旋轉時A超前于B的相位。逆時針旋轉時B超前于A的相位。
解碼原理:
- A相接單片機外部中斷引腳,設為下降沿觸發;
- B相接單片機GPIO引腳,設置為輸入引腳;
- 旋轉編碼器時A相下降沿觸發中斷,中斷服務程序里延時50us判斷A相是否為電平(去抖操作)
- A相下降去抖后延時100us判斷B相電平,低電平是順時針旋轉,高電平是逆時針旋轉;
- 兩個延時時間根據實際情況耐心微調,可以達到很好的去抖效果,本例實測超慢速度~超快速度,均能連續正確解碼旋轉方向值;
代碼
drv_encoder.h
#ifndef __DRV_ENCODER_H__
#define __DRV_ENCODER_H__enum {E_ENCODER_N=0,E_ENCODER_L=1,E_ENCODER_R
};void drv_encoder_init(void);uint8_t drv_encoder_value(void);void drv_encoder_notify(void);#endif
drv_encoder.c
#include "STC32G_Timer.h"
#include "STC32G_GPIO.h"
#include "STC32G_NVIC.h"
#include "STC32G_Exti.h"
#include "STC32G_Delay.h"#include "app_config.h"
#include "drv_encoder.h"
#include "debug.h"#if TCFG_DRV_ENCODER_SUPPORT#define D_ENCIO_A P33 // 編碼器A相
#define D_ENCIO_B P34 // 編碼器B相
static uint8_t encoder_value = E_ENCODER_N;void delay_us(unsigned int us)
{unsigned char data i;while(--us) {_nop_();_nop_();i = 3;while (--i);}
}void drv_encoder_init(void)
{EXTI_InitTypeDef Exti_InitStructure;P3_SPEED_LOW(GPIO_Pin_3|GPIO_Pin_4);// P3_SPEED_HIGH(GPIO_Pin_3|GPIO_Pin_4);P3_DRIVE_MEDIUM(GPIO_Pin_3|GPIO_Pin_4);// P3_DRIVE_HIGH(GPIO_Pin_3|GPIO_Pin_4);// P3_PULL_UP_ENABLE(GPIO_Pin_3|GPIO_Pin_4);P3_PULL_UP_DISABLE(GPIO_Pin_3|GPIO_Pin_4);// P3_MODE_IO_PU(GPIO_Pin_3|GPIO_Pin_4);P3_MODE_IN_HIZ(GPIO_Pin_3|GPIO_Pin_4);P3_DIGIT_IN_ENABLE(GPIO_Pin_3|GPIO_Pin_4);Exti_InitStructure.EXTI_Mode = EXT_MODE_Fall;//中斷模式, EXT_MODE_RiseFall,EXT_MODE_FallExt_Inilize(EXT_INT1, &Exti_InitStructure); //初始化NVIC_INT1_Init(ENABLE,Priority_1); //中斷使能, ENABLE/DISABLE; 優先級(低到高) Priority_0,Priority_1,Priority_2,Priority_3}/*** @brief 旋轉編碼器 通知* @param 無* @note * @return 無
*/
void drv_encoder_notify(void)
{encoder_value = E_ENCODER_N;
}/*** @brief 獲取旋轉編碼器值* @param 無* @note 同時設置編碼器值為none* @return 0:無操作,1:左旋轉(逆時針),2:右旋轉(順時針)
*/
uint8_t drv_encoder_value(void)
{uint8_t enc_value = encoder_value; drv_encoder_notify();return enc_value;
}/*** @brief 編碼器A相中斷處理函數* @note 下降沿觸發* @return 無
*/
void INT1_ISR_Handler (void) interrupt INT1_VECTOR //進中斷時已經清除標志
{// TODO: 旋轉編碼器去抖,A相中斷下降沿觸發,延時50us判斷A相是否為低電平,為低延時100us判斷B相電平 0=右旋轉(順時針),1=左旋轉(逆時針)D_ENCIO_A = 1;delay_us(50);if (0 == D_ENCIO_A) {D_ENCIO_B = 1;delay_us(100);if (D_ENCIO_B == 0) {encoder_value = E_ENCODER_R;} else {encoder_value = E_ENCODER_L;}}
}#endif //TCFG_DRV_ENCODER_SUPPORT
main.c
#include "drv_encoder.h"void main(void)
{uint8_t enc_value;// 系統初始化// ......// 旋轉編碼器drv_encoder_init();enc_value = drv_encoder_value();if (E_ENCODER_N != enc_value) { if (E_ENCODER_L == enc_value) {log_d("E_ENCODER_L\n");} else if (E_ENCODER_R == enc_value) {log_d("E_ENCODER_R\n");}}
}