一,屏幕概述
最近在学习lvgl,发现正点的屏幕实在是有点贵,就买了这块屏幕,但发现商家提供的源码是标准库的,这对于一个HAL库的使用者是一件十分头疼的事情,这里笔者给想省钱的读者提供一个HAL驱动的源码。
lcd驱动芯片:ST7796S
触摸芯片:XPT2046
二,修改后源码
lcd.h
#ifndef __LCD_H
#define __LCD_H
/* 头文件 */
#include "main.h"
#include "stdlib.h"
#include "spi.h"
/* 变量别名 */
typedef int32_t s32;
typedef int16_t s16;
typedef int8_t s8;
typedef const int32_t sc32; /*!< Read Only */
typedef const int16_t sc16; /*!< Read Only */
typedef const int8_t sc8; /*!< Read Only */
typedef __IO int32_t vs32;
typedef __IO int16_t vs16;
typedef __IO int8_t vs8;
typedef __I int32_t vsc32; /*!< Read Only */
typedef __I int16_t vsc16; /*!< Read Only */
typedef __I int8_t vsc8; /*!< Read Only */
typedef uint32_t u32;
typedef uint16_t u16;
typedef uint8_t u8;
typedef const uint32_t uc32; /*!< Read Only */
typedef const uint16_t uc16; /*!< Read Only */
typedef const uint8_t uc8; /*!< Read Only */
typedef __IO uint32_t vu32;
typedef __IO uint16_t vu16;
typedef __IO uint8_t vu8;
typedef __I uint32_t vuc32; /*!< Read Only */
typedef __I uint16_t vuc16; /*!< Read Only */
typedef __I uint8_t vuc8; /*!< Read Only */
/* LCD重要参数集 */
typedef struct
{
//LCD 宽度
u16 width;
//LCD 高度
u16 height;
//LCD ID
u16 id;
//横屏还是竖屏控制:0竖屏 1横屏
u8 dir;
//开始写gram指令
u16 wramcmd;
//设置x坐标指令
u16 setxcmd;
//设置y坐标指令
u16 setycmd;
}_lcd_dev;
/* 管理LCD重要参数结构体外部声明 */
extern _lcd_dev lcddev;
/***********************************用户配置区*******************************************/
//定义液晶屏顺时针旋转方向 0为0度旋转,1为90度旋转,2为180度旋转,3为270度旋转
#define USE_HORIZONTAL 1
//定义LCD的尺寸
#define LCD_W 320
#define LCD_H 480
//笔颜色变量外部声明
extern u16 POINT_COLOR;
//背景颜色变量外部声明
extern u16 BACK_COLOR;
/***********************************用户配置区结*****************************************/
/***********************************移植需要更改选项开始**********************************/
//GPIO组类型
#define GPIO_TYPE GPIOB
//背光控制引脚管脚类型随便,还可以接PWM调节亮度 PC13
#define LED GPIO_PIN_13
//片选引脚,管脚类型必需为GPIO_TYPE PB4
#define LCD_CS GPIO_PIN_4
//寄存器/数据选择引脚,管脚类型必需为GPIO_TYPE PB8
#define LCD_RS GPIO_PIN_8
//复位引脚,管脚类型必需为GPIO_TYPE PB6
#define LCD_RST GPIO_PIN_6
/***********************************移植需要更改选项结束**********************************/
/***********************************GPIO输出函数定义开始**********************************/
//GPIO置位(拉高)
#define LCD_CS_SET GPIO_TYPE->BSRR=LCD_CS
#define LCD_RS_SET GPIO_TYPE->BSRR=LCD_RS
#define LCD_RST_SET GPIO_TYPE->BSRR=LCD_RST
//GPIO复位(拉低)
#define LCD_CS_CLR GPIO_TYPE->BSRR=(LCD_CS<<16)
#define LCD_RS_CLR GPIO_TYPE->BSRR=(LCD_RS<<16)
#define LCD_RST_CLR GPIO_TYPE->BSRR=(LCD_RST<<16)
/***********************************GPIO输出函数定义结束**********************************/
/***********************************颜色定义开始*****************************************/
//画笔颜色
#define WHITE 0xFFFF
#define BLACK 0x0000
#define BLUE 0x001F
#define BRED 0XF81F
#define GRED 0XFFE0
#define GBLUE 0X07FF
#define RED 0xF800
#define MAGENTA 0xF81F
#define GREEN 0x07E0
#define CYAN 0x7FFF
#define YELLOW 0xFFE0
//棕色
#define BROWN 0XBC40
//棕红色
#define BRRED 0XFC07
//灰色
#define GRAY 0X8430
//深蓝色
#define DARKBLUE 0X01CF
//浅蓝色
#define LIGHTBLUE 0X7D7C
//灰蓝色
#define GRAYBLUE 0X5458
//浅绿色
#define LIGHTGREEN 0X841F
//浅灰色
#define LIGHTGRAY 0XEF5B
//浅灰色,窗体背景色
#define LGRAY 0XC618
//浅灰蓝色
#define LGRAYBLUE 0XA651
//浅棕蓝色
#define LBBLUE 0X2B12
/***********************************颜色定义结束****************************************/
/***********************************函数声明开始*****************************************/
/*
********************************************LCD上层函数
*/
/* 初始化函数 */
void LCD_Init(void);
/* 清屏函数 */
void LCD_Clear(u16 Color);
/* 坐标设置函数 */
void LCD_SetCursor(u16 Xpos, u16 Ypos);
/* 画点函数 */
void LCD_DrawPoint(u16 x,u16 y);
/* 设置显示窗口函数 */
void LCD_SetWindows(u16 xStar, u16 yStar,u16 xEnd,u16 yEnd);
/* 屏幕方向设置函数 */
void LCD_direction(u8 direction );
/* 块填充函数 */
void LCD_Color_Fill(u16 sx, u16 sy, u16 ex, u16 ey, u16* color);
/* 画十字函数 */
void lcd_draw_cross( u16 x, u16 y );
/*
********************************************LCD基本驱动函数
*/
void LCD_WR_REG(u8 data);
void LCD_WriteReg(u8 LCD_Reg, u16 LCD_RegValue);
void LCD_WR_DATA(u8 data);
void LCD_WriteRAM_Prepare(void);
void Lcd_WriteData_16Bit(u16 Data);
/***********************************函数声明结束*****************************************/
#endif
lcd.c
/* 我的LCD头文件 */
#include "lcd.h"
/* 初始化LCD参数结构体 */
_lcd_dev lcddev;
/* 设置画笔颜色 */
u16 POINT_COLOR = RED;
/* 设置背景颜色 */
u16 BACK_COLOR = 0xFFFF;
/*
********************************************LCD基本驱动函数
*/
/*
* 名字:LCD_WR_REG
* 功能:将8位命令写入LCD屏幕
* 参数data:要写入的命令值
* 返回值:无
*/
void LCD_WR_REG(u8 data)
{
u8 d[1];
d[0] = data;
LCD_CS_CLR;
LCD_RS_CLR;
HAL_SPI_Transmit( &hspi2, d, 1, 50 );
LCD_CS_SET;
}
/*
* 名字:LCD_WR_DATA
* 功能:将8位数据写入LCD屏幕
* 参数data:要写入的数据值
* 返回值:无
*/
void LCD_WR_DATA(u8 data)
{
u8 d[1];
d[0] = data;
LCD_CS_CLR;
LCD_RS_SET;
HAL_SPI_Transmit( &hspi2, d, 1, 50 );
LCD_CS_SET;
}
/*
* 名字:LCD_WriteReg
* 功能:将数据写入寄存器
* 参数LCD_Reg:寄存器地址
* 参数LCD_RegValue:要写入的数据
* 返回值:无
*/
void LCD_WriteReg(u8 LCD_Reg, u16 LCD_RegValue)
{
LCD_WR_REG(LCD_Reg);
LCD_WR_DATA(LCD_RegValue);
}
/*
* 名字LCD_WriteRAM_Prepare
* 功能:写GRAM前的准备函数
* 参数:无
* 返回值:无
*/
void LCD_WriteRAM_Prepare(void)
{
LCD_WR_REG(lcddev.wramcmd);
}
/*
* 名字:Lcd_WriteData_16Bit
* 功能:将16位数据写入LCD屏幕
* 参数Data:要写入的数据
* 返回值:无
*/
void Lcd_WriteData_16Bit(u16 Data)
{
u8 buf[2];
buf[0] = Data>>8;
buf[1] = Data;
LCD_CS_CLR;
LCD_RS_SET;
HAL_SPI_Transmit( &hspi2, buf, 2, 50 );
LCD_CS_SET;
}
/*
********************************************LCD上层函数
*/
/*
* 名字:画点函数
* 功能:在指定位置写入像素数据
* 参数x:像素的x坐标
* 参数y:像素的y坐标
* 返回值:无
*/
void LCD_DrawPoint(u16 x,u16 y)
{
//设置光标位置
LCD_SetCursor(x,y);
Lcd_WriteData_16Bit(POINT_COLOR);
}
/*
* 名字:清屏函数
* 功能:全屏填充LCD屏幕
* 参数color:填充颜色
* 返回值:无
*/
void LCD_Clear(u16 Color)
{
unsigned int i,m;
LCD_SetWindows(0,0,lcddev.width-1,lcddev.height-1);
LCD_CS_CLR;
LCD_RS_SET;
for(i=0;i<lcddev.height;i++)
{
for(m=0;m<lcddev.width;m++)
{
Lcd_WriteData_16Bit(Color);
}
}
LCD_CS_SET;
}
/*
* 名字:复位函数
* 功能:复位lcd
* 参数:无
* 返回值:无
*/
void LCD_RESET(void)
{
LCD_RST_CLR;
HAL_Delay(100);
LCD_RST_SET;
HAL_Delay(50);
}
/*
* 名字:LCD初始化函数
* 功能:初始化LCD屏幕
* 参数:无
* 返回值:无
*/
void LCD_Init(void)
{
/* LCD 复位 */
LCD_RESET();
/* ST7796S初始化 */
LCD_WR_REG(0xF0);
LCD_WR_DATA(0xC3);
LCD_WR_REG(0xF0);
LCD_WR_DATA(0x96);
LCD_WR_REG(0x36);
LCD_WR_DATA(0x68);
LCD_WR_REG(0x3A);
LCD_WR_DATA(0x05);
LCD_WR_REG(0xB0);
LCD_WR_DATA(0x80);
LCD_WR_REG(0xB6);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x02);
LCD_WR_REG(0xB5);
LCD_WR_DATA(0x02);
LCD_WR_DATA(0x03);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x04);
LCD_WR_REG(0xB1);
LCD_WR_DATA(0x80);
LCD_WR_DATA(0x10);
LCD_WR_REG(0xB4);
LCD_WR_DATA(0x00);
LCD_WR_REG(0xB7);
LCD_WR_DATA(0xC6);
LCD_WR_REG(0xC5);
LCD_WR_DATA(0x24);
LCD_WR_REG(0xE4);
LCD_WR_DATA(0x31);
LCD_WR_REG(0xE8);
LCD_WR_DATA(0x40);
LCD_WR_DATA(0x8A);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x29);
LCD_WR_DATA(0x19);
LCD_WR_DATA(0xA5);
LCD_WR_DATA(0x33);
LCD_WR_REG(0xC2);
LCD_WR_REG(0xA7);
LCD_WR_REG(0xE0);
LCD_WR_DATA(0xF0);
LCD_WR_DATA(0x09);
LCD_WR_DATA(0x13);
LCD_WR_DATA(0x12);
LCD_WR_DATA(0x12);
LCD_WR_DATA(0x2B);
LCD_WR_DATA(0x3C);
LCD_WR_DATA(0x44);
LCD_WR_DATA(0x4B);
LCD_WR_DATA(0x1B);
LCD_WR_DATA(0x18);
LCD_WR_DATA(0x17);
LCD_WR_DATA(0x1D);
LCD_WR_DATA(0x21);
LCD_WR_REG(0XE1);
LCD_WR_DATA(0xF0);
LCD_WR_DATA(0x09);
LCD_WR_DATA(0x13);
LCD_WR_DATA(0x0C);
LCD_WR_DATA(0x0D);
LCD_WR_DATA(0x27);
LCD_WR_DATA(0x3B);
LCD_WR_DATA(0x44);
LCD_WR_DATA(0x4D);
LCD_WR_DATA(0x0B);
LCD_WR_DATA(0x17);
LCD_WR_DATA(0x17);
LCD_WR_DATA(0x1D);
LCD_WR_DATA(0x21);
LCD_WR_REG(0X36);
LCD_WR_DATA(0xEC);
LCD_WR_REG(0xF0);
LCD_WR_DATA(0xC3);
LCD_WR_REG(0xF0);
LCD_WR_DATA(0x69);
LCD_WR_REG(0X13);
LCD_WR_REG(0X11);
LCD_WR_REG(0X29);
/* 设置LCD显示方向 */
LCD_direction(USE_HORIZONTAL);
/* 清全屏 */
LCD_Clear(LIGHTBLUE);
}
/*
* 名字:窗口设置函数
* 功能:设置LCD显示窗口大小
* 参数xStar:LCD显示窗口的开始x坐标
* 参数yStar:LCD显示窗口的开始y坐标
* 参数xEnd:LCD显示窗口的结束x坐标
* 参数yEnd:LCD显示窗口的结束y坐标
* 返回值:无
*/
void LCD_SetWindows(u16 xStar, u16 yStar,u16 xEnd,u16 yEnd)
{
LCD_WR_REG(lcddev.setxcmd);
LCD_WR_DATA(xStar>>8);
LCD_WR_DATA(0x00FF&xStar);
LCD_WR_DATA(xEnd>>8);
LCD_WR_DATA(0x00FF&xEnd);
LCD_WR_REG(lcddev.setycmd);
LCD_WR_DATA(yStar>>8);
LCD_WR_DATA(0x00FF&yStar);
LCD_WR_DATA(yEnd>>8);
LCD_WR_DATA(0x00FF&yEnd);
//开始写入GRAM
LCD_WriteRAM_Prepare();
}
/*
* 名字:设置光标函数
* 功能:设置光标位置
* 参数Xpos:x坐标
* 参数Ypos:y坐标
* 返回值:无
*/
void LCD_SetCursor(u16 Xpos, u16 Ypos)
{
LCD_SetWindows(Xpos,Ypos,Xpos,Ypos);
}
/*
* 名字:LCD方向函数
* 功能:设置LCD的显示方向
* 参数direction:为0不旋转
* 参数direction:为1旋转90度
* 参数direction:为2旋转180度
* 参数direction:为3旋转270度
* 返回值:无
*/
void LCD_direction(u8 direction)
{
lcddev.setxcmd=0x2A;
lcddev.setycmd=0x2B;
lcddev.wramcmd=0x2C;
switch(direction){
case 0:
lcddev.width=LCD_W;
lcddev.height=LCD_H;
LCD_WriteReg(0x36,(1<<3)|(1<<6));
break;
case 1:
lcddev.width=LCD_H;
lcddev.height=LCD_W;
LCD_WriteReg(0x36,(1<<3)|(1<<5));
break;
case 2:
lcddev.width=LCD_W;
lcddev.height=LCD_H;
LCD_WriteReg(0x36,(1<<3)|(1<<7));
break;
case 3:
lcddev.width=LCD_H;
lcddev.height=LCD_W;
LCD_WriteReg(0x36,(1<<3)|(1<<7)|(1<<6)|(1<<5));
break;
default:break;
}
}
/*
* 名字:LCD画十字函数
* 功能:在LCD上画十字
* 参数x:十字的中心x轴位置
* 参数y:十字的中心y轴位置
* 返回值:无
*/
void lcd_draw_cross( u16 x, u16 y )
{
u16 startX = x-6;
u16 startY = y-6;
for( u8 i = 0;i < 12;++i )
{
LCD_DrawPoint( startX, y );
++startX;
}
for( u8 j = 0; j < 12;++j )
{
LCD_DrawPoint( x, startY );
++startY;
}
}
/*
* 名字:LCD色块填充函数
* 功能:进行色块填充
* 参数sx:色块填充的开始x坐标
* 参数sy:色块填充的开始y坐标
* 参数ex:色块填充的结束x坐标
* 参数ey:色块填充的结束y坐标
* 参数color:要填充的颜色指针
* 返回值:无
*/
void LCD_Color_Fill(u16 sx, u16 sy, u16 ex, u16 ey, u16* color)
{
u16 height, width;
width = ex - sx + 1;
height = ey - sy + 1;
LCD_SetWindows(sx,sy,ex,ey);
for(uint32_t y = 0; y <width*height; y++)
{
Lcd_WriteData_16Bit(*color);
color++;
}
}
touch.h
#ifndef __TOUCH_H__
#define __TOUCH_H__
#include "main.h"
#include "stdio.h"
#include "stdlib.h"
/*****************************************移植需更改区开始********************************/
//T_PEN为中断引脚0有效,为0即为有按下
#define T_PEN HAL_GPIO_ReadPin(GPIOG, GPIO_PIN_12)
#define T_MISO HAL_GPIO_ReadPin(GPIOD, GPIO_PIN_11)
#define T_MOSI(x) do{ x ? \
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET) : \
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_RESET); \
}while(0)
#define T_CLK(x) do{ x ? \
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_SET) : \
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_RESET); \
}while(0)
#define T_CS(x) do{ x ? \
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9, GPIO_PIN_SET) : \
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9, GPIO_PIN_RESET); \
}while(0)
/*****************************************移植需更改区结束******************************/
/* 未校准坐标获取函数 */
uint16_t tp_write_and_read_ad(uint8_t cmd_data);
/* 校准后的坐标获取函数 */
void myGetX_Y( int xyBuf[2] );
#endif
touch.c
/* 我的触摸头文件 */
#include "touch.h"
/*
*名字:MyDelayUs
*参数us:要延时的时间
*作用:实现微秒延时
*返回值:无
*/
void MyDelayUs(uint32_t us)
{
__IO uint32_t currentTicks = SysTick->VAL;
const uint32_t tickPerMs = SysTick->LOAD + 1;
const uint32_t nbTicks = ((us - ((us > 0) ? 1 : 0)) * tickPerMs) / 1000;
uint32_t elapsedTicks = 0;
__IO uint32_t oldTicks = currentTicks;
do {
currentTicks = SysTick->VAL;
elapsedTicks += (oldTicks < currentTicks) ? tickPerMs + oldTicks - currentTicks :
oldTicks - currentTicks;
oldTicks = currentTicks;
} while (nbTicks > elapsedTicks);
}
/*
*名字:tp_write_and_read_ad
*参数cmd_data:读取命令
*作用:获取点击的坐标
*返回值:无
*/
uint16_t tp_write_and_read_ad(uint8_t cmd_data)
{
uint16_t rd_data = 0;
/* 开始状态 */
T_CLK(0);
T_MOSI(0);
/* 选中触摸IC */
T_CS(0);
/* MCU向XTP2046发送数据 */
for(uint8_t i = 0; i < 8; i++ )
{
/* MCU开始准备数据 */
T_CLK(0);
/* 数据要取最高位发送,MSB */
if (cmd_data & 0x80)
{
T_MOSI(1);
}
else
{
T_MOSI(0);
}
MyDelayUs(1);
/* MCU发送数据,XTP2046开始读取 */
T_CLK(1);
/* XTP2046读取数据完成 */
MyDelayUs(1);
/* 将次高位变为最高位,用于下次取最高位 */
cmd_data <<= 1;
}
/* 过滤忙信号 */
T_CLK(0);
MyDelayUs(1);
T_CLK(1);
MyDelayUs(1);
/* MCU读取XTP2046返回数据 */
for(uint8_t i = 0; i < 16; i++ )
{
/* XTP2046开始准备数据 */
T_CLK(0);
MyDelayUs(1);
/* MCU开始读取数据 */
T_CLK(1);
/* 空出最低位用来保存读取到的数据 */
rd_data <<= 1;
/* MCU读取数据 */
rd_data |= T_MISO;
MyDelayUs(1);
}
/* 结束状态 */
T_CLK(0);
/* 取消选中触摸IC */
T_CS(1);
return (rd_data >>= 4);
}
/*
*名字:myGetX_Y
*参数xyBuf:坐标存储数组
*作用:获取校准后点击的坐标
*返回值:无
*/
void myGetX_Y( int xyBuf[2] )
{
//x
xyBuf[0] = ((4095-tp_write_and_read_ad(0x90))-2015)/7.82+240;
//y
xyBuf[1] = ((4095-tp_write_and_read_ad(0xD0))-2150)/12+160;
}
三,移植说明
LCD部分
首先在你将这些.c和.h文件加入你的工程前你需要在cubemx进行一些配置:
1.屏幕LED管脚管脚连接到STM32的任意管脚,笔者选的是GPIOC_13,如果读者要改为别的引脚需要在lcd.h的《移植需要更改选项开始》的注释下进行简单的修改,最后将管脚配置为推挽输出,拉高。
2.屏幕的CS、RS、RESET分别配置为GPIOB类型的4号,8号,6号管脚,配置为推挽输出,拉高,速度高。同样要进行修改的话同上需要在lcd.h的《移植需要更改选项开始》的注释下进行简单的修改。CS、RS、RESET分别对应代码的LCD_CS、LCD_RS、LCD_RST。
3.屏幕lcd部分剩下的MOSI、MISO、SCK三个管脚,在cubemx中顺便初始化一个SPI将对应管脚连接即可,笔者采用的是spi2,速度为21MHZ。
4.应为笔者的芯片为STM32F429故《GPIO输出函数定义开始》注释下管脚拉低部分写法为:
//GPIO复位(拉低)
#define LCD_CS_CLR GPIO_TYPE->BSRR=(LCD_CS<<16)
#define LCD_RS_CLR GPIO_TYPE->BSRR=(LCD_RS<<16)
#define LCD_RST_CLR GPIO_TYPE->BSRR=(LCD_RST<<16)
如果你的芯片为STM32F1系列或者GPIO有BRR寄存器的芯片你的写法应该为:
//GPIO复位(拉低)
#define LCD_CS_CLR GPIO_TYPE->BRR=LCD_CS
#define LCD_RS_CLR GPIO_TYPE->BRR=LCD_RS
#define LCD_RST_CLR GPIO_TYPE->BRR=LCD_RST
TOUCH部分
该部分的连接采用的是软件模拟SPI的方式进行连接。
1.T_IQR对应代码的T_PEN宏定义,连接STM32的GPIOG_12管脚,配置为输入模式,拉高。同样需要修改为别的引脚的话需要,在tuoch.h《移植需更改区开始》的注释下进行行相应的简单的宏定义需改。该管脚为中断管脚,按下后该管脚被置0。
2.T_DO对应代码的T_MISO,连接到GPIOD_11,配置为输入模式,无上下拉。需修改管脚同上。
3.T_DIN对应代码的T_MOSI(x),连接到GPIOD_12,配置为推挽输出,无上下拉,速度高。需修改管脚同上。
4.T_CS和T_CLK分别对应代码的T_CS(x)和T_CLK(x),分别连接到GPIOC_9和GPIOC_7,都配置为推挽输出,无上下拉,速度高。需修改管脚同上。
5.tp_write_and_read_ad(0xD0)将返回读到的x坐标,tp_write_and_read_ad(0x90)返回读到的y坐标。
四,触摸功能的校准
笔者采用的是五点校准的办法,首先读者需要调用lcd_draw_cross()函数在屏幕这五个地方显示+的符号。
点击这些地方你会发现读到的坐标和你设置显示的坐标并不一致,例如你调用lcd_draw_cross()设置LCD屏幕右下角(24,24)即1处显示十字,但是你点击该处获取的触摸坐标的可能是(3807,3908)。这也是我们要进行校准的原因。 经过笔者对五个地方的读取发现lcd驱动芯片的坐标体系和触摸驱动芯片的不一致,如上图所示,且范围也不同,触摸的坐标体系X和Y的最大值都是4095,而lcd驱动的坐标体系X的最大值为480,Y的最大值为320。
接下来我们要将坐标进行统一,我们把触摸读到的Y坐标当作X坐标,把触摸读到的X坐标当作Y坐标,并且都用4095减它们,即可完成统一。看代码
x = 4095 - tp_write_and_read_ad(0x90);
y = 4095 - tp_write_and_read_ad(0xD0);
如果此时你再次点击(24,24)这里它就可能变成了(187,288),点击中间的十字(即5处)就能得到(2015,2150),是不是非常接近了,但比例还有问题,我们需要进一步处理。此时我们就需要用到这个式子来进行校准,它的原理也非常的简单。
X = ( XL - XLC ) / KX + XC
Y = ( YL - YLC ) / KY + YC
参数解读:
XL:点击的x值,即上面经过处理的x值,(187,288)中的187
YL:点击的y值,即上面经过处理的y值,(187,288)中的288
YLC:点击五个十字中,中间那个十字的得到的y值,(2015,2150)中的2150
XLC:点击五个十字中,中间那个十字的得到的x值,(2015,2150)中的2015
XC:lcd驱动芯片坐标体系中屏幕中心的x值,如你的屏幕为320*480横屏显示,则该值为240
YC:lcd驱动芯片坐标体系中屏幕中心的y值,如你的屏幕为320*480横屏显示,则该值为160
KX:触摸的坐标体系算出的3和2的距离与lcd驱动的坐标体系算出3和2的距离比值。例如你调用lcd_draw_cross()设置3和2的位置分别为(456,296)和(24,296),而经过坐标轴统一的触摸坐标体系,触摸这两次处的位置分别为(3566,3552)和(187,3552),则KX为7.82左右。
KY:触摸的坐标体系算出的2和1的距离与lcd驱动的坐标体系算出2和1的距离比值
X:校准过后的触摸x坐标值
Y:校准过后的触摸Y坐标值
如果需要更详细的校准介绍可以看这篇文章:STM32f103的电阻触摸屏的五点校正算法 - 知乎
最终代码:
jx = ( x - 2015 )/7.82+240;
jy = ( y - 2150 )/12+160;
五,结束语
有移植问题可以给我留言!!文章有错欢迎纠正!!!!