最近用ESP32做一个小玩意儿,需要使用EC11旋转编码器做目录导航操控,单独针对EC11旋转编码器(带按键)做了个CLASS封装,通过函数回调方式更新状态,可以实现按键产单击、双击、连击;编码器正反转的实时更新回调。操作丝滑,简单好用,现将相关代码分享给大家。
以下是电气连接说明:
/*
*EC11电气连接说明:
*编码器公共端、铵键K1端以及外壳接地(GND);
*IoPin_K------------------K2;
*IoPin_A------------------A;
*IoPin_B------------------B.
*
* K1 K2
* ---|---------|---
*| |____ |
*| | |
*| | |
*| | |
* ---|----|----|---
* A _|_ B
* GND
*
*/
以下是CLASS对象封装代码:文件名保存为EC11.h
#ifndef _STRUCT_EC11_OBJECT_H_
#define _STRUCT_EC11_OBJECT_H_
#include <esp32-hal-gpio.h>
class EC11OBJECT{
private:
uint8_t IoPin_K=255;
uint8_t IoPin_A=255;
uint8_t IoPin_B=255;
bool Old_Ec11_K=true;
bool Old_Ec11_A=true;
bool Old_Ec11_B=true;
int ClickCount=0;
int DoubleClickIntervalTime=250;
int releaseLastTime=0;
typedef void(*EC11Function)(bool,int);
EC11Function EC11_Object_CallBack_fun_fp=nullptr;
void Init(void){
pinMode(IoPin_K,INPUT_PULLUP);
pinMode(IoPin_A,INPUT_PULLUP);
pinMode(IoPin_B,INPUT_PULLUP);
}
protected:
void UpdateStatus(bool Mode,int Data){
if(EC11_Object_CallBack_fun_fp!=nullptr){
EC11_Object_CallBack_fun_fp(Mode,Data);
}else{
Serial.printf("\n\nEC11回调!\tMode:%d\tData:%d",Mode,Data);
Serial.printf("\n请使用setCallback(Ec11CallbackFunction);设置回调函数");
}
}
bool gpioRead(uint8_t keyPin){
uint8_t NowDigitalData;
uint8_t Count=20;
uint8_t Index=0;
NowDigitalData=0;
for(Index=0;Index<Count;Index++){
if(digitalRead(keyPin)){NowDigitalData++;}
}
if(NowDigitalData*2>Count){
return true;
}else{
return false;
}
}
public:
EC11OBJECT(void){;}
EC11OBJECT(uint8_t InIoPin_K,uint8_t InIoPin_A,uint8_t InIoPin_B){IoPin_K=InIoPin_K;IoPin_A=InIoPin_A;IoPin_B=InIoPin_B;Init();}
void begin(void){;}
void begin(uint8_t InIoPin_K,uint8_t InIoPin_A,uint8_t InIoPin_B){IoPin_K=InIoPin_K;IoPin_A=InIoPin_A;IoPin_B=InIoPin_B;Init();}
void setCallback(EC11Function fp){EC11_Object_CallBack_fun_fp=fp;}
void loop(void){
uint8_t Index;
bool NowDigitalData;
NowDigitalData=gpioRead(IoPin_K);
if(Old_Ec11_K!=NowDigitalData){
Old_Ec11_K=NowDigitalData;
if(Old_Ec11_K){
ClickCount++;
}else{
UpdateStatus(false,0);
}
releaseLastTime=millis();
}
if(releaseLastTime+DoubleClickIntervalTime<millis()&&ClickCount>0){UpdateStatus(false,ClickCount);ClickCount=0;}
NowDigitalData=gpioRead(IoPin_B);
if(Old_Ec11_B!=NowDigitalData){Old_Ec11_B=NowDigitalData;return;}
NowDigitalData=gpioRead(IoPin_A);
if(Old_Ec11_A!=NowDigitalData&&NowDigitalData==true){UpdateStatus(true,Old_Ec11_B);}
Old_Ec11_A=NowDigitalData;
}
};
#endif
以下是ESP32的ARDUINO测试代码:文件名为TEST.ino
#include "EC11.h"
EC11OBJECT Ec11Obj;
void setup() {
Serial.begin(115200);/*串口波特率设置*/
Ec11Obj.begin(19,18,5);/*编码器引脚设置(参数依次为K、A、B)*/
Ec11Obj.setCallback(EC11CallBackFunction);/*编码器回调*/
}
void loop() {
Ec11Obj.loop();
}
void EC11CallBackFunction(bool Mode,int Data){
switch(Mode){
case false:
switch(Data){
case 0:
Serial.printf("\n按下");
break;
case 1:
Serial.printf("\n单击");
break;
case 2:
Serial.printf("\n双击");
break;
default:
Serial.printf("\n%d连击",Data);
break;
}
break;
case true:
switch(Data){
case 0:
Serial.printf("\n反转");
break;
case 1:
Serial.printf("\n正转");
break;
default:
Serial.printf("\n未定义操作!");
break;
}
break;
}
}
测试波特率为115200,请给串口调试助手设置相应的波特率。以下是测试截图:
最后特别提醒:注意 Ec11Obj.loop();语句需要反复执行,不可以被其它过程阻塞!