• 对于Touch,RT-Thread有专门的设备驱动框架,官网文档有对相关API使用的说明,可以查看下面链接。这篇文章主要描述底层的touch驱动对接。应用相关的直接看文档中心。



    • 文档中心:https://www.rt-thread.org/document/site/programming-manual/device/touch/touch/
  • Touch 驱动对接,其实就是对接一个ops,然后通过API: rt_hw_touch_register(),就可以完事了:


struct rt_touch_ops
{
    rt_size_t (*touch_readpoint)(struct rt_touch_device *touch, void *buf, rt_size_t touch_num);
    rt_err_t (*touch_control)(struct rt_touch_device *touch, int cmd, void *arg);
};


  • 其实这两个api就是根据手册操作寄存器。
API: touch_control:

  • 主要操作0x8047 ~ 0x8100这186个寄存器。而作者比较懒,如果一个一个寄存器去配置,会花很长时间,其实我用的就是100ask_imx6ull,在韦老师的提供的linux代码中就有相对应的驱动,而且而且这些控制寄存器的相关配置是在设备树中,所以直接把设备树的这些寄存器拷贝过来就完事了,在韦老师的代码中,他的设备树支持不同尺寸的屏幕,所以不要搬错砖。

  • 其中在conctrol里面,主要就是对接下面这个cmd type。将下面cmd与相关寄存器一一对应。最后在一次性把相关寄存器配置写入。
/* Touch control cmd types */
#define  RT_TOUCH_CTRL_GET_ID            (0)   /* Get device id */
#define  RT_TOUCH_CTRL_GET_INFO          (1)   /* Get touch info */
#define  RT_TOUCH_CTRL_SET_MODE          (2)   /* Set touch's work mode. ex. RT_TOUCH_MODE_POLLING,RT_TOUCH_MODE_INT */
#define  RT_TOUCH_CTRL_SET_X_RANGE       (3)   /* Set x coordinate range */
#define  RT_TOUCH_CTRL_SET_Y_RANGE       (4)   /* Set y coordinate range */
#define  RT_TOUCH_CTRL_SET_X_TO_Y        (5)   /* Set X Y coordinate exchange */
#define  RT_TOUCH_CTRL_DISABLE_INT       (6)   /* Disable interrupt */
#define  RT_TOUCH_CTRL_ENABLE_INT        (7)   /* Enable interrupt */
API:touch_readpoint

  • 主要操作0x8140 ~ 0x8177这56个寄存器。先读取状态寄存器,根据状态寄存器去读取触摸点的信息。其实这一块的操作可以直接根据其他的软件,我编写的这个驱动就是参考gt9147软件包的。
注册int rt_hw_gt911_init(const char *name, struct rt_touch_config *cfg)
{
    struct rt_touch_device *touch_device = RT_NULL;

    touch_device = (struct rt_touch_device *)rt_malloc(sizeof(struct rt_touch_device));
    if(touch_device == RT_NULL)
    {
        LOG_E("touch device malloc fail");
        return -RT_ERROR;
    }
    rt_memset((void *)touch_device, 0, sizeof(struct rt_touch_device));

    /* hw init*/
    rt_pin_mode(*(rt_uint8_t *)cfg->user_data, PIN_MODE_OUTPUT);
    rt_pin_mode(cfg->irq_pin.pin, PIN_MODE_OUTPUT);
    rt_pin_write(*(rt_uint8_t *)cfg->user_data, PIN_LOW);
    rt_thread_delay(10);
    rt_pin_write(*(rt_uint8_t *)cfg->user_data, PIN_HIGH);
    rt_thread_delay(10);
    rt_pin_write(cfg->irq_pin.pin, PIN_MODE_INPUT);
    rt_thread_delay(100);

    gt911_client.bus = (struct rt_i2c_bus_device *)rt_device_find(cfg->dev_name);

    if(gt911_client.bus == RT_NULL)
    {
        LOG_E("Can't find %s device", cfg->dev_name);
        return -RT_ERROR;
    }

    if(rt_device_open((rt_device_t)gt911_client.bus, RT_DEVICE_FLAG_RDWR) != RT_EOK)
    {
        LOG_E("open %s device failed", cfg->dev_name);
        return -RT_ERROR;
    }

    gt911_client.client_addr = GT911_ADDRESS_HIGH;
    gt911_soft_reset(>911_client);

    /* register touch device */
    touch_device->info.type = RT_TOUCH_TYPE_CAPACITANCE;
    touch_device->info.vendor = RT_TOUCH_VENDOR_GT;
    rt_memcpy(&touch_device->config, cfg, sizeof(struct rt_touch_config));
    touch_device->ops = >911_touch_ops;

    rt_hw_touch_register(touch_device, name, RT_DEVICE_FLAG_INT_RX, RT_NULL);

    LOG_I("touch device gt911 init success");

    return RT_EOK;
}

  • 上面的代码,主要经过几个步骤,通过GPIO的初始化时序确定从机地址,时序图如下:

  • 然后关联对应的I2C总线


  • 复位触摸芯片


  • 配置触摸芯片的相关信息,其实就是填写下面结构体。


struct rt_touch_info
{
    rt_uint8_t     type;                       /* The touch type */
    rt_uint8_t     vendor;                     /* Vendor of touchs */
    rt_uint8_t     point_num;                  /* Support point num */
    rt_int32_t     range_x;                    /* X coordinate range */
    rt_int32_t     range_y;                    /* Y coordinate range */
};

  • 其中touch_config提供用户配置的。根据硬件实际情况进行配置。
struct rt_touch_config
{
    struct rt_device_pin_mode   irq_pin;       /* Interrupt pin, The purpose of this pin is to notification read data */
    char                        *dev_name;     /* The name of the communication device */
    void                        *user_data;
};

  • 然后通过rt_hw_touch_register()进行配置。这样就可以完成了驱动。



  • rt-smart相关文章



    • 《rt-smart的第一个应用程序,imx6ull用户态点灯》
    • 《rt-smart用户态通过IPC通信玩转传感器数据》
  • rt-thread驱动相关文章



    • 《rt-thread驱动框架分析》-pin驱动
    • 《rt-thread驱动框架分析》-i2c驱动
  • 对于imx6ull这个平台,目前RT-Thread是没有对应的BSP,已经相关的硬件驱动,所以通过这个平台来学习RT-Thread的驱动框架也是非常好的,而且又能玩rt-smart,两全其美。


  • 100ask_imx6ull带有7寸的屏幕,有屏幕不玩起来还是挺无聊的,所以花了点时间对接一下相关驱动,LCD驱动和touch驱动,我分成两篇。


  • 为了把屏幕跑起来,中间走了不少路,屏幕出现一闪一闪的(时钟配置错了),屏幕错位等,下面讲解的是我个人的做法,不对的地方,请指出。。。。


  • 关于RT-Smart对接屏幕,后面我会重新更新一篇文章,并对比一个rt-thread和rt-smart的不同之处。


  • 基于100ask_imx6ull的rt-thread和rt-smart仓库:



    • rt-thread的仓库:https://gitee.com/RiceChen0/imx6ull_rt_rthread
    • rt-smart的厂库:https://gitee.com/RiceChen0/imx6ull_rt_smart