触摸屏很早就有了,一开始是电阻触摸屏,电阻触摸屏只能单点触摸,需要手指按压一定的力度才有反映;和电阻屏相比电容屏的最大优点是支持多点触摸,只需要手指轻触即可,且不需要校准。
这里我不去研究电容屏的物理原理,只关注如何使用电容屏,如何得到其多点触摸坐标值即可。本实例中使用的屏幕时ATK-7016,该屏幕时由TFT LCD + 触摸屏组合起来的,低下是LCD面板,上面是触摸面板。电容触摸屏也需要一个驱动IC,驱动IC一般会提供I2C接口给主控制,主控制器通过I2C接口来读取驱动IC里面的触摸坐标数据
本例程中的驱动IC型号是FT5426,FT5426采用15*28的驱动结构,即15个感应通道,28个驱动通道,最多支持5点电容触摸。ATK-7016的电容触摸屏部分有4个IO用于连接主控制器:SCL、SDA、RST(复位引脚)和INT(中断引脚),一般通过INT引脚来通知主控制器有触摸点按下,然后在INT中断服务函数中读取触摸数据
和其他I2C器件一样,FT5426也是通过读写寄存器来完成初始化和触摸坐标数据读取的,IMX6U的I2C之前已经介绍过,这里主要就是读写FT5426的寄存器。FT5426的I2C设备地址为0x38,FT5426主要的寄存器见下表:
本例程用到的硬件资源如下:
- LED0
- RGB LCD屏幕
- 触摸屏
- 串口
触摸屏是和RGB LCD屏幕坐在一起的,所以触摸屏也在RGB LCD接口上
三、程序编写- 新建touchscreen文件夹,在文件夹中创建实时时钟驱动文件bsp_ft5xx6.c和bsp_ft5xx6.h
#define FT5426_ADDR 0x38
#define FT5426_DEVICE_MODE 0x00
#define FT5426_IDGLIB_VERSION 0xA1
#define FT5426_IDG_MODE 0xA4
#define FT5426_TD_STATUS 0x02
#define FT5426_TOUCH1_XH 0x03
#define FT5426_XYCOORDREG_NUM 30
#define FT5426_INIT_FINISHED 1
#define FT5426_INIT_NOTFINISHED 0
#define FT5426_TOUCH_EVENT_DOWN 0x00
#define FT5426_TOUCH_EVENT_UP 0x01
#define FT5426_TOUCH_EVENT_ON 0x02
#define FT5426_TOUCH_EVENT_RESERVED 0x03
struct ft5426_dev_struc
{
unsigned char initfalg;
unsigned char intflag;
unsigned char point_num;
unsigned short x[5];
unsigned short y[5];
};
extern struct ft5426_dev_struc ft5426_dev;
void ft5426_init(void);
void gpio1_io9_irqhandler(void);
unsigned char ft5426_write_byte(unsigned char addr,unsigned char reg, unsigned char data);
unsigned char ft5426_read_byte(unsigned char addr,unsigned char reg);
void ft5426_read_len(unsigned char addr,unsigned char reg,unsigned char len,unsigned char *buf);
void ft5426_read_tpnum(void);
void ft5426_read_tpcoord(void);
struct ft5426_dev_struc ft5426_dev;
void ft5426_init(void)
{
unsigned char reg_value[2];
ft5426_dev.initfalg = FT5426_INIT_NOTFINISHED;
int i;
for( i = 0; i < 5; i++ )
{
ft5426_dev.x[i] = 0;
ft5426_dev.y[i] = 0;
}
ft5426_dev.point_num = 0;
IOMUXC_SetPinMux(IOMUXC_UART5_TX_DATA_I2C2_SCL,1);
IOMUXC_SetPinMux(IOMUXC_UART5_RX_DATA_I2C2_SDA,1);
IOMUXC_SetPinConfig(IOMUXC_UART5_TX_DATA_I2C2_SCL,0x70B0);
IOMUXC_SetPinConfig(IOMUXC_UART5_RX_DATA_I2C2_SDA,0x70B0);
gpio_pin_config_t ctintpin_config;
IOMUXC_SetPinMux(IOMUXC_GPIO1_IO09_GPIO1_IO09,0);
IOMUXC_SetPinMux(IOMUXC_SNVS_SNVS_TAMPER9_GPIO5_IO09,0);
IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO09_GPIO1_IO09,0xF080);
IOMUXC_SetPinConfig(IOMUXC_SNVS_SNVS_TAMPER9_GPIO5_IO09,0x10B0);
ctintpin_config.direction = kGPIO_DigitalInput;
ctintpin_config.interruptMode = kGPIO_IntRisingOrFallingEdge;
gpio_init(GPIO1, 9, &ctintpin_config);
GIC_EnableIRQ(GPIO1_Combined_0_15_IRQn);
system_register_irqhandler(GPIO1_Combined_0_15_IRQn, (system_irq_handler_t)gpio1_io9_irqhandler, NULL);
gpio_enableint(GPIO1, 9);
ctintpin_config.direction=kGPIO_DigitalOutput;
ctintpin_config.interruptMode=kGPIO_NoIntmode;
ctintpin_config.outputLogic=1;
gpio_init(GPIO5, 9, &ctintpin_config);
i2c_init(I2C2);
gpio_pinwrite(GPIO5, 9, 0);
delayms(20);
gpio_pinwrite(GPIO5, 9, 1);
delayms(20);
ft5426_write_byte(FT5426_ADDR, FT5426_DEVICE_MODE, 0);
ft5426_write_byte(FT5426_ADDR, FT5426_IDG_MODE, 1);
ft5426_read_len(FT5426_ADDR, FT5426_IDGLIB_VERSION, 2, reg_value);
printf("Touch Frimware Version:%#Xrn", ((unsigned short)reg_value[0] << 8) + reg_value[1]);
ft5426_dev.initfalg = FT5426_INIT_FINISHED;
ft5426_dev.intflag = 0;
}
void gpio1_io9_irqhandler(void)
{
if(ft5426_dev.initfalg == FT5426_INIT_FINISHED)
{
//ft5426_dev.intflag = 1;
ft5426_read_tpcoord();
}
gpio_clearintflags(GPIO1, 9);
}
unsigned char ft5426_write_byte(unsigned char addr,unsigned char reg, unsigned char data)
{
unsigned char status=0;
unsigned char writedata=data;
struct i2c_transfer masterXfer;
masterXfer.slaveAddress = addr;
masterXfer.direction = kI2C_Write;
masterXfer.subaddress = reg;
masterXfer.subaddressSize = 1;
masterXfer.data = &writedata;
masterXfer.dataSize = 1;
if(i2c_master_transfer(I2C2, &masterXfer))
status=1;
return status;
}
unsigned char ft5426_read_byte(unsigned char addr,unsigned char reg)
{
unsigned char val=0;
struct i2c_transfer masterXfer;
masterXfer.slaveAddress = addr;
masterXfer.direction = kI2C_Read;
masterXfer.subaddress = reg;
masterXfer.subaddressSize = 1;
masterXfer.data = &val;
masterXfer.dataSize = 1;
i2c_master_transfer(I2C2, &masterXfer);
return val;
}
void ft5426_read_len(unsigned char addr,unsigned char reg,unsigned char len,unsigned char *buf)
{
struct i2c_transfer masterXfer;
masterXfer.slaveAddress = addr;
masterXfer.direction = kI2C_Read;
masterXfer.subaddress = reg;
masterXfer.subaddressSize = 1;
masterXfer.data = buf;
masterXfer.dataSize = len;
i2c_master_transfer(I2C2, &masterXfer);
}
void ft5426_read_tpnum(void)
{
ft5426_dev.point_num = ft5426_read_byte(FT5426_ADDR, FT5426_TD_STATUS);
}
void ft5426_read_tpcoord(void)
{
unsigned char i = 0;
unsigned char type = 0;
//unsigned char id = 0;
unsigned char pointbuf[FT5426_XYCOORDREG_NUM];
ft5426_dev.point_num = ft5426_read_byte(FT5426_ADDR, FT5426_TD_STATUS);
ft5426_read_len(FT5426_ADDR, FT5426_TOUCH1_XH, FT5426_XYCOORDREG_NUM, pointbuf);
for(i = 0; i < ft5426_dev.point_num ; i++)
{
unsigned char *buf = &pointbuf[i * 6];
ft5426_dev.x[i] = ((buf[2] << 8) | buf[3]) & 0x0fff;
ft5426_dev.y[i] = ((buf[0] << 8) | buf[1]) & 0x0fff;
type = buf[0] >> 6;
//id = (buf[2] >> 4) & 0x0f;
if(type == FT5426_TOUCH_EVENT_DOWN || type == FT5426_TOUCH_EVENT_ON )
{
} else {
}
}
}
- 主函数main.c中编写测试程序
void imx6ul_hardfpu_enable(void)
{
uint32_t cpacr;
uint32_t fpexc;
cpacr = __get_CPACR();
cpacr = (cpacr & ~(CPACR_ASEDIS_Msk | CPACR_D32DIS_Msk))
| (3UL << CPACR_cp10_Pos) | (3UL << CPACR_cp11_Pos);
__set_CPACR(cpacr);
fpexc = __get_FPEXC();
fpexc |= 0x40000000UL;
__set_FPEXC(fpexc);
}
int main(void)
{
unsigned char i = 0;
unsigned char state = OFF;
imx6ul_hardfpu_enable();
int_init();
imx6u_clkinit();
delay_init();
clk_enable();
led_init();
beep_init();
uart_init();
lcd_init();
if(tftlcd_dev.id == ATK7016 || tftlcd_dev.id == ATK7084) {
ft5426_init();
} else if(tftlcd_dev.id == ATK4384|| tftlcd_dev.id == ATK4342) {
gt9147_init();
}
tftlcd_dev.forecolor = LCD_RED;
lcd_show_string(50, 10, 400, 24, 24, (char*)"IMX6U-ALPHA TOUCH SCREEN TEST");
lcd_show_string(50, 40, 200, 16, 16, (char*)"TOUCH SCREEN TEST");
lcd_show_string(50, 60, 200, 16, 16, (char*)"ATOM@ALIENTEK");
lcd_show_string(50, 80, 200, 16, 16, (char*)"2019/3/27");
lcd_show_string(50, 110, 400, 16, 16, (char*)"TP Num :");
lcd_show_string(50, 130, 200, 16, 16, (char*)"Point0 X:");
lcd_show_string(50, 150, 200, 16, 16, (char*)"Point0 Y:");
lcd_show_string(50, 170, 200, 16, 16, (char*)"Point1 X:");
lcd_show_string(50, 190, 200, 16, 16, (char*)"Point1 Y:");
lcd_show_string(50, 210, 200, 16, 16, (char*)"Point2 X:");
lcd_show_string(50, 230, 200, 16, 16, (char*)"Point2 Y:");
lcd_show_string(50, 250, 200, 16, 16, (char*)"Point3 X:");
lcd_show_string(50, 270, 200, 16, 16, (char*)"Point3 Y:");
lcd_show_string(50, 290, 200, 16, 16, (char*)"Point4 X:");
lcd_show_string(50, 310, 200, 16, 16, (char*)"Point4 Y:");
tftlcd_dev.forecolor = LCD_BLUE;
while(1)
{
if(tftlcd_dev.id == ATK7016 || tftlcd_dev.id == ATK7084) {
lcd_shownum(50 + 72, 110, ft5426_dev.point_num , 1, 16);
lcd_shownum(50 + 72, 130, ft5426_dev.x[0], 5, 16);
lcd_shownum(50 + 72, 150, ft5426_dev.y[0], 5, 16);
lcd_shownum(50 + 72, 170, ft5426_dev.x[1], 5, 16);
lcd_shownum(50 + 72, 190, ft5426_dev.y[1], 5, 16);
lcd_shownum(50 + 72, 210, ft5426_dev.x[2], 5, 16);
lcd_shownum(50 + 72, 230, ft5426_dev.y[2], 5, 16);
lcd_shownum(50 + 72, 250, ft5426_dev.x[3], 5, 16);
lcd_shownum(50 + 72, 270, ft5426_dev.y[3], 5, 16);
lcd_shownum(50 + 72, 290, ft5426_dev.x[4], 5, 16);
lcd_shownum(50 + 72, 310, ft5426_dev.y[4], 5, 16);
} else if(tftlcd_dev.id == ATK4384|| tftlcd_dev.id == ATK4342) {
lcd_shownum(50 + 72, 110, gt9147_dev.point_num , 1, 16);
lcd_shownum(50 + 72, 130, gt9147_dev.x[0], 5, 16);
lcd_shownum(50 + 72, 150, gt9147_dev.y[0], 5, 16);
lcd_shownum(50 + 72, 170, gt9147_dev.x[1], 5, 16);
lcd_shownum(50 + 72, 190, gt9147_dev.y[1], 5, 16);
lcd_shownum(50 + 72, 210, gt9147_dev.x[2], 5, 16);
lcd_shownum(50 + 72, 230, gt9147_dev.y[2], 5, 16);
lcd_shownum(50 + 72, 250, gt9147_dev.x[3], 5, 16);
lcd_shownum(50 + 72, 270, gt9147_dev.y[3], 5, 16);
lcd_shownum(50 + 72, 290, gt9147_dev.x[4], 5, 16);
lcd_shownum(50 + 72, 310, gt9147_dev.y[4], 5, 16);
}
delayms(10);
i++;
if(i == 50)
{
i = 0;
state = !state;
led_switch(LED0,state);
}
}
return 0;
}
四、下载验证
- 修改Makefile文件:修改TARGET为touchscreen,追加“bsp/touchscreen”文件夹
- 使用imxdownload软件将bin文件下载到SD卡中
- 烧写成功后,插入SD卡,复位开发板后,用手指触摸屏幕时就会在LCD上显示出当前的触摸点个数及对应的触摸值



