ESP32 开发笔记(三)源码示例 24_XPT2046_Touch_Test 电阻触摸XPT2046驱动测试触摸校订

开发板购买连接算法

https://item.taobao.com/item.htm?spm=a2oq0.12575281.0.0.50111deb2Ij1As&ft=t&id=626366733674windows

开发板简介
开发环境搭建 windows
基础例程:
    0_Hello Bug (ESP_LOGX与printf)    工程模板/打印调试输出
    1_LED                                                    LED亮灭控制       
    2_LED_Task                                          使用任务方式控制LED
    3_LEDC_PWM                                      使用LEDC来控制LED实现呼吸灯效果
    4_ADC_LightR                                      使用ADC读取光敏电阻实现光照传感
    5_KEY_Short_Long                              按钮长按短按实现
    6_TouchPad_Interrupt                          电容触摸中断实现
    7_WS2812_RMT                                  使用RMT实现RGB_LED彩虹变色示例
    8_DHT11_RMT                                    使用RMT实现读取DHT11温湿度传感器
    9_SPI_SDCard                                    使用SPI总线实现TF卡文件系统示例
    10_IIC_ADXL345                                使用IIC总线实现读取ADXL345角度加速度传感器
    11_IIC_AT24C02                                 使用IIC总线实现小容量数据储存测试
    12_IR_Rev_RMT                                使用RMT实现红外遥控接收解码(NEC编码)
    13_IR_Send_RMT                              使用RMT实现红外数据发送(NEC编码)
    14_WIFI_Scan                                    附近WIFI信号扫描示例    
    15_WIFI_AP                                        建立软AP示例
    16_WIFI_AP_TCP_Server                  在软AP模式下实现TCP服务端
    17_WIFI_AP_TCP_Client                   在软AP模式下实现TCP客户端
    18_WIFI_AP_UDP                              在软AP模式下实现UDP通信
    19_WIFI_STA                                      建立STA站模链接路由器
    20_WIFI_STA_TCP_Server                在站模式STA下实现TCP服务端
    21_WIFI_STA_TCP_Client                 在站模式STA下实现TCP客户端
    22_WIFI_STA_UDP                            在站模式STA下实现UDP通信
    23_LCD_Test                                      LCD液晶触摸屏显示测试
    24_XPT2046_Touch_Test                   电阻触摸XPT2046驱动测试触摸校订 
    25_LVGL_Test                                     LVGL图形库简单示例缓存

电阻式触摸屏

电阻式触摸屏是一种传感器,并非屏幕,而是盖在液晶上面透明的电阻式传感器,它将矩形区域中触摸点(X,Y)的物理位置转换为表明X坐标和Y坐标的电压。不少LCD模块都采用了电阻式触摸屏,这种屏幕能够用四线、五线、七线或八线来产生屏幕偏置电压,同时读回触摸点的电压。app

电阻层结构原理:函数

上图是电阻触摸屏的一个侧面剖视图。手指触摸的表面是一个硬涂层,用以保护下面的PET层。PET层是很薄的有弹性的PET薄膜,当表面被触摸时它会向下弯曲,并使得下面的两层ITO涂层可以相互接触并在该点连通电路。两个ITO层之间是约千分之一英寸厚的一些隔离支点使两层分开。最下面是一个透明的硬底层用来支撑上面的结构,一般是玻璃或者塑料。性能

优势

电阻式触摸屏的优势是它的屏和控制系统都比较便宜,反应灵敏度很好,并且不论是四线电阻触摸屏仍是五线电阻触摸屏,它们都是一种对外界彻底隔离的工做环境,不怕灰尘和水汽,能适应各类恶劣的环境。它能够用任何物体来触摸,稳定性能较好。 测试

电阻式触摸屏的优势可归类为:ui

1.电阻式触控屏的精确度高,可到像素点的级别,适用的最大分辨率可达4096x4096。编码

2. 屏幕不受灰尘、水汽和油污的影响,能够在较低或较高温度的环境下使用。spa

3. 电阻式触控屏使用的是压力感应,能够用任何物体来触摸,即使是带着手套也能够操做,并能够用来进行手写识别。

4. 电阻式触控屏因为成熟的技术和较低的门槛,成本较为廉价。

缺点

缺点是电阻触摸屏的外层薄膜容易被划伤致使触摸屏不可用,多层结构会致使很大的光损失,对于手持设备一般须要加大背光光源来弥补透光性很差的问题,但这样也会增长电池的消耗。

电阻式触摸屏的缺点可归类为:

1. 电阻式触控屏可以设计成多点触控,但当两点同时受压时,屏幕的压力变得不平衡,致使触控出现偏差,于是多点触控的实现程度较难。

2. 电阻式触控屏较易由于划伤等致使屏幕触控部分受损。

XPT2046

XPT2046是一款4导线制触摸屏控制器,内含12位分辨率125KHz的转换速率逐步逼近型A / D转换器。

XPT2046支持从1.5V到5.25V的低电压I / O接口。

XPT2046能经过执行两次A / D转换查出被按的屏幕位置,除此以外,还能够测量加在触摸屏上的压力。

内部自带2.5V参考电压能够做为辅助输入,温度测量和电池监测模式之用, XPT2046电池监测的电压范围能够从0V到6V 。

片内集成有一个温度传感器,在2.7V的典型工做状态下,关闭参考电压,功耗可小于0.75MW 。

XPT2046 应该有 16 个引脚,如图:

 

其引脚说明以下:

 

从上面的引脚图,咱们知道,XPT2046 跟单片机的主要引脚主要有:BUSY、DIN(单 片机 SPI 输出端)、CS、DCLK(单片机 SPI 时钟端)、PEN(笔触中断)、DOUT(单片机 SPI 输入端)

1、硬件设计及原理

查看原理图,因为高速SPI用到了SD卡和液晶屏,触摸芯片采用普通GPIO模拟SPI来实现坐标采集,除了4线SPI还有一根中断线来判断是否有按压屏幕。

2、代码编写

要驱动触摸芯片少不了触摸校订环节,触摸芯片采集的只是XY坐标上的AD值,要根据屏幕分辨率转换为液晶坐标系,因此应先驱动液晶屏,详细看上文章23_LCD_Test

为何要校订?

电阻式触摸屏就是一种传感器,它利用压力感应进行控制,将矩形区域中触摸点(X,Y)的物理位置转换为表明 X坐标和 Y 坐标的电压 电阻式触摸屏的主要部分是一块与显示器表面很是配合的电阻薄膜屏,这是一种多层的复合薄膜,它以一层玻璃或硬塑料平板做为基层,表面涂有一层导电层(透明的导电电阻),上面再盖一层通过硬化处理 光滑防擦的塑料层 它的内表面也涂有一层透明导电层层, 在他们之间有许多细小的(小于 1/1000 英寸) 的透明隔离点把两层导电层隔开绝缘 当手指触摸屏幕时,两层导电层在触摸点位置就有了接触,电阻发生变化,其中一面导电层接通 Y 轴方向的 5V 均匀电压场,使得侦测层的电压由零变为非零,控制器侦测到这个接通后,进行 A/D 转换, 并将获得的电压值与 5V 相比便可得触摸点的 Y 轴坐标, 同理也能得出 X 轴的坐标, 而后再根据模拟鼠标的方式运做。 这就是全部电阻技术触摸屏共同的最基本原理由压力感应获得坐标值的并不能达到 100%的精度,它存在着偏差。因为偏差的存在, 在触摸屏上所绘制的图形和液晶屏上的图形,对应点的集合会有所误差 在触摸屏上点击某一按钮或选择某项功能时, 内置的软件便没法对触摸屏上的点击作出正确响应,而触摸屏具备离散性,任意两个触摸点密度都不能彻底一致, 因此几乎全部带阻性触摸屏的设备在出厂前均要通过必定的校准 校准是一种图形重建的过程,即将图形通过变换,换算出与液晶屏相一致的点集合, 现有的校准算法主要是用来改善上述中的固有偏差。

直接用上个LCD液晶测试的工程,添加XPT2046.C和.H

lcd.c和gui.c就不说了,上个文章有讲

先看主函数流程

初始化lcd -> 初始化xpt2046 -> 设置为纵向 -> 开始校订 -> 完成后显示画图界面->建立画图任务

void app_main(void)
{
	esp_err_t ret;
	ESP_LOGI(TAG, "APP Start......");
	Init_LCD(WHITE);
	//初始化 XPT2046
	xpt2046_init();
	LCD_Set_Orientation(LCD_DISPLAY_ORIENTATION_PORTRAIT);// 纵向
	TP_Adjust();
	// 实心矩形
	LCD_DrawFillRectangle(0,0,30,30,BLUE);
	LCD_DrawFillRectangle(30,0,60,30,BROWN);
	LCD_DrawFillRectangle(60,0,90,30,GREEN);
	LCD_DrawFillRectangle(90,0,120,30,GBLUE);
	LCD_DrawFillRectangle(120,0,150,30,RED);
	LCD_DrawFillRectangle(150,0,180,30,MAGENTA);
	LCD_DrawFillRectangle(180,0,210,30,YELLOW);
	LCD_DrawRectangle(210,0,240,30,RED);
	LCD_ShowString(215,9,WHITE,BLACK,16,"Cle",0);
	LCD_DrawFillRectangle(0,31,240,320,WHITE);
	xTaskCreate(&Draw, "Draw", 4096, NULL, 5, NULL);
	while(1){
		vTaskDelay(1000 / portTICK_PERIOD_MS);
	}
}

画图任务函数

static void Draw(void *pvParameters)
{
	uint16_t CurrentColor = BLUE;
	while (1){
		if(xpt2046_read()){
			if(TouchY<=30 && TouchX<=30){
				CurrentColor = BLUE;
			}else if(TouchY<=30 && TouchX>30 && TouchX<60){
				CurrentColor = BROWN;
			}else if(TouchY<=30 && TouchX>60 && TouchX<90){
				CurrentColor = GREEN;
			}else if(TouchY<=30 && TouchX>90 && TouchX<120){
				CurrentColor = GBLUE;
			}else if(TouchY<=30 && TouchX>120 && TouchX<150){
				CurrentColor = RED;
			}else if(TouchY<=30 && TouchX>150 && TouchX<180){
				CurrentColor = MAGENTA;
			}else if(TouchY<=30 && TouchX>180 && TouchX<210){
				CurrentColor = YELLOW;
			}else if(TouchY<=30 && TouchX>210 && TouchX < 240){
				LCD_DrawFillRectangle(0,31,240,320,WHITE);
			}
			else{
				LCD_DrawPoint1(TouchX,TouchY,CurrentColor);//画点 
			}
		}
		vTaskDelay(10 / portTICK_PERIOD_MS);

	}
	vTaskDelete(NULL);
}

lcd初始化和绘图看上编文章

XPT2046初始化,其中只是初始化了所到的GPIO,下一步用这些IO虚拟SPI来读取坐标参数

//初始化 XPT2046
void xpt2046_init(void)
{
    gpio_config_t irq_config = {
        .pin_bit_mask = BIT64(XPT2046_IRQ),
        .mode = GPIO_MODE_INPUT,
        .pull_up_en = GPIO_PULLUP_DISABLE,
        .pull_down_en = GPIO_PULLDOWN_DISABLE,
        .intr_type = GPIO_INTR_DISABLE,
    };
    esp_err_t ret = gpio_config(&irq_config);
    /**/
    gpio_config_t miso_config = {
        .pin_bit_mask = BIT64(XPT2046_MISO),
        .mode = GPIO_MODE_INPUT,
        .pull_up_en = GPIO_PULLUP_DISABLE,
        .pull_down_en = GPIO_PULLDOWN_DISABLE,
        .intr_type = GPIO_INTR_DISABLE,
    };
    ret = gpio_config(&miso_config);
    gpio_pad_select_gpio(XPT2046_MOSI);
    gpio_set_direction(XPT2046_MOSI, GPIO_MODE_OUTPUT);// 设置GPIO为推挽输出模式
    gpio_pad_select_gpio(XPT2046_CLK);
    gpio_set_direction(XPT2046_CLK, GPIO_MODE_OUTPUT);// 设置GPIO为推挽输出模式
    gpio_pad_select_gpio(XPT2046_CS);
    gpio_set_direction(XPT2046_CS, GPIO_MODE_OUTPUT);// 设置GPIO为推挽输出模式
    
    printf("%s->XPT2046 Initialization\n",TAG);
    assert(ret == ESP_OK);
}

虚拟SPI写入一个命令

void xpt2046_gpio_Write_Byte(uint8_t num)    
{  
	uint8_t count=0;   
	for(count=0;count<8;count++){
		if(num&0x80){
			gpio_set_level(XPT2046_MOSI, 1);  
		}else{
			gpio_set_level(XPT2046_MOSI, 0);
		}  
		num<<=1; 
		gpio_set_level(XPT2046_CLK, 0);
		gpio_set_level(XPT2046_CLK, 1);
	}
}

虚拟SPI读取数据

uint16_t xpt2046_gpio_spi_read_reg(uint8_t reg)
{
	uint8_t count=0;
	uint16_t ADValue=0;
	gpio_set_level(XPT2046_CLK, 0);		// 先拉低时钟 	 
	gpio_set_level(XPT2046_MOSI, 0); 	// 拉低数据线
	gpio_set_level(XPT2046_CS, 0); 		// 选中触摸屏IC
	xpt2046_gpio_Write_Byte(reg);		// 发送命令字
	ets_delay_us(6);					// ADS7846的转换时间最长为6us
	gpio_set_level(XPT2046_CLK, 0);
	ets_delay_us(1);
	gpio_set_level(XPT2046_CLK, 1);		// 给1个时钟,清除BUSY
	gpio_set_level(XPT2046_CLK, 0);
	for(count=0;count<16;count++){		// 读出16位数据,只有高12位有效
		ADValue<<=1; 	 
		gpio_set_level(XPT2046_CLK, 0);	// 降低沿有效
		gpio_set_level(XPT2046_CLK, 1);	
		if(gpio_get_level(XPT2046_MISO))ADValue++;
	}  	
	ADValue>>=4;						// 只有高12位有效.
	gpio_set_level(XPT2046_CS, 1);		// 释放片选
	return(ADValue);
}

有了上现的两个函数实现,就能够读取坐标数据了

读取坐标数据屡次求平均

uint16_t TP_Read_XOY(uint8_t xy)
{
	uint8_t LOST_VAL = 1;//丢弃值  
	uint16_t i,j,temp,buf[Read_Count];
	uint32_t sum=0;
	for(i=0;i<Read_Count;i++){
		buf[i]=xpt2046_gpio_spi_read_reg(xy);
	}
	for(i=0;i<Read_Count-1; i++){//排序
		for(j=i+1;j<Read_Count;j++){
			if(buf[i]>buf[j]){//升序排列
				temp=buf[i];
				buf[i]=buf[j];
				buf[j]=temp;
			}
		}
	}
	sum=0;
	for(i=LOST_VAL;i<Read_Count-LOST_VAL;i++){
		sum+=buf[i];
	}
	temp = sum/(Read_Count-2*LOST_VAL);
	return temp;
}

重点来了,校订函数,采用4点校订,这里的校订结果参数只是保存为变量,实际应该保存在EEPROM中下次读取

void TP_Adjust(void)
{
	uint8_t Last_LCD_Orientation = LCD_Orientation;// 记录校订前屏幕方向,完成后还原
	uint16_t pos_temp[4][2];//坐标缓存值
	uint8_t  cnt=0,GetTouchOK = 0;	
	uint16_t d1,d2;
	uint32_t tem1,tem2;
	float fac; 	
	uint16_t outtime=0;
 	cnt=0;
	uint16_t rX,rY;
	// 校订触摸时要显示为纵向
	LCD_Set_Orientation(LCD_DISPLAY_ORIENTATION_PORTRAIT);// 纵向
	LCD_Clear(WHITE);//清屏
	LCD_ShowString(10,40,WHITE,BLUE,16,"Please use the stylus click",1);//显示提示信息
	LCD_ShowString(10,56,WHITE,BLUE,16,"the cross on the screen.",1);//显示提示信息
	LCD_ShowString(10,72,WHITE,BLUE,16,"The cross will always move",1);//显示提示信息
	LCD_ShowString(10,88,WHITE,BLUE,16,"until the screen adjustment",1);//显示提示信息
	LCD_ShowString(10,104,WHITE,BLUE,16,"is completed.",1);//显示提示信息
	TP_Drow_Touch_Point(20,20,RED);//画点1 
	while(1){//若是连续10秒钟没有按下,则自动退出
		vTaskDelay(10 / portTICK_PERIOD_MS);
		if (gpio_get_level(XPT2046_IRQ) == 0) {
			rX = TP_Read_XOY(CMD_X_READ);
			rY = TP_Read_XOY(CMD_Y_READ);
			while(!gpio_get_level(XPT2046_IRQ)){
				vTaskDelay(100 / portTICK_PERIOD_MS);
			}
			GetTouchOK = 1;
		}
		if(GetTouchOK==1){
			GetTouchOK = 0;
			pos_temp[cnt][0]=rX;
			pos_temp[cnt][1]=rY;
			cnt++;
			switch(cnt){
				case 1:
					TP_Drow_Touch_Point(20,20,WHITE);						// 清除点1 
					TP_Drow_Touch_Point(LCD_Width-20,20,RED);				// 画点2
					vTaskDelay(1000 / portTICK_PERIOD_MS);
					break;
				case 2:
					TP_Drow_Touch_Point(LCD_Width-20,20,WHITE);				// 清除点2
					TP_Drow_Touch_Point(20,LCD_Height-20,RED);				// 画点3
					vTaskDelay(1000 / portTICK_PERIOD_MS);
					break;
				case 3:
					TP_Drow_Touch_Point(20,LCD_Height-20,WHITE);			// 清除点3
					TP_Drow_Touch_Point(LCD_Width-20,LCD_Height-20,RED);	// 画点4
					break;
				case 4:	 //所有四个点已经获得
					//对边相等
					tem1=abs(pos_temp[0][0]-pos_temp[1][0]);//x1-x2
					tem2=abs(pos_temp[0][1]-pos_temp[1][1]);//y1-y2
					tem1*=tem1;
					tem2*=tem2;
					d1=sqrt(tem1+tem2);//获得1,2的距离
					
					tem1=abs(pos_temp[2][0]-pos_temp[3][0]);//x3-x4
					tem2=abs(pos_temp[2][1]-pos_temp[3][1]);//y3-y4
					tem1*=tem1;
					tem2*=tem2;
					d2=sqrt(tem1+tem2);//获得3,4的距离
					fac=(float)d1/d2;
					if(fac<0.95||fac>1.05||d1==0||d2==0){//不合格{
						cnt=0;
						TP_Drow_Touch_Point(LCD_Width-20,LCD_Height-20,WHITE);	//清除点4
						TP_Drow_Touch_Point(20,20,RED);								//画点1
						TP_Adj_Info_Show(pos_temp[0][0],pos_temp[0][1],pos_temp[1][0],pos_temp[1][1],pos_temp[2][0],pos_temp[2][1],pos_temp[3][0],pos_temp[3][1],fac*100);//显示数据   
						continue;
					}
					tem1=abs(pos_temp[0][0]-pos_temp[2][0]);//x1-x3
					tem2=abs(pos_temp[0][1]-pos_temp[2][1]);//y1-y3
					tem1*=tem1;
					tem2*=tem2;
					d1=sqrt(tem1+tem2);//获得1,3的距离
					
					tem1=abs(pos_temp[1][0]-pos_temp[3][0]);//x2-x4
					tem2=abs(pos_temp[1][1]-pos_temp[3][1]);//y2-y4
					tem1*=tem1;
					tem2*=tem2;
					d2=sqrt(tem1+tem2);//获得2,4的距离
					fac=(float)d1/d2;
					if(fac<0.95||fac>1.05){//不合格{
						cnt=0;
						TP_Drow_Touch_Point(LCD_Width-20,LCD_Height-20,WHITE);	//清除点4
						TP_Drow_Touch_Point(20,20,RED);								//画点1
						TP_Adj_Info_Show(pos_temp[0][0],pos_temp[0][1],pos_temp[1][0],pos_temp[1][1],pos_temp[2][0],pos_temp[2][1],pos_temp[3][0],pos_temp[3][1],fac*100);//显示数据   
						continue;
					}//正确了
									
					//对角线相等
					tem1=abs(pos_temp[1][0]-pos_temp[2][0]);//x1-x3
					tem2=abs(pos_temp[1][1]-pos_temp[2][1]);//y1-y3
					tem1*=tem1;
					tem2*=tem2;
					d1=sqrt(tem1+tem2);//获得1,4的距离

					tem1=abs(pos_temp[0][0]-pos_temp[3][0]);//x2-x4
					tem2=abs(pos_temp[0][1]-pos_temp[3][1]);//y2-y4
					tem1*=tem1;
					tem2*=tem2;
					d2=sqrt(tem1+tem2);//获得2,3的距离
					fac=(float)d1/d2;
					if(fac<0.95||fac>1.05)//不合格
					{
						cnt=0;
						TP_Drow_Touch_Point(LCD_Width-20,LCD_Height-20,WHITE);	//清除点4
						TP_Drow_Touch_Point(20,20,RED);								//画点1
						TP_Adj_Info_Show(pos_temp[0][0],pos_temp[0][1],pos_temp[1][0],pos_temp[1][1],pos_temp[2][0],pos_temp[2][1],pos_temp[3][0],pos_temp[3][1],fac*100);//显示数据   
						continue;
					}//正确了
					//计算结果
					xfac=(float)(TP_Adjust_Width-40)/(pos_temp[0][0] - pos_temp[2][0]);	// 获得xfac	点2-点1的X AD差值
					xoff=(TP_Adjust_Width-xfac*(pos_temp[0][0]+pos_temp[2][0]))/2;		// 获得xoff		
					yfac=(float)(TP_Adjust_Height-40)/(pos_temp[3][1] - pos_temp[2][1]);// 获得yfac	点4-点3的Y AD差值
					yoff=(TP_Adjust_Height-yfac*(pos_temp[3][1]+pos_temp[2][1]))/2;		// 获得yoff

					printf("%s->XPT2046 Read fac(%f,%f)\n",TAG, xfac, yfac);
					printf("%s->XPT2046 Read off(%d,%d)\n",TAG, xoff, yoff);
					printf("%s->XPT2046 Read pos_temp1(X %d,Y %d)\n",TAG, pos_temp[0][0], pos_temp[0][1]);
					printf("%s->XPT2046 Read pos_temp2(X %d,Y %d)\n",TAG, pos_temp[1][0], pos_temp[1][1]);
					printf("%s->XPT2046 Read pos_temp3(X %d,Y %d)\n",TAG, pos_temp[2][0], pos_temp[2][1]);
					printf("%s->XPT2046 Read pos_temp4(X %d,Y %d)\n",TAG, pos_temp[3][0], pos_temp[3][1]);

					if(abs(xfac)>2||abs(yfac)>2){//触屏和预设的相反了.
						cnt=0;
						TP_Drow_Touch_Point(LCD_Width-20,LCD_Height-20,WHITE);	//清除点4
						TP_Drow_Touch_Point(20,20,RED);								//画点1
						LCD_ShowString(40,26,WHITE,BLUE, 16,"TP Need readjust!",1);
						vTaskDelay(1000 / portTICK_PERIOD_MS);
					}		
					LCD_Clear(WHITE);//清屏
					LCD_Set_Orientation(Last_LCD_Orientation);// 校订完成后还原开始时屏幕方向
					LCD_ShowString(35,110,WHITE,BLUE, 16,"Touch Screen Adjust OK!",1);//校订完成
					vTaskDelay(1000 / portTICK_PERIOD_MS);
					//TP_Save_Adjdata();  
					//LCD_Clear(WHITE);//清屏   
					return;//校订完成
			}
		}
 	}
}

根据校订的结果读取XY坐标并根据当前屏幕方向转换坐标系

bool xpt2046_read(void)
{
	static int16_t last_x = 0,last_y = 0;
	bool valid = true;
	int16_t swap_tmp;
	uint16_t x = 0,y = 0;
	uint16_t ux = 0,uy = 0;
	uint8_t irq = gpio_get_level(XPT2046_IRQ);
	if (irq == 0) {
		ux = TP_Read_XOY(CMD_X_READ);   //5700   61700
		uy = TP_Read_XOY(CMD_Y_READ);   //3000   62300

		//printf("%s->XPT2046 Read ADC(X:%d,Y:%d)\n",TAG, ux, uy);

		x = xfac * ux + xoff;//将结果转换为屏幕坐标
		y = yfac * uy + yoff; 
/*
校准后采集的触摸坐标系,要结合当前液晶显示坐标系翻转、调换XY,将触摸坐标系转为显示坐标系
				X0						X320
			Y0	-----------------------------
				|							|
				|							|
				软							|
				排							|
				线							|
				|							|
				|							|
			Y240-----------------------------
*/
		//printf("%s->LCD_DISPLAY_ORIENTATION_PORTRAIT  %d\n",TAG,LCD_Orientation);
		if(LCD_Orientation == LCD_DISPLAY_ORIENTATION_PORTRAIT){// 纵向
			// 调换XY
			swap_tmp = x;
			x = y;
			y = swap_tmp;
			// 翻转Y
			y =  LCD_Height - y;
		}else if(LCD_Orientation == LCD_DISPLAY_ORIENTATION_PORTRAIT_INVERTED){// 纵向翻转
			// 调换XY
			swap_tmp = x;
			x = y;
			y = swap_tmp;
			// 翻转X
			x =  LCD_Width - x;
		}else if(LCD_Orientation == LCD_DISPLAY_ORIENTATION_LANDSCAPE){// 横向
			// 翻转X
			x =  LCD_Width - x;
			// 翻转Y
			y =  LCD_Height - y;			
		}else if(LCD_Orientation == LCD_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED){// 横向翻转

		}
		//printf("%s->XPT2046 Read Touch(X:%d,Y:%d)\n",TAG, x, y);
		TouchX = x;
		TouchY = y;
		return true;
	}
	return false;
}

下面为液晶屏的4个方向坐标系

3、下载测试

打开ESP-IDF Command Prompt

cd命令进入此工程目录

cd F:\ESP32_DevBoard_File\24_XPT2046_Touch_Test

查看电脑设备管理器中开发板的串口号

执行idf.py -p COM9 flash monitor从串口9下载并运行打开口显示设备调试信息   Ctrl+c退出运行

显示效果以下