Edit online

获取和配置 IC 关键信息

Read time: 6 minute(s)
执行 CTP 移植流程之前,须获取触摸 IC 的关键信息,包括但不限于:
  • 从机设备地址

  • 触摸坐标信息,须至少包含下列信息:
    • 触摸点 ID 号
    • X 轴坐标值
    • Y 轴坐标值
    • 触摸点个数
    • 硬件上电时序

从机设备地址

获取触摸芯片的从机地址是主控和外设通信的关键步骤,常见的获取从机设备地址的方法如下所示:
  • 执行硬件扫描:

    通过 i2c-tools 扫描硬件获取从机设备的地址,须确保硬件连接正常。详细流程如下:
    1. 使能 i2c-tools 测试代码。
      Local packages options  --->
          Third-party packages options  --->
              [*] i2c-tools: a collection of i2c tools including scan/read/write
    2. 在任意串口执行 i2c scan i2c interface 命令,例如:

      i2c scan i2c1

      i2c interface 需按照实际使用的接口进行设置。

      系统输出示例如下,表示 GT911 当前的从机地址为 0x5D:
      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
      00: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
      10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
      20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
      30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
      40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
      50: -- -- -- -- -- -- -- -- -- -- -- -- -- 5D -- --
      60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
      70: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    注: i2c-tools 也可以用于检测主控与外设之间的硬件连接关系是否正常。如果执行上述命令后扫描不到任何从机地址,则需检查硬件是否正常以及 I2C 是否有外部上拉电阻等情况。
  • 从对应 IC 的规格书中获取信息。

    通常情况下,IC 规格书会按照以下方式列示相关从机地址:
    • 直接提供 7 位从机地址。例如,GSL3676 的规格书中列示了 7 位从机地址为 0x40。
      gsl_slave_addr

      如果直接列示了从机地址,则在新建或修改 CTP 驱动时,直接使用该从机地址,例如位 0x40。
      #define GSL3676_SLAVE_ADDR                  0x40
      gsl3676_client.client_addr = GSL3676_SLAVE_ADDR;
    • 列示含读写位(8 位)的从机地址。例如,GT911 的规格书给出 0xBA/ 0xBB 的从机地址,差值为 1,说明列示的地址为 8 位,含读写位。


      gt911_slave_addr

      如果列示了含读写位的 8 位从机地址,则在新建或修改 CTP 驱动时,须将地址右移 1 位,例如将 0xBA/0xBB 右移 1 位后得到 0x5D 的从机地址。
      #define GT911_ADDRESS_HIGH 0x5D
      gt911_client.client_addr = GT911_ADDRESS_HIGH;

触摸点 ID 号

坐标数据的数组内容存储都是以 ID 作为下标索引,可在规格书中搜索包含 ID 字样的字段,示例如下:
  • Track ID 示例:

    ft7252_track_id

     off_set = read_index * C145HAX01_POINT_INFO_LEN;
     read_id = (read_buf[off_set + 3] >> 4) & 0x0f;
     pre_id[read_index] = read_id;
     input_x = ((read_buf[off_set + 1] & 0x0f) << 8) | read_buf[off_set + 2];
     input_y = ((read_buf[off_set + 3] & 0xf) << 8) | read_buf[off_set + 4];
  • Touch ID 示例:
    gt911_track_id

     off_set = read_index * 8;
     read_id = read_buf[off_set] & 0x0f;
     pre_id[read_index] = read_id;
     input_x = read_buf[off_set + 1] | (read_buf[off_set + 2] << 8); /* x */
     input_y = read_buf[off_set + 3] | (read_buf[off_set + 4] << 8); /* y */
     input_w = read_buf[off_set + 5] | (read_buf[off_set + 6] << 8); /* size */

XY 坐标计算

常见 CTP 的 XY 在 16 bit 的数据范围内,一般由两个字节组合而成,需要通过一定的逻辑计算出真实的坐标值。

在处理 CTP 的 XY 坐标时,通常需要将两个字节组合成一个 16 位的数据。一个坐标值通常由高位和低位组合而成。以下是如何通过逻辑操作从读取缓冲区中提取坐标值并将其存储为变量的详细步骤:

gt911_xy_coordinate

 off_set = read_index * 8;
 read_id = read_buf[off_set] & 0x0f;
 pre_id[read_index] = read_id;
 input_x = read_buf[off_set + 1] | (read_buf[off_set + 2] << 8); /* x */
 input_y = read_buf[off_set + 3] | (read_buf[off_set + 4] << 8); /* y */
 input_w = read_buf[off_set + 5] | (read_buf[off_set + 6] << 8); /* size */

触摸点个数

触摸事件可分为按下、移动和抬起,事件的获取是通过当前触摸点个数与上一次触摸点个数比较得到的,下面是几种比较常见的获取当前触摸点个数的方式:

  • 从寄存器可以直接获取当前的触摸点个数


    gt911_real_time_touch_num

    touch_num = point_status & 0x0f; /* get point num */
  • 通过每根手指的触摸事件间接计算:







     cmd[0] = (rt_uint8_t)((ST77922_TOUCH_INFO >> 8) & 0xFF);
     cmd[1] = (rt_uint8_t)(ST77922_TOUCH_INFO & 0xFF);
     /* read point num is touch_num */
     if (st77922_read_regs(&st77922_client, cmd, read_buf, sizeof(read_buf)) != RT_EOK) {
         rt_kprintf("read point failed\n");
         read_num = 0;
         goto __exit;
     }
    
     for (i = 0; i < ST77922_MAX_TOUCH; i++) {
         num_valid = ((read_buf[7 * i + 4] & 0x80) != 0) ? 1 : 0;
         touch_num += num_valid;
     }

TP 硬件上电时序


gt911_power_on

 rt_pin_mode(*(rt_uint8_t *)cfg->user_data, PIN_MODE_OUTPUT);
 rt_pin_write(*(rt_uint8_t *)cfg->user_data, PIN_LOW);
 rt_thread_delay(10);
 // irq output 0
 rt_pin_mode(cfg->irq_pin.pin, PIN_MODE_OUTPUT);
 rt_pin_write(cfg->irq_pin.pin, PIN_LOW);
 rt_thread_delay(2);
 // rst output 1
 rt_pin_mode(*(rt_uint8_t *)cfg->user_data, PIN_MODE_OUTPUT);
 rt_pin_write(*(rt_uint8_t *)cfg->user_data, PIN_HIGH);
 rt_thread_delay(5);
 // rst input
 rt_pin_mode(*(rt_uint8_t *)cfg->user_data, PIN_MODE_INPUT);
 //irq output 0
 rt_pin_mode(cfg->irq_pin.pin, PIN_MODE_OUTPUT);
 rt_pin_write(cfg->irq_pin.pin, PIN_LOW);
 rt_thread_delay(50);
 rt_pin_mode(cfg->irq_pin.pin, PIN_MODE_INPUT);