ec11 旋转编码器驱动

用到该编码器实现复合菜单操作,主控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);
}

你可能感兴趣的:(单片机,c语言)