深圳市航顺芯片技术研发有限公司
直播中

熊本熊

8年用户 1411经验值
擅长:处理器/DSP
私信 关注
[问答]

一文读懂电阻屏的原理是什么

电阻屏的原理是什么?
ADC可以用来做为电阻式触摸屏控制器吗?

回帖(1)

谭艳红

2021-10-20 17:16:27
  1. 电阻屏原理
  电阻屏X层上X-到X+和Y-到Y+的电阻是均匀分布的。
  当计算触摸点时分为两步:
  1、计算Y坐标,在Y+电极施加驱动电压V,Y-接地,芯片通过X+测量接触点的电压。
  
  由于ITO层均匀导电,触点电压与V电压之比等于触点Y坐标与屏高度之比。
  2、计算X坐标,在X+电极施加驱动电压V, X-电极接地,Y+做为引出端测量得到接触点的电压,由于ITO层均匀导电,触点电压与Vdrive电压之比等于触点X坐标与屏宽度之比。
  
  测得的电压通常由ADC转化为数字信号,再进行简单处理就可以做为坐标判断触点的实际位置。
  2. ADC
  2.1 Device:
  /* TSc controller */
  static struct tsc_data am335x_touchscreen_data = {
  .wires = 4,
  .x_plate_resistance = 600,
  .steps_to_configure = 5,
  };
  static struct adc_data am335x_adc_data = {
  .adc_channels = 4,
  };
  static struct mfd_tscadc_board tscadc = {
  .tsc_init = &am335x_touchscreen_data,
  .adc_init = &am335x_adc_data,
  };
  创建了对应的Platform Device:mfd_tscadc_init() -》 am33xx_register_mfd_tscadc() -》 omap_device_build() -》 omap_device_build_ss() -》 omap_device_register()
  2.2 Driver:
  kernelarcharmplat-omapomap_device.c中定义了driver:
  static struct platform_driver ti_tscadc_driver = {
  .driver = {
  .name = “ti_tscadc”,
  .owner = THIS_MODULE,
  },
  .probe = ti_tscadc_probe,
  .remove = __devexit_p(ti_tscadc_remove),
  .suspend = tscadc_suspend,
  .resume = tscadc_resume,
  };
  ↓
  static int __devinit ti_tscadc_probe(struct platform_device *pdev)
  {
  /* 解析出Touch Screen Controller的配置:
  其中4路ADC用来做为电阻式触摸屏控制器
  */
  /* TSC Cell */
  if (pdata-》tsc_init) {
  cell = &tscadc-》cells[children];
  cell-》name = “tsc”;
  cell-》platform_data = tscadc;
  cell-》pdata_size = sizeof(*tscadc);
  children++;
  }
  /* 解析出ADC的配置:
  另外4路ADC用来做独立的ADC使用
  */
  /* ADC Cell */
  if (pdata-》adc_init) {
  cell = &tscadc-》cells[children];
  cell-》name = “tiadc”;
  cell-》platform_data = tscadc;
  cell-》pdata_size = sizeof(*tscadc);
  children++;
  }
  /* 创建TSC和ADC对应的Platform Device */
  err = mfd_add_devices(&pdev-》dev, pdev-》id, tscadc-》cells,
  children, NULL, 0);
  }
  3. TouchSceen
  触摸屏设备对应event1和touchscreen0:
  root@am335x-evm:~# ls /dev/input/event1
  /dev/input/event1
  root@am335x-evm:~# ls -l /dev/input/touchscreen0
  lrwxrwxrwx 1 root root 6 Jan 1 00:03 /dev/input/touchscreen0 -》 event1
  /dev/input/event1读取出的数据是原始的ADC数据,它的最大值为2^12。需要经过tslib根据fb的分辨率转换以后,才能得到需要使用的X、Y轴的坐标值。
  3.1 Device
  在kernelarcharmplat-omapomap_device.c驱动的ti_tscadc_probe函数中创建了TSC的Platform Device。
  3.2 Driver
  drivers/input/touchscreen/ti_tsc.c:
  static struct platform_driver ti_tsc_driver = {
  .probe = tscadc_probe,
  .remove = __devexit_p(tscadc_remove),
  .driver = {
  .name = “tsc”,
  .owner = THIS_MODULE,
  },
  .suspend = tsc_suspend,
  .resume = tsc_resume,
  };
  ↓
  初始化时注册input_device,对应/sys/class/input/input0/:
  static int __devinit tscadc_probe(struct platform_device *pdev)
  {
  input_dev = input_allocate_device();
  input_dev-》name = “ti-tsc”;
  input_dev-》dev.parent = &pdev-》dev;
  input_dev-》evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
  input_dev-》keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
  input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
  input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
  input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0);
  /* register to the input system */
  err = input_register_device(input_dev);
  }
  中断时上报input_event:
  static irqreturn_t tscadc_interrupt(int irq, void *dev)
  {
  /*
  * Sample found inconsistent by debouncing
  * or pressure is beyond the maximum.
  * Don‘t report it to user space.
  */
  /* 上报电阻触摸屏的X、Y、Z值。
  X、Y为坐标值,Z为压力值
  */
  if (pen == 0) {
  if ((diffx 《 15) && (diffy 《 15)
  && (z 《= MAX_12BIT)) {
  input_report_abs(input_dev, ABS_X,
  val_x);
  input_report_abs(input_dev, ABS_Y,
  val_y);
  input_report_abs(input_dev, ABS_PRESSURE,
  z);
  input_report_key(input_dev, BTN_TOUCH,
  1);
  input_sync(input_dev);
  }
  }
  status = tscadc_readl(ts_dev, TSCADC_REG_RAWIRQSTATUS);
  if (status & TSCADC_IRQENB_PENUP) {
  /* Pen up event */
  fsm = tscadc_readl(ts_dev, TSCADC_REG_ADCFSM);
  if (fsm == 0x10) {
  pen = 1;
  bckup_x = 0;
  bckup_y = 0;
  input_report_key(input_dev, BTN_TOUCH, 0);
  input_report_abs(input_dev, ABS_PRESSURE, 0);
  input_sync(input_dev);
  } else {
  pen = 0;
  }
  irqclr |= TSCADC_IRQENB_PENUP;
  }
  }
  3.3 uDev
  Udev就是在用户空间接收内核sysfs netlink热插拔消息的程序,而内核态调用用户空间程序的方式调用的是“/***in/hotplug”,后一种方式已经被淘汰。
  用户空间对热插拔消息的处理有几类动作:
  1、创建或者移除设备的设备节点;如果设备有devt属性,即“/sys/class/” 路径下包含“dev”文件属性的内核设备,发生增加或移除操作时,udev会帮其在用户空间“/dev”路径下增加或移除设备节点。2、根据规则文件,给设备改名、创建符号链接等。3、根据规则文件,调用外部程序。例如,调用modprobe插入驱动。 /etc/udev/rules.d/local.rules:
  # Create a symlink to any touchscreen input deviceSUBSYSTEM, KERNEL, ATTRS{modalias}==“input:*-e0*,3,*a0,1
  4. KeyBoard
  键盘设备对应event0:
  root@am335x-evm:~# ls /dev/input/event0
  /dev/input/event0
  4.1 Device
  kernelarcharmmach-omap2board-am335xevm.c中定义了device:
  /* Matrix GPIO Keypad Support for profile-0 only: TODO */
  /* pinmux for keypad device */
  static struct pinmux_config matrix_keypad_pin_mux[] = {
  {”gpmc_a7.gpio1_23“, OMAP_MUX_MODE7 | AM33XX_PIN_INPUT}, //T15
  {”gpmc_a10.gpio1_26“, OMAP_MUX_MODE7 | AM33XX_PIN_INPUT}, //T16
  {”gpmc_a2.gpio1_18“, OMAP_MUX_MODE7 | AM33XX_PIN_INPUT}, //U14
  {”gpmc_a8.gpio1_24“, OMAP_MUX_MODE7 | AM33XX_PIN_OUTPUT}, //V16
  {”gpmc_a6.gpio1_22“, OMAP_MUX_MODE7 | AM33XX_PIN_OUTPUT}, //U15
  {”gpmc_a5.gpio1_21“, OMAP_MUX_MODE7 | AM33XX_PIN_OUTPUT}, //V15
  {”gpmc_a1.gpio1_17“, OMAP_MUX_MODE7 | AM33XX_PIN_OUTPUT}, //V14
  {”gpmc_a4.gpio1_20“, OMAP_MUX_MODE7 | AM33XX_PIN_OUTPUT}, //R14
  {”gpmc_a3.gpio1_19“, OMAP_MUX_MODE7 | AM33XX_PIN_OUTPUT}, //T14
  {”mcasp0_axr0.gpio3_16“, OMAP_MUX_MODE7 | AM33XX_PIN_OUTPUT}, //D12
  // {”ecap0_in_pwm0_out.gpio0_7“, OMAP_MUX_MODE7 | AM33XX_PIN_OUTPUT}, //C18. hx del 12.13
  {”uart1_rxd.gpio0_14“, OMAP_MUX_MODE7 | AM33XX_PIN_OUTPUT},//D16
  {NULL, 0},
  };
  /* Keys mapping */
  static const uint32_t am335x_evm_matrix_keys[] = {
  KEY(0, 0, KEY_F1), KEY(0, 1, KEY_F2), KEY(0, 2, KEY_F3), KEY(0, 3, KEY_F4), KEY(0, 4, KEY_1), KEY(0, 5, KEY_2), KEY(0, 6, KEY_3), KEY(0, 7, KEY_0),
  KEY(1, 0, KEY_F5), KEY(1, 1, KEY_F6), KEY(1, 2, KEY_F7), KEY(1, 3, KEY_BACKSPACE), KEY(1, 4, KEY_4), KEY(1, 5, KEY_5), KEY(1, 6, KEY_6), KEY(1, 7, KEY_MINUS),
  KEY(2, 0, KEY_F9), KEY(2, 1, KEY_ENTER), KEY(2, 2, KEY_F11), KEY(2, 3, KEY_F12), KEY(2, 4, KEY_7), KEY(2, 5, KEY_8), KEY(2, 6, KEY_9), KEY(2, 7, KEY_DOT),
  };
  const struct matrix_keymap_data am335x_evm_keymap_data = {
  .keymap = am335x_evm_matrix_keys,
  .keymap_size = ARRAY_SIZE(am335x_evm_matrix_keys),
  };
  static const unsigned int am335x_evm_keypad_row_gpios[] = {
  GPIO_TO_PIN(1, 18), GPIO_TO_PIN(1, 26), GPIO_TO_PIN(1, 23)
  };
  static const unsigned int am335x_evm_keypad_col_gpios[] = {
  GPIO_TO_PIN(1, 24), GPIO_TO_PIN(1, 22), GPIO_TO_PIN(1, 21), GPIO_TO_PIN(1, 17),
  GPIO_TO_PIN(1, 20), GPIO_TO_PIN(1, 19), GPIO_TO_PIN(3, 16), GPIO_TO_PIN(0, 14)
  };
  static struct matrix_keypad_platform_data am335x_evm_keypad_platform_data = {
  .keymap_data = &am335x_evm_keymap_data,
  .row_gpios = am335x_evm_keypad_row_gpios,
  .num_row_gpios = ARRAY_SIZE(am335x_evm_keypad_row_gpios),
  .col_gpios = am335x_evm_keypad_col_gpios,
  .num_col_gpios = ARRAY_SIZE(am335x_evm_keypad_col_gpios),
  .active_low = false,
  .debounce_ms = 5,
  .col_scan_delay_us = 2,
  };
  static struct platform_device am335x_evm_keyboard = {
  .name = ”matrix-keypad“,
  .id = -1,
  .dev = {
  .platform_data = &am335x_evm_keypad_platform_data,
  },
  };
  static void matrix_keypad_init(int evm_id, int profile)
  {
  int err;
  setup_pin_mux(matrix_keypad_pin_mux);
  err = platform_device_register(&am335x_evm_keyboard);
  if (err) {
  pr_err(”failed to register matrix keypad (2x3) devicen“);
  }
  }
  4.2 Driver
  kerneldriversinputkeyboardmatrix_keypad.c:
  static struct platform_driver matrix_keypad_driver = {
  .probe = matrix_keypad_probe,
  .remove = __devexit_p(matrix_keypad_remove),
  .driver = {
  .name = ”matrix-keypad“,
  .owner = THIS_MODULE,
  #ifdef CONFIG_PM
  .pm = &matrix_keypad_pm_ops,
  #endif
  },
  };
  ↓
举报

更多回帖

发帖
×
20
完善资料,
赚取积分