S5PV210 (Study210)裸机移植触摸屏驱动
前言
最近在做嵌入式作业的裸机开发部分,看到板子在Linux下触摸屏是支持单点触控的,然而在裸机提供的示例程序中并没有提供触摸屏相关驱动,因此在Linux驱动的基础上进行了移植从而在裸机下同样支持触摸操作
1.获取电容屏型号
查阅数据手册及原理图
通过查询S5PV210的数据手册,可以看到其包含了8个ADC引脚用于电阻屏的接入(可以接两块),然而对于Study210开发板来说,通过对Linux下的触摸进行测试,初步判断屏幕为电容屏,电容屏一般是通过I2C驱动,因此需要寻找板子上的I2C引脚。
通过查看Study210的原理图可知,LCD显示接口上有I2C相关引脚,推测用于触摸。
通过原理图可以看到,通过I2C1与电容屏进行通信,两个GPIO推测一个用于供电,一个用于产生触摸中断。
然而I2C通信还需要知道设备的地址等信息,也就意味着需要知道电容屏的型号以及其数据手册,才能实现与电容屏的通信。
查找Linux驱动程序源码
因为Linux下可以正常驱动电容屏,因此可以在Linux下查看设备型号以及对应驱动程序。
(LInux查看input,查看设备信息)
据此,我们得到了电容屏的型号为gslx680。
在Linux内核源码中,可以找到gslx680驱动的源码,但是由于其依赖于Linux库,因此不能简单移植到裸机上使用,不过从源码中可以得知,EINT7
为中断引脚,EINT6
为供电引脚。
因此,I2C的实现以及触摸屏的驱动需要我们进行手动实现。
查询电容屏数据手册
GSLX680引脚定义
通过搜索gslx680,我们可以找到其 介绍 ,设备制造商同样只提供了Linux下的驱动但是给出了触摸屏的驱动原理。
The chip has four main pins to communicate with a CPU:
- SDA and SCL: these two pins conform an I2C bus, allowing to exchange data between the chip and the main CPU.
- IOCNTL: this pin, when active (logic 1) enables the chip, making it to answer to I2C commands and read the touch screen. When inactive (logic 0), the chip is in Low Power state.
- INT: when there is data available (a press) or in other cases (not sure, not have enough documentation), this pin gets active to signal this to the CPU.
可以看到其一共有4个引脚,SDA与SCL用于I2C通信,IOCNTL用于使能,INT用于产生触摸中断。
GSLX680内部寄存器读写
在文档的I2C Communication
部分,介绍了设备的I2C地址以及设备的寄存器地址所代表的含义。
可以看到设备的I2C地址为0x40
。
当I2C发送数据时,首先需要发送从设备的地址,在这里也就是0x40
,随后才是发送的数据,I2C一次可以发送8位(一字节)。
在文档中介绍,如果需要对gslx680的寄存器进行写入(后续设备初始化要用到),需要按照以下的格式。
START(W) 0x40 0x10 0x00 0x01 0xF5 0x41 0xFF STOP
即开始I2C写入后,首先写入设备地址0x40
,随后写入需要被写入的寄存器地址0x10
,接下来的内容是要被写入的数据(变长),最后是I2C终止信号。
上述指令下,会往0x10
地址写入数据0x00
,往0x11
地址写入数据0x01
,往0x12
地址写入0xF5
以此类推。
这样就可以通过I2C完成对gslx680内部寄存器的写入。
文档中介绍,如果要读取GSLX680的内部寄存器,需要先以写入模式写入需要读取的地址,随后即可一直读取内容。
例如如果需要读取0x80
地址的5个字节内容,首先需要发送
START(W) 0x40 0x80 STOP
表示需要从0x80
地址开始读取,随后切换到读取模式,读取5次发出停止信号,即可读取到0x80-0x84
寄存器中的内容。
文档中介绍了每一个寄存器所代表的含义:
- 0x00-0x7F: these registers are used to load portions of the firmware
- 0x80: contains the number of touches in the screen. If zero, the user isn't touching the screen; if one, only one finger is on the screen; if two, there are two fingers; and so on.
- 0x84-0x87: contains the coordinates for the first touch.
- 0x88-0x8B: contains the coordinates for the second touch.
- 0x8C-0xAB: contains the coordinates for the third, fourth, and so on (up to five in some devices, up to ten in other), touches, in the same format than the previous ones (four bytes for each touch).
- 0xE0: STATUS register
- 0xE4, 0xBC-0xBF: some kind of control registers. Needed for uploading the firmware and soft resetting the chip (there's not more data available about them).
- 0xF0: PAGE register. Contains the memory page number currently mapped in the 0x00-0x7F registers.
可以看到0x00-0x7F
地址包含了触摸屏的固件程序,固件包含在Linux驱动的.h头文件中。
0x80
地址包含了屏幕上被触摸的点的个数,这块屏幕支持多点触控,测试为10点触控(然而一般也用不着bushi)
0x84-0x87
包含了第一个触摸点的坐标,其他触摸点以此类推地址增加。
0xE0
是状态寄存器,用于控制触摸屏是否工作
0xF0
是分页寄存器,用于控制固件区域0x00-0x7F
的分页(类似MMU),向其写入固件时,需要往多个分页内写入数据。(所以虽然0x00到0x7F一共才128个Byte,头文件内包含的固件有2000多行)
接下来文档介绍了触摸屏的触摸点坐标格式。从上述描述中我们可以看到第一个触摸点的数据坐标是由0x84-0x87
四个字节存储的,其中前两个字节存储x坐标,后两个字节存储y坐标。x坐标的低12位表示x的坐标值;y坐标的低12位表示y的坐标值,高4位表示触摸的手指编号(多点触控需要用)
触摸屏,启动!
随后文档介绍了触摸屏的初始化流程
Enable the chip (set IOCTNL to 1)
Reset the chip (explained later)
Upload the firmware (explained later)
Startup chip (set STATUS register to 0)
Reset the chip
Disable the chip (set IOCTNL to 0)
Wait 50 ms
Enable the chip (set IOCTNL to 1)
Wait 30 ms
Disable the chip (set IOCTNL to 0)
Wait 5 ms
Enable the chip (set IOCTNL to 1)
Wait 20 ms
Reset the chip
Startup chip (set STATUS register to 0)
可以看到初始化流程还是比较复杂的,(关关开开x),首先当然要上电,设置IOCTNL
为高电平,随后进行Reset
set the STATUS register to 0x88
wait 10 ms
set register 0xE4 to 0x04
wait 10 ms
set registers 0xBC-0xBF to 0x00
wait 10 ms.
Reset需要设置状态寄存器以及部分寄存器的内容,即利用我们上面介绍的I2C写入方式对这些寄存器进行操作。
同时我们可以看到,其中有一步是Upload the firmware,触摸屏内部不含有固件,需要每次通过I2C进行写入。
固件包含在gslx680.h中,上文我们介绍了固件在gslx680中是分页存储的,每一页的内容描述如下:
{0xf0,0x3},
{0x00,0xa5a5ffc0},
{0x04,0x00000000},
{0x08,0xe810c4e1},
{0x0c,0xd3dd7f4d},
{0x10,0xd7c56634},
{0x14,0xe3505a2a},
{0x18,0x514d494f},
{0x1c,0x5836e48b},
{0x20,0x00000000},
{0x24,0x00000000},
{0x28,0x00000000},
{0x2c,0x00000000},
{0x30,0x00001000},
{0x34,0x00000000},
{0x38,0x00000000},
{0x3c,0x00000000},
{0x40,0x00000001},
{0x44,0x00000000},
{0x48,0x00000000},
{0x4c,0x00000000},
{0x50,0x00000000},
{0x54,0x01020304},
{0x58,0x05060708},
{0x5c,0x090a0b0c},
{0x60,0x0d0e0e0f},
{0x64,0x10111213},
{0x68,0x14151617},
{0x6c,0x18191a1b},
{0x70,0x1b1c1e1f},
{0x74,0x00000000},
{0x78,0x00010000},
{0x7c,0x8c846af3},
即首先向0xf0
写入0x3
表示切换到0x3
分页,随后向0x00
写入4个Byte,以此类推直到0x7C
。当然根据我们上面介绍了I2C的特点,你也可以直接向0x00
地址写入128个Byte(事实上这样速度更快)
这样的分页在头文件中一共有145个,可以使用循环进行写入。
按照以上流程,进行初始化后,触摸屏就可以正常使用了,当有点击的时候,EINT7引脚会触发中断,此时读取0x80
地址以及0x84-0x87
地址即可获取触摸点坐标。
当前页面是本站的「Google AMP」版。查看和发表评论请点击:完整版 »