打印

百为STM32开发板教程之六——触摸画板程序

[复制链接]
5696|21
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
xi_liang|  楼主 | 2013-7-20 14:05 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
百为STM32开发板教程之六——触摸画板程序

一、四线电阻触摸屏的结构与工作原理
二、ADS7843触摸屏控制器与触摸坐标读取
三、触摸校准原理与算法


一、四线电阻触摸屏的结构与工作原理
1、四线电阻触摸屏主要由三部分构成:两层透明导体层、隔离层和电极。




2、触摸的检测。当在电极Y-和Y+上加电压时,从未加电压的X+或X-上可以读出触摸点的电压。同样在X-和X+上加电压时,可以从Y+或Y-上读出另一个方向的电压。


3、触摸屏的排线引出有4个信号:XL,YD,XR,YU:


这四个信号是接到ADS7843(ADS7843和TSC2046、XPT2046都是兼容的)上的,看百为stm32开发板光盘\原理图\tft_2.8_lcd_v3.0.pdf就知道了:





这里为什么YU接的是Y-而不是Y+呢,我的理解是这样的,因为LCD的坐标系是这样的:

所以默认把Y-和Y+倒过来了。


二、ADS7843触摸屏控制器与触摸坐标读取

1、ADS7843引脚定义


2、ADS7843典型应用电路

3、ADS7843寄存器操作。ADS7843的控制字结构如下:

其中S为数据传输起始标志位,该位必为"1"。
A2~A0进行信道选择(见表2和3)。
MODE用来选择A/D转换的精度,"1"选择8位,"0"选择12位。
SER/选择参考电压的输入模式(见表2和3)。
PD1、PD0选择省电模式:"00"省电模式允许,在两次A/D转换之间掉电,且中断允许;"01"同"00",只是不允许中断;"10"保留;"11"禁止省电模式。

我们这里用的是电压差动输入模式,12位精度,省电模式。所以要读取X坐标,S = 1,A2 A1 A0 = 0 0 1,SER/DFR = 0,PD1 PD0 = 00
即读X坐标时控制字要为0x90,同样得出读Y坐标时控制字要为0xD0(A2 A1 A0 = 1 0 1)。

4、读取触摸坐标程序设计
ADS7843控制器的PENIRQ引脚,当有触摸按下时,该引脚会输出低电平。所以程序中可以采用中断的方式检测触摸,也可以用查询方式检测触摸,
我们这里采用第二种方式。

PENIRQ引脚在百为STM32开发板上是接到STM32的PB10的,所以检测并读取坐标程序如下:
void getxy(int *x, int *y)
{
int i;
*x=0;
*y=0;
while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10)==Bit_SET);  //检测低电平,即检测是否有触摸按下
for(i=0; i<10; i++)
{
   *y += SPI_TOUCH_Read_X();
   *x += SPI_TOUCH_Read_Y();
}  
while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10)==Bit_RESET);
*x=*x/10;
*y=*y/10;
}

读X坐标程序:
u16 SPI_TOUCH_Read_X(void)
{
  u16 xPos = 0, Temp = 0, Temp0 = 0, Temp1 = 0;

  /* Select the TP: Chip Select low */
  SPI_TOUCH_CS_LOW();
SPI_Delay(10);
  /* Send Read xPos command */
  SPI_TOUCH_SendByte(0x90);
SPI_Delay(10);
  /* Read a byte from the TP */
  Temp0 = SPI_TOUCH_ReadByte();
SPI_Delay(10);  
  /* Read a byte from the TP */
  Temp1 = SPI_TOUCH_ReadByte();  
SPI_Delay(10);
  /* Deselect the TP: Chip Select high */
  SPI_TOUCH_CS_HIGH();

  Temp = (Temp0 << 8) | Temp1;
  
  xPos = Temp>>3;

  return xPos;
}

读Y坐标程序:
u16 SPI_TOUCH_Read_Y(void)
{
  u16 yPos = 0, Temp = 0, Temp0 = 0, Temp1 = 0;

  /* Select the TP: Chip Select low */
  SPI_TOUCH_CS_LOW();
SPI_Delay(10);
  /* Send Read yPos command */
  SPI_TOUCH_SendByte(0xD0);
SPI_Delay(10);
  /* Read a byte from the TP */
  Temp0 = SPI_TOUCH_ReadByte();
  SPI_Delay(10);
  /* Read a byte from the TP */
  Temp1 = SPI_TOUCH_ReadByte();  
SPI_Delay(10);
  /* Deselect the TP: Chip Select high */
  SPI_TOUCH_CS_HIGH();

  Temp = (Temp0 << 8) | Temp1;
  
  yPos = Temp>>3;

  return yPos;
}


三、触摸校准原理与算法

1、为什么需要触摸校准呢?
因为触摸屏和LCD显示屏坐标之间存在误差,这误差包括比例系数、机械不同轴性等。LCD显示屏与触摸屏之间的机械不同轴性又包括移动与旋转误差。

缩放:


平移:


旋转:



因此,从上面的缩放,平移,旋转,可以得出LCD坐标和触摸屏坐标的计算公式

XL=XT*A+XT*B+C
YL=YT*D+YT*E+F

所以,只要计算出参数A,B,C,D,E,F,
我们就可以将从触摸芯片(ADS7843/TSC2046/XPT2046)上读出的触摸屏坐标转换成LCD坐标

2、我们采用tslib的五点校准算法,
其中触摸采样采用tslib里的排序取中间值,另外加上阈值判断的滤波算法。

typedef struct {
int x[5], xfb[5];
int y[5], yfb[5];
int a[7];
} calibration;

xfb[5],yfb[5]存放预先设定的5个LCD坐标值
x[5],y[5]存放从触摸芯片读回来的触摸坐标值

函数get_sample调用put_cross输出田字形光标,并通过getxy采样触摸坐标值
static void get_sample (calibration *cal, int index, int x, int y, char *name)
{

put_cross(x, y, 2 | XORMODE);
while(!getxy (&cal->x [index], &cal->y [index]));         //调用getxy将采样到的触摸坐标值存放在x[],y[]数组里
put_cross(x, y, 2 | XORMODE);

//将预先设定的LCD坐标值存放在xfb[],yfb[]数组里
cal->xfb [index] = x;
cal->yfb [index] = y;
}

getxy就是调用底层函数读取20组触摸坐标值,进行排序取中值平均,并进行阈值检查的函数

#define MAX_SAMPLES 20
struct ts_sample samp[MAX_SAMPLES];
int getxy(int *x, int *y)
{
int i;
int index, middle;

while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10)==Bit_SET);  //检测是否有触摸按下

index = 0;

  while((index < MAX_SAMPLES)&&(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10)==Bit_RESET))  //采样MAX_SAMPLES个点,直到触摸松开
  {
   index++;  
   samp[index].x = SPI_TOUCH_Read_X();
   samp[index].y = SPI_TOUCH_Read_Y();  
  }

middle = index/2;
if (x) {
  qsort(samp, index, sizeof(struct ts_sample), sort_by_x);  //对采样到的数据进行排序
  if(samp[middle].x - samp[middle-1].x > 5)
   return 0;
  if (index & 1)  //若为奇数个点,则取中间3个点平均
   *x = (samp[middle-1].x + samp[middle].x + samp[middle+1].x)/ 3;
  else               //否则取中间4个点平均
   *x = (samp[middle-1].x + samp[middle].x + samp[middle-2].x + samp[middle+1].x) / 4;
}
if (y) {
  qsort(samp, index, sizeof(struct ts_sample), sort_by_y); //对采样到的数据进行排序
  if(samp[middle].y - samp[middle-1].y > 5)
   return 0;
  if (index & 1) //若为奇数个点,则取中间3个点平均
   *y = (samp[middle-1].y + samp[middle].y + samp[middle+1].y) / 3;
  else              //否则取中间4个点平均
   *y = (samp[middle-1].y + samp[middle].y + samp[middle-2].y + samp[middle+1].y) / 4;
}
return 1;
}

3、得到5个点的采样数据之后,下面就可以通过perform_calibration计算上面的参数A,B,C,D,E,F了

求解方法采用了克拉姆法则,这个是线性代数的内容了,若看不懂的话要复习下线性代数的行列式和矩阵的内容。

5点校准这部分内容也可以参考下《Tslib中触摸屏校准原理及其实现.pdf》

计算的到上面的参数后,存放在cal.a[]数组中。
然后程序就可以利用上面参数,计算出LCD坐标了,其中a[6]是放大倍数(因为部分参数是小数,所以把全部参数放大倍数,方便存储)
   xtemp = cal.x[0];
   ytemp = cal.y[0];
   x =  (int)(( cal.a[0] + cal.a[1]*xtemp + cal.a[2]*ytemp ) / cal.a[6]);
   y =  (int)(( cal.a[3] + cal.a[4]*xtemp + cal.a[5]*ytemp ) / cal.a[6]);

得到触摸按下时对应LCD的x,y坐标之后,我们就利用它来做触摸画板,GUI触摸输入等应用了


沙发
hawksabre| | 2013-7-20 18:43 | 只看该作者
好项目   好**   学一学   谢谢了   楼主   顶一个  很不错   不错

使用特权

评论回复
板凳
xi_liang|  楼主 | 2013-7-30 09:27 | 只看该作者
这么好的东西没人顶啊,自己顶下

使用特权

评论回复
地板
wuguoyan| | 2013-7-30 10:03 | 只看该作者
好东西,顶

使用特权

评论回复
5
outstanding| | 2013-7-30 12:52 | 只看该作者
  真不错

使用特权

评论回复
6
Regsen| | 2013-10-29 15:53 | 只看该作者
今天才看到。谢谢楼主,很不错的。

使用特权

评论回复
7
xiaoye870928| | 2013-10-29 16:10 | 只看该作者
写的很好,易懂

使用特权

评论回复
8
txcy| | 2013-10-29 16:11 | 只看该作者
很好的学习教程

使用特权

评论回复
9
无冕之王| | 2013-10-29 16:29 | 只看该作者
相当实用的教程

使用特权

评论回复
10
pkat| | 2013-10-29 16:34 | 只看该作者
很详细的教程

使用特权

评论回复
11
abin0415| | 2013-10-29 20:59 | 只看该作者
为了LZ的无私奉献精神,顶起

使用特权

评论回复
12
gxgclg| | 2013-10-29 22:22 | 只看该作者
很好的开发板教程

使用特权

评论回复
13
zhaoqingtao007| | 2014-2-28 20:45 | 只看该作者
今天用到,很好

使用特权

评论回复
14
xi_liang|  楼主 | 2014-5-15 23:31 | 只看该作者
多谢各位支持,好久没看,没想到这么多回复了

使用特权

评论回复
15
tanyulian| | 2014-8-28 10:52 | 只看该作者
楼主,我买了一个百为stm32ZET6的那种红板,还想要一个配套的TFT屏,那个TFT屏为什么是30引脚的,TFT的驱动芯片是什么?

使用特权

评论回复
16
xi_liang|  楼主 | 2014-8-29 22:38 | 只看该作者
tanyulian 发表于 2014-8-28 10:52
楼主,我买了一个百为stm32ZET6的那种红板,还想要一个配套的TFT屏,那个TFT屏为什么是30引脚的,TFT的驱动 ...

噢,是你啊。多谢支持

使用特权

评论回复
17
kkzz| | 2014-8-29 23:10 | 只看该作者
这个不错呢

使用特权

评论回复
18
kkzz| | 2014-8-29 23:10 | 只看该作者
移植过

使用特权

评论回复
19
kkzz| | 2014-8-29 23:10 | 只看该作者
移植过51的

使用特权

评论回复
20
kkzz| | 2014-8-29 23:11 | 只看该作者

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:http://baiweijishu.taobao.com/ 百为STM32开发板 兼容官方STM3210E-EVAL开发板 WM-G-MR-09 WIFI开发板

41

主题

285

帖子

10

粉丝