基于单片机的ILI2132驱动调试
由于工作原因,需要将原先的电阻式触摸屏更换为电容式(TP)的。TOUCH方案选择了可靠性更高的奕力ILI2132,厂家提供的参考代码是基于Linux的,没法直接使用;而且厂家提供的驱动过于庞杂,对于不怎么接触Linux或者没写过TOUCH驱动的工程师来说比较困难。故此根据奕力提供的说明手册,自己实现了一个基于单片机的驱动;
- IIC总线调试
一般的电容式触摸屏均是通过IIC通讯的,成品对外引脚有6根,分别是SDA,SCL,INT,RST,VCC,GND;其中SDA与SCL是IIC通讯引脚,INT是中断引脚,当TP芯片检测到触摸信号时,会拉低该引脚;单片机可检测该引脚的电平变化来判断是否读取TP的信息;RST是TP的复位引脚,VCC和GND分别为电源和地;
关于IIC总线的协议,可自行搜索了解。由于TP芯片出厂时会自行烧录一份固件程序,所以一般在使用的过程中几乎不会去往TP的IC寄存器中写数据,我们只需要读取相应的寄存器数据即可,下图(图1)为TP的IC手册提供的读信号操作;
其中Slave Address为TP的IC作为从机的地址,根据芯片2132手册,地址是7位的,值为0x41,加上读写标志位一个bit,共同构成一个Byte,其中高7位为从机地址,最后一位为读写标志位,0表示写,1表示读;故写数据是地址为0x82,读数据是地址为0x83,如下图(图2);
根据图1与图2,iic从TP的ic中读取信息分为两步,第一是要和IC握手成功,然后IC会根收到的命令返回寄存器中的内容;参考代码如下;
/*******************************************************************************
* Function Name : ILI_WR_Reg
* Description : 向ILI读入一次数据
* Input : reg:起始寄存器地址
buf:数据缓缓存区
len:写数据长度
* Output : None
* Return : 0,成功;1,失败.
*******************************************************************************/
uint8_t ILI_WR_Reg(uint8_t reg,uint8_t *buf,uint8_t len)
{
struct i2c_msg msgs[2];
int32_t ret=-1;
int32_t retries = 0;
/*一个读数据的过程可以分为两个传输过程:
* 1. IIC 写入 要读取的寄存器地址
* 2. IIC 读取 数据
* */
msgs[0].flags = !I2C_M_RD;
msgs[0].addr = GTP_ADDRESS;
msgs[0].len = GTP_ADDR_LENGTH;
msgs[0].buf = ®//&buf[0];
msgs[1].flags = I2C_M_RD;
msgs[1].addr = GTP_ADDRESS;
msgs[1].len = len ;
msgs[1].buf = &buf[0];
while(retries < 5)
{
ret = I2C_Transfer( msgs, 2); //调用IIC数据传输过程函数,有2个传输过程
if(ret == 2)break;
retries++;
}
if((retries >= 5))
{
}
return ret;
}
传输函数
/**
* @brief 使用IIC进行数据传输
* @param
* @arg i2c_msg:数据传输结构体
* @arg num:数据传输结构体的个数
* @retval 正常完成的传输结构个数,若不正常,返回0xff
*/
int I2C_Transfer( struct i2c_msg *msgs,int num)
{
int im = 0;
int ret = 0;
for (im = 0; ret == 0 && im != num; im++)
{
if ((msgs[im].flags&I2C_M_RD)) //根据flag判断是读数据还是写数据
{
ret = Touch_I2C_ReadBytes(msgs[im].addr, msgs[im].buf, msgs[im].len); //IIC读取数据
}
else
{
ret = Touch_I2C_WriteBytes(msgs[im].addr, msgs[im].buf, msgs[im].len); //IIC写入数据
}
}
if(ret)
return ret;
return im; //正常完成的传输结构个数
}
读数据
/**
* @brief Read bytes by I2C
* @param
* @arg deviceAddr:Address of device.
* @arg pBuffer:pointer to data buffer.
* @arg NumByteToRead: number of data.
* @retval
*/
uint32_t Touch_I2C_ReadBytes(uint8_t deviceAddr,uint8_t* pBuffer, uint16_t NumByteToRead)
{
/* step 1: start I2C */
Touch_I2C_Start();
/* step 2: send device address and w/r control. */
Touch_I2C_SendByte(deviceAddr | Touch_I2C_RD);
/* step 3: wait ack. */
if (Touch_I2C_WaitAck() != 0)
{
/* stop I2C */
Touch_I2C_Stop();
return 1;
}
while(NumByteToRead)
{
*pBuffer = Touch_I2C_ReadByte();
/* increment the pointer. */
pBuffer++;
if(NumByteToRead == 1)
{
Touch_I2C_NoAck(); /* Read the last byte data,then cpu send NoACK(SDA = 1). */
/* stop I2C. */
Touch_I2C_Stop();
}
/* decrement the counter. */
NumByteToRead--;
Touch_I2C_Ack(); /* Send ack(SDA = 0). */
}
/* Stop I2C. */
Touch_I2C_Stop();
return 0; /* Seccessful. */
}
写数据
/**
1. @brief Write bytes by I2C
2. @param
3. @arg deviceAddr:Address of device.
4. @arg pBuffer:pointer to data buffer.
5. @arg NumByteToWrite:number od data.
6. @retval
*/
uint32_t Touch_I2C_WriteBytes(uint8_t deviceAddr,uint8_t* pBuffer, uint8_t NumByteToWrite)
{
uint16_t m;
Touch_I2C_Stop();
for (m = 0; m < 1000; m++)
{
/* step 1: start I2C */
Touch_I2C_Start();
/* step 2: send device address and w/r control. */
Touch_I2C_SendByte(deviceAddr | Touch_I2C_WR); /* ?????? */
/* step 3: wait ack. */
if (Touch_I2C_WaitAck() == 0)
{
break;
}
}
if (m == 1000)
{
Touch_I2C_Stop();
return 1;
}
while(NumByteToWrite--)
{
/* step 4:send data */
Touch_I2C_SendByte(*pBuffer);
/* step 5:wait ack. */
if (Touch_I2C_WaitAck() != 0)
{
Touch_I2C_Stop();
return 1;
}
pBuffer++; /* increment the pointer. */
}
/* stop I2C */
Touch_I2C_Stop();
return 0;
}
2. 根据TP的IC命令读取相应的数据内容
根据TP的IC手册来读取信息;下图中(图3)命令0x40表示读取IC固件的版本信息,0x42表示读取固件协议的版本信息,一般用于通过读取Chip ID以及Major Protocol version来判断单片机与TP的IC通讯是否OK,若读取的信息与IC固件的烧录信息一致,表示通讯OK,可进行下一步的操作;
读取TP的 IC固件分辨率(非常重要);当有触摸时,TP的IC会记录触摸位置的坐标,这个坐标是相对于TP的IC分辨率的,并不是相对于屏幕的,要与屏幕一一对应就要将固件的分辨率与屏的分辨率一一映射;下图(图4)为固件配置的基本信息;
从0x20处读取的0-1个字节是X最大分辨率,2-3为Y的最大分辨率;第4-5个字节为TOUCH配置的X方向通道数(表格有误),第5-6个字节为TOUCH配置的Y方向的通道数(表格有误),第7个字节为TOUCH配置的最大支持的手指触摸的个数,等等…
当有触摸时,触摸点的坐标可从0X10处读取;如下图(图5)
byte1是需要读取的手指坐标的状态,bit6表示是否有触摸,为1表示有触摸发生,0表示无效;bit0-bit5为该有效触摸点的ID,若为多点触控时,没跟手指触摸时对应的ID是不同的;byte2-byte3是触摸点的X坐标,byte4-5是触摸点的Y坐标;
屏实际对应的坐标通过下列公式计算:
X=((屏x)/ maximum X coordinate)(X Position )
Y=((屏Y)/ maximumY coordinate)(Y Position )
3.实际调试信息
基本信息读取
坐标信息读取
驱动完整代码连接
https://download.csdn.net/download/WQIANGEE/87722582