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

【经验分享】STM32F7驱动GT9147电容触摸屏控制芯片,并移植到STemWin

[复制链接]
STMCU小助手 发布时间:2021-12-17 12:05
一  电阻驱动与电容驱动原理0 V: P# R3 d8 ?1 }1 i& x
: B! a; e+ |4 l; P2 \6 G
1. 电阻屏等效电路如下所示, 当产生按压时:

8 h& \1 }' v% {4 d6 d7 r  vX-接地,X+接电源,Y+接ADC输入.通过读取Y+的电压以及电阻分压原理,可以得出触点的x坐标
5 W- r( E% m6 F+ n0 J2 U7 m5 \" i& KY-接地,Y+接电源,X+接ADC输入.通过读取X+的电压以及电阻分压原理,可以得出触点的y坐标0 p" Q+ O. E0 T* `  ?' k
; p' Y0 C: w5 A( G; ?5 N
2019061911075212.png

3 W, t6 m; |& D8 V0 {* M1 H& y
$ ?  V* u, A3 A  e$ T8 `& }; {2. 电容屏等效图如下所示, 检测原理类似矩阵按键, 当产生按压时:
2 b; A1 p- U6 G7 ~# j) P+ A& F) l5 J- c
X轴产生从上至下依次产生激励信号(AC交流信号), Y轴电极同时接受信号 (该激励信号是交流电,可以通过电容穿到Y轴).& @( r5 x1 a4 a: e

7 @: B% O: c) G假设有如下两个按压点(分别位于(1,1)与(2,2)的位置),检测过程如下:( B8 `3 q5 S. y. @$ X
当X1产生激励信号时,Y1接受到的交流信号产生了变化, 所以可以确认(1,1)处有触摸." d( ^$ v8 w8 o  H
接着当当X2产生激励信号时,Y2接受到的交流信号产生了变化, 所以可以确认(2,2)处也有有触摸.
% z4 |/ e# y2 E/ a
& X0 E) I' a) F' I# Z" ]" U5 I! z
20190619115448553.png
: ?* Z8 N6 _1 G' @- s9 U
& U7 D) }5 l) {! }" D% ^2 Y
二 软件模拟IIC) }2 n, G7 o% G- F  _5 }# t: L
由于stm32的硬件iic有各种各样的问题,所以采用软件模拟IIC的方式,主要实现IIC起始信号函数、IIC停止信号函数、等待ACK函数、产生ACK应答函数、不产生ACK应答函数、发送字节函数、读字节函数- R# y4 W, b0 t( J# Y
5 u5 @7 Y, t: l- g
1. 起始信号与停止信号
, z& N0 R2 U$ J' X, y) x: A4 W* w! F7 z. m
下图是IIC起始信号与停止信号时序图,通过观察该图编写起始信号与停止信号函数。
1 ~% h. l5 p8 m. R" S! ?4 o( _
* Z& C" f. W- d6 q& V: g
aHR0cHM6Ly9pbWFnZXMwLmNuYmxvZ3MuY29tL2Jsb2cvNDcwOTA5LzIwMTMwNS8yODE2MzczMy01MjE5.png
; t; {4 n) x0 @) _  \* q

/ G  j5 v, J& L7 p# y/ y* p2 N7 S起始信号:当SCL为高期间,SDA由高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号。
; p8 @$ z! u; H4 |8 O* I
  1. /***************************************************************************************
    8 W* ?% G2 T' Z/ l
  2.   * @brief  产生IIC起始信号,当SCL为高期间,SDA由高到低的跳变
    % m) ?2 D( B4 o0 Z
  3. ***************************************************************************************/: @! G/ \7 R0 ]& V. e6 h( _
  4. void CT_IIC_Start(void)
    0 {: G0 r* E6 C
  5. {
    6 X/ M+ f* Y9 ~- I6 W! ~
  6.         CT_SDA_OUT();     //sda线输出
    . M" O, Q) ]2 p5 I  t$ r- [
  7.     CT_IIC_SCL(1);8 m! h& [) }/ s8 W7 f% k3 K; W
  8.         CT_IIC_SDA(1);                    , f% V  {; A2 _% i5 `
  9.         CT_Delay();) s9 E( T7 @) C$ T) m
  10.          CT_IIC_SDA(0);
    4 u+ x: X2 V3 F3 v
  11. }
复制代码

) B  m- b$ l- K/ Y1 ~+ ^( E停止信号:当SCL为高期间,SDA由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。
) U; _: [- e6 K9 v3 X+ E. \
  1. /***************************************************************************************
    - Q5 c: h. ]& h; q5 p8 q
  2.   * @brief  产生IIC停止信号,当SCL为高期间,SDA由低到高的跳变
    , k# W% k' R1 y# n: }
  3. ***************************************************************************************/
    . m  q% {' N" O) c7 f2 }% r! {4 `
  4. void CT_IIC_Stop(void)
    $ O. F7 a1 }, [  j
  5. {2 L9 k/ Y; ~! L7 c
  6.         CT_SDA_OUT();//sda线输出: N. e: u+ A9 X2 [; R  V& {+ k; M
  7.         CT_IIC_SCL(1);
    1 ?- {9 p& f1 J, S
  8.         CT_IIC_SDA(0);//STOP:when CLK is high DATA change form low to high# P; G1 S2 C! u/ E
  9.         CT_Delay();
    ( y4 P2 j/ s% v/ h' k1 w
  10.         CT_IIC_SDA(1);% z6 t/ O7 D, u& E& m
  11. }
复制代码

. N& b& H) W4 V( A在GT9147数据手册中可以发现如下截图所示内容,SCL在低电平期间至少保持1.3us,其他电平最小保持0.6! V4 R2 a9 `( B1 t
4 W6 Q" q' w. S
20190622160910729.png

! ^" P: M: l* S8 A3 T. t
' y) [8 F6 \' V6 V所以将IIC延时函数定时为2us可以满足所有时序。(一般支持最高速度400k的IIC设备,基本都可以使用2us延时。)
* i/ ]6 q* g8 f% a: W1 d* @; i- y# M# e+ F# w& N
  1. //控制I2C速度的延时
    0 u4 F; s! Y6 m
  2. void CT_Delay(void)$ l; Y* I2 i6 e  c
  3. {8 G9 i! {) b) d2 d& w3 e5 J
  4.         delay_us(2);
    & x- u' ]0 @# C  Y
  5. }
复制代码
4 U7 T+ u& M3 H2 j% P' Y5 l' s
2. 数据传输 与 ACK时序
2 l" |& `5 n: Z1 G+ @: |! b$ U  W$ M6 e5 L: k+ I1 c9 L
下图是ACK时序与 传输数据0的时序图,这两种时序图是一样的,区别在于ACK是在8个数据时序后产生,且SDA电平是由接受数据端拉低的。& k" g3 b+ U- v* A. w

$ N9 w8 z4 n5 g8 G. u' ?( i9 P
20190622161607756.png
$ [' G" T, V+ X6 ~* K0 h

0 k) ~# z, c1 L& ?3 S4 P产生ACK时序:在SCL高电平期间,SDA为低电平状态。
$ {: l) Q: s3 K  R
  1. /***************************************************************************************
    1 l$ u. A3 S# I9 ]: M
  2.   * @brief  产生ACK应答,7 m3 E, f' S2 j, v! l
  3. ***************************************************************************************/) ?  X5 n6 k* Y$ p' ]$ g
  4. void CT_IIC_Ack(void)
    , d9 B( b1 c' |6 P; K) p
  5. {
    6 `  \" x6 h6 J1 u4 E: l7 M
  6.         CT_IIC_SCL(0);; C% p/ ?8 i" O1 S$ x8 |
  7.         CT_Delay();
    8 c) I0 s+ l, i) {1 _: _* J
  8.         CT_SDA_OUT();! \- f- G/ y# M3 I' ~8 o
  9.         CT_IIC_SDA(0);
    0 G  m1 r' x( T. e8 o( Y8 J9 j! Y
  10.         CT_IIC_SCL(1);5 Z; A3 n! O( Q% k2 j. M9 A! S; t
  11.         CT_Delay();
    # B/ w) u+ `4 g( Z8 G- j% G
  12.         CT_IIC_SCL(0);
    , D; X* [5 m6 p) B: Y0 G
  13. }
复制代码
& @; Q: i: b5 E2 l! g
等待ACK时序:拉高SCL与SDA后, 然后设置SDA为输入检测状态,等待接受数据端拉低SDA
  Z- a; I" d9 c1 H
  1. /***************************************************************************************
      I& k/ ?% n' F/ A" q2 L
  2.   * @brief   等待应答信号到来,等待接受数据端拉低SDA
    8 M" D, _' Q2 s/ F
  3.   * @input   
    8 n) c9 N+ j! q. p, _' R# @) A
  4.   * @return  1,接收应答失败 ; 0,接收应答成功& P% Z6 b5 f7 F" i; q$ |7 u
  5. ***************************************************************************************/
    ( R1 w3 ]  t/ Q! u/ f
  6. uint8_t CT_IIC_Wait_Ack(void)( I! A, X# H5 e9 U1 o  k$ t6 B
  7. {
    7 p& ^( s7 N, N7 J
  8.         uint8_t ucErrTime=0;" ~9 l+ j; W. u1 t
  9.         CT_IIC_SDA(1);           / Y! W1 J9 l: c8 V& W" W7 m
  10.         CT_IIC_SCL(1);8 d. T; b# D9 t* Z
  11.         CT_SDA_IN();      //SDA设置为输入  " V) q  g" ]. J% ~' X; S
  12.         while(CT_READ_SDA)
    8 N1 U- c) I4 p: U, h* p' C; q
  13.         {% j' `, B" [, j: h' T
  14.                 ucErrTime++;
    3 t5 K, v- p* N( N
  15.                 if(ucErrTime>250){
    0 r8 B1 e) D  V
  16.                         CT_IIC_Stop();1 R4 A& {# o9 q, D& E
  17.                         return 1;
    % t+ W8 j. N/ ^
  18.                 }% ^" A; X( _: B) S
  19.                 CT_Delay();
    " K, G4 {& t# Q3 T* S5 l+ C1 C
  20.         }
    " d$ G- n) c3 D5 J8 {
  21.         CT_IIC_SCL(0);6 Y$ ^/ s/ X7 h
  22.         return 0;  
    * f( N7 r1 ~7 X9 Y& S6 U
  23. }
复制代码
5 Q- {2 I, K5 @" b$ c* v+ r1 W
下图是nACK时序与 传输数据1的时序图,这两种时序图是一样的,区别在于ACK是在8个数据时序后产生,且SDA电平是由接受数据端拉低的。
* h) O" B/ ?  F
# }% v; v' h% Q3 k  j" X& o4 S
20190622164227486.png
1 b% Z; H# v9 d4 @9 O( X

: T' V+ A/ k9 G) t产生ACK时序:在SCL高电平期间,SDA为高电平状态。( U/ d3 G3 e& _/ }' }& w7 u+ s0 T
  1. /***************************************************************************************
    , u  M2 G- }' Z1 w
  2.   * @brief  不产生ACK应答        
    4 f9 f: W2 c0 z
  3. ***************************************************************************************/
    / B) ]' F0 `3 O4 t
  4. void CT_IIC_NAck(void)
    1 @5 G+ h) J) X, o3 R: s
  5. {$ n- H4 z0 M+ n' a8 g+ ^
  6.         CT_IIC_SCL(0);% O3 P9 N0 V1 O4 o+ V) `" [  b2 j8 D1 f
  7.         CT_Delay();
    ) V& j5 R0 g, R4 o  P
  8.         CT_SDA_OUT();3 M1 r, E! D# Y* s+ O0 _
  9.         CT_IIC_SDA(1);. ^& @6 m9 q6 N+ G- N6 T
  10.         CT_IIC_SCL(1);; _6 ~  h3 g% x7 i4 t. l
  11.         CT_Delay();& G* B7 }, u5 q7 c6 c9 U
  12.         CT_IIC_SCL(0);9 E! S/ z- X7 {2 y- Q
  13. }
复制代码
( }/ \5 c( w' P, P
发送一个字节函数,优先发送高位,即从bit7开始发送。0 u" h9 r' P6 S- C
  1. /***************************************************************************************  v8 i7 k! s, D  h
  2.   * @brief   IIC发送一个字节,
    / ~2 K& l. e, b% e9 [
  3.   * @input   
    ! d! {, w; c0 B" ]( K
  4.   * @return  ( a# K  s( O* f4 K" k( w
  5. ***************************************************************************************/
    $ d3 o! K0 E3 U7 h1 C% \& {7 f
  6. void CT_IIC_Send_Byte(uint8_t txd)  D! M# _$ p+ u4 B- \
  7. {4 N) D' z% o4 b9 p  z
  8.     uint8_t t;   & A# K& q+ y5 @
  9.     CT_SDA_OUT();            
    ; x. @0 m8 a# C" G
  10.     CT_IIC_SCL(0);//拉低时钟开始数据传输) B! ?( D; O4 S+ |
  11.     CT_Delay();
    # A$ U; Q* @& W9 _
  12.     for(t=0;t<8;t++)
    3 |( |: @: ?; J0 R- T! o
  13.     {% S; k. n* s+ G7 C; \' m; @6 F
  14.         CT_IIC_SDA((txd&0x80)>>7);//发送bit7位+ ~9 [4 D. [  R# C: P* T. F& l
  15.         txd<<=1; //将txd的次高位左移到最高位              
    # }2 g: x, x2 I$ s# D* [
  16.         CT_IIC_SCL(1);
    3 a- k$ t; P* Y2 W7 u
  17.         CT_Delay();# o+ a# P$ g( {; k; C* m4 O0 L7 r$ W
  18.         CT_IIC_SCL(0);        - _" v+ c0 {& l0 ~7 u
  19.         CT_Delay();
    8 o0 G8 U; Q- M' w8 s4 y4 x+ U. r
  20.     }
    1 E9 y9 C0 N+ B1 P4 ~
  21. }
复制代码
$ C2 S8 \* b. }  @3 g/ C
读字一个字节函数,接受到1bit数据后,将该bit放在bit0位置(通过receive++实现),如果还要继续接受数据,则将之前接受到的数据左移一位(通过receive<<=1实现),留出bit0位置接受新的数据。
$ ~5 V2 Y) j2 X
  1. /***************************************************************************************
    0 s3 E" b4 g6 ]9 c% T
  2.   * @brief   读1个字节
    + ^- x$ f) N. c: J2 T: J
  3.   * @input   ack=1时,发送ACK,ack=0,发送nACK
    0 u& I4 w! V" X! E5 K
  4.   * @return  ! _  ?0 ~; h$ L
  5. ***************************************************************************************/
    : }# s' n3 O! ~2 W. l
  6. uint8_t CT_IIC_Read_Byte(unsigned char ack), d5 v* N  T, U" L: X  g7 N
  7. {
    4 F& i+ |2 h. o
  8.         uint8_t i,receive=0;& _7 A5 Q7 F, D, F5 f
  9.          CT_SDA_IN();//SDA设置为输入
    8 C, N) Q4 u) t+ C6 A9 _4 d$ G# b
  10.         CT_Delay();
    2 t! d2 Y  X' D5 i$ N
  11.         for(i=0;i<8;i++ )
    % J+ M" r: G3 o* s
  12.         {
    . B' k' B0 Z# L% [- G
  13.                 CT_IIC_SCL(0);                        ! Q  v- k& N3 i
  14.                 CT_Delay();
    - b* \# {8 L2 Y) I0 E
  15.                 CT_IIC_SCL(1);         ; T  M6 d1 J0 V4 |. t
  16.                 receive<<=1;( H/ H$ i8 b3 f* \$ }9 ~! {' [4 _) C
  17.                 if(CT_READ_SDA)receive++;   
    3 E3 i: \- r8 B# l4 w' M
  18.         }                                           . e; K6 s/ |+ q( C4 B
  19.         if (!ack)
    ( ?/ P, S% o, L$ R
  20.         CT_IIC_NAck();//发送nACK
    / s4 K* b5 I% a/ f
  21.         else 7 x- J6 r) L1 }' T# m& y1 S" G7 f. N
  22.         CT_IIC_Ack(); //发送ACK   
    8 {; I: x) s- T
  23.          return receive;
    ' ]! e8 v) J8 d/ |2 s
  24. }
复制代码
! ?& t0 n8 W. {0 i2 v9 q
三 GT9147电容触摸屏控制芯片驱动
0 W6 m- q+ p6 N1. GT914内部结构框图如下图所示7 {" ]9 `9 @8 {- D
; r4 v1 z, F  D2 s
2019061913180610.png
' W. P6 h# R4 Z  Z

( ?/ V+ d9 a7 v# Q3 M
5L5)3BWQK[DM1E_`8%S}J0F.png
' e+ ^- z6 J6 ?  h
2 W) V# D2 O, i1 B( k
2. 上电流程
9 |. h- V0 e: [. ~1 f/ E  k! R3 q7 `( O  q
GT9147上电初始化流程如下所示:7 }( f& X# q; l2 G8 _
1 ?. X5 [* |, `0 g* |# S( ]
配置RST输出低电平,INT输出低(或者高)电平后,位置100us以上,此阶段配置IIC地址为 0xBA/0xBB(或者0x28/0x29)
; _( {' n4 U" z接着配置RST输出高电平并维持5ms以上后,可以配置INT引脚为悬浮输入模式。1 ~! B/ E4 d9 J; U' R
等待50ms以上后,可以发送配置信息。
1 T; _/ }/ i' R( q! _8 Y$ q5 }$ u! u; S5 E6 h
2019062113491579.png
1 P7 r% O  c" k! M; r/ M+ |

7 U" G  p# H+ [' P代码参考原子例程编写,贴上代码:
3 `0 R; F# Z" S4 O! n& Z
8 Q: g, z7 P0 _' p& A% _4 i& [2 B7 G
  1. uint8_t GT9147_Init(void)
    & S/ I, ?# p" r" s9 H4 H4 I
  2. {
    4 s2 Z( y3 \; W& ]+ [, z& \% q
  3.     uint8_t temp[5];( z9 N/ ]( c, Q
  4. 5 a6 I+ H' M5 X, V/ f4 |, Y1 O
  5.     GPIO_InitTypeDef GPIO_Initure;  m: o6 z, k; u
  6. , h% q2 U/ q  [4 b1 o
  7.     GPIO_Initure.Pin = GPIO_PIN_7;          //PH7
    % |; e& f8 N1 I' |) t7 J  G3 `. Q
  8.     GPIO_Initure.Mode = GPIO_MODE_INPUT;    //输出# t7 c" z, D" R/ b; q/ D
  9.     GPIO_Initure.Pull = GPIO_PULLUP;        //上拉' p5 @% M. L4 b+ }
  10.     GPIO_Initure.Speed = GPIO_SPEED_HIGH;   //高速" U/ b& _7 w* I; }8 H
  11.     HAL_GPIO_Init(GPIOH, &GPIO_Initure);    //初始化
    " I! O* j9 e& {7 Q$ i( |
  12. 8 q1 ]- A8 N5 `3 u3 @; L- I! D" z  y
  13.     GPIO_Initure.Pin = GPIO_PIN_8;           //PI82 a6 F4 P' r6 j* }5 T
  14.     GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP; //推挽输出+ }, Q9 ~+ Z8 I1 B' g0 X
  15.     HAL_GPIO_Init(GPIOI, &GPIO_Initure);     //初始化
    $ \8 A; m& d' i- S# R% j

  16. 9 p: `9 k! d* `' q% Q
  17.     CT_IIC_Init();              //初始化电容屏的I2C总线
    9 p1 C2 y' H0 j/ ?/ g

  18. + K  W, k! U# k3 X0 W6 _1 T+ z& k
  19.     GT_RST(0);                                //复位
    " R9 j5 m) R2 N+ H9 l
  20.     delay_ms(1);            //INT引脚电平维持100us以上
    % l. P; O, [% Q& {5 s  t3 T
  21.     GT_RST(1);                                //释放复位
    ' C3 f" Q- a7 _% b. x
  22.     delay_ms(10);           //释放复位后维持5ms以上,设置INT为悬浮输入7 K5 x+ @, b  @1 r: x
  23.     GPIO_Initure.Pin = GPIO_PIN_7;
    ! j# R" Q. Y: h7 m* m; a7 u
  24.     GPIO_Initure.Mode = GPIO_MODE_IT_RISING;
    9 ~9 ?( }/ E. I1 H5 J
  25.     GPIO_Initure.Pull = GPIO_NOPULL;
    7 F( {: q  r4 r. g2 y( U1 b$ W
  26.     HAL_GPIO_Init(GPIOH, &GPIO_Initure);    //初始化
    ) X. E5 D* X" e) i8 R
  27.     delay_ms(60);) Y) ^# s8 i$ k  x4 E) O/ R: Z

  28. ; I, g. f$ |" B4 Q
  29.     GT9147_RD_Reg(GT_PID_REG, temp, 4); //读取产品ID
    1 x$ \1 G! s: Y1 n- c6 v9 L
  30.     temp[4] = 0;
    5 n3 |$ b# S/ h& `) ~; k4 Y* e
  31.     printf("CTP ID:0x%s\r\n", temp);        //打印ID' v& J" e) L2 d; X  |/ z, D

  32. 7 \; r/ d9 W2 a
  33.     GT9147_Send_Cfg(1);//更新并保存配置
    3 e" ]  w: x6 S0 ~) _; f

  34. + q' A7 V, z  f4 G$ }6 }5 ]
  35.     return 1;& Y' y, J9 l+ ^) S
  36. }
复制代码
2 N- q, c& R7 F& z9 C0 x
3. 读取坐标流程
/ j7 N% Z; L8 F8 o! @& \0 A1 C; W1 r- p% y; U5 A' n
使用中断方式读取坐标,需要注意的是,如果不及时读取坐标信息会一直产生中断。GT9147的中断脚与STM32的LINE7中断线相连,中断回调函数如下所示。当按下触摸屏时,touch_x与touch_y分别保存触摸时的xy坐标;当松开触摸屏时,touch_x,touch_y赋值0xffff! \1 Z3 m6 \3 r2 q: l
5 N- t. F) S. U5 C9 C, u, z
  1. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
    " O7 Y+ }' G4 R& X/ Y2 B8 {9 f
  2. {" `. r. d- d5 Q. d& f" a
  3.     uint8_t buf[4];# M3 A  _# \' A9 M2 D
  4.     uint8_t i = 0, mode = 0, temp = 0;& {" l8 F2 e: Y& R
  5.     uint16_t x[5], y[5];* r* J4 f/ _/ L- t
  6.     if(GPIO_Pin == GPIO_PIN_7) { //读取坐标, 否则会一直有INT脉冲8 a, t' A7 J1 j# U  B0 ?
  7.         GT9147_RD_Reg(GT_GSTID_REG, &mode, 1);        //读取触摸点的状态
    , T  j7 J9 z6 }7 p; _9 A% e( G2 ~7 a
  8.         if(mode & 0X80 && ((mode & 0XF) < 6)) //有坐标可读取) D7 k4 p' y' l1 ~. Q, Q/ E
  9.         {, `4 ~# O( _; Z0 `
  10.             temp = 0;; h+ N  o: l$ \7 k- S& @
  11.             GT9147_WR_Reg(GT_GSTID_REG, &temp, 1);//清标志
    % [& O& \* \0 C$ {, W# y2 A! N
  12.         }
    8 F1 e8 x' M1 T! \
  13.         if( (mode & 0xF) && ((mode & 0xF) < 6)) //判断触摸点个数
    ' R; x" [! R4 e2 e+ O$ O
  14.         {# D- Y" B! J% u
  15.             for(i = 0; i < (mode & 0xF); i++)9 O# h" X# a9 N8 J; i: m
  16.             {
    " S0 A) V4 j# E" I+ q# X* _
  17.                 GT9147_RD_Reg(GT9147_TPX_TBL<i>, buf, 4);        //读取XY坐标值, B7 B/ N5 t9 o: E! M- ]' S
  18.                 </i>x = (((uint16_t)buf[1] << 8) + buf[0]);% B: h; d- X$ e
  19.                 y = (((uint16_t)buf[3] << 8) + buf[2]);
    ) c' _, B. w8 u. J# @+ x4 o
  20.             }; d% o& B. s- l% A. d
  21.             touch_x = x[0];
    ) l) K0 i5 M  a. Q% z
  22.             touch_y = y[0];
    / m* G7 x; L5 X# q! ^
  23.         }
    # B  i1 X- `! U1 r3 s
  24. % b6 f1 ~9 G8 M% X* }! `2 Z( Y
  25.         if((mode&0x8F)==0x80)//无触摸点按下,xy赋值为0xffff# J& {: e9 x( x! U; b' Y9 Q
  26.         {1 A/ H* ^2 @2 \! B4 ^- A, E5 {: R% S# s5 z
  27.           touch_x = 0xffff;1 g3 x& q* A" t: Q  w; b
  28.           touch_y = 0xffff;
    5 \1 J- }4 c/ M8 H
  29.         }# `- Q8 Z: t, T# q
  30.     }" q! p- j4 B& w- o9 t0 J4 k
  31. }
复制代码
4.主机 对 GT9147 进行读操作时序
8 q. Z% r/ m4 j" `3 t( M+ _1 y  D" {& ~# c0 [( f6 V
20190621161601926.png

" ?; E# y2 T! e; W* }* u9 P7 }
( v! @3 m  P2 {( q3 F$ k7 s根据该时序图编写读寄存器函数如下:9 W0 _8 R$ l9 j6 O% G( {

, o! x- y1 K, P3 X
  1. /***************************************************************************************
    8 ~2 t( P5 b) V  \) B
  2.   * @brief   从GT9147读出一次数据
    ! E6 M! K8 [8 T& @! e
  3.   * @input   reg:起始寄存器地址
    * u$ ?# C' G6 y! F, _
  4.              buf:数据缓缓存区2 O3 K8 F1 I1 N9 W6 j6 e
  5.              len:读数据长度        & m* X1 n" q+ S
  6.   * @return  0 X2 e) z; J7 q- P$ K% o6 j
  7. ***************************************************************************************/
    4 _$ z# v" o* q) v
  8. void GT9147_RD_Reg(uint16_t reg,uint8_t *buf,uint8_t len)
    7 a+ V2 i7 d. F$ |
  9. {
    1 t' y  m1 C2 m1 g7 Q0 F
  10.         uint8_t i;
    % r' V1 T# F" p0 V+ z: k- C* K4 Z: {
  11.          CT_IIC_Start();        4 m% C* V9 B! |# ^
  12.          CT_IIC_Send_Byte(GT_CMD_WR);   //发送写命令         
      Z8 P2 H  U4 a& }! P+ F3 R& q" U
  13.         CT_IIC_Wait_Ack();
    # `3 K( r3 O% ]0 h
  14.          CT_IIC_Send_Byte(reg>>8);           //发送高8位地址
    ) u, E8 o& F3 w2 C- {: M4 s: V
  15.         CT_IIC_Wait_Ack();                                                                                                               + ^7 A( ]% l9 \' m. B; I7 F0 q, R
  16.          CT_IIC_Send_Byte(reg&0XFF);           //发送低8位地址4 ?- V$ ^4 ^# d! H7 ^! ?! X
  17.         CT_IIC_Wait_Ack();  % F7 j$ I9 W% E6 A& G2 d
  18.          CT_IIC_Start();                     
    8 V8 {$ N) C5 ~
  19.         CT_IIC_Send_Byte(GT_CMD_RD);   //发送读命令                  
    , M" s# b8 h! {: @' k8 S
  20.         CT_IIC_Wait_Ack();           % Y: k/ p1 d5 B1 }0 Z0 m
  21.         for(i=0;i<len;i++)$ f8 @2 T- M' B2 p  B
  22.         {4 a& G+ x5 S. S4 ^2 G( o
  23.             buf<span style="font-style: italic;"><span style="font-style: normal;">=CT_IIC_Read_Byte(i==(len-1)?0:1); //发数据          + B3 V+ w: I2 F, l7 ~! l- U
  24.         }) o: U5 C4 ?5 g$ ^% ^* l
  25.         CT_IIC_Stop();//产生一个停止条件    " t: H4 t4 L7 U3 [6 T6 ^
  26. }</span></span>
复制代码

, N$ I+ L, }/ M* C; Z6 f- D6 P5 x5.主机对 GT9147 进行写操作时序
7 I6 f1 t' e% E% X
9 ?+ A( Z5 L* x  D
20190621161509843.png
* N! ]. C) D% v
# E/ c5 o; ]9 G( C- M
通过该时序图,编写写寄存器函数如下
$ h: b7 E3 |3 z/ u( c# ]) C$ O1 n) b3 Y! N$ U/ {& X+ W
  1. /***************************************************************************************( F1 w  Q+ x. W5 D1 r
  2.   * @brief   向GT9147写入一次数据& v/ Y! z' I5 T, s6 ]" l
  3.   * @input   reg:起始寄存器地址; ; |' l1 r% q9 h* {5 d( Z, e
  4.              buf:数据缓缓存区
    1 y9 [$ q# S( {1 K
  5.              len:写数据长度. R; ?% M& I; |  U2 Q1 B
  6.   * @return  0,成功; 1,失败., F; _+ K! Y# }% i7 n
  7. ***************************************************************************************/9 U9 [* ^3 S  l7 o2 {  e, ~" w4 u
  8. uint8_t GT9147_WR_Reg(uint16_t reg,uint8_t *buf,uint8_t len), f5 b3 }0 G4 r$ W2 g7 G3 f
  9. {
    : c3 z8 V0 c: B2 B6 w( R' s
  10.         uint8_t i;8 Y& i: R8 N8 ]6 |! c% r
  11.         uint8_t ret=0;2 ^$ R) X; i  n' n1 }! k( s! S
  12.         CT_IIC_Start();        " Z7 s# _( r; I' [) S
  13.          CT_IIC_Send_Byte(GT_CMD_WR);           //发送写命令         
    + `# X+ a9 Q! W
  14.         CT_IIC_Wait_Ack();! ]% s" J& a3 C# v9 W* @/ }
  15.         CT_IIC_Send_Byte(reg>>8);           //发送高8位地址1 n$ b. \. f; L! O' B8 Q* L
  16.         CT_IIC_Wait_Ack();                                                                                                               2 L$ a& Z8 a9 \8 N* \( [
  17.         CT_IIC_Send_Byte(reg&0XFF);           //发送低8位地址/ D5 Q' O/ b* a9 h
  18.         CT_IIC_Wait_Ack();  ( E! e( @" j2 f- f
  19.         for(i=0;i<len;i++)
    3 T& u; L6 z1 H# k, v
  20.         {
    ; V& Y0 h: b) T4 b5 `/ z2 W
  21.             CT_IIC_Send_Byte(buf<span style="font-style: italic;"><span style="font-style: normal;">);          //发数据
    - \5 v" r, z' F  ]
  22.                 ret = CT_IIC_Wait_Ack();
    ) @/ K% D. B$ q1 p$ L: f
  23.                 if(ret)break;  . S1 j; [: I2 M
  24.         }1 j% D, W& R) c' `) D3 |! F
  25.     CT_IIC_Stop();                                        //产生一个停止条件            
    . O+ x. K# y5 r! Q0 w/ R  W  Q4 z: B
  26.         return ret;
      `8 E; _- y# g' Y. F% g9 k9 G
  27. }</span></span>
复制代码

6 l  u3 A& g$ G- @2 ^# F6. GT9147配置函数如下,GT9147_CFG_TBL针对分辨率480×272的触摸屏。  b" V' n* O( z* g6 _7 L! h& j# r3 \

" G+ B" y+ K$ H" c+ M, B配置寄存器时是要注意以下几点:$ M4 m) i$ t; ]

2 {$ M# I9 V0 a) a新的版本号大于等于GT9147内部flash原有版本号,才会更新配置.1 ]$ _1 c! R& Q! _
写完GT9147_CFG_TBL中的配置后,还需要往0x80FF寄存器中写入校验,0x8100寄存器中写1。9 [6 D5 a) @# g9 l7 h* B7 m, W  h" k& p
关于配置更详细的信息可以参考GT9147编程参考手册4 N3 o# j2 {. C( y8 d' l
  1. const uint8_t GT9147_CFG_TBL[]=2 ^! h# O7 k: y+ C# F/ Z" j
  2. {
    & L% K0 o' ?$ \
  3.     0x60,0xe0,0x01,0x10,0x01,0x05,0x0C,0x00,0x01,0x08,
    ! ~3 p7 R% s6 i( ]3 H: Z, V! I
  4.     0x28,0x05,0x50,0x32,0x03,0x05,0x00,0x00,0xff,0xff,6 ?/ h2 c5 e5 o: `4 a
  5.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x89,0x28,0x0a,
    & l/ ]; _& O' f% b
  6.     0x17,0x15,0x31,0x0d,0x00,0x00,0x02,0x9b,0x03,0x25,
    0 w5 |& G, |* P8 ]3 K' {! ]
  7.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0x00,0x00,( C9 D6 [5 e# U9 L$ r, P6 ~/ G
  8.     0x00,0x0f,0x94,0x94,0xc5,0x02,0x07,0x00,0x00,0x04,% a1 y  |' n) h4 X
  9.     0x8d,0x13,0x00,0x5c,0x1e,0x00,0x3c,0x30,0x00,0x29," `, \% U& M8 e$ f
  10.     0x4c,0x00,0x1e,0x78,0x00,0x1e,0x00,0x00,0x00,0x00,2 c% ]- o& t; I5 }; R
  11.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    7 A9 b' ^3 G8 R1 I1 G8 X# m
  12.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    ; E# X' |5 O* x* r2 h
  13.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,# Y- a, K9 k7 a
  14.     0x00,0x00,0x08,0x0a,0x0c,0x0e,0x10,0x12,0x14,0x16,
    5 G2 D- t, ?5 H* H+ _# I
  15.     0x18,0x1a,0x00,0x00,0x00,0x00,0x1f,0xff,0xff,0xff,' |3 C0 }9 T- b& _8 A6 D
  16.     0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,. c) T. C  f! D/ S7 t- Q' U7 L
  17.     0xff,0xff,0x00,0x02,0x04,0x05,0x06,0x08,0x0a,0x0c,& p3 \+ k" t% l4 O) l
  18.     0x0e,0x1d,0x1e,0x1f,0x20,0x22,0x24,0x28,0x29,0xff,2 w  I0 A* f9 c9 C3 i% {
  19.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,/ V+ F9 b. n  N% ~9 h
  20.     0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,- _  J; @& m, u  d
  21.     0xff,0xff,0xff,0xff," p6 }1 U6 @3 ]. ?1 k* ?& l: r/ L
  22. };
    9 Q8 _7 n  h9 m% \, L& b9 P

  23. 7 m; l3 Z* {/ V4 {4 ]9 C! S" `, C
  24. uint8_t GT9147_Send_Cfg(uint8_t mode)
    4 y) Q0 O2 W7 [, ?; L
  25. {
    * k; w+ o6 T: L; _  {
  26.         uint8_t buf[2];2 R) c3 U$ z0 N# d/ f
  27.         uint8_t i=0;5 x$ V7 t2 e2 X3 r
  28.         buf[0]=0;
    # `+ I' Z5 q; \2 t. }
  29.         buf[1]=mode;        //是否写入到GT9147 FLASH?  即是否掉电保存
    9 O0 _7 U3 G; U1 d/ f) U* m
  30.         for(i=0;i<sizeof(GT9147_CFG_TBL);i++)
    2 W; M, Y" |1 A
  31.             buf[0]+=GT9147_CFG_TBL<span style="font-style: italic;"><span style="font-style: normal;">;//计算校验和. y6 ]' @3 e5 n: x
  32.         buf[0]=(~buf[0])+1;
    1 s1 K0 h2 ~6 w# P" @# t
  33.         GT9147_WR_Reg(GT_CFGS_REG,(uint8_t*)GT9147_CFG_TBL,sizeof(GT9147_CFG_TBL));//发送寄存器配置* c9 e9 h* N- s  b' v
  34.         GT9147_WR_Reg(GT_CHECK_REG,buf,2);//写入校验和,和配置更新标记
    2 i) e- P4 F2 B4 w5 @
  35.         return 0;+ n  E( y2 T! ^: f& C
  36. }</span></span>
复制代码

4 M5 H; P- h- n0 v" d+ d+ y
四 移植触摸屏驱动到STemWin  v2 [5 C0 K0 e4 C5 v
这里假设已经成功移植了STemWin到STM32F7工程。/ }# `1 j4 ]& h& k% L: P; }
$ l1 n" |1 ]' M" Z$ i& w
1. 在GUIConf打开STemWin触摸屏驱动宏
5 A/ q  i+ \1 p. x
, V" r4 B% u+ J' M
  1. #define GUI_SUPPORT_TOUCH       (1)  // Support touchscreen
复制代码

3 @* f) N7 U4 T) n7 R1 U+ A* ^* A8 F% B2. 新建GUI_X_Touch_Analog.c文件实现以下四个函数,在第三章第3小节我们知道touch_x,touch_y表示当前触摸的xy坐标。整个文件的内容如下所示。2 J- r* Q1 P$ A( x& ^5 j: O

0 I/ c6 ]/ j0 e8 i6 U
  1. void GUI_TOUCH_X_ActivateX(void)
    * r3 A% T7 ^) M  v
  2. {& c( T- E+ w1 p5 q% n1 R4 j+ ]

  3. " e( j6 _" m! Y+ {# @- f2 T
  4. }
    6 J5 R- [! X& _, v

  5. : {# C" i2 ^- z8 U" ~9 y+ n8 v
  6. void GUI_TOUCH_X_ActivateY(void)* ?: a& @! S7 I( n) v: S
  7. {
    3 X6 M3 E$ o' p; ]
  8. / `* K: o3 B; i1 u
  9. }
      [* D8 o+ C3 o) P$ t% n: N

  10. % f5 J9 B( c7 v; q, B
  11. /*获取x坐标*/( I: d) R7 f% ^- T* {
  12. int  GUI_TOUCH_X_MeasureX (void)) k# H  A$ R3 u7 g
  13. {
    / H/ u5 H+ D9 q- S, E# w
  14.   return touch_x;
    , L& v# d, w+ v# F5 c, N7 K% N
  15. }4 d* u' p  _: |& n* n4 F3 v. W

  16. ) c& r) Z4 n. x& Z# N  r1 E  I
  17. /*获取y坐标*/5 l0 X% y# M. r% K* f* S
  18. int  GUI_TOUCH_X_MeasureY (void)# i$ _; |0 f1 e% a: }
  19. {+ q- c# s# v7 G6 D1 k+ |6 L
  20.   return touch_y;0 {6 p0 {1 d$ x5 W
  21. }
复制代码

! [0 t1 k; ]+ L% |4 w* o. I$ E3. 使用GUI_TOUCH_Calibrate函数校准x与y值,然后才能调用GUI_TOUCH_Exec()函数处理触摸事件。
! @5 Q& \% Y- e- _" _7 G
  u* g% S% S: m7 {% S0 P( U; c
  1. void StartTouchTask(void const * argument)2 p$ @# e* y# D+ b; ?, n
  2. {1 ~" a  B& Y* D! ?
  3.   /* USER CODE BEGIN StartTouchTask */, n1 p. @" _3 ^# {! M2 w
  4.   GUI_CURSOR_Show();//显示鼠标指针( `, I8 z; B! I7 @0 V1 b! g
  5.   GUI_TOUCH_Calibrate(GUI_COORD_X,0,LCD_WIDTH,0,LCD_WIDTH);   : t* z+ H. u6 T1 ~" C
  6.   GUI_TOUCH_Calibrate(GUI_COORD_Y,0,LCD_HEIGHT,0,LCD_HEIGHT);
    , c% r; ?2 W, N$ m4 f
  7.   /* Infinite loop */! G' G6 p: u. j
  8.   for(;;)
    - y3 @& ?. v6 E( g% F2 C
  9.   {' X/ }& f+ X8 K
  10.     GUI_TOUCH_Exec();( L. R1 a' k3 G/ `
  11.     osDelay(5);6 W0 _+ w0 L7 e: o/ N% x
  12.   }5 M! H2 P. n" d
  13.   /* USER CODE END StartTouchTask */
    ; r+ x' K) }5 a$ p% z9 u$ h
  14. }
复制代码
# P, j0 x$ y" o
: V! r! f) T% i$ e' s  ]" }9 F8 N$ M& m

( Y+ k& v- {  o0 o" c1 ]! |! T" o- h! |! ]# f/ ^6 P
收藏 评论0 发布时间:2021-12-17 12:05

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版