licheepi nano添加BS818A触摸按键

原来使用了荔枝派nano的Lradc按键,挺好用的。但是在使用过程中发现当采样的数据线太长时,最后采样的电压会飘,导致按键不准,所以引出此文。

一、BS818A

BS818A是一款具有8个触摸按键的触摸解决方案芯片,采用串行接口用2根io线即可实现触摸控制。

当检测到有按键按下时,会在data脚输出低电平,可用来唤醒主机。主机在接收到低电位后,由clock输出时钟信号,并从data脚回读按键值。

licheepi nano添加BS818A触摸按键_第1张图片

二、按键驱动修改

内核是4.15.0-rc8,里面已经有了按键驱动,位于Device Drivers > Input device support > Keyboards->GPIO Buttons,选中它。

我们需要修改这个驱动,但是事先必须把设备树中的gpio配置好。硬件上我用的是PE9,PE10,PE9用作BS818A的data脚,PE10用作BS818A的clock脚。

	pio: pinctrl@1c20800 {
            ......
            test_pin1: test_pin@1 {
        		pins = "PE9";
        		function = "gpio_in";
    		};
    };
    mygpio-key {
	        compatible = "gpio-keys";
	        input-name = "key-test";
	        pinctrl-names = "default";
	        pinctrl-0 = <&test_pin1>;

	        k2@0 {
	            lable = "key-test";
	            linux,code = <232>;
	            gpios = <&pio 4 9 GPIO_ACTIVE_HIGH>;
	        };        
    };

接下来就是修改驱动代码了。打开内核 driver/input/keboard/gpio_keys.c文件,找到下面的函数

static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata)
{
	const struct gpio_keys_button *button = bdata->button;
	struct input_dev *input = bdata->input;
	unsigned int type = button->type ?: EV_KEY;
	int state;

	state = gpiod_get_value_cansleep(bdata->gpiod);
	if (state < 0) {
		dev_err(input->dev.parent, "failed to get gpio state: %d\n", state);
		return;
	}

	if (type == EV_ABS) {
		if (state)
			input_event(input, type, button->code, button->value);
	} else {
		input_event(input, type, *bdata->code, state);
	}
	input_sync(input);
}

在PE9产生中断时,会进入到该函数,首先通过函数gpiod_get_value_cansleep读取指定IO的电平,即是PE9的电平。type是EV_KEY,最后上报数据就是input_event(input, type, *bdata->code, state);函数。我们要添加的代码就在下面中 

if (type == EV_ABS) {
	if (state)
		input_event(input, type, button->code, button->value);
} else {
	//添加处理BS818A的代码
}

根据上面BS818A的操作方式,可以添加如下代码。

if(state==0){ //touch pressed
	Clock_L();
	udelay(80);
	for(i=0;i<16;i++)
	{
		Clock_H();
		udelay(80);
		//read PE9 data io status
		if(((*dat9)>>9)&0x01)
			t_Val |= (1<>12)&0xff)==0x0A)//bit12-15 allways 1010
	{
		if(((t_Val>>8)&0x0f)==0x01)
		{
			tmpkey = t_Val&0xff;
			for(i=0;i<8;i++)
			{
				if(tmpkey == keymap[i].keyval)
				{	
					tmpkey = keymap[i].key;
					input_event(input, type, *bdata->code, tmpkey);
					break;
				}
			}
		}
	}
}
else //PRESS UP
{
	input_event(input, type, *bdata->code, 0);
}

上面添加的代码中,有Clock_H和Clock_L函数,分别表示控制PE10口的电平,产生BS818A需要的clock波形。

最后编译内核,可以在根文件系统中看到/dev/input/event0节点已经生成。

三、应用层测试

#include 
#include 
#include 
#include 
#include 
#include 

int main(int argc, char const *argv[])
{
    int fd = 0;
    struct input_event event;
    int ret = 0;


    fd = open("/dev/input/event0",O_RDONLY);
    if (fd < 0) {
        perror("open");
        return -1;
    }

    while(1){
        ret = read(fd, &event, sizeof(event));
        if(ret < 0) {
            perror("read");
            return -1;
        }
		if(event.type == EV_KEY && event.value>0)
			printf("ret:%d, code:%d,val:%d\n", ret, event.code,event.value);
    }
    return 0;
}

测试结果,8个按键触摸,分别显示不同的按键代号1到8

licheepi nano添加BS818A触摸按键_第2张图片

至此,licheepi nano 添加触摸驱动测试完毕。

 

 

 

你可能感兴趣的:(linux驱动,linux,c)