访问电脑版页面

导航:老古开发网手机版STM32单片机STM32F103单片机

STM32f103的电阻触摸屏的五点校正算法

导读:
关键字:
STM32F103,算法,触摸屏,

  由于电阻式触摸屏就是一种传感器,它利用压力感应进行控制,将矩形区域中触摸点(X,Y)的物理位置转换为代表X坐标和Y坐标的电压。这里先引入两个概念,物理坐标和逻辑坐标。物理坐标指触摸屏上点的实际位置,通常以液晶上点的个数来度量。逻辑坐标指这点被触摸时A/D转换后的坐标值。如图1,我们假定液晶最左下角为坐标轴原点A,在液晶上任取一点B(十字线交叉中心),B在X方向距离A10个点,在Y方向距离A20个点,则这点的物理坐标为(10,20)。如果我们触摸这一点时得到的X向A/D转换值为100,Y向A/D转换值为200,则这点的逻辑坐标为(100,200)。

  常用的电阻式触摸屏矫正方法有两点校准法和三点校准法。本文这里介绍的是结合了不同的电阻式触摸屏矫正法的优化算法:五点校正法。其中主要的原理是使用4点矫正法的比例运算以及三点矫正法的基准点运算。五点校正法优势在于可以更加精确的计算出X和Y方向的比例缩放系数,同时提供了中心基准点,对于一些线性电阻系数比较差电阻式触摸屏有很好的校正功能。

  校正相关的变量主要有:

  x[5],y[5]五点定位的物理坐标

  xl[5],yl[5]五点定位的逻辑坐标

  KX,KY横纵方向伸缩系数

  XLC,YLC中心基点逻辑坐标

  XC,YC中心基点物理坐标(数值采用LCD显示屏的物理长宽分辨率的一半)

  触摸屏常和点阵式液晶显示(LCD)屏叠加在一起配套使用,构成一个矩形的实际物理平面;而由用户触摸的触摸点集合经过A/D转换器,得到具体显示坐标的集合,这个集合构成了一个逻辑平面。由于存在误差,这两个平面并不重合,校准的作用就是要将逻辑平面映射到物理平面上,即得到触点在液晶屏上的位置坐标。校准算法的中心思想也就是要建立这样一个映射函数现有的校准算法大多是基于线性校准,即首先假定物理平面和逻辑平面之间的误差是线性误差,由旋转和偏移形成。

  STM32f103的电阻触摸屏的五点校正算法
图 1

  x[5],y[5]五点定位的物理坐标是已知的,其中4点分别设置在LCD的角落,一点设置在LCD正中心,作为基准矫正点。校正关键点和距离布局如图。

校正步骤如下:

  1.通过先后点击LCD的4个角落的矫正点,获取4个角落的逻辑坐标值。

  2.计算s1’=xl[2]-xl[1]、s3’=xl[3]-xl[4]、s2’=yl[3]-yl[2]、s4’=yl[4]-yl[1]

  计算s1=x[2]-x[1]、s3=x[3]-x[4]、s2=y[3]-y[2]、s4=y[4]-y[1],一般取点可以人为的设定s1=s3和s2=s4,以方便运算。

  计算KX=(s1’+s3’)/2/s1、KY=(s2’+s4’)/2/s2

  3.点击LCD正中心,获取中心点的逻辑坐标,作为矫正的基准点。

  4.完成以上步骤则校正完成。下次点击触摸屏的时候获取的逻辑值XL和YL,可根据公式转换成物理值:

  X=(XL-XLC)/KX+XC

  Y=(YL-YLC)/KY+YC

  换算出来的X,Y即是和LCD像素相对应的物理坐标值,方便对触屏响应程序做区域判别。

  以下是校正程序:

  *名称:voidLCD_Adjustd(void)

  *功能:校正电阻屏系数

  *入口参数:null

  *出口参数:无

  *说明:null

  *调用方法:LCD_Adjustd();

  ****************************************************************************/

  u8LCD_Adjustd(void)

  {

  EXTI_InitTypeDefEXTI_InitStructure;

  EXTI_InitStructure.EXTI_Line=EXTI_Line7;

  EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;//为中断请求

  EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;//Falling下降沿Rising上升

  EXTI_InitStructure.EXTI_LineCmd=DISABLE;

  EXTI_Init(&EXTI_InitStructure);

  //显示停止刷屏

  TIM_Cmd(TIM3,DISABLE);//使能TIMx外设

  LCD_Clear(White);

  LCD_printString(110,20,“AdjustdBegin”,Black);

  delay_ms(5000);

  //定第一个点

  LCD_Draw_Target(20,20,Red);

  while(GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_7));

  while((1-GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_7)))

  {

  x[0]=Read_XY(CMD_RDX);

  y[0]=Read_XY(CMD_RDY);

  LCD_ShowNum(150,80,x[0],Black);

  LCD_ShowNum(150,110,y[0],Black);

  delay_ms(200);

  LCD_Color_Fill(150,80,200,120,White);

  }

  //定第二个点

  LCD_Draw_Target(300,20,Red);

  LCD_Draw_Target(20,20,White);

  while(GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_7));

  while((1-GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_7)))

  {

  x[1]=Read_XY(CMD_RDX);

  y[1]=Read_XY(CMD_RDY);

  LCD_ShowNum(150,80,x[1],Black);

  LCD_ShowNum(150,110,y[1],Black);

  delay_ms(200);

  LCD_Color_Fill(150,80,200,120,White);

  }

  if(abs(y[1]-y[0])》60)

  {

  LCD_Clear(White);

  LCD_printString(110,20,“AdjustdFail”,Black);

  delay_ms(5000);

  LCD_Clear(White);

  return1;

  }

  //定第三个点

  LCD_Draw_Target(20,220,Red);

  LCD_Draw_Target(300,20,White);

  while(GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_7));

  while((1-GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_7)))

  {

  x[2]=Read_XY(CMD_RDX);

  y[2]=Read_XY(CMD_RDY);

  LCD_ShowNum(150,80,x[2],Black);

  LCD_ShowNum(150,110,y[2],Black);

  delay_ms(200);

  LCD_Color_Fill(150,80,200,120,White);

  }

  if(abs(x[2]-x[0])》80)

  {

  LCD_Clear(White);

  LCD_printString(110,20,“AdjustdFail”,Black);

  delay_ms(5000);

  LCD_Clear(White);

  return1;

  }

  //定第四个点

  LCD_Draw_Target(300,220,Red);

  LCD_Draw_Target(20,220,White);

  while(GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_7));

  while((1-GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_7)))

  {

  x[3]=Read_XY(CMD_RDX);

  y[3]=Read_XY(CMD_RDY);

  LCD_ShowNum(150,80,x[3],Black);

  LCD_ShowNum(150,110,y[3],Black);

  delay_ms(200);

  LCD_Color_Fill(150,80,200,120,White);

  }

  if((abs(y[2]-y[3])》60)||(abs(x[1]-x[3])》80))

  {

  LCD_Clear(White);

  LCD_printString(110,20,“AdjustdFail”,Black);

  delay_ms(5000);

  LCD_Clear(White);

  return1;

  }

  //定第五个点

  LCD_Draw_Target(160,120,Red);

  LCD_Draw_Target(300,220,White);

  while(GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_7));

  while((1-GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_7)))

  {

  x[4]=Read_XY(CMD_RDX);

  y[4]=Read_XY(CMD_RDY);

  delay_ms(200);

  }

  //计算校正系数

  //KX=((abs(y[0]-y[2])/280+abs(y[1]-y[3])/280)/2);

  //KY=((abs(x[0]-x[1])/200+abs(x[2]-x[3])/200)/2);

  KX=(((float)(y[0]-y[2])/280+(float)(y[1]-y[3])/280)/2);

  KY=(((float)(x[0]-x[1])/200+(float)(x[2]-x[3])/200)/2);

  XC=160;

  YC=120;

  XLC=y[4];

  YLC=x[4];

  //定点完成

  LCD_Clear(White);

  LCD_printString(110,20,“AdjustdDone”,Black);

  delay_ms(5000);

  LCD_Color_Fill(110,20,200,35,White);

  LCD_printString(110,20,“Testing”,Black);

  EXTI_InitStructure.EXTI_Line=EXTI_Line7;

  EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;//为中断请求

  EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;//Falling下降沿Rising上升

  EXTI_InitStructure.EXTI_LineCmd=ENABLE;

  EXTI_Init(&EXTI_InitStructure);

  EXTI_ClearITPendingBit(EXTI_Line7);//清除线路挂起位

  //显示开始刷屏

  TIM_Cmd(TIM3,ENABLE);//使能TIMx外设

  Add_Button();

  return0;

  }

来源:网络整理   作者:沈丹  2017/12/8 10:26:00
栏目: [ STM32F103单片机]

相关阅读

STM32F103学习笔记 (八) PWM输出

STM32F103学习笔记 (十) TFTLCD 显示

STM32F103试用体验:LCD显示与DHT11测量实验

STM32F103利用模拟I2C驱动ADS1115

STM32F103外部晶振由8M变为12M

基于STM32F103ZE的USART2 端口时钟

STM32F103系列单片机中的定时器工作原理解析

嵌入式微处理器STM32F103有什么特点和应用?怎样去开发?

stm32F103单片机无源晶振不起振排除问题

利用stm32f103的TIM2实现精确延时

STM32F103ZET6 之 通用定时器单脉冲模式实验

STM32F103 开发板试用体验:超声波测距功能的实现

STM32F103C8T6 ULN2003步进电机驱动代码

基于STM32F103的USB数据采集模块的设计

stm32f103zet6与stm32f103rct6的区别

STM32F103试用体验(四):硬件原理与机壳组装

STm32F103ZET6红牛开发板原理图

stm32f103zet6如何识别flash大小

基于单片机Stm32f103 DAC电流输出解决方案

STM32F103的复位及时钟控制模块头文件