三通道输入一通道输出实现三路触摸功能

华诚HC8T046P触控IC有4个输入/输出管脚,所以最大可以实现三通道输入。用这颗IC实现三通道触摸的最大难点在于只有一个通道负责输出,三个通道三种波形,如果对波形识别不准确就会导致窜键的产生。
三通道输入一通道输出实现三路触摸功能_第1张图片
P10~P13是4个输入/输出管脚

IC定制P10、P11、P13触摸输入管脚,P12为PWM输出管脚。IC上电P12输出为低电平;P10通道被触摸P12通道持续输出高电平,P10触摸松开后P12恢复低电平;P11通被道触摸P12输出高-低-高,P11触摸松开后P12恢复低电平;P13通道被触摸P12输出高-低-高-低-高,P13触摸松开后P12恢复低电平;高低电平要持续10ms后才继续变化且IC只响应单通道触摸。

一开始的思路是按下触摸产生中断,由于高/低电平会持续稳定10ms,启动定时器进行10ms一次的采样,将采集到数据(几高几低)与P10、P11、P13的波形进行对比,就可以判断出是哪个通道被触摸。

static void touch_keys_timer(unsigned long _data)
{
    struct rk_keys_drvdata *pdata = rk_key_get_drvdata();
    struct rk_keys_button *button = (struct rk_keys_button *)_data;
    struct input_dev *input = pdata->input;
    int state, i, j;
    int touch_state[10] = {0};

    printk("%s :__LINE__ %d,  code %d, gpio_get_value %d\n", __FUNCTION__,\
        __LINE__, button->code, gpio_get_value(button->gpio));
    while(i < 10)
    {
        touch_state[i] = gpio_get_value(button->gpio);
        for(j = 0; j <= i ; j++)
        {
            printk("%s:touch_state[%d] %d\n", __func__, j, touch_state[j]);
        }

        if(4 == i)
        {
            for(j = 0; j <= i ; j++)
            {
                printk("%s:touch_state[%d] %d\n", __func__, j, touch_state[j]);
            }
            if(1 == touch_state[0] && 0 == touch_state[1] && 0 == touch_state[2]\
                && 0 == touch_state[3] && 0 == touch_state[4])
            {
                printk("i %d, 按键一\n", i);
                input_event(input, EV_KEY, 158, 1);
                input_sync(input);

                input_event(input, EV_KEY, 158, 0);
                input_sync(input);
                button->isisr = 0;
                return;
            }
            else if(1 == touch_state[0] && 1 == touch_state[1] && \
                1 == touch_state[2] && 1 == touch_state[3] && 1 == touch_state[4])
            {
                printk("i %d, 按键一\n", i);
                input_event(input, EV_KEY, 158, 1);
                input_sync(input);

                input_event(input, EV_KEY, 158, 0);
                input_sync(input);
                button->isisr = 0;
                return;
            }
            else if(1 == touch_state[0] && 0 == touch_state[1] && \
                1 == touch_state[2] && 0 == touch_state[3] && 0 == touch_state[4])
            {
                    printk("i %d, 按键二\n", i);
                    input_event(input, EV_KEY, 115, 1);
                    input_sync(input);

                    input_event(input, EV_KEY, 115, 0);
                    input_sync(input);
                    button->isisr = 0;
                    return;
            }
            else if(1 == touch_state[0] && 0 == touch_state[1] && \
                1 == touch_state[2] && 1 == touch_state[3] && 1 == touch_state[4])
            {
                    printk("i %d, 按键二\n", i);
                    input_event(input, EV_KEY, 115, 1);
                    input_sync(input);

                    input_event(input, EV_KEY, 115, 0);
                    input_sync(input);
                    button->isisr = 0;
                    return;
            }
            else if(1 == touch_state[0] && 0 == touch_state[1] && \
                1 == touch_state[2] && 0 == touch_state[3] && 1 == touch_state[4])
            {
                    printk("i %d, 按键三\n", i);
                    input_event(input, EV_KEY, 114, 1);
                    input_sync(input);

                    input_event(input, EV_KEY, 114, 0);
                    input_sync(input);
                    button->isisr = 0;
                    return;
            }
            else
            {
                printk("其他情况\n");
                button->isisr = 0;
                return;
            }
        }
        i++;
        mdelay(11);
    };
    button->isisr = 0;
    button->isr_count = 0;
    return; 

}

然而担心的问题出现了,不管怎么调整采样的时间,都会出现窜键。通过示波器观察波形,导致窜键的原因是高/低电平有几率出现不到10ms就开始变化,如下图:
三通道输入一通道输出实现三路触摸功能_第2张图片
在查看LOG过程中,我发现对应的通过产生的中断个数是固定的。比如触摸P10通道,输出高电平,这时候只产生一个中断;触摸P11通道,输出高-低-高,产生两个中断;触摸P13通道,输出高-低-高-低-高,产生三个中断(设置为上升沿中断)。
于是可以通过采样中断次数来判断是哪个通道被触摸,将上面的代码修改如下:

static void touch_keys_timer(unsigned long _data)
{
    struct rk_keys_drvdata *pdata = rk_key_get_drvdata();
    struct rk_keys_button *button = (struct rk_keys_button *)_data;
    struct input_dev *input = pdata->input;
    int state, i, j;
    int touch_state[10] = {0};

    printk("%s :__LINE__ %d,  code %d, gpio_get_value %d\n",__FUNCTION__,\
        __LINE__, button->code, gpio_get_value(button->gpio));
    while(i < 10)
    {
        touch_state[i] = gpio_get_value(button->gpio);
        for(j = 0; j <= i ; j++)
        {
            printk("%s:touch_state[%d] %d\n", __func__, j, touch_state[j]);
        }

        if(4 == i)
        {               
            printk("中断次数 %d\n", button->isr_count);
            if(button->isr_count == 1)
            {
                printk("i %d, 按键一\n", i);
                input_event(input, EV_KEY, 158, 1);
                input_sync(input);

                input_event(input, EV_KEY, 158, 0);
                input_sync(input);
                button->isisr = 0;
                button->isr_count = 0;
                return;
            }
            else if(button->isr_count == 2)
            {
                printk("i %d, 按键二\n", i);
                input_event(input, EV_KEY, 115, 1);
                input_sync(input);

                input_event(input, EV_KEY, 115, 0);
                input_sync(input);
                button->isisr = 0;
                button->isr_count = 0;
                return;
            }
            else if (button->isr_count == 3)
            {
                    printk("i %d, 按键三\n", i);
                    input_event(input, EV_KEY, 114, 1);
                    input_sync(input);

                    input_event(input, EV_KEY, 114, 0);
                    input_sync(input);
                    button->isisr = 0;
                    button->isr_count = 0;
                    return;
            }
            else
            {
                printk("其他情况\n");
                button->isisr = 0;
                button->isr_count = 0;
                return;
            }
        }
        i++;
        mdelay(11);
    };
    button->isisr = 0;
    button->isr_count = 0;
    return; 

}

目前触控只是实现了短触的功能,长触还为实现。

你可能感兴趣的:(三通道输入一通道输出实现三路触摸功能)