《嵌入式硬件(二十二):基于IMX6ULL的触摸控制器(TS)操作》
一、触摸控制器
LCD是一种最常见的输出设备,事实上,LCD屏搭载了一个多点触摸IC控制器,用于实现人机互交时的输入设备。触摸屏很早就有了,一开始是电阻触摸屏,电阻触摸屏只能单点触摸,在以前的学习机、功能机时代被广泛使用。2007 年 1 月 9 日苹果发布了划时代的第一代 Iphone,也就是 Iphone 2G,Iphone 2G 上使用了多点电容触摸屏,而当时的手机基本都是使用的电阻触摸屏。电容触摸屏优秀的触摸品质和手感瞬间征服了消费者,带来了手机触摸屏的大变革,后面新出的手机也都采用了多点电容触摸屏。和电阻触摸屏相比,电容触摸屏最大的优点是支持多点触摸(后面的电阻屏也支持多点触摸,但是为时已晚),电容屏只需要手指轻触即可,而电阻屏是需要手指给予一定的压力才有反应,而且电容屏不需要校准。如今多点电容触摸屏已经得到了广泛的应用,手机、平板、电脑、广告机等等,如果要做人机交互设备的开发,多点电容触摸屏基本是不可能绕过去的。
我们使用的开发板是由正点原子提供的ATK-7016RGB LCD,其实是由 TFT LCD+触摸屏组合起来的。底下是 LCD 面板,上面是触摸面板,将两个封装到一起就成了带有触摸屏的 LCD 屏幕。电容触摸屏也是需要一个驱动 IC的,驱动 IC 一般会提供一个 I2C 接口给主控制器,主控制器可以通过 I2C 接口来读取驱动 IC里面的触摸坐标数据。ATK-7016使用的触摸控制 IC 是 GT9147。
GT9147 这款驱动 IC 采用 15*28 的驱动结构,也就是 15 个感应通道,28 个驱动通道,最多支持 5 点电容触摸。ATK-7016 的电容触摸屏部分有 4 个 IO 用于连接主控制器:SCL、SDA、RST 和 INT,SCL 和 SDA 是 I2C 引脚,RST 是复位引脚,INT 是中断引脚。一般通过 INT 引脚来通知主控制器有触摸点按下,然后在 INT 中断服务函数中读取触摸数据。也可以不使用中断功能,当然也可以采用轮询的方式不断查询是否有触摸点按下,本次实验我们使用中断方式来获取触摸数据。
由俩款触摸屏,他们的驱动不同,唯一的区别是使用I2C时,设备地址不同。
标识 使用驱动 设备地址
ALIENTEK 4.3' GT9147 0X14
4.3'' GT1148 0X5D
二、寄存器
1.引脚设置

![]()
2.通信时序

3.坐标信息

前四位为设备地址

中断方式


0x8150, 0x8158, 0x8160, 0x8168, 0x8170:这5个寄存器保存的是触摸事件发生后每个点的坐标。前俩位为y,后俩位为x。
4.设备地址选择
复位引脚从低到高的变化时,中断引脚是低电平(设定地址为 0xBA/0xBB )

三、代码
1.ts.h
#ifndef _TS_H_
#define _TS_H_
extern void init_ts(void);
struct TS_Device
{
int available;
int num;
unsigned short x[5];
unsigned short y[5];
};
extern struct TS_Device ts_dev;
#endif
2.ts.c
#include "ts.h"
#include "MCIMX6Y2.h"
#include "fsl_iomuxc.h"
#include "gpio.h"
#include "delay.h"
#include "i2c.h"
#include "stdio.h"
#include "interrupt.h"
#include "core_ca7.h"
void ts_read(unsigned short reg_addr, unsigned char *data, int len)
{
struct I2C_MSG msg =
{
.dev_address = 0x14,
.reg_address = reg_addr,
.reg_len = 2,
.data = data,
.len = len,
.deiection = I2C_Read
};
xfer(I2C2, &msg);
}
void ts_write(unsigned short reg_addr, unsigned char *data, int len)
{
struct I2C_MSG msg =
{
.dev_address = 0x14,
.reg_address = reg_addr,
.reg_len = 2,
.data = data,
.len = len,
.deiection = I2C_Write
};
xfer(I2C2, &msg);
}
struct TS_Device ts_dev;
const unsigned short ts_regs[5] = {0x8150, 0x8158, 0x8160, 0x8168, 0x8170};
void read_points(void)
{
unsigned char buffer[16];
ts_read(0x814E, buffer, 1);
ts_dev.num = buffer[0] & 0x0F;
int i;
for(i = 0;i < ts_dev.num;++i)
{
ts_read(ts_regs[i], buffer, 4);
ts_dev.x[i] = buffer[1] << 8 | buffer[0];
ts_dev.y[i] = buffer[3] << 8 | buffer[2];
}
if(ts_dev.num == 0)
{
ts_dev.available = 0;
}
else
{
ts_dev.available = 1;
}
buffer[0] = 0;
ts_write(0x814E, buffer, 1);
}
void ts_int_interrupt_handler(void)
{
if((GPIO1->ISR & (1 << 9)) != 0)
{
read_points();
GPIO1->ISR |= (1 << 9);
}
}
void init_ts(void)
{
IOMUXC_SetPinMux(IOMUXC_GPIO1_IO09_GPIO1_IO09, 0); //INT
IOMUXC_SetPinMux(IOMUXC_SNVS_SNVS_TAMPER9_GPIO5_IO09, 0); //RST
IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO09_GPIO1_IO09, 0x10B0);
IOMUXC_SetPinConfig(IOMUXC_SNVS_SNVS_TAMPER9_GPIO5_IO09, 0x10B0);
struct GPIO_Type_t t =
{
.direction = gpio_output,
.defalut_value = 1
};
init_gpio(GPIO1, 9, &t);
init_gpio(GPIO5, 9, &t);
write_gpio(GPIO1, 9, 0);
write_gpio(GPIO5, 9, 0);
delayms(10);
write_gpio(GPIO5, 9, 1);
delayms(100);
t.direction = gpio_input;
init_gpio(GPIO1, 9, &t);
IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO09_GPIO1_IO09, 0xF080);
unsigned char buffer[16] = {0};
ts_read(0x8140, buffer, 4);
printf("TS id = %s\n", (const char *)buffer);
ts_read(0x8056, buffer, 1);
printf("interrupt way = %d\n", buffer[0] & 0x03);//0000 0011
GPIO1->ICR1 |= (3 << 18);//GPIO1_IO09 falling
GPIO1->IMR |= (1 << 9);
system_interrupt_register(GPIO1_Combined_0_15_IRQn, ts_int_interrupt_handler);
GIC_EnableIRQ(GPIO1_Combined_0_15_IRQn);
}
3.main.c
#include "string.h"
#include "led.h"
#include "beep.h"
#include "MCIMX6Y2.h"
#include "key.h"
#include "interrupt.h"
#include "clock.h"
#include "epit.h"
#include "gpt.h"
#include "delay.h"
#include "uart.h"
#include "stdio.h"
#include "i2c.h"
#include "lm75.h"
#include "adc.h"
#include "spi.h"
#include "adxl345.h"
#include "lcd.h"
#include "framebuffer.h"
#include "pwm.h"
#include "ts.h"
int main(void)
{
init_clock();
system_interrupt_init();
init_led();
init_beep();
// init_key();
// init_epit1();
init_gpt1();
init_uart1();
init_i2c1();
init_i2c2();
init_adc1_channle1();
init_spi3();
// init_adxl345();
init_lcd();
lcd_clear(0x00FFFFFF);
init_pwm1();
init_ts();
while(1)
{
char s[32];
if(ts_dev.available != 0)
{
printf("num = %d\n", ts_dev.num);
int i;
for(i = 0;i < ts_dev.num;++i)
{
sprintf(s, "x = %d, y = %d ", ts_dev.x[i], ts_dev.y[i]);
lcd_show_string(100, 100 + 32 * i, 16 * strlen(s), 32, 32, s);
}
}
}
return 0;
}
更多推荐



所有评论(0)