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

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

[复制链接]
STMCU小助手 发布时间:2021-12-17 12:05
一  电阻驱动与电容驱动原理
& t/ `! u+ V% F& F. y) b
! l1 V0 F- ]; b3 i8 K1 p1. 电阻屏等效电路如下所示, 当产生按压时:

) e! e6 {' a+ s2 b: yX-接地,X+接电源,Y+接ADC输入.通过读取Y+的电压以及电阻分压原理,可以得出触点的x坐标5 Z2 v- ]( l. y2 g( w
Y-接地,Y+接电源,X+接ADC输入.通过读取X+的电压以及电阻分压原理,可以得出触点的y坐标
& p; f% J7 g" ?6 {; x" F3 T* q+ E
5 F5 N7 R; s2 d. F6 c3 e( o6 T/ `7 I9 m
2019061911075212.png

1 y6 ^+ K; `+ i8 L- _+ p& T3 {: e( u1 T
2. 电容屏等效图如下所示, 检测原理类似矩阵按键, 当产生按压时:
9 {1 [5 t  x: [7 [7 g- S: g) x% v4 U
X轴产生从上至下依次产生激励信号(AC交流信号), Y轴电极同时接受信号 (该激励信号是交流电,可以通过电容穿到Y轴).: [& R; [0 T+ T4 d0 f" n- v# R

. q) E2 s9 n- c- V假设有如下两个按压点(分别位于(1,1)与(2,2)的位置),检测过程如下:. z* \' N4 M9 ?, w; `- M# E
当X1产生激励信号时,Y1接受到的交流信号产生了变化, 所以可以确认(1,1)处有触摸.* e/ H, Q6 i) X, Y) m+ i
接着当当X2产生激励信号时,Y2接受到的交流信号产生了变化, 所以可以确认(2,2)处也有有触摸.
; J+ z: o, D: }+ U4 p, Y* i: a' e8 Z( ?
20190619115448553.png

! `. ]/ F6 q+ M8 W4 E$ ?; `* C3 u- ]8 U; }, E
二 软件模拟IIC! x  M2 ^, t' l6 L
由于stm32的硬件iic有各种各样的问题,所以采用软件模拟IIC的方式,主要实现IIC起始信号函数、IIC停止信号函数、等待ACK函数、产生ACK应答函数、不产生ACK应答函数、发送字节函数、读字节函数
. I, O& b& R* R& z% ?& r1 i9 h
: \8 K& p3 j2 j: e0 A2 z) X1. 起始信号与停止信号
6 d% h6 D6 z# }/ S/ O$ I* U3 T
- O0 ^& x' L! Z9 f2 @$ {下图是IIC起始信号与停止信号时序图,通过观察该图编写起始信号与停止信号函数。
' ~& _( Q5 N. U  L
2 Y4 B0 q# s0 Q8 U' p
aHR0cHM6Ly9pbWFnZXMwLmNuYmxvZ3MuY29tL2Jsb2cvNDcwOTA5LzIwMTMwNS8yODE2MzczMy01MjE5.png
. S  |+ E" x% f* d/ C3 Q
, S; I4 T4 S# x* E% _
起始信号:当SCL为高期间,SDA由高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号。
5 Q9 Q1 t$ T9 _+ V- Q
  1. /***************************************************************************************3 A6 C( b2 e) I  t
  2.   * @brief  产生IIC起始信号,当SCL为高期间,SDA由高到低的跳变
    $ ]& ?9 m( g8 c/ p9 @; K( _- ]
  3. ***************************************************************************************/
    6 F! n/ B# R0 {& f$ w5 K, D) f  m$ A
  4. void CT_IIC_Start(void)! @3 G3 ~8 ?1 h7 a9 H" r+ b" F2 E' N
  5. {
    . Z, X  h; g  M* F
  6.         CT_SDA_OUT();     //sda线输出: z7 @  C; \' F/ H
  7.     CT_IIC_SCL(1);5 S5 ^# q9 M' _. X4 K
  8.         CT_IIC_SDA(1);                    1 g7 ~$ S, z) W: Q9 Q
  9.         CT_Delay();" N5 D7 q. X" v8 t: Q
  10.          CT_IIC_SDA(0);
    ' U5 {8 m" M# ?, r1 l/ {
  11. }
复制代码

3 A( ]+ I) j; P. Q, U( w4 U' T& _停止信号:当SCL为高期间,SDA由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。+ m& I6 ~) l- F7 X! p) g$ s6 n
  1. /***************************************************************************************
    6 Z; \+ r) v3 z4 k6 W" \
  2.   * @brief  产生IIC停止信号,当SCL为高期间,SDA由低到高的跳变+ D7 D; T, |) W1 C% O' _
  3. ***************************************************************************************/( N* E5 ~4 J. I" R8 x
  4. void CT_IIC_Stop(void)6 N2 n% |* W1 r
  5. {# ^# S) Q% Z' M7 d& ]- C
  6.         CT_SDA_OUT();//sda线输出* L5 z8 Y: p: N8 g- s
  7.         CT_IIC_SCL(1);7 l* M* C9 r/ u+ z6 l  j
  8.         CT_IIC_SDA(0);//STOP:when CLK is high DATA change form low to high, y3 z) A5 g6 P6 O! r  h0 ~0 T0 |- I+ D. j
  9.         CT_Delay();' x3 j+ _+ u) i6 |! [# I
  10.         CT_IIC_SDA(1);) l+ L7 [, b) ?3 b2 j  y
  11. }
复制代码

3 x7 l+ B4 n: ^3 p在GT9147数据手册中可以发现如下截图所示内容,SCL在低电平期间至少保持1.3us,其他电平最小保持0.6
& ?+ s3 Y1 ^; g( Z; z! c) `% B3 E% C8 o! ?
20190622160910729.png

8 f; ~# H3 X2 Z4 \5 k* S& g+ x0 G  w# q( I+ A& k
所以将IIC延时函数定时为2us可以满足所有时序。(一般支持最高速度400k的IIC设备,基本都可以使用2us延时。)8 o3 p5 w2 x$ k' f

0 q/ k! S  o1 ^1 u  x! R# ~1 L, w2 s
  1. //控制I2C速度的延时
    , U6 {* l2 O# d7 ?$ `- T
  2. void CT_Delay(void)
    $ N# y* N% l: O9 y5 ?
  3. {
    0 W2 A4 U( h; J0 k; J; F
  4.         delay_us(2);
    4 w  a5 ~% d2 ]& i% x- Q- J9 N
  5. }
复制代码

$ W* N* F/ ~8 k4 p; Q+ E2. 数据传输 与 ACK时序
' o- m# f; B" ?( j/ E: F, }
$ B0 }- z1 @$ i" T& {/ y% v$ e4 q4 ?下图是ACK时序与 传输数据0的时序图,这两种时序图是一样的,区别在于ACK是在8个数据时序后产生,且SDA电平是由接受数据端拉低的。: ^8 J! L, H, p) o

! y, N0 O. o7 N; m6 m" q0 Q( R
20190622161607756.png

) E5 O. i( D# _( t* L: k3 R9 I/ @9 S, N/ i) c5 V/ m% @
产生ACK时序:在SCL高电平期间,SDA为低电平状态。
4 s- M; ~3 y6 A" o
  1. /***************************************************************************************% `9 `  t/ d* J5 h& q
  2.   * @brief  产生ACK应答,
    ; j7 G/ P# n' L  w
  3. ***************************************************************************************/7 n' H4 F- h9 z$ j: V
  4. void CT_IIC_Ack(void)
    5 h! X# e/ M5 l* v
  5. {' P  J% `/ S( u; E( \
  6.         CT_IIC_SCL(0);
    * B3 u# R( D' R4 y: ~
  7.         CT_Delay();
    4 B4 \1 e  a# l. Y9 l) _. }1 N5 B/ {
  8.         CT_SDA_OUT();
    3 a& j/ K; E6 Z' p8 s- `" ~
  9.         CT_IIC_SDA(0);" ?0 Y4 x' D" s: {2 ]2 y$ o
  10.         CT_IIC_SCL(1);' t+ p' ]6 t7 G) F7 r( S- N
  11.         CT_Delay();& u9 j2 W  S, {7 W4 q6 s1 f
  12.         CT_IIC_SCL(0);
    8 e- n( c: L9 e7 G
  13. }
复制代码

8 ]2 [3 x: c6 Z& E8 k等待ACK时序:拉高SCL与SDA后, 然后设置SDA为输入检测状态,等待接受数据端拉低SDA. X. I" {/ M7 y- a/ k
  1. /***************************************************************************************
      z: U) a# X. T. }# ~/ @
  2.   * @brief   等待应答信号到来,等待接受数据端拉低SDA
    6 P' V. }2 u0 ?' }' [- D
  3.   * @input   3 H# Q# ~2 M) N
  4.   * @return  1,接收应答失败 ; 0,接收应答成功
      S: e$ @) s3 A% _2 |" B
  5. ***************************************************************************************/
    2 \4 t2 b& c0 ]- @8 s
  6. uint8_t CT_IIC_Wait_Ack(void), w+ J/ z  G. d/ K  U. i; p
  7. {
    9 _. X# d1 p! K
  8.         uint8_t ucErrTime=0;
    ) T/ g: x% s1 Q- f$ R
  9.         CT_IIC_SDA(1);           
    3 Q7 z. }# R8 R+ Y$ n
  10.         CT_IIC_SCL(1);6 P- F# T% j0 _
  11.         CT_SDA_IN();      //SDA设置为输入  ; d7 }3 F0 K8 {& Y4 z
  12.         while(CT_READ_SDA)
    / _+ x0 x- j+ q6 b* c  \; {
  13.         {
    4 m/ L" Y+ O7 v! o5 Y
  14.                 ucErrTime++;0 N! j' Z) M& Z& T8 s6 z8 H3 H
  15.                 if(ucErrTime>250){
    & C% j$ \& f+ o1 j! I: x) m9 W
  16.                         CT_IIC_Stop();( q3 X5 H! A! d2 a: q' n+ \
  17.                         return 1;
    , M6 p* G4 v4 L) N' v
  18.                 }, y% u" j" Z$ T
  19.                 CT_Delay();
    2 v; E# c+ j4 J0 Q0 J4 u, h) X
  20.         }
    ' [( V0 w: Z, l, v! H! o* u- i2 K: T
  21.         CT_IIC_SCL(0);9 r3 p& \0 r; r' y9 {+ T7 J
  22.         return 0;  $ I/ j7 S! u, O6 |
  23. }
复制代码
; U1 h+ R5 q" c0 b4 X
下图是nACK时序与 传输数据1的时序图,这两种时序图是一样的,区别在于ACK是在8个数据时序后产生,且SDA电平是由接受数据端拉低的。
; F8 e. a6 F' |
& c  f; a5 ~9 @. a
20190622164227486.png

1 V. o9 k7 V& `* u( u0 ^% G9 R! T7 u6 i) Y! E& g
产生ACK时序:在SCL高电平期间,SDA为高电平状态。
4 z% K" v( X0 @# k% A! u" }, V
  1. /***************************************************************************************) Q& I% w& j. D# l5 ]
  2.   * @brief  不产生ACK应答        
    & H" W2 D6 W$ b9 ^) _# l* U) F
  3. ***************************************************************************************/
    ' i% c- ]8 j' ?) {6 @
  4. void CT_IIC_NAck(void)# S0 I6 A/ J0 f4 b
  5. {
    ) R% E- t, ]7 M8 h6 `; P2 R  U3 i
  6.         CT_IIC_SCL(0);
    + k9 `4 ^( y% O7 z1 w
  7.         CT_Delay();% s) D! O: F. c  l
  8.         CT_SDA_OUT();
    1 O( A' p% v) h( A
  9.         CT_IIC_SDA(1);. Y" O5 J/ @7 l6 c
  10.         CT_IIC_SCL(1);
    1 e% v7 x) k; u1 {, {1 [7 A
  11.         CT_Delay();
    ; w% k0 A; c2 R! j! J
  12.         CT_IIC_SCL(0);
    ( V2 S! Q% L$ v9 t
  13. }
复制代码
" o' P& V' W5 `, |7 g
发送一个字节函数,优先发送高位,即从bit7开始发送。# u5 p3 b% g6 ]
  1. /***************************************************************************************& m7 I1 H2 O8 S# b* `$ ^
  2.   * @brief   IIC发送一个字节,! T$ l2 B4 J: g7 m' [" g3 @
  3.   * @input   ! l% M* _5 k, M
  4.   * @return    W2 p& Q& \/ b
  5. ***************************************************************************************/
    " L, s8 l; j% T' F( F+ P* Q+ f  ^
  6. void CT_IIC_Send_Byte(uint8_t txd)# k, m# j. P8 h. Z  |
  7. {
    - Y4 C$ R9 c+ j
  8.     uint8_t t;   
    * A) H) Z* Z! I  d
  9.     CT_SDA_OUT();            
    ' m, p+ t/ D; [( j. b
  10.     CT_IIC_SCL(0);//拉低时钟开始数据传输; k8 B5 Y/ }) c5 z; E% B( ~  J
  11.     CT_Delay();  @% z" r+ X3 |7 M
  12.     for(t=0;t<8;t++)  M  w  V/ u$ K. }+ a1 d
  13.     {: m# E2 \2 s% g$ ~+ Y- V( h
  14.         CT_IIC_SDA((txd&0x80)>>7);//发送bit7位9 i2 X8 I" ?. {
  15.         txd<<=1; //将txd的次高位左移到最高位              % K. _7 h$ K3 W5 I
  16.         CT_IIC_SCL(1);
    0 h# j9 h& u/ g) `
  17.         CT_Delay();
    9 n4 t: q$ V- X  _! [) E
  18.         CT_IIC_SCL(0);        
    * q# L: G. d1 m+ B, j
  19.         CT_Delay();# H) X0 f* p. e6 P6 C. Z- Z
  20.     }1 m. w2 [( i$ |8 M; R0 i
  21. }
复制代码

+ U5 u% g$ ~+ s, a5 S读字一个字节函数,接受到1bit数据后,将该bit放在bit0位置(通过receive++实现),如果还要继续接受数据,则将之前接受到的数据左移一位(通过receive<<=1实现),留出bit0位置接受新的数据。9 |8 R9 B; w& I2 r4 ~" M
  1. /***************************************************************************************
    $ Y$ P! l" B2 z) \
  2.   * @brief   读1个字节% B7 T/ R2 T/ |9 W
  3.   * @input   ack=1时,发送ACK,ack=0,发送nACK
    2 l8 h5 T) P+ i
  4.   * @return  
    " ?& g4 b8 k$ z/ ^" G' a
  5. ***************************************************************************************/& c) a' o/ f# ~$ y1 O
  6. uint8_t CT_IIC_Read_Byte(unsigned char ack)
    ( @" R) [1 j  |; C' d0 ^* }" t4 M
  7. {
    8 D+ }1 i; v: K4 \6 ~5 {$ d
  8.         uint8_t i,receive=0;
    " y9 `& p' U: U7 b- \8 {5 E
  9.          CT_SDA_IN();//SDA设置为输入! p6 A* w1 I6 y$ G
  10.         CT_Delay();
    % c, w; D# k& \2 M
  11.         for(i=0;i<8;i++ )2 U+ Z$ a( @8 l) n5 k" m
  12.         { # f& X9 r+ c* Y% Z% K8 g
  13.                 CT_IIC_SCL(0);                        
    0 v8 U/ H7 L7 o! _
  14.                 CT_Delay();( j8 E) d/ |& p0 k% x8 x+ I* w
  15.                 CT_IIC_SCL(1);         
      q3 N, A/ s9 k( ^2 D
  16.                 receive<<=1;
    * j+ {" z7 v$ @, a1 C9 q+ s
  17.                 if(CT_READ_SDA)receive++;   8 ^* C6 n9 I* F: p) w0 z
  18.         }                                          
    5 f1 A5 n+ n% g
  19.         if (!ack)
    # W; t7 A9 L4 o1 M
  20.         CT_IIC_NAck();//发送nACK  b/ Y" a6 |5 O4 W# d4 A! x: t) v
  21.         else
    : l- [0 p0 ~4 V
  22.         CT_IIC_Ack(); //发送ACK   % I0 S  K3 s& i) D
  23.          return receive;
    . p/ z/ A- L7 A4 w8 u
  24. }
复制代码
  ^" v2 y5 T8 X9 T6 W
三 GT9147电容触摸屏控制芯片驱动
, C2 [3 t2 O$ o6 e+ h: O% \1. GT914内部结构框图如下图所示/ W8 B0 [2 S* B" A# h+ x: c
9 I, ^* [1 i6 }7 `/ z
2019061913180610.png

6 G8 O3 ]1 r- t2 ^6 D5 R# ]0 w! ]! V
5L5)3BWQK[DM1E_`8%S}J0F.png
5 Y/ Z& y& f- e* B. F: H
9 H3 D1 [& b# O2 w/ z  M
2. 上电流程
  F7 r/ l/ v+ x
7 v' D2 M& ?: z  Z, aGT9147上电初始化流程如下所示:' |6 w: j- L; D  Y# h! S2 M

& Q/ ], ~% p3 V配置RST输出低电平,INT输出低(或者高)电平后,位置100us以上,此阶段配置IIC地址为 0xBA/0xBB(或者0x28/0x29)
. X/ f: h% B& U/ P; V  i; u4 ^接着配置RST输出高电平并维持5ms以上后,可以配置INT引脚为悬浮输入模式。7 D' G& j8 {, `4 j
等待50ms以上后,可以发送配置信息。1 s; T' m2 x. R' [2 Q( o9 x
$ a* K. `6 ~4 V8 E2 C2 \% ?1 H2 K7 x- ~
2019062113491579.png
5 Y& p  g# X% \" S2 X) g

6 G5 N# {0 K- E代码参考原子例程编写,贴上代码:9 W" T1 Z2 ~" E' W

+ i& a6 T1 q1 W* Y
  1. uint8_t GT9147_Init(void)
    + t  {: L2 e% y3 g' D
  2. {
    ; _3 Z5 K6 z4 A- e* m3 f& D* Q
  3.     uint8_t temp[5];
    % A8 k" I/ G# [8 P
  4. & ?: S8 y3 u% V' u3 v' c
  5.     GPIO_InitTypeDef GPIO_Initure;4 g) b- Q2 y* \, J( @

  6. 6 ?; T" A& o* u5 t
  7.     GPIO_Initure.Pin = GPIO_PIN_7;          //PH7
    0 _: x) ~! y& Q
  8.     GPIO_Initure.Mode = GPIO_MODE_INPUT;    //输出
    % i* b: X. q1 m2 E: {
  9.     GPIO_Initure.Pull = GPIO_PULLUP;        //上拉
    $ @( G( e( P8 z; Z8 q2 Y; j& S
  10.     GPIO_Initure.Speed = GPIO_SPEED_HIGH;   //高速
    " i8 f, C& ]7 k2 H" A
  11.     HAL_GPIO_Init(GPIOH, &GPIO_Initure);    //初始化  D. j( }! i7 B  c# a7 N% e

  12. / \) b4 L) B" Z5 W3 N/ K- Q
  13.     GPIO_Initure.Pin = GPIO_PIN_8;           //PI8' h4 n2 K! N! a2 a5 F7 T/ ]
  14.     GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP; //推挽输出; j& u1 [+ [3 H5 b  U
  15.     HAL_GPIO_Init(GPIOI, &GPIO_Initure);     //初始化$ C+ \; c3 G; b0 J: g  z7 d
  16. # T# v9 V  g) t- k; L- M
  17.     CT_IIC_Init();              //初始化电容屏的I2C总线% N; M% n' r$ t) m% X7 ?! x

  18. 5 [" V3 K/ m0 ^' E3 E) \7 Q
  19.     GT_RST(0);                                //复位
    - Q" c- F) s* O# P* M
  20.     delay_ms(1);            //INT引脚电平维持100us以上: ]& y. s( c# q$ v
  21.     GT_RST(1);                                //释放复位
    6 r& L" j8 r/ Q9 t' E# j3 f2 R8 g
  22.     delay_ms(10);           //释放复位后维持5ms以上,设置INT为悬浮输入1 `5 E& Z, l! ?& U! Q0 Q2 a4 ?- ~: z
  23.     GPIO_Initure.Pin = GPIO_PIN_7;
    $ N+ R9 g) t) I/ |0 [$ h5 H+ O
  24.     GPIO_Initure.Mode = GPIO_MODE_IT_RISING;
    4 _, j% B8 X. ]0 L/ n& I
  25.     GPIO_Initure.Pull = GPIO_NOPULL;
    : W' K  g8 a% `/ _5 h6 _
  26.     HAL_GPIO_Init(GPIOH, &GPIO_Initure);    //初始化
    5 r% a; M7 T) U8 j4 m( A; y
  27.     delay_ms(60);
    ) S$ w7 d- g1 @* t1 \

  28. & v7 P; p1 f; I( Y0 C% I6 i
  29.     GT9147_RD_Reg(GT_PID_REG, temp, 4); //读取产品ID: n- s+ x' \, R) x- e1 t2 {
  30.     temp[4] = 0;1 V/ l/ [  b3 `7 ^; D9 m2 o5 b
  31.     printf("CTP ID:0x%s\r\n", temp);        //打印ID
    5 |" g( w  g' |3 K( {  @

  32. 3 E2 h$ z! J& Q6 \  E& _
  33.     GT9147_Send_Cfg(1);//更新并保存配置# f* }' n6 {, K/ V8 D( ?, M7 x

  34. & g( G0 C6 A; [- L2 e$ R7 ]
  35.     return 1;- {! m9 m' H, |! m* g
  36. }
复制代码
/ X, N; w1 L8 a( a
3. 读取坐标流程
+ f4 \5 g  p/ f3 a/ Y  W3 c# l
; ]+ j  m/ l3 b) d) S6 p' c6 S使用中断方式读取坐标,需要注意的是,如果不及时读取坐标信息会一直产生中断。GT9147的中断脚与STM32的LINE7中断线相连,中断回调函数如下所示。当按下触摸屏时,touch_x与touch_y分别保存触摸时的xy坐标;当松开触摸屏时,touch_x,touch_y赋值0xffff
) D; M6 j# J# k: b* X
+ W1 R" |) C. I
  1. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)8 [+ m5 g; z1 v# [* v. [
  2. {$ e: R* l3 Z% U& S9 P- |9 ]
  3.     uint8_t buf[4];' A: v+ A* q% [: N) P1 Q) g8 s
  4.     uint8_t i = 0, mode = 0, temp = 0;
    - Z8 ]$ M2 t& ^0 i9 P
  5.     uint16_t x[5], y[5];
    ' i. o3 [0 F: O( \+ U+ r
  6.     if(GPIO_Pin == GPIO_PIN_7) { //读取坐标, 否则会一直有INT脉冲
    7 [3 i  F5 S# W) U
  7.         GT9147_RD_Reg(GT_GSTID_REG, &mode, 1);        //读取触摸点的状态% N+ p. X# l2 T- S
  8.         if(mode & 0X80 && ((mode & 0XF) < 6)) //有坐标可读取
    9 |4 W8 o% f" C$ t! c0 P# ?
  9.         {
    7 J0 ]3 f9 Z* E+ v5 M- h
  10.             temp = 0;$ j# \+ W1 f1 Z) A2 P
  11.             GT9147_WR_Reg(GT_GSTID_REG, &temp, 1);//清标志3 h7 Q7 J$ y/ Q! @) L' Y2 l
  12.         }% C& k0 J  _% ^& t0 P
  13.         if( (mode & 0xF) && ((mode & 0xF) < 6)) //判断触摸点个数/ q! Q+ q2 ^0 S+ Y& z; ^$ w
  14.         {
    # P+ M8 k- G, I
  15.             for(i = 0; i < (mode & 0xF); i++)
    8 T2 \# r# W1 p& x
  16.             {
    2 h& E- t4 x; X) z( l/ {
  17.                 GT9147_RD_Reg(GT9147_TPX_TBL<i>, buf, 4);        //读取XY坐标值
    ! g3 |) Y4 V" n9 W- E" w( X4 F* S
  18.                 </i>x = (((uint16_t)buf[1] << 8) + buf[0]);
    ; S& n; t. @. S
  19.                 y = (((uint16_t)buf[3] << 8) + buf[2]);
    ' Q; t+ L! Y* M2 W$ |$ K9 t
  20.             }& H* A) K! a2 k0 M5 i+ H$ p
  21.             touch_x = x[0];
    : C" q- W$ i4 T/ g
  22.             touch_y = y[0];
    5 M& v" N# ?: l9 c. m- w3 X: J
  23.         }% g( G: l( m+ K% A  m
  24. 9 x; ~* \% a* \
  25.         if((mode&0x8F)==0x80)//无触摸点按下,xy赋值为0xffff
    4 r; p* Y  r# ~
  26.         {- r, {- d5 V* k7 `
  27.           touch_x = 0xffff;6 c$ e. s1 w3 `5 K% l- e2 N- P
  28.           touch_y = 0xffff;+ d+ _( T' Q6 \( v5 B8 `
  29.         }
    & Y9 k6 p' |1 Y0 ~+ Z
  30.     }
    4 q0 z  x$ P- u! I. q8 W
  31. }
复制代码
4.主机 对 GT9147 进行读操作时序" b8 r! u& Z) Q

7 [* X8 }$ M% o* _4 `
20190621161601926.png
$ i# D) c$ F/ ^- Q% G: G, Y/ V

( Q* t2 e) d% P. V4 `0 ?$ j根据该时序图编写读寄存器函数如下:
# F6 B% @0 k; v$ X7 ]( {
' O+ H- }' z' w  b' B
  1. /***************************************************************************************
    ' n% k" ~7 C7 t1 }, t
  2.   * @brief   从GT9147读出一次数据
    " z6 v" n& }9 J2 x4 e5 Q0 |
  3.   * @input   reg:起始寄存器地址0 _) Q. G9 o3 D0 P$ X7 Y3 M
  4.              buf:数据缓缓存区
    ! i; M8 d6 p" P* K( G4 U
  5.              len:读数据长度        / d- h, d, Q; K0 r1 ]2 h* {
  6.   * @return  
    5 \% ~$ K; d* I7 Z# g
  7. ***************************************************************************************/
    # f% L4 _; ?& ^9 D( Z
  8. void GT9147_RD_Reg(uint16_t reg,uint8_t *buf,uint8_t len)% m! e9 L0 A$ J) w! P
  9. {
    ' s3 M& E) c7 K9 S6 ?1 Y
  10.         uint8_t i; 2 G0 y, }( r2 ?/ n
  11.          CT_IIC_Start();        
    $ x: m. S* H, W6 t, m. F; P
  12.          CT_IIC_Send_Byte(GT_CMD_WR);   //发送写命令          / D- v4 T# |( ]& c) o9 D* i/ A* @. V
  13.         CT_IIC_Wait_Ack();
      x% E) z' p$ {& m
  14.          CT_IIC_Send_Byte(reg>>8);           //发送高8位地址: E- k# Y/ h  Q) V3 `9 u
  15.         CT_IIC_Wait_Ack();                                                                                                               . ]4 c/ k* j  [2 q& j; x
  16.          CT_IIC_Send_Byte(reg&0XFF);           //发送低8位地址
    ( y9 Y) i3 |5 A
  17.         CT_IIC_Wait_Ack();  
    7 \8 I9 ]" \0 r
  18.          CT_IIC_Start();                      - \) @$ J2 B5 u% I) e; r
  19.         CT_IIC_Send_Byte(GT_CMD_RD);   //发送读命令                     t, W" z  S* i9 P& b: @3 x/ G
  20.         CT_IIC_Wait_Ack();           : l: e( F* c2 v3 R2 e* ?) q
  21.         for(i=0;i<len;i++)
    4 v3 g' W1 {% X6 i/ X% g4 J; ^9 f8 b, J
  22.         {
    9 u5 P3 q" S8 `. Z0 o8 Z. ~
  23.             buf<span style="font-style: italic;"><span style="font-style: normal;">=CT_IIC_Read_Byte(i==(len-1)?0:1); //发数据          ' u3 E. `$ g! w; F2 Y5 f# t, A* Y
  24.         }9 {# l4 A- `( c3 Q. F
  25.         CT_IIC_Stop();//产生一个停止条件   
    2 P, X4 F- G% R+ `! e2 x
  26. }</span></span>
复制代码
. ]$ m0 U% c9 ?2 d" d+ T
5.主机对 GT9147 进行写操作时序7 q* e8 e0 ^, N* K$ i9 K; r
" b, z) \4 _1 j7 |
20190621161509843.png

: n, J) l4 ]) o0 q3 b
9 Z) ]; |7 }3 M# C$ \9 m% E通过该时序图,编写写寄存器函数如下  {& \- A4 @/ ^- M6 r$ p

7 i$ c- G- N+ o5 q' |) A: g) ]
  1. /***************************************************************************************, |1 r( M3 O* X
  2.   * @brief   向GT9147写入一次数据" I4 p. X; o; \! U: O/ c. L4 v
  3.   * @input   reg:起始寄存器地址;
    % p0 Y& r0 l. D4 L1 [
  4.              buf:数据缓缓存区
    3 i' M4 N+ _; c" B( L
  5.              len:写数据长度- u- h6 R; [& k3 H$ i6 ^; Y
  6.   * @return  0,成功; 1,失败.
    ! @8 i5 O' ^% D$ }% B
  7. ***************************************************************************************/
    1 q0 K$ `3 `$ G- r
  8. uint8_t GT9147_WR_Reg(uint16_t reg,uint8_t *buf,uint8_t len)
    * C7 ]6 M' T# g: U3 U5 F
  9. {# k5 l) v. U" y4 i5 F
  10.         uint8_t i;
    - p2 P3 {$ K% v- W9 f# m
  11.         uint8_t ret=0;* Y8 Z3 \6 M8 o# |
  12.         CT_IIC_Start();        : z" [9 I( V: T* L' ^
  13.          CT_IIC_Send_Byte(GT_CMD_WR);           //发送写命令          ; l. L+ f0 e2 V6 Y, ?
  14.         CT_IIC_Wait_Ack();8 K3 I" |+ ]- V" ^
  15.         CT_IIC_Send_Byte(reg>>8);           //发送高8位地址
    / Q+ o( u9 V& L
  16.         CT_IIC_Wait_Ack();                                                                                                               
    : L  N5 V* H/ Y4 k; M# \! I; p+ v
  17.         CT_IIC_Send_Byte(reg&0XFF);           //发送低8位地址- k8 j" K/ I' e: c
  18.         CT_IIC_Wait_Ack();  2 L2 w; M- F$ v3 [8 c
  19.         for(i=0;i<len;i++)) [5 o: q6 H: o! Z
  20.         {
    0 N8 s4 B* q9 z. C
  21.             CT_IIC_Send_Byte(buf<span style="font-style: italic;"><span style="font-style: normal;">);          //发数据1 w, D' _* [2 H1 }
  22.                 ret = CT_IIC_Wait_Ack();
    " G9 I( n& F/ N/ w6 {  G
  23.                 if(ret)break;  
    " Q/ g& Q1 Q) X% p  o
  24.         }
    + }: Q0 m5 o0 I. e6 `
  25.     CT_IIC_Stop();                                        //产生一个停止条件            
    8 Y) t6 F3 Y0 }2 z, {! n
  26.         return ret;
    ; Q# C3 D, c- _+ O
  27. }</span></span>
复制代码

6 M# K. P3 f% e8 G! E6. GT9147配置函数如下,GT9147_CFG_TBL针对分辨率480×272的触摸屏。
) V* F- _4 {* q
& d$ L( M& E$ q) L配置寄存器时是要注意以下几点:2 z% m- C! X- A7 e9 k  w+ u  D

$ b4 g; Z5 z0 M( o( \新的版本号大于等于GT9147内部flash原有版本号,才会更新配置.) U) n% @: y8 @8 l1 m# Y, |  C
写完GT9147_CFG_TBL中的配置后,还需要往0x80FF寄存器中写入校验,0x8100寄存器中写1。
+ Z4 S8 l0 B5 {2 Q关于配置更详细的信息可以参考GT9147编程参考手册
9 I4 J) ?& @/ I6 M
  1. const uint8_t GT9147_CFG_TBL[]=
    5 f, q. x2 n( Z4 w& Q: L  s7 d
  2. {$ |0 |& k' d2 V0 V
  3.     0x60,0xe0,0x01,0x10,0x01,0x05,0x0C,0x00,0x01,0x08,
    3 ]5 I2 [4 ~: J, t* h' K5 n% Y
  4.     0x28,0x05,0x50,0x32,0x03,0x05,0x00,0x00,0xff,0xff,4 g* J1 v. g! g- A# Q) D, d
  5.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x89,0x28,0x0a,& N$ g( D; J4 y; G* w1 k
  6.     0x17,0x15,0x31,0x0d,0x00,0x00,0x02,0x9b,0x03,0x25,. o' ]6 W* c. e' I
  7.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0x00,0x00,
    3 w: g. A0 O: P' y
  8.     0x00,0x0f,0x94,0x94,0xc5,0x02,0x07,0x00,0x00,0x04,
    2 K+ v; G" j$ @$ o. T. |
  9.     0x8d,0x13,0x00,0x5c,0x1e,0x00,0x3c,0x30,0x00,0x29,
    ; @$ s5 ^  @6 P5 V0 }; r9 q
  10.     0x4c,0x00,0x1e,0x78,0x00,0x1e,0x00,0x00,0x00,0x00,
    . e' `# _# l! _, v0 I7 n. T8 f% c9 t
  11.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    9 \5 ?7 H6 b6 b' s2 O) J; J: f+ \
  12.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,4 E. k+ ]/ N4 l+ v4 F: D7 u, B
  13.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,- ^  C! x% k, _  w
  14.     0x00,0x00,0x08,0x0a,0x0c,0x0e,0x10,0x12,0x14,0x16,7 m. ]6 B. z" Y1 ~/ L
  15.     0x18,0x1a,0x00,0x00,0x00,0x00,0x1f,0xff,0xff,0xff,
    ' A- e# i( W: e7 t- a
  16.     0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
    . K' ^  A7 |7 L% H, S
  17.     0xff,0xff,0x00,0x02,0x04,0x05,0x06,0x08,0x0a,0x0c,
    ! \0 C) i3 o' i+ P, u. ~
  18.     0x0e,0x1d,0x1e,0x1f,0x20,0x22,0x24,0x28,0x29,0xff,
    / p" ~) W( w9 z" V
  19.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,9 |1 ]% g  W& b4 k7 A& S- F
  20.     0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
    8 U* x* H4 V0 S9 X$ H6 L* Z
  21.     0xff,0xff,0xff,0xff,% }+ O& f. q" b0 y" j/ O. l
  22. };
    + d; y& q; g1 z( T6 f
  23. ' H3 B5 `2 z! W" p2 l
  24. uint8_t GT9147_Send_Cfg(uint8_t mode), n' ~- H6 X; ~2 I; h) f8 W
  25. {
    & }! h" g) d( k9 \2 N5 E* ?
  26.         uint8_t buf[2];
    9 {; x% P2 v* s4 O: g4 b6 l" n
  27.         uint8_t i=0;
    ; `4 |; E3 {3 x6 W1 g
  28.         buf[0]=0;
    * T/ a* d0 }, z2 l; n
  29.         buf[1]=mode;        //是否写入到GT9147 FLASH?  即是否掉电保存
    ( p; l  i6 G) e, t) M
  30.         for(i=0;i<sizeof(GT9147_CFG_TBL);i++)
    - L5 d) d! R; N% k
  31.             buf[0]+=GT9147_CFG_TBL<span style="font-style: italic;"><span style="font-style: normal;">;//计算校验和
    & i: F- L- ~7 X7 Q" Z: s
  32.         buf[0]=(~buf[0])+1;0 t- O" U3 @3 v) h* ~
  33.         GT9147_WR_Reg(GT_CFGS_REG,(uint8_t*)GT9147_CFG_TBL,sizeof(GT9147_CFG_TBL));//发送寄存器配置) t. Z; c: ^4 B3 Y7 f1 N
  34.         GT9147_WR_Reg(GT_CHECK_REG,buf,2);//写入校验和,和配置更新标记- w6 O6 D4 o" N6 z$ E$ v! \# @- o/ F
  35.         return 0;8 a+ z" \8 X  t. A$ u/ D
  36. }</span></span>
复制代码

+ b- D6 C1 \* s6 d7 V
四 移植触摸屏驱动到STemWin
* ^: D( c8 D9 d这里假设已经成功移植了STemWin到STM32F7工程。' l; e2 a! \: u% P
0 z" i4 D5 G" X' F1 ?
1. 在GUIConf打开STemWin触摸屏驱动宏1 b/ X% t' C7 c3 s. K

& b- J' W% L; K
  1. #define GUI_SUPPORT_TOUCH       (1)  // Support touchscreen
复制代码
4 W1 y9 q0 S% d8 p; t+ a
2. 新建GUI_X_Touch_Analog.c文件实现以下四个函数,在第三章第3小节我们知道touch_x,touch_y表示当前触摸的xy坐标。整个文件的内容如下所示。8 f4 C5 F+ `4 D$ H
9 ~7 _6 K/ H7 f' ^# @; v
  1. void GUI_TOUCH_X_ActivateX(void)
    8 R) D: T! X- f% P" r
  2. {
    0 @) \1 p: ^# ~/ u4 W8 Z5 Y$ d
  3. 4 e8 E8 Y; f* t
  4. }
    : x8 q' c  H1 F$ J% Y7 i' _
  5. ; A! v( M) B+ _# E4 i7 w4 P  x3 i
  6. void GUI_TOUCH_X_ActivateY(void)
    / B( q' O1 t( Q
  7. {, r$ H5 T# U/ }! l
  8. - e& y' R/ f6 C/ B5 k5 l4 x/ O
  9. }9 b1 z! |# B  f3 e$ l" @9 F

  10. % t& D  {6 J6 a! @/ u
  11. /*获取x坐标*/: K& e; I& g4 H+ T$ e6 x+ V, X
  12. int  GUI_TOUCH_X_MeasureX (void)2 b. }$ ]% P/ ^. m6 Q! I1 F
  13. {
    + r( N$ n) B9 x. Z7 D7 C$ H
  14.   return touch_x;2 @. H7 N, _5 L2 \
  15. }: T3 D+ u* ~& x- N0 r0 }, m3 w
  16. 9 v& i2 r: v* p. Q
  17. /*获取y坐标*/+ b4 E  e: t+ R# M
  18. int  GUI_TOUCH_X_MeasureY (void)0 N" [1 p% B% b) v# ]
  19. {4 n0 z! z% n# _- o! j+ y4 u
  20.   return touch_y;7 G: Q5 x/ {  D% i3 _
  21. }
复制代码

! T3 y& p3 M) i% M, y- X9 |7 U3. 使用GUI_TOUCH_Calibrate函数校准x与y值,然后才能调用GUI_TOUCH_Exec()函数处理触摸事件。
- n3 J: s4 V$ m" S; J4 n6 _( V  P/ J
  1. void StartTouchTask(void const * argument)
    1 ]; K4 a6 O) j. f! R; |
  2. {( Z+ H8 b  N! E9 V, z3 T
  3.   /* USER CODE BEGIN StartTouchTask */. d8 x. K3 ^/ f+ {/ ?
  4.   GUI_CURSOR_Show();//显示鼠标指针% f2 |9 c+ b+ H- P9 `: i+ h
  5.   GUI_TOUCH_Calibrate(GUI_COORD_X,0,LCD_WIDTH,0,LCD_WIDTH);   7 `! F5 b4 Z9 `
  6.   GUI_TOUCH_Calibrate(GUI_COORD_Y,0,LCD_HEIGHT,0,LCD_HEIGHT);
    4 V3 n8 z# M1 s, q. Q, Z3 \
  7.   /* Infinite loop */
    1 q+ U1 N7 A! \8 |& P% D
  8.   for(;;)4 a' x. W# @5 ~0 {$ v  B
  9.   {
    ; o: X& M0 {4 Y8 u- n3 X- D
  10.     GUI_TOUCH_Exec();4 e' @0 T$ M; d" c- D* G) `
  11.     osDelay(5);
    . O, H1 S7 ^9 `8 j1 b" b% _
  12.   }) U3 x  Q5 \6 e6 `, ?/ j7 A
  13.   /* USER CODE END StartTouchTask */
    7 R4 q$ c# n" G6 T: G
  14. }
复制代码

) \: I* |( X2 e# w3 @. i1 q  a. x! d

2 ~2 Y, U1 B7 ]1 ^9 I' N) K' `5 F* m5 g0 W, W
收藏 评论0 发布时间:2021-12-17 12:05

举报

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