本帖最后由 donatello 于 2017-7-21 12:57 编辑
【SPI480272高速工业液晶屏试用体验】使用串口打印触摸坐标
SPI480272屏幕的触摸模块也是一个SPI总线的主控芯片,官方例程中对触摸屏SPI信号的处理是采用IO模拟SPI的方法,这样的考虑有二:第一,DIP40封装的STC12单片机只有一个硬件SPI接口,如果彩屏显示SPI信号和触摸处理SPI信号这两组信号接在同一组MISO、MOSI、CLK上面,并用CS引脚切换的话,会严重影响彩屏显示的效果;第二,触摸屏SPI信号对SPI频率有上限要求,频率最快不能高于125KHz,因此,官方例程采用的是硬件SPI信号驱动彩屏,IO模拟SPI信号处理触摸屏的方法。
另外,SPI480272屏幕的触摸板坐标和屏幕坐标的取值并不是重合的,触摸板坐标的取值为200+到4800+(相对坐标,x0、y0取值均为此范围内),而屏幕坐标的取值则是x:0到479,y:0到271,是绝对坐标,转换公式为:
x=(x0-X0_AD)*10/TLx;
y=(y0-Y0_AD)*10/TLy;
其中x、y为屏幕绝对坐标变量;x0、y0为触摸板相对坐标变量;X0_AD=148,Y0_AD=365为偏移量常数;TLx=77, TLy=128为比率常数,用此公式转换之后,触摸板相对坐标就变成有实用意义的屏幕绝对坐标了。再来看下官方例程中对触摸捕捉的处理:
unsigned char TOUCH_GetAdXY(unsigned int *x,unsigned int *y)
{
#define TIME 10 //循环读数次数 最大16次
unsigned char t=0,t1,count=0;
unsigned char X_EABLE=0,Y_EABLE=0;//数据有效指示位 1 有效
unsigned int databuffer={5,7,9,3,2,6,4,0,3,1};//数据组
unsigned int i=0;
while(T_INT==0&&count
其中
if(X_EABLE&&Y_EABLE)
{
TOUCH_result=1;
TOUCH_X=(*x-X0_AD)*10/TLx; //(Xt,Yt)为触摸板的坐标
TOUCH_Y=(*y-Y0_AD)*10/TLy; //(TLCD_x,TLCD_y)为触摸板坐标对应的LCD上的坐标
if(TOUCH_X>LCD_XSIZE) TOUCH_X=LCD_XSIZE;
if(TOUCH_Y>LCD_YSIZE) TOUCH_Y=LCD_YSIZE;
return 1;
}
这段代码是用于触摸捕捉消抖的,实际应用中加入了此段代码会使单位时间(大概100ms)内的几个点的触摸坐标完全一样,但是我们在测试中可以不要这种效果,因此可以把if注释掉,看下我的触摸捕捉代码:
unsigned char TOUCH_GetAdXY(unsigned int *x,unsigned int *y)
{
unsigned char t=0,t1,count=0;
unsigned char X_EABLE=0,Y_EABLE=0;//数据有效指示位 1 有效
unsigned int databuffer={5,7,9,3,2,6,4,0,3,1};//数据组
unsigned int i=0,x0,y0;
while(T_INT==0&&countdatabuffer)//升序排列
{
i=databuffer;
databuffer=databuffer;
databuffer=i;
t1=1;
}
}
}while(t1);
i=(databuffer+databuffer+databuffer)/3;
x0=i;
if(databuffer>databuffer) //抖动检测,甩掉乱点
{ if((databuffer-databuffer)<3) X_EABLE=1; }
else
{ if((databuffer-databuffer)<3) X_EABLE=1; }
}
count=0;
while(T_INT==0&&countdatabuffer)//升序排列
{
i=databuffer;
databuffer=databuffer;
databuffer=i;
t1=1;
}
}
}while(t1);
i=(databuffer+databuffer+databuffer)/3;
y0=0xfff-i;
//if(databuffer>databuffer) //抖动检测,甩掉乱点
//{ if((databuffer-databuffer)<3) Y_EABLE=1; }
//else
//{ if((databuffer-databuffer)<3) Y_EABLE=1; }
}
//将获取的触摸AD值转换成对应液晶坐标
*x=(x0-X0_AD)*10/TLx;
*y=(y0-Y0_AD)*10/TLy;
return 0;
}
这段代码的实际效果与常识所想的一样,每个点的触摸坐标都是基本上不一样的,这个消抖操作在实际应用中视乎情况添加。
再顺便说说51的串口处理,51的串口是直接与定时器挂钩的,因此配置串口就免不了要配置定时器。在配置了与串口有关的两个寄存器SCON = 0x50;TMOD = 0x20;之后,设置定时器1的重载值即TH1 = 256-(12000000/baud/384); 注意,波特率baud最高只能取9600(19200没试过,或许也可以?),不然(12000000/baud/384)式子中baud再大,整个式子的结果也只能是0。
void UART_Init(int baud)
{
SCON = 0x50;
TMOD = 0x20;
TH1 = 256-(12000000/baud/384);
//ES = 1;
//EA = 1;
TR1 = 1;
//启动定时器1
}
发送函数:
void UART_Send_String(char s)
{
int i=0;
while(s!='\0')
{
SBUF = s;
while(TI==0);
TI=0;
i++;
}
}
主循环:
while(1)
{
if(T_INT==0)
{
TOUCH_GetAdXY(&x,&y);
sprintf(s,"X:%d Y:%d\n",(int)x,(int)y);
UART_Send_String(s);
Delay_ms(100);
}
}
注意,51使用sprintf的话,sprintf的变量一定要加强制类型转换如(int)、(char)、(float),不然输出会出问题。
看看效果:
上传工程文件。
本帖最后由 donatello 于 2017-7-21 12:57 编辑
【SPI480272高速工业液晶屏试用体验】使用串口打印触摸坐标
SPI480272屏幕的触摸模块也是一个SPI总线的主控芯片,官方例程中对触摸屏SPI信号的处理是采用IO模拟SPI的方法,这样的考虑有二:第一,DIP40封装的STC12单片机只有一个硬件SPI接口,如果彩屏显示SPI信号和触摸处理SPI信号这两组信号接在同一组MISO、MOSI、CLK上面,并用CS引脚切换的话,会严重影响彩屏显示的效果;第二,触摸屏SPI信号对SPI频率有上限要求,频率最快不能高于125KHz,因此,官方例程采用的是硬件SPI信号驱动彩屏,IO模拟SPI信号处理触摸屏的方法。
另外,SPI480272屏幕的触摸板坐标和屏幕坐标的取值并不是重合的,触摸板坐标的取值为200+到4800+(相对坐标,x0、y0取值均为此范围内),而屏幕坐标的取值则是x:0到479,y:0到271,是绝对坐标,转换公式为:
x=(x0-X0_AD)*10/TLx;
y=(y0-Y0_AD)*10/TLy;
其中x、y为屏幕绝对坐标变量;x0、y0为触摸板相对坐标变量;X0_AD=148,Y0_AD=365为偏移量常数;TLx=77, TLy=128为比率常数,用此公式转换之后,触摸板相对坐标就变成有实用意义的屏幕绝对坐标了。再来看下官方例程中对触摸捕捉的处理:
unsigned char TOUCH_GetAdXY(unsigned int *x,unsigned int *y)
{
#define TIME 10 //循环读数次数 最大16次
unsigned char t=0,t1,count=0;
unsigned char X_EABLE=0,Y_EABLE=0;//数据有效指示位 1 有效
unsigned int databuffer={5,7,9,3,2,6,4,0,3,1};//数据组
unsigned int i=0;
while(T_INT==0&&countdatabuffer)//升序排列
{
i=databuffer;
databuffer=databuffer;
databuffer=i;
t1=1;
}
}
}while(t1);
i=(databuffer+databuffer+databuffer)/3;
if(TOUCH_MIRROR_X) *x=0xfff-i; //调整坐标系方向
else *x=i;
if(databuffer>databuffer) //抖动检测,甩掉乱点
{ if((databuffer-databuffer)<3) X_EABLE=1; }
else
{ if((databuffer-databuffer)<3) X_EABLE=1; }
}
count=0;
while(T_INT==0&&countdatabuffer)//升序排列
{
i=databuffer;
databuffer=databuffer;
databuffer=i;
t1=1;
}
}
}while(t1);
i=(databuffer+databuffer+databuffer)/3;
if(TOUCH_MIRROR_Y) *y=0xfff-i; //调整坐标系方向
else *y=i;
if(databuffer>databuffer) //抖动检测,甩掉乱点
{ if((databuffer-databuffer)<3) Y_EABLE=1; }
else
{ if((databuffer-databuffer)<3) Y_EABLE=1; }
}
//==========================将获取的触摸AD值转换成对应液晶坐标
if(X_EABLE&&Y_EABLE)
{
TOUCH_result=1;
TOUCH_X=(*x-X0_AD)*10/TLx; //(Xt,Yt)为触摸板的坐标
TOUCH_Y=(*y-Y0_AD)*10/TLy; //(TLCD_x,TLCD_y)为触摸板坐标对应的LCD上的坐标
if(TOUCH_X>LCD_XSIZE) TOUCH_X=LCD_XSIZE;
if(TOUCH_Y>LCD_YSIZE) TOUCH_Y=LCD_YSIZE;
return 1;
}
else return 0;
}
其中
if(X_EABLE&&Y_EABLE)
{
TOUCH_result=1;
TOUCH_X=(*x-X0_AD)*10/TLx; //(Xt,Yt)为触摸板的坐标
TOUCH_Y=(*y-Y0_AD)*10/TLy; //(TLCD_x,TLCD_y)为触摸板坐标对应的LCD上的坐标
if(TOUCH_X>LCD_XSIZE) TOUCH_X=LCD_XSIZE;
if(TOUCH_Y>LCD_YSIZE) TOUCH_Y=LCD_YSIZE;
return 1;
}
这段代码是用于触摸捕捉消抖的,实际应用中加入了此段代码会使单位时间(大概100ms)内的几个点的触摸坐标完全一样,但是我们在测试中可以不要这种效果,因此可以把if注释掉,看下我的触摸捕捉代码:
unsigned char TOUCH_GetAdXY(unsigned int *x,unsigned int *y)
{
unsigned char t=0,t1,count=0;
unsigned char X_EABLE=0,Y_EABLE=0;//数据有效指示位 1 有效
unsigned int databuffer={5,7,9,3,2,6,4,0,3,1};//数据组
unsigned int i=0,x0,y0;
while(T_INT==0&&countdatabuffer)//升序排列
{
i=databuffer;
databuffer=databuffer;
databuffer=i;
t1=1;
}
}
}while(t1);
i=(databuffer+databuffer+databuffer)/3;
x0=i;
if(databuffer>databuffer) //抖动检测,甩掉乱点
{ if((databuffer-databuffer)<3) X_EABLE=1; }
else
{ if((databuffer-databuffer)<3) X_EABLE=1; }
}
count=0;
while(T_INT==0&&countdatabuffer)//升序排列
{
i=databuffer;
databuffer=databuffer;
databuffer=i;
t1=1;
}
}
}while(t1);
i=(databuffer+databuffer+databuffer)/3;
y0=0xfff-i;
//if(databuffer>databuffer) //抖动检测,甩掉乱点
//{ if((databuffer-databuffer)<3) Y_EABLE=1; }
//else
//{ if((databuffer-databuffer)<3) Y_EABLE=1; }
}
//将获取的触摸AD值转换成对应液晶坐标
*x=(x0-X0_AD)*10/TLx;
*y=(y0-Y0_AD)*10/TLy;
return 0;
}
这段代码的实际效果与常识所想的一样,每个点的触摸坐标都是基本上不一样的,这个消抖操作在实际应用中视乎情况添加。
再顺便说说51的串口处理,51的串口是直接与定时器挂钩的,因此配置串口就免不了要配置定时器。在配置了与串口有关的两个寄存器SCON = 0x50;TMOD = 0x20;之后,设置定时器1的重载值即TH1 = 256-(12000000/baud/384); 注意,波特率baud最高只能取9600(19200没试过,或许也可以?),不然(12000000/baud/384)式子中baud再大,整个式子的结果也只能是0。
void UART_Init(int baud)
{
SCON = 0x50;
TMOD = 0x20;
TH1 = 256-(12000000/baud/384);
//ES = 1;
//EA = 1;
TR1 = 1;
//启动定时器1
}
发送函数:
void UART_Send_String(char s)
{
int i=0;
while(s!='\0')
{
SBUF = s;
while(TI==0);
TI=0;
i++;
}
}
主循环:
while(1)
{
if(T_INT==0)
{
TOUCH_GetAdXY(&x,&y);
sprintf(s,"X:%d Y:%d\n",(int)x,(int)y);
UART_Send_String(s);
Delay_ms(100);
}
}
注意,51使用sprintf的话,sprintf的变量一定要加强制类型转换如(int)、(char)、(float),不然输出会出问题。
看看效果:
上传工程文件。