STM32 触摸屏触摸功能

发布者:Serendipity22最新更新时间:2022-07-18 来源: csdn关键字:STM32  触摸屏  触摸功能 手机看文章 扫描二维码
随时随地手机看文章

要用到触摸屏首先就要对触摸屏的原理有一定的了解,我想这个是前提,也不用太多说的。就是当触笔触到屏上时,对应的位置就会产生相应大小的电压,输入到芯片,AD转换后得到一个数据。而触摸校准就是将接受到的原始模数转换值转换成屏幕像素坐标。

再就是了解触摸芯片,知道他的工作方式,以及跟STM32的连线。触摸实验中,我的实验板是用SPI口来实现数据的传输的,即SPI与xpt2046相连。

触摸屏控制芯片ADS7843中文资料

ADS7843是一个内置12位模数转换、低导通电阻模拟开关串行接口芯片。供电电压2.7~5 V,参考电压VREF为1 V~+VCC,转换电压的输入范围为0~ VREF,最高转换速率为125 kHz。


ADS7843引脚图及引脚功能说明了:

 

ADS7843的引脚配置如图3所示。表1为引脚功能说明,图4为典型应用。

 

ADS7843典型应用电路

ADS7843之所以能实现对触摸屏的控制,是因为其内部结构很容易实现电极电压的切换,并能进行快速A/D转换。图5所示为其内部结构,A2~A0和SER/为控制寄存器中的控制位,用来进行开关切换和参考电压的选择。


ADS7843之所以能实现对触摸屏的控制,是因为其内部结构很容易实现电极电压的切换,并能进行快速A/D转换。图5所示为其内部结构,A2~A0和SER/为控制寄存器中的控制位,用来进行开关切换和参考电压的选择。

 

我们传统的鼠标是一种相对定位系统,只和前一次鼠标的位置坐标有关。而触摸屏则是一种绝对坐标系统,要选哪就直接点哪,与相对定位系统有着本质的区别。绝对坐标系统的特点是每一次定位坐标与上一次定位坐标没有关系,每次触摸的数据通过校准转为屏幕上的坐标,不管在什么情况下,触摸屏这套坐标在同一点的输出数据是稳定的。不过由于技术原理的原因,并不能保证同一点触摸每一次采样数据相同,不能保证绝对坐标定位,点不准,这就是触摸屏最怕出现的问题:漂移。对于性能质量好的触摸屏来说,漂移的情况出现并不是很严重。


所以很多应用触摸屏的系统启动后,进入应用程序前,先要执行校准程序。  通常应用程序中使用的LCD 坐标是以像素为单位的。比如说:左上角的坐标是一组非 0 的数值,比如(20,20),而右下角的坐标为(220,300)。这些点的坐标都是以像素为单位的,而从触摸屏中读出的是点的物理坐标,其坐标轴的方向、XY 值的比例因子、偏移量都与 LCD 坐标不同,所以,可以在程序中使用一个函数(我们采用 Convert_Pos 函数)中把物理坐标首先转换为像素坐标,然后再赋给 POS 结构,达到坐标转换的目的。


校正思路:在了解了校正原理之后,我们可以得出下面的一个从物理坐标到像素坐标的转换关系式:

                                                LCDx=xfac*Px+xoff;

                                                LCDy=yfac*Py+yoff;

其中(LCDx,LCDy)是在 LCD 上的像素坐标,(Px,Py)是从触摸屏读到的物理坐标。xfac,yfac 分别是 X 轴方向和 Y 轴方向的比例因子,而 xoff 和 yoff 则是这两个方向的偏移量。


这样我们只要事先在屏幕上面显示 4 个点(这四个点的坐标是已知的),分别按这四个点就可以从触摸屏读到 4 个物理坐标,这样就可以通过待定系数法求出 xfac、yfac、xoff、yoff 这四个参数。我们保存好这四个参数,在以后的使用中,我们把所有得到的物理坐标都按照这个关系式来计算,得到的就是准确的屏幕坐标。达到了触摸屏校准的目的。


以下是自己的校准程序(在正点原子上做了一些改变,没有用到中断):

//触摸屏校准代码
//得到四个校准参数

void Touch_Adjust(void)
{        
 u16 pos_temp[4][2];//坐标缓存值
 u8  cnt=0; 
 u16 d1,d2;
 u32 tem1,tem2;
 float fac;    
 cnt=0;    
 TextColor=Blue;
 BackColor =White;      //TextColor = 0x0000, BackColor = 0xFFFF;
 LCD_Clear(White);//清屏  
// POINT_COLOR=RED;//红色
// LCD_Clear(WHITE);//清屏
 Drow_Touch_Point(20,20);//画点1
 delay_ms(1000);
// Pen_Point.Key_Sta=Key_Up;//消除触发信号
// Pen_Point.xfac=0;//xfac用来标记是否校准过,所以校准之前必须清掉!以免错误 
 while(1)
 {
  if(Read_ADS2(&x,&y))//按键按下了
  {
   //if(Read_TP_Once())//得到单次按键值
  // {            
    pos_temp[cnt][0]=x;
    pos_temp[cnt][1]=y;
    cnt++;
    delay_ms(100);
  // }   
   switch(cnt)
   {     
    case 1:
     LCD_Clear(White);//清屏
     delay_ms(1000);
     Drow_Touch_Point(20,300);//画点2
     break;
    case 2:
     LCD_Clear(White);//清屏
     delay_ms(1000);
     Drow_Touch_Point(220,20);//画点3
     break;
    case 3:
     LCD_Clear(White);//清屏
     delay_ms(1000);
     Drow_Touch_Point(220,300);//画点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;
      LCD_Clear(White);//清屏
      Drow_Touch_Point(20,20);
      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;
      LCD_Clear(White);//清屏
      Drow_Touch_Point(20,20);
      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;
      LCD_Clear(White);//清屏
      Drow_Touch_Point(20,20);
      continue;
     }//正确了
     //计算结果
     x1=pos_temp[0][0];
     x2=pos_temp[1][0];
     x3=pos_temp[2][0];
     x4=pos_temp[3][0];
     y1=pos_temp[0][1];
     y2=pos_temp[1][1];
     y3=pos_temp[2][1];
     y4=pos_temp[3][1];
     TextColor=Blue;
     LCD_Clear(White);//清屏
     ili9320_PutChars(120,120,"Touch Screen Adjust OK!",23,TextColor,BackColor);//校正完成
     delay_ms(1000);
     LCD_Clear(Blue);//清屏  
     return;//校正完成    
   }
  }
 }


我的算法,跟正点原子不同,他的我没有理解。


以下是带清屏的程序:

 while (1)
    {
  if(Read_ADS2(&X,&Y))
     {
   zuobiaox=20+(s32)(X-x1)*200/(x3-x1);
     zuobiaoy=20+(s32)(Y-y1)*280/(y2-y1);
   if(zuobiaox>0&&zuobiaox<20&&zuobiaoy>0&&zuobiaoy<40)
   {
    LCD_Clear(Blue);//清屏
    LCD_DrawRectFill(0, 0, 20, 40,Yellow);
    ili9320_PutChars(0,0,"RST",3,Red,Yellow); 
   }          
   else if(zuobiaox>0&&zuobiaox<240&&zuobiaoy>0&&zuobiaoy<320)
     lcd_fill_circle(zuobiaox,zuobiaoy, Red);
     }
 }

----------------------
    |  +  (x1,y1)    + | (x2,y2)
    |                    |
    |  +   (x3,y3)     + | (x4,y4)
    ----------------------

触摸屏校准

上图理解为触摸屏,应为实际应用中触摸屏边角出电压相对不稳定,所以放弃一部分,四个点分别为(20,20)(20,300)(220,20)(220,300),对应的AD值分别设为(x1,y1)(x2,y2)(x3,y3)(x4,y4).

首先:在LCD上绘制四个对应的“+”用来取较准点;
其次:点四个“+”,得到各点的AD值,由于其中的电阻是线性的,可以根据x轴上两点的x的AD值如x1,x3以及对应LCD坐标值求出x轴上x的AD值与LCD坐标值对应的关系,是一条直线的方程,再根据此方程由AD值求LCD坐标值即可;y轴上也是一样的道理。
      最后:计算  (注:触摸屏电压最小点,为LCD显示坐标最大点,(X,Y)为触摸电压)

zuobiaox=20+(s32)(X-x1)*200/(x3-x1);


zuobiaoy=20+(s32)(Y-y1)*280/(y2-y1);


-------------------------

→_→在校准函数中,不断扫描TP_Scan()函数,如果这时候你触摸了一下屏幕,PEN所对应STM32的引脚将会从高电平跳变为低电平,详情看上文第二讲的注意→_→。即Ttp_dev.sta=1100,0000(根据上图第一个方框得出)。不满足校准函数中的if((tp_dev.sta&0xc0)==TP_CATH_PRES),故不会进行下面的画点。如果之前并没有按下触摸屏,这时同样是不满足上面if的。如果之前按下后松下了,这时Ttp_dev.sta=0111,1111,这时满足校准函数中的if((tp_dev.sta&0xc0)==TP_CATH_PRES),然后在校准函数中标记下触摸已经被处理了(清除tp_dev.sta),清除第一个点,画第二个点,清除第二个点,画第三个点,清除第三个点,画第四个点,清除第四个点。也就是,触摸屏幕有两个状态:按下和松开。当按下时,程序执行的是将按下的AD值坐标存到两个数组中即上图中的TP_Read_XY2(&tp_dev.x[0],&tp_dev.y[0]);当松开时,清除原来的点,并画一个新点。这样触摸4次。

[1] [2]
关键字:STM32  触摸屏  触摸功能 引用地址:STM32 触摸屏触摸功能

上一篇:STM32CbueIDE下载和汉化
下一篇:stm32 串口格式化打印字符串 函数封装

推荐阅读最新更新时间:2024-11-17 23:28

STM32 USB虚拟串口问题汇总
汇总1:STM32的USB例程修改步骤,来自http://blog.csdn.net/cy757/archive/2010/01/01/5117610.aspx 以下是笔者将ST的Custom_HID例程修改为“自定义USB设备”例程时总结出来的,因为笔者也是刚刚学USB开发不久,某些方面理解错误在所难免,请各位大虾指正。 一、usb_desc.c文件 根据你程序使用的通信方式修改。usb_desc.h文件中定义要根据usb_desc.c文件中的数组的大小;ConfigDescriptor 下添加需要处理的端点;根据需要添加或删除报告描述符(主要用于HID)和CDC接口描述符(主要用于实现USB转串口)等。具体方法可以下载个“
[单片机]
STM32跑马灯例程总结
//======================================================// **基于学习STM32有一段时间了,特意写下一篇关于一个简单的跑马灯 的例程,梳理思路,也希望我自己的理解能帮到一些学习STM32的初学者 /**再此,鸣谢余师傅在学习上的大力帮助!!**/ //======================================================// 首先,GPIO的配置种类有8种。分别为模拟输入、浮空输入,上拉输入、下拉输入、开漏输出、推挽输出、复用开漏输出、复用推挽输出。 下面将以实例的方式讲解GPIO的设置及实现过程。 事例1:跑马灯实验 跑马灯实
[单片机]
stm32 数据类型的定义(常用的U8,U16,U32到底代表什么)
在Keil MDK 开发环境里,比如一个 无符号32位整形数据会有很多种表示方法: 1,unsigned int 32 (C语言标准表达方法) 2,uint32_t ; 3 ,u32; 这三种方式都是在表达同一个意思,可为什么ST的开发人员要搞的这么乱呢? 还有其他好多你可能看起来很陌生 ,很不好理解的表达方式, 如:_IO int32_t 他等同于vs32(这个你同样很陌生),不过他还等同于 volatile int32_t, 还等同于 volatile signed int 32; 最后这种表达方式才是C语言的标准表达方式,够乱吧,能把初学者弄的晕头转向。 u8,u16,u32都是unsigned char类型,不过u8是
[单片机]
STM32内存分布学习
1.STM32内存分布 下图是一张stm32的内存映射图,其中代码区是从0x0800 0000开始的,他的结束地址是0x0800 0000加上实际芯片的flash大小,他的ram的起始地址是0x2000 0000,然后结束地址依然是加上芯片实际的ram大小。 2.单片机中RAM\ROM\FLASH区别 1.RAM(Random Access Memory) 特点: 1. 掉电丢失数据; 2. 随机存取; 分类: 静态RAM/(SRAM) :不需要刷新电路保持数据,贵快,cpu的一级二级缓存; 动态RAM/(DRAM):需要刷新电路保持数据,比SRAM慢,比任何ROM快,计算机内存; 2.ROM(Read Onl
[单片机]
STM32实例之I/O控制中的按键实验
键盘是嵌入式重要的设备之一。通过对键盘的操作可以给系统以指令,使得系统知道做什么操作,进行什么处理。就本质而言,系统对键盘的处理就是对I/O口电平的读取和处理。 在本实例中,使用OpenM3V开发板,他通过7个按键分别控制7个I/O口,这里我们通过LED等的点亮与熄灭来表征是否有按键的动作。 在做设计之前我们必须理清楚软件结构和硬件结构(这是做设计必须理清楚的重要点)。从硬件电路来说,当有按键按下时,和按键相连的I/O口为低电平;没有按下键时,和按键相连的I/O口为高电平。在该实验中,使用E端口来读取数据。在读取GPIOE数据后,首先需要把高9位用Temp &= 0x7f屏蔽,只留下先来后到7为工作。然后在依次和各个按键进行对比处
[单片机]
STM32学习笔记—ADC采集数据常见问题
ADC,Analog-to-Digital Converter(模数转换器),其应用非常广泛,比如温度、湿度、压力、声音等传感器领域。 今天是第 7 篇分享, 《STM32学习笔记》之ADC采集数据常见问题 。 ADC的类型很多,STM32内部集成的ADC为逐次逼近型。STM32虽然是通用MCU芯片,但它内部集成的ADC也非常出色,不比一些专用ADC芯片差。 STM32 ADC 基础内容 STM32内部集成的ADC与型号有关,有16位、12位ADC,内部集成ADC多达4个,通道数多达40个,甚至更多。 1. ADC分辨率 分辨率决定了ADC的转换精度,按理说分辨率越高越好,但价格更贵。 STM32内部集成的ADC最高1
[单片机]
unity在stm32上的使用
按照本文的描述,应该可以在你所处的 硬件 上跑通代码。 先决条件:装有编译和集成的开发环境,比如: Keil uVision5。 板子硬件要求:无, 芯片 自带的串口功能即可完成。 源码获取 Unity 是一个轻量级的 C 语言单元测试框架,它的设计理念是简单易用。 Unity 支持测试套件和测试用例,同时提供了丰富的断言函数,包括比较、异常和日志等。 源码入口: GitHub - ThrowTheSwitch/Unity: Sim ple Unit Te sting f or C https://github.com/ThrowTheSwitch/Unity/ 源码里面结构,接下来准备一个stm32的基础工程,把相关代码
[单片机]
unity在<font color='red'>stm32</font>上的使用
编译可加载触摸屏驱动的uImage内核
pc:Centos5.4 内核:linux 3.0.1 开发板:ok6410 交叉编译器:arm-linux-gcc 4.4.1 1. make menuconfig 去掉原来的触摸屏驱动程序 - Device Drivers - Input device support - Generic input layer - Touchscreens s3c touchscreens make uImage 错误:undefined refer to s3c_device_ts 修改 arch/arm/mach-s3c64xx/目录下的makefile,将跟ts有关的.o注释掉(无用); 进入arch/a
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved