STM32F4驱动ILI9341的TFT-LCD触摸屏(HAL库)(二)

前言

  本章更新TFT-LCD触摸屏的触摸驱动。
  显示驱动可跳转至STM32F4驱动ILI9341的TFT-LCD触摸屏(HAL库)(一),本章在此基础上完成触摸功能
  实验硬件:STM32F407ZGT6;2.4寸TFT-LCD模块(ILI9341驱动芯片、XTP2046触摸芯片)
  最终目标:使用STMF407ZGT6驱动2.4寸TFT-LCD触摸屏,并移植LVGL库
  本节目标:ILI9341显示芯片驱动实现
  软件:STM32CubeMX;Keil
  完整项目在文章末尾github链接中

一、XPT2046介绍

  XPT2046 是一款 4 线制电阻式触摸屏控制器,内含 12 位分辨率 125KHz 转换速率逐步逼近型 A/D 转换器。XPT2046 支持从 1.5V 到 5.25V 的低电压 I/O 接口。XPT2046 能通过执行两次 A/D 转换查出被按的屏幕位置,除此之外, 还可以测量加在触摸屏上的压力。内部自带 2.5V 参考电压,可以作为辅助输入、 温度测量和电池监测之用,电池监测的电压范围可以从 0V 到 6V。

二、CubeMX配置

1、GPIO配置,部分配置已于STM32F4驱动ILI9341的TFT-LCD触摸屏(HAL库)(一)配置完成
在这里插入图片描述2、串口配置,由于LCD显示驱动未编写显示字符函数,本文采用串口进行调试,也可不进行配置
在这里插入图片描述

三、XPT2046触摸驱动实现

  本文只展示部分关键代码,完整程序请至文末github链接自行获取。

  • 24ccxx.h
      AT24CXX主要是保存电阻式触摸屏校准的参数数据,利用模拟I2C通讯。
#include "24cxx.h"

/**
 * @brief  初始化AT24CXX
 * @param  None
 * @retval None
 */
void AT24CXX_Init(void)
{
    IIC_Init();
}

/**
 * @brief  在AT24CXX指定地址读出一个数据
 * @param  ReadAddr: 开始读数的地址  
 * @retval 读到的数据
 */
uint8_t AT24CXX_ReadOneByte(uint16_t ReadAddr)
{				  
    uint8_t temp = 0;		  	    																 
    IIC_Start();  
    
    if(EE_TYPE > AT24C16)
    {
        IIC_Send_Byte(AT24CXX_ADDR);     // 发送写命令
        IIC_Wait_Ack();
        IIC_Send_Byte(ReadAddr >> 8);     // 发送高地址
        IIC_Wait_Ack();		 
    }
    else
    {
        IIC_Send_Byte(AT24CXX_ADDR + ((ReadAddr/256) << 1));   // 发送器件地址0XA0,写数据 	 
    }

    IIC_Wait_Ack(); 
    IIC_Send_Byte(ReadAddr % 256);   // 发送低地址
    IIC_Wait_Ack();	    
    IIC_Start();  	 	   
    IIC_Send_Byte(AT24CXX_ADDR | 0x01);           // 进入接收模式			   
    IIC_Wait_Ack();	 
    temp = IIC_Read_Byte(0);		   
    IIC_Stop();
    
    return temp;
}

/**
 * @brief  在AT24CXX指定地址写入一个数据
 * @param  WriteAddr: 写入数据的目的地址    
 * @param  DataToWrite: 要写入的数据
 * @retval None
 */
void AT24CXX_WriteOneByte(uint16_t WriteAddr, uint8_t DataToWrite)
{				   	  	    																 
    IIC_Start();  
    
    if(EE_TYPE > AT24C16)
    {
        IIC_Send_Byte(AT24CXX_ADDR);     // 发送写命令
        IIC_Wait_Ack();
        IIC_Send_Byte(WriteAddr >> 8);    // 发送高地址	  
        IIC_Wait_Ack();		 
    }
    else
    {
        IIC_Send_Byte(AT24CXX_ADDR + ((WriteAddr/256) << 1));   // 发送器件地址0XA0,写数据
    }
    
    IIC_Wait_Ack();	   
    IIC_Send_Byte(WriteAddr % 256);   // 发送低地址
    IIC_Wait_Ack(); 	 										  		   
    IIC_Send_Byte(DataToWrite);     // 发送字节							   
    IIC_Wait_Ack();  		    	   
    IIC_Stop();
    
    HAL_Delay(10);    // 注意:这里要等待写入完成
}

/**
 * @brief  在AT24CXX里面的指定地址开始写入长度为Len的数据
 * @param  WriteAddr: 开始写入的地址  
 * @param  DataToWrite: 数据数组首地址
 * @param  Len: 要写入数据的长度2,4
 * @retval None
 */
void AT24CXX_WriteLenByte(uint16_t WriteAddr, uint32_t DataToWrite, uint8_t Len)
{  	
    for(uint8_t t = 0; t < Len; t++)
    {
        AT24CXX_WriteOneByte(WriteAddr + t, (DataToWrite >> (8*t)) & 0xFF);
    }												    
}

/**
 * @brief  在AT24CXX里面的指定地址开始读出长度为Len的数据
 * @param  ReadAddr: 开始读出的地址 
 * @param  Len: 要读出数据的长度2,4
 * @retval 读取到的数据
 */
uint32_t AT24CXX_ReadLenByte(uint16_t ReadAddr, uint8_t Len)
{  	
    uint32_t temp = 0;
    for(uint8_t t = 0; t < Len; t++)
    {
        temp <<= 8;
        temp += AT24CXX_ReadOneByte(ReadAddr + Len - t - 1); 	 				   
    }
    return temp;												    
}

/**
 * @brief  检查AT24CXX是否正常
 * @param  None
 * @retval 0: 检测成功
 *         1: 检测失败
 */
uint8_t AT24CXX_Check(void)
{
    uint8_t temp;
    temp = AT24CXX_ReadOneByte(255);     // 避免每次开机都写AT24CXX			   
    if(temp == 0x55)
        return 0;		   
    else    // 排除第一次初始化的情况
    {
        AT24CXX_WriteOneByte(255, 0x55);
        temp = AT24CXX_ReadOneByte(255);	  
        if(temp == 0x55)
            return 0;
    }
    return 1;											  
}

/**
 * @brief  在AT24CXX里面的指定地址开始读出指定个数的数据
 * @param  ReadAddr: 开始读出的地址 
 * @param  pBuffer: 数据数组首地址
 * @param  NumToRead: 要读出数据的个数
 * @retval None
 */
void AT24CXX_Read(uint16_t ReadAddr, uint8_t *pBuffer, uint16_t NumToRead)
{
    while(NumToRead)
    {
        *pBuffer++ = AT24CXX_ReadOneByte(ReadAddr++);	
        NumToRead--;
    }
}  

/**
 * @brief  在AT24CXX里面的指定地址开始写入指定个数的数据
 * @param  WriteAddr: 开始写入的地址 
 * @param  pBuffer: 数据数组首地址
 * @param  NumToWrite: 要写入数据的个数
 * @retval None
 */
void AT24CXX_Write(uint16_t WriteAddr, uint8_t *pBuffer, uint16_t NumToWrite)
{
    while(NumToWrite--)
    {
        AT24CXX_WriteOneByte(WriteAddr, *pBuffer);
        WriteAddr++;
        pBuffer++;
    }
}

  • 24ccxx.c
#include "24cxx.h"

/**
 * @brief  初始化AT24CXX
 * @param  None
 * @retval None
 */
void AT24CXX_Init(void)
{
    IIC_Init();
}

/**
 * @brief  在AT24CXX指定地址读出一个数据
 * @param  ReadAddr: 开始读数的地址  
 * @retval 读到的数据
 */
uint8_t AT24CXX_ReadOneByte(uint16_t ReadAddr)
{				  
    uint8_t temp = 0;		  	    																 
    IIC_Start();  
    
    if(EE_TYPE > AT24C16)
    {
        IIC_Send_Byte(AT24CXX_ADDR);     // 发送写命令
        IIC_Wait_Ack();
        IIC_Send_Byte(ReadAddr >> 8);     // 发送高地址
        IIC_Wait_Ack();		 
    }
    else
    {
        IIC_Send_Byte(AT24CXX_ADDR + ((ReadAddr/256) << 1));   // 发送器件地址0XA0,写数据 	 
    }

    IIC_Wait_Ack(); 
    IIC_Send_Byte(ReadAddr % 256);   // 发送低地址
    IIC_Wait_Ack();	    
    IIC_Start();  	 	   
    IIC_Send_Byte(AT24CXX_ADDR | 0x01);           // 进入接收模式			   
    IIC_Wait_Ack();	 
    temp = IIC_Read_Byte(0);		   
    IIC_Stop();
    
    return temp;
}

/**
 * @brief  在AT24CXX指定地址写入一个数据
 * @param  WriteAddr: 写入数据的目的地址    
 * @param  DataToWrite: 要写入的数据
 * @retval None
 */
void AT24CXX_WriteOneByte(uint16_t WriteAddr, uint8_t DataToWrite)
{				   	  	    																 
    IIC_Start();  
    
    if(EE_TYPE > AT24C16)
    {
        IIC_Send_Byte(AT24CXX_ADDR);     // 发送写命令
        IIC_Wait_Ack();
        IIC_Send_Byte(WriteAddr >> 8);    // 发送高地址	  
        IIC_Wait_Ack();		 
    }
    else
    {
        IIC_Send_Byte(AT24CXX_ADDR + ((WriteAddr/256) << 1));   // 发送器件地址0XA0,写数据
    }
    
    IIC_Wait_Ack();	   
    IIC_Send_Byte(WriteAddr % 256);   // 发送低地址
    IIC_Wait_Ack(); 	 										  		   
    IIC_Send_Byte(DataToWrite);     // 发送字节							   
    IIC_Wait_Ack();  		    	   
    IIC_Stop();
    
    HAL_Delay(10);    // 注意:这里要等待写入完成
}

/**
 * @brief  在AT24CXX里面的指定地址开始写入长度为Len的数据
 * @param  WriteAddr: 开始写入的地址  
 * @param  DataToWrite: 数据数组首地址
 * @param  Len: 要写入数据的长度2,4
 * @retval None
 */
void AT24CXX_WriteLenByte(uint16_t WriteAddr, uint32_t DataToWrite, uint8_t Len)
{  	
    for(uint8_t t = 0; t < Len; t++)
    {
        AT24CXX_WriteOneByte(WriteAddr + t, (DataToWrite >> (8*t)) & 0xFF);
    }												    
}

/**
 * @brief  在AT24CXX里面的指定地址开始读出长度为Len的数据
 * @param  ReadAddr: 开始读出的地址 
 * @param  Len: 要读出数据的长度2,4
 * @retval 读取到的数据
 */
uint32_t AT24CXX_ReadLenByte(uint16_t ReadAddr, uint8_t Len)
{  	
    uint32_t temp = 0;
    for(uint8_t t = 0; t < Len; t++)
    {
        temp <<= 8;
        temp += AT24CXX_ReadOneByte(ReadAddr + Len - t - 1); 	 				   
    }
    return temp;												    
}

/**
 * @brief  检查AT24CXX是否正常
 * @param  None
 * @retval 0: 检测成功
 *         1: 检测失败
 */
uint8_t AT24CXX_Check(void)
{
    uint8_t temp;
    temp = AT24CXX_ReadOneByte(255);     // 避免每次开机都写AT24CXX			   
    if(temp == 0x55)
        return 0;		   
    else    // 排除第一次初始化的情况
    {
        AT24CXX_WriteOneByte(255, 0x55);
        temp = AT24CXX_ReadOneByte(255);	  
        if(temp == 0x55)
            return 0;
    }
    return 1;											  
}

/**
 * @brief  在AT24CXX里面的指定地址开始读出指定个数的数据
 * @param  ReadAddr: 开始读出的地址 
 * @param  pBuffer: 数据数组首地址
 * @param  NumToRead: 要读出数据的个数
 * @retval None
 */
void AT24CXX_Read(uint16_t ReadAddr, uint8_t *pBuffer, uint16_t NumToRead)
{
    while(NumToRead)
    {
        *pBuffer++ = AT24CXX_ReadOneByte(ReadAddr++);	
        NumToRead--;
    }
}  

/**
 * @brief  在AT24CXX里面的指定地址开始写入指定个数的数据
 * @param  WriteAddr: 开始写入的地址 
 * @param  pBuffer: 数据数组首地址
 * @param  NumToWrite: 要写入数据的个数
 * @retval None
 */
void AT24CXX_Write(uint16_t WriteAddr, uint8_t *pBuffer, uint16_t NumToWrite)
{
    while(NumToWrite--)
    {
        AT24CXX_WriteOneByte(WriteAddr, *pBuffer);
        WriteAddr++;
        pBuffer++;
    }
}

  • touch.h
      touch.h文件包含触摸屏控制结构体定义以及各IO口宏定义。
#ifndef __TOUCH_H__
#define __TOUCH_H__

#include <stdint.h>
#include "main.h"             
#include "spi.h"              
#include "gpio.h"             
#include "stm32f4xx_hal.h"    

// 触摸屏状态
#define TP_PRESS_DOWN    0x80  // 触屏被按下
#define TP_PRESS_LIFT    0x40  // 触屏被按下后松开

// 触摸屏控制器结构体
typedef struct {
    uint8_t (*init)(void);     // 初始化触摸屏控制器
    uint8_t (*scan)(uint8_t);  // 扫描触摸屏
    void (*adjust)(void);      // 触摸屏校准
    uint16_t x0;              // 原始坐标(第一次按下时的坐标)
    uint16_t y0;
    uint16_t x;               // 当前坐标(此次扫描时的坐标)
    uint16_t y;
    uint8_t sta;             // 笔的状态
    float xfac;              // 触摸屏校准参数
    float yfac;
    short xoff;
    short yoff;
    uint8_t touchtype;       // 触摸屏类型
} TouchTypeDef;

extern TouchTypeDef tp_dev;

// 触摸屏IO定义
#define TOUCH_PEN_PIN       GPIO_PIN_1   // T_PEN   (PB1)
#define TOUCH_PEN_PORT      GPIOB
#define TOUCH_MISO_PIN      GPIO_PIN_2   // T_MISO  (PB2)
#define TOUCH_MISO_PORT     GPIOB
#define TOUCH_MOSI_PIN      GPIO_PIN_11  // T_MOSI  (PF11)
#define TOUCH_MOSI_PORT     GPIOF
#define TOUCH_CLK_PIN       GPIO_PIN_0   // T_SCK   (PB0)
#define TOUCH_CLK_PORT      GPIOB
#define TOUCH_CS_PIN        GPIO_PIN_5   // T_CS    (PC5)
#define TOUCH_CS_PORT       GPIOC

// IO操作函数
#define PEN_READ()   HAL_GPIO_ReadPin(TOUCH_PEN_PORT, TOUCH_PEN_PIN)
#define DOUT_READ()  HAL_GPIO_ReadPin(TOUCH_MISO_PORT, TOUCH_MISO_PIN)
#define TDIN(n)      HAL_GPIO_WritePin(TOUCH_MOSI_PORT, TOUCH_MOSI_PIN, ((n) ? GPIO_PIN_SET : GPIO_PIN_RESET))
#define TCLK(n)      HAL_GPIO_WritePin(TOUCH_CLK_PORT, TOUCH_CLK_PIN, ((n) ? GPIO_PIN_SET : GPIO_PIN_RESET))
#define TCS(n)       HAL_GPIO_WritePin(TOUCH_CS_PORT, TOUCH_CS_PIN, ((n) ? GPIO_PIN_SET : GPIO_PIN_RESET))

// 函数声明
void TP_Write_Byte(uint8_t num);
uint16_t TP_Read_AD(uint8_t cmd);
uint16_t TP_Read_XOY(uint8_t xy);
uint8_t TP_Read_XY(uint16_t *x, uint16_t *y);
uint8_t TP_Read_XY2(uint16_t *x, uint16_t *y);
void TP_Drow_Touch_Point(uint16_t x, uint16_t y, uint16_t color);
void TP_Draw_Big_Point(uint16_t x, uint16_t y, uint16_t color);
uint8_t TP_Scan(uint8_t tp);
void TP_Save_Adjdata(void);
uint8_t TP_Get_Adjdata(void);
void TP_Adjust(void);
uint8_t TP_Init(void);
void TP_Adj_Info_Show(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, 
                      uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3, uint16_t fac);

void Touch_Test(void);

#endif
  • touch.c
      touch.c需完成模拟SPI、读取坐标值、扫描触摸状态、校准及保存校准参数至AT24C02、初始化等功能
  • 读取坐标值,两次读取保证数据准确
/**
 * @brief  读取触摸屏的AD值
 * @param  cmd: 读取命令
 * @retval 读取到的AD值
 */
uint16_t TP_Read_AD(uint8_t cmd)
{
    uint8_t count = 0;
    uint16_t Num = 0;
    TCLK(0);
    TDIN(0);
    TCS(0);
    TP_Write_Byte(cmd);
    delay_us(6);
    TCLK(0);
    delay_us(1);
    TCLK(1);
    delay_us(1);
    TCLK(0);
    for(count = 0; count < 16; count++)
    {
        Num <<= 1;
        TCLK(0);
        delay_us(1);
        TCLK(1);
        if(DOUT_READ()) Num++;
    }
    Num >>= 4;
    TCS(1);
    return(Num);
}

#define READ_TIMES 5
#define LOST_VAL 1

/**
 * @brief  读取一个坐标值
 * @param  xy: 指令(CMD_RDX/CMD_RDY)
 * @retval 读取到的值
 */
uint16_t TP_Read_XOY(uint8_t xy)
{
    uint16_t i, j;
    uint16_t buf[READ_TIMES];
    uint16_t sum = 0;
    uint16_t temp;
    
    for(i = 0; i < READ_TIMES; i++) buf[i] = TP_Read_AD(xy);
    for(i = 0; i < READ_TIMES - 1; i++)
    {
        for(j = i + 1; j < READ_TIMES; j++)
        {
            if(buf[i] > buf[j])
            {
                temp = buf[i];
                buf[i] = buf[j];
                buf[j] = temp;
            }
        }
    }
    sum = 0;
    for(i = LOST_VAL; i < READ_TIMES - LOST_VAL; i++) sum += buf[i];
    temp = sum / (READ_TIMES - 2 * LOST_VAL);
    return temp;
}

/**
 * @brief  读取x,y坐标
 * @param  x,y: 读取到的坐标值
 * @retval 0-读取失败,1-读取成功
 */
uint8_t TP_Read_XY(uint16_t *x, uint16_t *y)
{
    *x = TP_Read_XOY(CMD_RDX);
    *y = TP_Read_XOY(CMD_RDY);
    return 1;
}

#define ERR_RANGE 50

/**
 * @brief  连续读取两次触摸值,判断是否有效
 * @param  x,y: 读取到的坐标值
 * @retval 0-读取失败,1-读取成功
 */
uint8_t TP_Read_XY2(uint16_t *x, uint16_t *y)
{
    uint16_t x1, y1;
    uint16_t x2, y2;
    uint8_t flag;
    
    flag = TP_Read_XY(&x1, &y1);
    if(flag == 0) return 0;
    flag = TP_Read_XY(&x2, &y2);
    if(flag == 0) return 0;
    
    if(((x2 <= x1 && x1 < x2 + ERR_RANGE) || (x1 <= x2 && x2 < x1 + ERR_RANGE)) &&
       ((y2 <= y1 && y1 < y2 + ERR_RANGE) || (y1 <= y2 && y2 < y1 + ERR_RANGE)))
    {
        *x = (x1 + x2) / 2;
        *y = (y1 + y2) / 2;
        return 1;
    }
    else return 0;
}

  • 扫描触摸状态
/**
 * @brief  扫描触摸屏状态
 * @param  tp: 0-屏幕坐标; 1-物理坐标
 * @retval 当前触屏状态
 */
uint8_t TP_Scan(uint8_t tp)
{
    if(!PEN_READ())
    {
        if(tp)
        {
            TP_Read_XY2(&tp_dev.x, &tp_dev.y);
        }
        else if(TP_Read_XY2(&tp_dev.x, &tp_dev.y))
        {
            tp_dev.x = tp_dev.xfac * tp_dev.x + tp_dev.xoff;
            tp_dev.y = tp_dev.yfac * tp_dev.y + tp_dev.yoff;
        }
        if((tp_dev.sta & TP_PRESS_DOWN) == 0)
        {
            tp_dev.sta = TP_PRESS_DOWN | TP_PRESS_LIFT;
            tp_dev.x0 = tp_dev.x;
            tp_dev.y0 = tp_dev.y;
        }
    }
    else
    {
        if(tp_dev.sta & TP_PRESS_DOWN)
        {
            tp_dev.sta &= ~(1 << 7);
        }
        else
        {
            tp_dev.x0 = 0;
            tp_dev.y0 = 0;
            tp_dev.x = 0xffff;
            tp_dev.y = 0xffff;
        }
    }
    return tp_dev.sta & TP_PRESS_DOWN;
}
  • 触摸校准
      校准使用了串口打印进行调试,编写代码时可通过连接串口查看调试情况,也可更改为直接在屏幕上打印。
      校准需依次点击屏幕中的校准点,程序记录每个点的触摸原始坐标(x,y)到pos_temp数组,如果比例在0.95~1.05之间,说明触摸基本均匀,校准可信,否则需要重新校准。
/**
 * @brief  触摸屏校准
 */
void TP_Adjust(void)
{
    uint16_t pos_temp[4][2];
    uint8_t cnt = 0;
    uint16_t d1, d2;
    uint32_t tem1, tem2;
    double fac;
    uint16_t outtime = 0;

    printf("开始进行校准.\r\n");
    
	TP_Drow_Touch_Point(20, 20, RED);
	printf("Please touch point1.\r\n");
    while(1)
    {
        tp_dev.scan(1);
        if((tp_dev.sta & 0xc0) == TP_PRESS_LIFT)
        {
            outtime = 0;
            tp_dev.sta &= ~(1 << 6);
            
            pos_temp[cnt][0] = tp_dev.x;
            pos_temp[cnt][1] = tp_dev.y;
            cnt++;
            
            switch(cnt)
            {
			case 0:

				break;
			case 1:
                    TP_Drow_Touch_Point(20, 20, WHITE); // 清除点1
                    TP_Drow_Touch_Point(lcddev.width - 20, 20, RED); // 画点2
				printf("Please touch point2.\r\n");
                    break;
                case 2:
                    TP_Drow_Touch_Point(lcddev.width - 20, 20, WHITE); // 清除点2
                    TP_Drow_Touch_Point(20, lcddev.height - 20, RED); // 画点3
				printf("Please touch point3.\r\n");
                    break;
                case 3:
                    TP_Drow_Touch_Point(20, lcddev.height - 20, WHITE); // 清除点3
                    TP_Drow_Touch_Point(lcddev.width - 20, lcddev.height - 20, RED); // 画点4
				printf("Please touch point4.\r\n");
                    break;
                case 4:
                    // 开始计算
                    tem1 = abs(pos_temp[0][0] - pos_temp[1][0]);
                    tem2 = abs(pos_temp[0][1] - pos_temp[1][1]);
                    tem1 *= tem1;
                    tem2 *= tem2;
                    d1 = sqrt(tem1 + tem2);
                    
                    tem1 = abs(pos_temp[2][0] - pos_temp[3][0]);
                    tem2 = abs(pos_temp[2][1] - pos_temp[3][1]);
                    tem1 *= tem1;
                    tem2 *= tem2;
                    d2 = sqrt(tem1 + tem2);
                    fac = (float)d1 / d2;
                    
                    if(fac < 0.95 || fac > 1.05 || d1 == 0 || d2 == 0)
                    {
                        cnt = 0;
					TP_Drow_Touch_Point(lcddev.width - 20, lcddev.height - 20, WHITE);
					TP_Drow_Touch_Point(20, 20, RED); // 画点1
                        printf("Calibration failed! Please try again!\r\n");
					printf("Please touch point1.\r\n");
                        continue;
                    }
                    
                    // 计算结果
                    tp_dev.xfac = (float)(lcddev.width - 40) / (pos_temp[1][0] - pos_temp[0][0]);
                    tp_dev.xoff = (lcddev.width - tp_dev.xfac * (pos_temp[1][0] + pos_temp[0][0])) / 2;
                    
                    tp_dev.yfac = (float)(lcddev.height - 40) / (pos_temp[2][1] - pos_temp[0][1]);
                    tp_dev.yoff = (lcddev.height - tp_dev.yfac * (pos_temp[2][1] + pos_temp[0][1])) / 2;
                    
                    if(abs(tp_dev.xfac) > 2 || abs(tp_dev.yfac) > 2)
                    {
                        cnt = 0;
					TP_Drow_Touch_Point(lcddev.width - 20, lcddev.height - 20, WHITE);
					TP_Drow_Touch_Point(20, 20, RED); // 画点1
					printf("Calibration failed! Please try again!\r\n");
					printf("Please touch point1.\r\n");
                        tp_dev.touchtype = !tp_dev.touchtype;
                        if(tp_dev.touchtype)
                        {
                            CMD_RDX = 0X90;
                            CMD_RDY = 0XD0;
                        }
                        else
                        {
                            CMD_RDX = 0XD0;
                            CMD_RDY = 0X90;
                        }
                        continue;
                    }
                    TP_Drow_Touch_Point(lcddev.width - 20, lcddev.height - 20, WHITE);
                    printf("Touch Screen Adjust OK!\r\n");
                    HAL_Delay(1000);
                    TP_Save_Adjdata();
                    return;
            }
        }
        HAL_Delay(10);
        outtime++;
        if(outtime > 1000)
        {
            TP_Get_Adjdata();
            break;
        }
    }
}
  • 初始化
/**
 * @brief  触摸屏初始化
 * @retval 0-初始化失败,1-初始化成功
 */
uint8_t TP_Init(void)
{
    TP_Read_XY(&tp_dev.x, &tp_dev.y);
    AT24CXX_Init();
    
    if(TP_Get_Adjdata())
    {
        return 0;
    }
    else
    {
        TP_Adjust();
        TP_Save_Adjdata();
    }
    TP_Get_Adjdata();
    
    return 1;
}
  • 测试程序
      测试程序会先进行触摸校准,校准完成后可在屏幕上触摸描点
void Touch_Test(void)
{
	TP_Init();
    uint16_t x, y;
    uint8_t touchStatus;

    while (1)
    {
        // 使用 TP_Scan 函数检测触摸状态
        touchStatus = TP_Scan(0); // 0 表示获取屏幕坐标

        if (touchStatus & TP_PRESS_DOWN) // 如果触摸屏被按下
        {
            x = tp_dev.x;
            y = tp_dev.y;
//            printf("Touch detected at: x=%d, y=%d\r\n", x, y);

            // 在触摸点绘制一个大点
            TP_Draw_Big_Point(x, y, BLACK);
        }
        else
        {

        }
    }
}

点此前往github获取完整工程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值