硬件介绍
首先介绍一下硬件,我购买的液晶屏大小为480*320,液晶屏控制芯片为ST996S,两者均采用SPI通讯协议,这节只讲触摸屏控制芯片XPT2064的部分。
如果你需要阅读有关液晶屏控制芯片ST996S的部分可以点击下方链接:https://blog.csdn.net/Griffin_SAT8/article/details/113728367
时序说明
根据时序图我们可以看到XPT2064是使用SPI的第0种方式进行通讯的,也就是CPOL=0(时钟在空闲时为低电平),CPHA=1 Edge(在奇数跳沿进行采样),并且当我们发送了指令后XPT2064返回来的是一个12位的值。
以上三个表格为我们展示了如何确定我们要发送的指令,其中除了A0-A2和第7位(MSB)其他的我们都可以选择为0,A0-A2则是最重要的,为了搞清楚这个我们需要先了解下触摸屏的原理。
根据图中我们可以看到其实触摸屏主要是由两块ITO涂层构成的,并且分别由间隔点分割开来。当我们向X方向通电时,我们可以测得触摸点X方向的电压,并由AD转换器转换后将值返回到STM32,同理向Y轴通电时则反之。
那么我们就可以得出控制的命令为:0b10010000和0b11010000,换算成16进制后就是0x90和0xD0,其中0x90为向YP,YN方向通电,0xD0反之。
有一点我们需要注意一下,触摸屏的X方向与Y方向是不会改变的,但LCD显示屏的方向是可以根据扫描方向改变的,所以当显示方向为竖屏时,0x90代表的是Y方向,而显示方向为横屏时0x90代表的是X方向,这个在我们之后进行触摸屏校准时会涉及。
CUBEMX配置
网上大部分有关XPT2064的文章都是使用软件SPI进行控制,但其实XPT2064是完全可以使用硬件SPI进行控制的。
SPI模式选择主机全双工模式,分频器设置64分频,CPOL为0,CPHA为1 Edge(也就是在奇数跳沿时采用),片选引脚使用软件控制。
其中PB12为中断引脚,当触摸屏检测到电压变化时会输出低电平,我们将PB12上拉后作为输入引脚使用。PB13则为软件控制的片选引脚。
注意:在接线时,MISO与T_DO相连,MOSI与T_DIN相连!
.
驱动代码
/*发送命令并获取XPT2064返回的数值*/
int16_t XPT2064_TouchGet(uint8_t command){
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,GPIO_PIN_RESET);
uint8_t data=0;
uint8_t _data=0;
uint16_t r_data=0;
HAL_SPI_Transmit(&hspi2, &command, sizeof(command), 5);
HAL_SPI_TransmitReceive(&hspi2,&_data,&data,sizeof(data), 5);
r_data=data<<8;
HAL_SPI_TransmitReceive(&hspi2,&_data,&data,sizeof(data), 5);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,GPIO_PIN_SET);
r_data=(r_data|data)>>3;
return r_data;
}
这里在接收信息时使用了HAL_SPI_TransmitReceive()这个函数,至于为什么不使用HAL_SPI_Receive()这个函数,是因为使用了HAL_SPI_Receive()后会导致接收到的数据不正常,目前猜测的原因是HAL_SPI_Receive()这个函数最后还是会调用HAL_SPI_TransmitReceive()这个函数,并且会将缓存区中的数据发送出去,这导致了与时序图不符。
还有个可能的原因是根据时序图,在发送指令和接收数据之间并不是完全的无缝连接,其中会有个BUSY周期,而HAL_SPI_TransmitReceive()这个函数正好弥补了这个周期。如果有人知道原因的话我非常希望能够在评论区中指出来。
#define Touch 1
#define N_Touch 0
typedef enum{
XPT2064_StateRelease=0,
XPT2064_StateWaiting,
XPT2064_StatePressed,
}Touch_State;
/*触摸屏状态机*/
uint8_t XPT2064_TouchDetect(void){
static Touch_State state=XPT2064_StateRelease; //初始化状态为XPT2064_StateRelease
static uint32_t t;
uint8_t result=N_Touch;
switch(state){
/*未检测到触摸*/
case XPT2064_StateRelease:
/*如果检测到中断引脚为低电平则将状态更新为XPT2064_StateWaiting*/
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_12)==GPIO_PIN_RESET){
state=XPT2064_StateWaiting;
result=N_Touch;
}
else{
state=XPT2064_StateRelease;
result=N_Touch;
}
break;
/*真在判断是否为触摸*/
case XPT2064_StateWaiting:
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_12)==GPIO_PIN_RESET){
t++;
if(t>10){
/*如果连续检测10次均为低电平则更新状态为XPT2064_StatePressed*/
state=XPT2064_StatePressed;
result=Touch; //输出结果为1
}
else{
state=XPT2064_StateWaiting;
result