用到该编码器实现复合菜单操作,主控GD32F303,一个器件操作全局,看似复杂实则一点不简单:
void timer3_init(uint32_t outclk){
rcu_periph_clock_enable(RCU_TIMER1);
uint32_t arr =0;
int32_t psc =-1;
do{
psc++;
arr =SystemCoreClock/(psc+1)/outclk -1;
}while(arr>=0xffff);
TIMER_CTL0(TIMER1) =(1<<7);
TIMER_PSC(TIMER1) = psc;
TIMER_CAR(TIMER1) = arr;
TIMER_SWEVG(TIMER1) = (1<<0);
nvic_irq_enable(TIMER1_IRQn, 5, 1);
TIMER_DMAINTEN(TIMER1) |=(1<<0);
TIMER_CTL0(TIMER1) |=0x01;
}
#define _ENCODER_FIFO_SIZE 32
struct encoder_fifo{
uint8_t count ;
uint8_t rear;
uint8_t front;
uint8_t data[_ENCODER_FIFO_SIZE];
} mencoder_fifo={0};
static inline int8_t _encoder_in_fifo(uint8_t data){
if(mencoder_fifo.count>=_ENCODER_FIFO_SIZE)return -1;
mencoder_fifo.data[mencoder_fifo.rear]= data;
mencoder_fifo.rear =(mencoder_fifo.rear+1)%_ENCODER_FIFO_SIZE;
mencoder_fifo.count++;
return 0;
}
uint8_t _encoder_out_fifo(void){
if(mencoder_fifo.count==0)return 0;
uint8_t ret =0;
ret =mencoder_fifo.data[mencoder_fifo.front];
mencoder_fifo.front =(mencoder_fifo.front+1)%_ENCODER_FIFO_SIZE;
mencoder_fifo.count --;
return ret;
}
void encoder_init(void){
memset(&mencoder_fifo,0,sizeof(struct encoder_fifo));
rcu_periph_clock_enable( ENCODER_A_RCU_GPIO );
gpio_init( ENCODER_A_GPIOx , \
GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, ENCODER_A_PIN );
rcu_periph_clock_enable( ENCODER_B_RCU_GPIO );
gpio_init( ENCODER_B_GPIOx , \
GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, ENCODER_B_PIN );
rcu_periph_clock_enable( ENCODER_OK_RCU_GPIO );
gpio_init( ENCODER_OK_GPIOx , \
GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, ENCODER_OK_PIN );
timer3_init(10000);/*0.1ms*/
}
//旋转编码对应fifo输出
#define _EN_CODER_VALUE_ADD 0x01
#define _EN_CODER_VALUE_SUB 0x02
#define _EN_CODER_VALUE_OK_LONG 0x04
//500ms 短按 ,短按2次 -> 0x82 ...
#define _EN_CODER_VALUE_OK_SHORT 0x81
#define _ENCODER_PROCESS(parl,ena,enb,enok,enok_en,enok_count){\
parl =GPIO_ISTAT(ENCODER_A_GPIOx);\
ena<<=1;\
ena |=parl&ENCODER_A_PIN?1:0;\
enb<<=1;\
enb |=parl&ENCODER_B_PIN?1:0;\
enok<<=1;\
enok |=(GPIO_ISTAT(ENCODER_OK_GPIOx)&ENCODER_OK_PIN)?1:0;\
if((ena==0xf0)&&(enb==0xff)){\
_encoder_in_fifo(_EN_CODER_VALUE_ADD);\
}else if((ena==0xff)&&(enb==0xf0)){\
_encoder_in_fifo(_EN_CODER_VALUE_SUB);\
}\
if(enok_en&0x40000000){\
if(enok==0xff){\
enok_en =0;\
}\
}else if(enok_en &0x00010000){\
enok_en++;\
if(enok==0x0f){\
enok_count++;\
}\
if(enok_en &0x00020000){\
if((enok_en&0xffff)>=20000){\
_encoder_in_fifo(_EN_CODER_VALUE_OK_LONG);\
enok_en|=0x40000000;\
}else if(enok_count>0){\
_encoder_in_fifo(_EN_CODER_VALUE_OK_SHORT);\
enok_en|=0x40000000;\
}\
}else if((enok_en&0xffff)>=5000){\
if(enok_count==0){\
enok_en|=0x00020000;\
}else{\
_encoder_in_fifo(enok_count|0x80);\
enok_en|=0x40000000;\
}\
}\
}else if(enok==0xf0){\
enok_en =0x00010000;\
enok_count =0;\
}\
}
static uint32_t enok_en=0;
static uint8_t enok=0xff;
static uint8_t ena,enb;
static uint8_t enok_count =0;
void TIMER1_IRQHandler(void){
uint16_t parl_temp;
_ENCODER_PROCESS(parl_temp,ena,enb,enok,enok_en,enok_count);/*key scan*/
TIMER_INTF(TIMER1) = (~(uint32_t)TIMER_INT_FLAG_UP);
}
//demo:
int main(){
encoder_init();
uint8_t key =0;
do{
key = _encoder_out_fifo();
if(key>0){
printf("encoder key =%02x \r\n",key);
}
}while(1);
}