你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

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

[复制链接]
Savy1314 发布时间:2017-7-18 14:26
  STM32f103的电阻触摸屏的五点校正算法
由于电阻式触摸屏就是一种传感器,它利用压力感应进行控制,将矩形区域中触摸点(X,Y)的物理位置转换为代表 X坐标和 Y 坐标的电压。这里先引入两个概念,物理坐标和逻辑坐标。物理坐标指触摸屏上点的实际位置,通常以液晶上点的个数来度量。逻辑坐标指这点被触摸时A/D 转换后的坐标值。如图1,我们假定液晶最左下角为坐标轴原点A ,在液晶上任取一点B (十字线交叉中心),B 在X 方向距离A 10 个点,在Y 方向距离A20 个点,则这点的物理坐标为(10,20)。如果我们触摸这一点时得到的X 向A/D 转换值为100,Y 向A/D 转换值为200,则这点的逻辑坐标为(100,200)。
: N6 [1 P. T9 K, q/ N! {$ O) y( b' W9 i
       常用的电阻式触摸屏矫正方法有两点校准法和三点校准法。本文这里介绍的是结合了不同的电阻式触摸屏矫正法的优化算法:五点校正法。其中主要的原理是使用4点矫正法的比例运算以及三点矫正法的基准点运算。五点校正法优势在于可以更加精确的计算出X和Y方向的比例缩放系数,同时提供了中心基准点,对于一些线性电阻系数比较差电阻式触摸屏有很好的校正功能。# G8 U7 ]1 H7 G, }# M" A

; A: Q; n5 P( Z4 n& s       校正相关的变量主要有:
% Y" f3 d% x" m. A) z" F* n; {# ~; [) B8 }6 h0 z/ r
       x[5] , y[5] 五点定位的物理坐标
( {& r( n# b) j# X# Q  w
2 g( f: w6 L) V) S
       xl[5] , yl[5] 五点定位的逻辑坐标1 f1 i# C. I; X! I( X

3 k5 j  V" r$ E8 v4 ~5 `       KX , KY 横纵方向伸缩系数
* T) d. I+ J/ m; v3 Y+ j
8 h' B/ t8 w  {+ N       XLC , YLC 中心基点逻辑坐标
& G- v9 Y, c3 C
3 E/ U# j. V  n2 m0 O, m2 _) n       XC , YC 中心基点物理坐标(数值采用LCD显示屏的物理长宽分辨率的一半)
2 E" f1 g/ v- J/ j

3 @$ ]& T: b7 Y' q9 p6 }       触摸屏常和点阵式液晶显示(LCD)屏叠加在一起配套使用,构成一个矩形的实际物理平面; 而由用户触摸的触摸点集合经过 A/D 转换器,得到具体显示坐标的集合,这个集合构成了一个逻辑平面。 由于存在误差,这两个平面并不重合,校准的作用就是要将逻辑平面映射到物理平面上,即得到触点在液晶屏上的位置坐标。 校准算法的中心思想也就是要建立这样一个映射函数现有的校准算法大多是基于线性校准, 即首先假定物理平面和逻辑平面之间的误差是线性误差,由旋转和偏移形成。1 n. z0 Z8 v/ p' V
8.jpg
; z( [* P4 b" p/ A" F9 t1 l+ J: M6 ~0 v; }
  x[5] , y[5] 五点定位的物理坐标是已知的,其中4点分别设置在LCD的角落,一点设置在LCD正中心,作为基准矫正点。校正关键点和距离布局如图。校正步骤如下:7 s6 m* }$ a9 I) T  e7 E
        1. 通过先后点击LCD的4个角落的矫正点,获取4个角落的逻辑坐标值。# \" {! J4 r( b; F
        2. 计算 s1’ = xl[2] - xl[1] 、 s3’ = xl[3] - xl[4] 、 s2’ = yl[3] - yl[2] 、 s4’ = yl[4] - yl[1]
' F4 A$ q0 g" Z' p7 {            计算 s1 = x[2] - x[1] 、 s3 = x[3] - x[4] 、 s2 = y[3] - y[2] 、 s4 = y[4] - y[1],一般取点可以人为的设定s1 = s3 和 s2 = s4,以方便运算。4 K$ g4 s$ K6 X  R+ l2 b
            计算 KX = ( s1’ + s3’ )/2/s1 、KY = ( s2’ + s4’ )/2/s2
* s/ B1 h9 |/ y$ T        3. 点击LCD正中心,获取中心点的逻辑坐标,作为矫正的基准点。
# U9 W6 e3 s/ `        4. 完成以上步骤则校正完成。下次点击触摸屏的时候获取的逻辑值XL和YL,可根据公式转换成物理值:
0 W. d0 S  L! o1 G* V            X = ( XL - XLC ) / KX + XC ; g4 n: F/ }! H) N
            Y = ( YL - YLC ) / KY + YC7 T! P: a$ s0 Z* Q! E4 y" h
        换算出来的X , Y即是和LCD像素相对应的物理坐标值,方便对触屏响应程序做区域判别。
$ D( D/ X' V8 M  F# r
5 e0 \; ~  S% Q' W5 a" x- N2 l- v以下是校正程序:
4 I9 ?/ L# o# u! K; J! j
  1. * 名    称:void LCD_Adjustd(void)
    4 b  i: d/ b( w1 n2 G9 u$ \
  2. * 功    能:校正电阻屏系数 ! Y2 _, S# E8 X$ G3 ], p5 t
  3. * 入口参数: null . C1 I& W" O6 S: `& \% P3 i
  4. * 出口参数:无 4 c! `2 ?9 `  P! Q5 U- i& B* Y1 ?
  5. * 说    明:null . W0 [" F* O6 ]1 i1 @: R. D
  6. * 调用方法:LCD_Adjustd();
    ' ~5 u6 g% o: v. _7 r, J
  7. ****************************************************************************/  * b8 p' n* L/ g& K$ F6 I7 o8 W
  8. u8 LCD_Adjustd(void)  ! K& ~2 e' G7 q' e2 E  [
  9. {  2 ?+ X" x) {% q& k% T. x
  10.     EXTI_InitTypeDef EXTI_InitStructure;  ! W; I" ?9 k& B; I4 _. K
  11.       
    - @* s( b5 r! B3 |. n9 e
  12.     EXTI_InitStructure.EXTI_Line    = EXTI_Line7;  ' M6 o7 I+ H! z( M. Y7 O. u
  13.     EXTI_InitStructure.EXTI_Mode    = EXTI_Mode_Interrupt;  //为中断请求  
    $ i3 [8 L$ H6 t$ G' {& n
  14.     EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//Falling下降沿 Rising上升  
    3 S3 @/ ]  I3 O. _; ]( m9 f% Y
  15.     EXTI_InitStructure.EXTI_LineCmd = DISABLE;  
    ) G) J( f# }6 q8 V* W
  16.     EXTI_Init(&EXTI_InitStructure);  
    $ M7 s& |' S$ _8 j; o* t
  17.     //显示停止刷屏  + d: u" P* u# Z, P$ @
  18.     TIM_Cmd(TIM3, DISABLE);  //使能TIMx外设  8 j( R& I$ m+ e+ |! E& m; e
  19.       
    - A* ^  b+ s+ g! l
  20.     LCD_Clear(White );  
    . F8 j$ ]4 r& u9 M7 h& ~1 T- S) h
  21.     LCD_printString(110,20, "Adjustd Begin" ,Black);  
    " y& b/ j; }0 o" U1 x
  22.     delay_ms(5000);  
    ; x3 \! j/ U) J5 j- o* h
  23.     // 定第一个点  / d. `! A  v' x5 P3 r7 n: Y  }! U2 k3 H
  24.     LCD_Draw_Target(20, 20, Red);  
    1 |% o7 i' r! j$ }& d
  25.     while( GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_7));  - }/ e( z; V6 f1 w1 h+ \  d
  26.     while( (1-GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_7)))  
    6 j" [* K% d& {) A' Y0 W$ _
  27.     {  1 P, D  o! R+ M" R8 R* K0 o
  28.         x[0] = Read_XY(CMD_RDX);  
    ! u/ N0 L/ x% T9 F
  29.         y[0] = Read_XY(CMD_RDY);   
    : v' J6 C, a/ U$ K
  30.         LCD_ShowNum(150,80,x[0],Black);  6 B. W/ V8 V0 p) e* \! V5 B
  31.         LCD_ShowNum(150,110,y[0],Black);  7 e( ]& l/ V: j0 d  ^4 u5 l& m
  32.         delay_ms(200);  0 j1 e6 D& m) @
  33.         LCD_Color_Fill(150,80,200,120, White);  : d1 ~4 U1 k, [; J
  34.     }  
    6 Y1 C5 v" x8 A1 P
  35.     // 定第二个点  # x+ H( [4 I5 d$ U
  36.     LCD_Draw_Target(300, 20, Red);  
    ' p" C! x; N3 q% f2 q5 y7 W- O4 \4 z: U
  37.     LCD_Draw_Target(20, 20, White);  
    % P; a( L' g2 b/ M
  38.     while( GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_7));  
    ! [0 \4 Q- O: X4 Z+ s5 ~
  39.     while( (1-GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_7)))  
    - {% R9 _# t( k- R
  40.     {  
    ' V  V3 f- N# Z
  41.         x[1] = Read_XY(CMD_RDX);  ' ^$ m$ T1 F7 A! o! _8 l/ M
  42.         y[1] = Read_XY(CMD_RDY);   , ?1 c/ _( l$ ~3 u7 d
  43.         LCD_ShowNum(150,80,x[1],Black);  ) B9 O8 t; Y$ Z7 @
  44.         LCD_ShowNum(150,110,y[1],Black);  ) _) T; S& P0 }1 I# K& A
  45.         delay_ms(200);  
    6 ^0 c7 Q$ N8 ]) G
  46.         LCD_Color_Fill(150,80,200,120, White);  
    + L( D! K, u% y! o9 J9 b
  47.     }  
    0 |/ d' q" u7 B; C
  48.     if(abs(y[1]-y[0]) >60)  
    # |) S" h/ q9 r
  49.     {  9 u) k" p/ @! S- k) t$ C
  50.         LCD_Clear(White );  ( Q# k8 R, |3 D/ I9 u
  51.         LCD_printString(110,20, "Adjustd Fail" ,Black);  9 U/ x# P8 e- h3 Z- D
  52.         delay_ms(5000);  7 p2 [+ c: [. w! {5 [+ r' ^
  53.         LCD_Clear(White );  
    ( `$ s7 Q2 v: Z5 i' w0 g
  54.         return 1;  
    1 J8 \% ^7 s7 y7 r, C6 l* ^, J1 f
  55.     }  
    $ b* t, K5 j7 z! P' v+ A
  56.     // 定第三个点  
    1 k6 J; s- N: u4 o+ z
  57.     LCD_Draw_Target(20, 220, Red);  
    0 P0 m4 u- I7 J8 |- S, U, E% p% q
  58.     LCD_Draw_Target(300, 20, White);  / Y0 `* Y5 M) O$ ?# M$ Z
  59.     while( GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_7));  
    ' o8 W* p6 d4 |6 s
  60.     while( (1-GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_7)))  + |+ E/ f( I- w6 G
  61.     {  7 v. w  p' G" I4 U& [' x" O
  62.         x[2] = Read_XY(CMD_RDX);  . P  S3 v8 W8 f% Q# ]
  63.         y[2] = Read_XY(CMD_RDY);   - q  p! K, y! V+ I
  64.         LCD_ShowNum(150,80,x[2],Black);  6 g: x. E: c. b' I# E7 v& ?
  65.         LCD_ShowNum(150,110,y[2],Black);  
    $ q& k9 P0 ]9 G! A
  66.         delay_ms(200);  
    , }$ Z: o8 k! @9 b0 V8 T% f3 c
  67.         LCD_Color_Fill(150,80,200,120, White);  : s( A. @) b9 }& B6 v
  68.     }  3 @% T& A9 c' _+ E4 s, b
  69.     if(abs(x[2]-x[0]) >80)  
    * Z6 K; g- w, H8 H& ~
  70.     {  
    : a  [3 D4 @5 i
  71.         LCD_Clear(White );  
    & t  b( X/ \) V2 d
  72.         LCD_printString(110,20, "Adjustd Fail" ,Black);  + S8 K: q' o" w7 r* m6 V
  73.         delay_ms(5000);  
    + z7 h5 j+ t6 U/ x0 l
  74.         LCD_Clear(White );  % l' b0 w& n% r2 w# k/ y
  75.         return 1;  
    0 l7 S- g- z/ A. A
  76.     }    g7 p2 ?' c$ {0 O
  77.     // 定第四个点  
    : k- C% I, [1 Q: E/ B
  78.     LCD_Draw_Target(300, 220, Red);  ' D- Z& t& ]. X7 w" Z% Y
  79.     LCD_Draw_Target(20, 220, White);  
    2 t5 e& S4 E9 l7 U
  80.     while( GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_7));  - k( q+ F8 U. `, C: A7 Y1 V7 U8 b
  81.     while( (1-GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_7)))  
    7 k* r) M# V' n3 M, ^7 Q3 t
  82.     {  ( S( F* w- j4 W8 C; d; U
  83.         x[3] = Read_XY(CMD_RDX);  5 W( o% D6 X, i- o- Q# r) v
  84.         y[3] = Read_XY(CMD_RDY);   : P, M  A4 D$ z4 J7 Z
  85.         LCD_ShowNum(150,80,x[3],Black);  " i4 w3 B( I8 F+ V
  86.         LCD_ShowNum(150,110,y[3],Black);  
    6 w; {& Z  s2 d) R
  87.         delay_ms(200);  $ J2 Z+ P* i9 f" `9 ^
  88.         LCD_Color_Fill(150,80,200,120, White);  
    ) @. O" O6 v/ L4 y) _1 Z" ~$ E% T3 _, ^
  89.     }  
    5 L$ Q; \# [8 a+ c, _' i' y
  90.     if((abs(y[2]-y[3]) >60) || (abs(x[1]-x[3]) >80))  , w6 l+ `4 W6 b5 i+ e* P
  91.     {  % `5 W8 \6 ?* _2 ~3 C! D
  92.         LCD_Clear(White );  
    6 h4 i: B( B6 n  G$ ]6 e
  93.         LCD_printString(110,20, "Adjustd Fail" ,Black);  ; K( _" A& W  L9 @+ @
  94.         delay_ms(5000);  + ]5 _" X% f) S8 S0 ~  q7 \
  95.         LCD_Clear(White );  
    # _0 A- G3 X6 D& g) J* o, i# v+ _
  96.         return 1;  
    8 {  F! R  x* N, l9 t7 \+ o
  97.     }  
    " A4 H- E% {6 Q) T4 b( X5 f7 K( H
  98.     // 定第五个点  
    * {: [1 T1 v  \* [& {6 @
  99.     LCD_Draw_Target(160, 120, Red);  # P+ l% q3 b. G
  100.     LCD_Draw_Target(300, 220, White);  : l4 p6 A* l' {' I3 H* W- X# C
  101.     while( GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_7));  
    ; o1 N# R: g! K' {  [: v: k
  102.     while( (1-GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_7)))  8 j* e1 x" P0 O' O3 g
  103.     {  4 E! }4 ~) p, q) h9 l  j# p
  104.         x[4] = Read_XY(CMD_RDX);    Y  K4 \3 `5 A0 L. @3 q
  105.         y[4] = Read_XY(CMD_RDY);  " w+ k4 C6 e; w/ t* z: M
  106.         delay_ms(200);  
    : _0 ?: i  B) w
  107.     }  
    - z. q$ X- _& w" F! r2 E/ C
  108.     //计算校正系数  
    & v/ j6 L3 j/ M8 z
  109. //  KX  = ((abs(y[0]-y[2])/280+abs(y[1]-y[3])/280)/2);    \  S# R6 e2 T- [; ]+ a  Y
  110. //  KY  = ((abs(x[0]-x[1])/200+abs(x[2]-x[3])/200)/2);  ! S1 s+ J' l7 W; y
  111.     KX  = (((float)(y[0]-y[2])/280+(float)(y[1]-y[3])/280)/2);  5 J0 b% f9 y: R4 f9 @  T  T: H* e# p
  112.     KY  = (((float)(x[0]-x[1])/200+(float)(x[2]-x[3])/200)/2);  
    ; P" Y, H2 b6 p$ o8 ^  ~: x6 U* ?
  113.     XC = 160;  
    , ?$ q# u2 [5 `" ?
  114.     YC = 120;  
    6 J. i# b! P5 H8 Q
  115.     XLC  = y[4];  # A4 S, }5 ~* p* l$ q( a
  116.     YLC  = x[4];  * O+ d7 v$ C( `# h
  117.       9 Z+ Q1 g9 s7 p5 j. j! f
  118.     // 定点完成  * a( H. D2 _' Z$ t& V+ c# ?
  119.     LCD_Clear(White );  
    0 ^8 S* u0 E. ]
  120.     LCD_printString(110,20, "Adjustd Done" ,Black);  
    3 ^' h1 E. |, c
  121.     delay_ms(5000);    c9 ^8 q5 A1 m7 |: u- Z9 s
  122.     LCD_Color_Fill(110,20,200,35, White);  
    + x" x; n; }% z. T9 C  M' L3 V- I
  123.     LCD_printString(110,20, "Testing" ,Black);  
    " W# s1 s' s& u! h
  124.       
    % y9 r* ]1 P) w9 W' g
  125.     EXTI_InitStructure.EXTI_Line    = EXTI_Line7;  
    $ L7 g1 `/ o9 h/ N" R
  126.     EXTI_InitStructure.EXTI_Mode    = EXTI_Mode_Interrupt;  //为中断请求  
    $ R$ ~! }' U: v9 p0 ^
  127.     EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//Falling下降沿 Rising上升  
    * J0 V  Y5 D) h# y. p6 ^) g
  128.     EXTI_InitStructure.EXTI_LineCmd = ENABLE;  
    5 R3 m: ~& H; H1 c( _
  129.     EXTI_Init(&EXTI_InitStructure);  
    % R6 \  \+ e  f" e" h1 _
  130.     EXTI_ClearITPendingBit(EXTI_Line7);    //清除线路挂起位  
    7 W$ u) X. X0 W( w7 v: O
  131.       ( J8 q2 g8 E7 f. N
  132.     //显示开始刷屏  
    % U' N0 P; Y% Z+ v1 ~
  133.     TIM_Cmd(TIM3, ENABLE);  //使能TIMx外设  
    : a  b- _; Q7 G+ ~) |# c; A
  134.       
    % ?' L' @* g* ^6 K/ P: e
  135.     Add_Button();  
    * n- x- Q9 g- e4 m  X  S2 j
  136.       
    ! {: [6 f# o, g
  137.     return 0;  $ \9 \6 g" Y8 x  \) n
  138. }  
复制代码
" ?4 w% z: C* K
& c1 V* R( @* Z# u& z

评分

参与人数 1 ST金币 +2 收起 理由
MrJiu + 2 赞一个!

查看全部评分

赞 收藏 4 评论5 发布时间:2017-7-18 14:26

举报

5个回答
huaiqiao 回答时间:2017-7-18 21:12:39
多谢分享,学习啦
MrJiu 回答时间:2017-7-19 08:41:42
正需要!!!
埃斯提爱慕 回答时间:2017-7-19 13:05:28
提示: 作者被禁止或删除 内容自动屏蔽
epochal 回答时间:2017-7-28 19:20:45
谢谢分享!
五哥1 回答时间:2017-7-29 17:01:05
多谢分享,学习啦
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版