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);
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 gpio-keyc的基础上改写的旋转按钮 ec11的驱动,已经经过了测试。可自定义左旋和右旋的键值。如果按键值输入是第三个引脚,也支持按键操作 补存的头文件: gpio_ec11.h #ifndef _GPIO_EC11_H #define _GPIO_EC11_H struct device; struct gpio_desc; /** * struct gpio_ec11_button - configuration parameters * @leftcode: ec11 left direction input event code (KEY_*, SW_*) * @rightcode: ec11 right direction input event code (KEY_*, SW_*) * @gpio: %-1 if this key does not support gpio * @gpio: %-1 if this key does not support gpio * @active_low: %true indicates that button is considered * depressed when gpio is low * @desc: label that will be attached to button's gpio * @type: input event type (%EV_KEY, %EV_SW, %EV_ABS) * @wakeup: configure the button as a wake-up source * @debounce_interval: debounce ticks interval in msecs * @can_disable: %true indicates that userspace is allowed to * disable button via sysfs * @value: axis value for %EV_ABS * @irq: Irq number in case of interrupt keys * @gpiod: GPIO descriptor */ struct gpio_ec11_button { unsigned int code; unsigned int leftcode; /*记录左旋键值*/ unsigned int rightcode; /*记录右旋键值*/ int gpio; /*旋转编码器A引脚的gpio号*/ int subgpio; /*旋转编码器B引脚的gpio号*/ int active_low; const char *desc; unsigned int type; int wakeup; int debounce_interval; bool can_disable; int value; unsigned int irq; unsigned int irq_flags; struct gpio_desc *gpiod; }; /** * struct gpio_ec11_platform_data - platform data for gpio_ec11 driver * @buttons: pointer to array of &gpio;_keys_button structures * describing buttons attached to the device * @nbuttons: number of elements in @buttons array * @poll_interval: polling interval in msecs - for polling driver only * @rep: enable input subsystem auto repeat * @enable: platform hook for enabling the device * @disable: platform hook for disabling the device * @name: input device name */ struct gpio_ec11_platform_data { struct gpio_ec11_button *buttons; int nbuttons; unsigned int poll_interval; unsigned int rep:1; int (*enable)(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值