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

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

[复制链接]
STMCU小助手 发布时间:2021-12-17 12:05
一  电阻驱动与电容驱动原理: [# e. X. V( r/ o& a

' Z7 ?, N- Z( ^3 b. R; L1. 电阻屏等效电路如下所示, 当产生按压时:

4 ~$ ]( M- _: dX-接地,X+接电源,Y+接ADC输入.通过读取Y+的电压以及电阻分压原理,可以得出触点的x坐标( C- v$ B0 g# a8 h2 W' h3 U
Y-接地,Y+接电源,X+接ADC输入.通过读取X+的电压以及电阻分压原理,可以得出触点的y坐标" I& @/ W6 y+ [' t
& W( K! l7 I7 Z1 h. }; h
2019061911075212.png

- `7 L' ]0 N# [  P4 `; s
! u% C; p8 K/ S/ M2. 电容屏等效图如下所示, 检测原理类似矩阵按键, 当产生按压时:
- J5 A5 I$ _* I, @& x8 i4 _
; S3 V1 X8 i) O: P! t  t# {/ B# KX轴产生从上至下依次产生激励信号(AC交流信号), Y轴电极同时接受信号 (该激励信号是交流电,可以通过电容穿到Y轴).. r$ s: Q# Q+ Y* v+ E" Z8 \
$ N8 K' Q0 U* x+ O0 ?3 F) }) H
假设有如下两个按压点(分别位于(1,1)与(2,2)的位置),检测过程如下:) c/ d4 B0 z/ y
当X1产生激励信号时,Y1接受到的交流信号产生了变化, 所以可以确认(1,1)处有触摸.) {+ r+ H, W" N
接着当当X2产生激励信号时,Y2接受到的交流信号产生了变化, 所以可以确认(2,2)处也有有触摸.% A5 s& ]" L$ h' |
; ^1 d1 t; }5 G4 F- j1 ^3 w
20190619115448553.png
; A1 C/ X- M6 x& T( f( W8 d

0 w. z" [: {* O+ J8 u二 软件模拟IIC; {' n1 e$ j/ S* x
由于stm32的硬件iic有各种各样的问题,所以采用软件模拟IIC的方式,主要实现IIC起始信号函数、IIC停止信号函数、等待ACK函数、产生ACK应答函数、不产生ACK应答函数、发送字节函数、读字节函数. |% x4 }2 I, B5 ^; k5 v& u( I

: ?& \# U- n8 f1 f( d+ ^; ~1. 起始信号与停止信号
  M; k; y) ]) b+ O1 H$ `8 \& v. h9 {; F( d  P0 \( G
下图是IIC起始信号与停止信号时序图,通过观察该图编写起始信号与停止信号函数。
- {: w3 L7 S! T0 t5 t. c7 }) E2 B' k9 _3 x0 ?, K
aHR0cHM6Ly9pbWFnZXMwLmNuYmxvZ3MuY29tL2Jsb2cvNDcwOTA5LzIwMTMwNS8yODE2MzczMy01MjE5.png
/ m0 A/ E5 z4 s
+ ~- z: p, s0 N9 _$ G1 g: e
起始信号:当SCL为高期间,SDA由高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号。" ?1 P: w3 {) |% k3 n  H' {* Q/ q
  1. /***************************************************************************************
    6 {+ k$ j  B2 ~- I, i6 |# p# K
  2.   * @brief  产生IIC起始信号,当SCL为高期间,SDA由高到低的跳变8 L) q* |0 A& T: _
  3. ***************************************************************************************/: t* f) i! U- G' Y3 b- m
  4. void CT_IIC_Start(void)/ K$ ^" l$ o6 T0 s; e* D" o0 o
  5. {
    3 M- R* O9 X  V
  6.         CT_SDA_OUT();     //sda线输出
    0 a* |' |8 l7 z" a( Y* r$ N
  7.     CT_IIC_SCL(1);8 v7 ]3 E* Q' x& Q
  8.         CT_IIC_SDA(1);                    - g* y2 F. o& X6 V, W& P" B# Y
  9.         CT_Delay();% x% s' X" f& h( s9 B" h0 ?
  10.          CT_IIC_SDA(0);
    ) ]3 H0 W$ A# d+ T
  11. }
复制代码
# X. ~- M; o# o, o! q3 o7 J, f* K: d. O3 ]
停止信号:当SCL为高期间,SDA由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。
% A& m% H2 J( o, i
  1. /***************************************************************************************
    2 G7 G- S' c* Y- u$ J
  2.   * @brief  产生IIC停止信号,当SCL为高期间,SDA由低到高的跳变
    ; ], u. E+ o( R6 s0 _
  3. ***************************************************************************************/) K/ ]1 s5 g# e
  4. void CT_IIC_Stop(void)8 _/ N+ h4 ?0 M! c5 a% u
  5. {5 l1 I. s2 Y2 P% t  F3 O  d
  6.         CT_SDA_OUT();//sda线输出
    ' h1 e* z1 P- H8 r% S6 V4 ]
  7.         CT_IIC_SCL(1);
    - k) d2 v" g( E( t
  8.         CT_IIC_SDA(0);//STOP:when CLK is high DATA change form low to high
    ' c% o- u7 J" o, Z
  9.         CT_Delay();
      f) w6 C! E6 \0 K
  10.         CT_IIC_SDA(1);6 V/ P7 m) H$ D  G2 ?3 p8 V/ }
  11. }
复制代码

6 T1 ^6 C1 N& I" _' W( E1 ~# d- w在GT9147数据手册中可以发现如下截图所示内容,SCL在低电平期间至少保持1.3us,其他电平最小保持0.61 T0 |, e, x8 P6 b% n

/ {; r: z4 F+ z; s! g) z& P
20190622160910729.png
% I; b) N- Z  A3 _; v1 P! W

( W( @5 b5 g7 N  X所以将IIC延时函数定时为2us可以满足所有时序。(一般支持最高速度400k的IIC设备,基本都可以使用2us延时。)
! `/ L$ F, m5 {! J4 R8 C0 E" d$ O) }5 f+ ]2 s" k3 O) m8 V0 r
  1. //控制I2C速度的延时: T8 u' Y; d+ o% L7 Q
  2. void CT_Delay(void)8 G% @. T( O9 w/ m
  3. {
    , @: }8 @  w- [( }& m3 I! T0 l  x
  4.         delay_us(2);
    - V- D7 O( l1 X( B
  5. }
复制代码
* J* j4 O8 ]5 F# a
2. 数据传输 与 ACK时序8 X3 ^# v3 k! l3 Q

: D  U* m! a7 A  P) ]) H5 y下图是ACK时序与 传输数据0的时序图,这两种时序图是一样的,区别在于ACK是在8个数据时序后产生,且SDA电平是由接受数据端拉低的。2 k+ e5 {% X' V' e0 }2 u9 w
( x  q4 N4 y) P9 G3 n. D8 b3 P
20190622161607756.png

9 W6 [' j: m3 k( t  O% Q) w0 ~  t: ]0 |4 z. y+ [% y8 s
产生ACK时序:在SCL高电平期间,SDA为低电平状态。
8 G' U# L. n+ ]3 I' v
  1. /**************************************************************************************** [0 S! `, _) D& @. X! Y7 [$ c+ R4 O
  2.   * @brief  产生ACK应答," y) c! a7 Y/ p7 U% H
  3. ***************************************************************************************/
    & K% R  V% w5 {4 @$ l: A
  4. void CT_IIC_Ack(void): H3 R* q2 t& ~8 f/ W" X
  5. {0 @8 P) Z0 `( Z  z5 o8 |( U( |/ s
  6.         CT_IIC_SCL(0);8 A: k5 t" Q, b# D
  7.         CT_Delay();  x4 C: B7 @$ @! T  j. `
  8.         CT_SDA_OUT();
    3 R! [+ v- ~' s! u) t+ v4 h
  9.         CT_IIC_SDA(0);
    8 l" T4 U$ x. ^) y1 G
  10.         CT_IIC_SCL(1);
    ! `2 P6 S; ?: k! w
  11.         CT_Delay();, |$ y6 g. h8 \
  12.         CT_IIC_SCL(0);* d: e2 l; ~" [! c2 o  X
  13. }
复制代码

; W8 o& ]% ~: C7 J5 p0 E等待ACK时序:拉高SCL与SDA后, 然后设置SDA为输入检测状态,等待接受数据端拉低SDA: w* q. L8 V" b2 W: |+ y) |% [) |
  1. /***************************************************************************************
    7 ^5 T& c3 y) [, z
  2.   * @brief   等待应答信号到来,等待接受数据端拉低SDA
    ( ~9 M( u; ~  D( ~
  3.   * @input   
    ( J" B4 S) W  h9 q* M0 p
  4.   * @return  1,接收应答失败 ; 0,接收应答成功
    ; F" ]7 e' y5 L% ?/ V
  5. ***************************************************************************************/
    3 Q' c& U* @( e
  6. uint8_t CT_IIC_Wait_Ack(void)) N: e4 G- O9 J( b3 j
  7. {
    2 D! c' t/ B; U7 A6 M, ]3 y, J
  8.         uint8_t ucErrTime=0;) \2 ]: k) v/ f7 }
  9.         CT_IIC_SDA(1);           ( D7 X7 J4 n0 u9 J1 K1 A+ ?" z
  10.         CT_IIC_SCL(1);: ~' ?9 p0 X. A; d
  11.         CT_SDA_IN();      //SDA设置为输入  
    0 K* z/ ^& _9 ?; F! g
  12.         while(CT_READ_SDA)
    8 K0 w5 a+ {2 T5 }+ V" h
  13.         {
    ' v1 o$ ^5 q4 ~0 a! W
  14.                 ucErrTime++;* j+ G' R; b( f( X
  15.                 if(ucErrTime>250){+ I% P8 A8 i/ T' f5 _4 u8 X/ z
  16.                         CT_IIC_Stop();! T. C& m( _3 w" z$ n: t5 r7 `9 l
  17.                         return 1;( d' z4 Z4 ^+ X2 G5 A( h, v
  18.                 }
    - c9 d. V% a. {3 M
  19.                 CT_Delay();
    3 I" a: K  J; e7 R0 y7 V
  20.         }
    # O) ^8 G2 N* M% \, ?* o1 V
  21.         CT_IIC_SCL(0);
    1 |# A  s/ u- h- d8 j; D% J
  22.         return 0;  
    + N8 d) ?$ x8 t: w* u) _
  23. }
复制代码

! j1 F( Z& Y5 P4 ?  f: t下图是nACK时序与 传输数据1的时序图,这两种时序图是一样的,区别在于ACK是在8个数据时序后产生,且SDA电平是由接受数据端拉低的。0 F7 }& M/ z, O$ p5 O

5 ]* L4 @0 Z- n+ A/ T$ j- k
20190622164227486.png
! F/ u  _# L4 [* p% V1 K2 @
2 X& H1 T9 ?7 x& S9 j: |
产生ACK时序:在SCL高电平期间,SDA为高电平状态。7 k2 S4 a+ A) }% K3 p
  1. /***************************************************************************************
    5 x6 D' O! T9 x2 R1 E
  2.   * @brief  不产生ACK应答        
    0 ?& F2 s6 G7 k+ m! f& Q* y
  3. ***************************************************************************************/
    $ p* p; r/ F$ ^( M
  4. void CT_IIC_NAck(void)1 F6 I. ]/ X+ D, t/ c
  5. {
    8 Z/ [/ h$ X& F% \
  6.         CT_IIC_SCL(0);7 X5 N; i9 s; e# v& c
  7.         CT_Delay();
    ! j2 b! S  V1 }  C: `6 f3 T
  8.         CT_SDA_OUT();
    $ D$ a5 w: ]/ e% a% w( ?' Y) a. f
  9.         CT_IIC_SDA(1);. Z' A; H5 ?  B, `( J: b
  10.         CT_IIC_SCL(1);
    ! y! r2 J- O  y2 b
  11.         CT_Delay();, |8 I; Z$ p+ n: I: V/ h9 k) ^
  12.         CT_IIC_SCL(0);  ]* R2 N2 O& r
  13. }
复制代码

5 ]. V3 i- `* a' p* w发送一个字节函数,优先发送高位,即从bit7开始发送。
: V  d7 d- @3 F. [& f
  1. /***************************************************************************************; @3 k; f1 ]0 W% Z. D, H
  2.   * @brief   IIC发送一个字节,
    8 z1 @5 Y# A" Y: t# b, b9 |9 o1 d
  3.   * @input   
    & b5 F1 c; p, G* g! ?
  4.   * @return  $ }7 d. |  R5 y& ~& h
  5. ***************************************************************************************/" |2 X0 y" s1 U( ]& O
  6. void CT_IIC_Send_Byte(uint8_t txd)
      d0 l  G( M4 u$ N. g3 A9 B
  7. {; g2 `  m0 c2 j9 X
  8.     uint8_t t;   6 z$ w' F& G2 Y7 h. Z* V5 `
  9.     CT_SDA_OUT();             6 z9 N: ~. E$ Y% e( L3 y. c
  10.     CT_IIC_SCL(0);//拉低时钟开始数据传输* [" j8 i, W1 g+ D! k6 w) g
  11.     CT_Delay();
    : s1 G0 H# m4 {) p# G: ^/ `
  12.     for(t=0;t<8;t++)0 ^& N9 c& Z" u5 S
  13.     {
    ) U3 P5 N$ ^& s  D
  14.         CT_IIC_SDA((txd&0x80)>>7);//发送bit7位
    ( Z# I: N5 y6 ]+ n8 j
  15.         txd<<=1; //将txd的次高位左移到最高位              ) D) D8 }3 F$ d( a( V  Y! R0 s
  16.         CT_IIC_SCL(1);   ]; f- W, |) Z8 b) m: @5 `2 k, o
  17.         CT_Delay();
    % S2 i+ L$ d# m/ D* T+ y6 a; }( @6 B
  18.         CT_IIC_SCL(0);        
    5 l; I. b% l  H7 s7 @% p/ b
  19.         CT_Delay();1 ~+ H7 @3 H; K; s' r
  20.     }& ?( v. J0 Z/ |0 o  `/ _5 x
  21. }
复制代码
5 j& A7 H" v+ Q: Q; {" u
读字一个字节函数,接受到1bit数据后,将该bit放在bit0位置(通过receive++实现),如果还要继续接受数据,则将之前接受到的数据左移一位(通过receive<<=1实现),留出bit0位置接受新的数据。
1 `3 i% B$ h3 B' {: M
  1. /***************************************************************************************
    4 F, ^0 b4 `4 @/ f& P
  2.   * @brief   读1个字节
    " M6 G& o+ x- J* S+ R% c
  3.   * @input   ack=1时,发送ACK,ack=0,发送nACK6 L. `. O4 e* I9 d8 x
  4.   * @return  ' U3 ]2 \/ ?# S
  5. ***************************************************************************************/
    * i6 ^! i  O8 M- r8 J
  6. uint8_t CT_IIC_Read_Byte(unsigned char ack)
    6 a6 e- ]) x* ~6 o" H( j, n: \$ i
  7. {
    : P+ z* {8 a- Z) a3 t
  8.         uint8_t i,receive=0;. I& N: Y- q# \, L* N$ g
  9.          CT_SDA_IN();//SDA设置为输入0 m' P" ?* H5 l6 @: p3 ]
  10.         CT_Delay();8 F2 p& j( q' I7 ^2 }+ @- {
  11.         for(i=0;i<8;i++ )7 r# U: }' U* T5 u0 V$ V& z% R  ^4 A
  12.         {
    , q6 u& r% e& w7 k- f+ d
  13.                 CT_IIC_SCL(0);                        : z$ {+ @  D4 e2 Y
  14.                 CT_Delay();( A) i  A8 p: J& a/ ~
  15.                 CT_IIC_SCL(1);         
    6 V" V/ |( E. L
  16.                 receive<<=1;+ G/ J$ l% G) m3 ^- u
  17.                 if(CT_READ_SDA)receive++;   
    " [7 F2 u3 ^- N) f( Q6 l7 g9 O: e
  18.         }                                          
    2 u4 l  C, f8 T1 `
  19.         if (!ack)
    & C, N& j4 h' C6 k
  20.         CT_IIC_NAck();//发送nACK( V/ _/ v" U; N+ Q* Z! Q' D, m6 w% S
  21.         else
    8 d5 ^9 y6 x4 V& _4 L+ q% v' |9 Q7 c
  22.         CT_IIC_Ack(); //发送ACK   , g# y/ b2 H' V
  23.          return receive;
    + C6 i: X  s# F6 _% ~9 I8 S( R
  24. }
复制代码

3 _9 ^4 ]9 ?$ C0 t! F1 U" |三 GT9147电容触摸屏控制芯片驱动
0 y& S4 Y; @* v2 P3 z8 {1. GT914内部结构框图如下图所示+ @8 ?; Y/ o4 `! n) A$ K

3 E7 e! `) j; Q7 A
2019061913180610.png
% t: o% M, W- I3 E& Z; b
3 b5 D/ s# y+ ], b  \
5L5)3BWQK[DM1E_`8%S}J0F.png

- _; m0 m0 i& g0 i. |/ t5 ~7 a: x5 A  g4 {, Y' n
2. 上电流程
6 N: Q% W/ V& V" g* ?+ R8 ?2 H2 c4 M6 B) f& }
GT9147上电初始化流程如下所示:
  P, O& k0 f' Y' g- |9 I
$ i' @  f( x) _! r( g配置RST输出低电平,INT输出低(或者高)电平后,位置100us以上,此阶段配置IIC地址为 0xBA/0xBB(或者0x28/0x29)& Q. c1 W+ Z2 N) j' E+ L
接着配置RST输出高电平并维持5ms以上后,可以配置INT引脚为悬浮输入模式。3 K% C- T1 r# r- K+ P0 H4 X; h
等待50ms以上后,可以发送配置信息。! W0 }# Y) z3 b1 y$ b

5 N; f+ n2 Y1 k
2019062113491579.png

4 h4 _+ w& @. ~4 r9 j0 u* k* B  `% V  T' k7 \, W, N
代码参考原子例程编写,贴上代码:
% c8 }; p9 s  Q3 O2 u  Q+ g2 j( {; l: [7 i; S
  1. uint8_t GT9147_Init(void)' `# b& r2 \' ~0 b% g/ m
  2. {* b$ K  f1 Z) D$ i8 L0 ]8 X: x
  3.     uint8_t temp[5];% {7 H. @  q( ^( A: R- f; Y4 F

  4. ; G) r- V7 x0 v1 T1 @7 r
  5.     GPIO_InitTypeDef GPIO_Initure;# V" W8 c! B8 O1 j5 X% ]
  6. 5 B! c( N1 e- F4 H
  7.     GPIO_Initure.Pin = GPIO_PIN_7;          //PH7
    8 J6 E- D" o6 b
  8.     GPIO_Initure.Mode = GPIO_MODE_INPUT;    //输出4 w* _! V: N% s
  9.     GPIO_Initure.Pull = GPIO_PULLUP;        //上拉6 M4 z; f% h9 A% x
  10.     GPIO_Initure.Speed = GPIO_SPEED_HIGH;   //高速% j) ^* E5 b  ^
  11.     HAL_GPIO_Init(GPIOH, &GPIO_Initure);    //初始化: w( h" q  {, l! D" K7 E

  12. 6 |# R/ l5 p* o* y$ @6 E
  13.     GPIO_Initure.Pin = GPIO_PIN_8;           //PI8& ]% x; Y0 ~8 c) @* C
  14.     GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP; //推挽输出
    2 _7 [8 R% G) v( u9 P; E
  15.     HAL_GPIO_Init(GPIOI, &GPIO_Initure);     //初始化
    / H% H- E$ m, _6 @7 D* @6 P3 s
  16. ' _5 q. v5 U  u, a9 d1 d
  17.     CT_IIC_Init();              //初始化电容屏的I2C总线9 `% A6 S% M' ^7 e$ V4 [; s6 j

  18. 9 W: r  P0 A% W2 v% r& M/ @3 e
  19.     GT_RST(0);                                //复位
    ' P8 b9 q& Y' a' J/ ^- @
  20.     delay_ms(1);            //INT引脚电平维持100us以上! E8 N8 _- p& S: m1 X
  21.     GT_RST(1);                                //释放复位. o& h8 x! k, d; T9 |/ H1 M
  22.     delay_ms(10);           //释放复位后维持5ms以上,设置INT为悬浮输入: g" ^6 K0 S% A
  23.     GPIO_Initure.Pin = GPIO_PIN_7;6 Z: ~, g, L+ u
  24.     GPIO_Initure.Mode = GPIO_MODE_IT_RISING;, C. R7 e0 ]6 h. o* }3 p  j
  25.     GPIO_Initure.Pull = GPIO_NOPULL;
    4 s+ I4 v# V! {! {3 _
  26.     HAL_GPIO_Init(GPIOH, &GPIO_Initure);    //初始化
    6 H9 d- c7 h5 w" t2 c( c& C4 i
  27.     delay_ms(60);4 Z; k8 ^2 L  d$ ~

  28. ! S" ]! c1 Y0 B9 o, l" M
  29.     GT9147_RD_Reg(GT_PID_REG, temp, 4); //读取产品ID
    : o- p4 `5 r+ e) B, c
  30.     temp[4] = 0;
    : S. J- ~& g+ U) H5 o' I+ v/ {# }- b
  31.     printf("CTP ID:0x%s\r\n", temp);        //打印ID: g( V7 p) Q+ `

  32. ) ]$ A* l6 O+ ^* |
  33.     GT9147_Send_Cfg(1);//更新并保存配置
    ) L& c2 K" M8 y7 J7 G( {6 v/ I8 V( e
  34. 1 K4 _. W; b% R* h
  35.     return 1;8 {: W, p9 {) F
  36. }
复制代码
# E! O5 j6 U7 F  q  t! A2 h
3. 读取坐标流程; c: i/ D% h% w8 `* i( B' k2 s% ~

! w7 E% g, H- R! P0 a' a使用中断方式读取坐标,需要注意的是,如果不及时读取坐标信息会一直产生中断。GT9147的中断脚与STM32的LINE7中断线相连,中断回调函数如下所示。当按下触摸屏时,touch_x与touch_y分别保存触摸时的xy坐标;当松开触摸屏时,touch_x,touch_y赋值0xffff* t/ N' `4 L( d9 s5 N2 R8 U! z) K
% P1 ?& X, f0 j. ~- Z3 Y
  1. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin): X4 L# |2 L. {' ~1 O/ |7 N
  2. {+ w& R/ b5 h) {: B- v) ]5 V
  3.     uint8_t buf[4];
    5 ~# K" O1 n$ U& D# P# m7 h
  4.     uint8_t i = 0, mode = 0, temp = 0;: ~! |3 m: [0 X1 B. i
  5.     uint16_t x[5], y[5];! [2 @. [$ y" c& W1 l
  6.     if(GPIO_Pin == GPIO_PIN_7) { //读取坐标, 否则会一直有INT脉冲
    1 l* q6 m. e9 Q1 G: l* J
  7.         GT9147_RD_Reg(GT_GSTID_REG, &mode, 1);        //读取触摸点的状态  p3 k  ]! C! T" {$ ^, t+ m' S/ s# a
  8.         if(mode & 0X80 && ((mode & 0XF) < 6)) //有坐标可读取
    , B8 H7 T1 J1 a8 T" B1 n
  9.         {
    6 o! S( s0 _! t+ ~) ]) f  ~
  10.             temp = 0;
    ( T, L1 h. d  R
  11.             GT9147_WR_Reg(GT_GSTID_REG, &temp, 1);//清标志9 T) M1 D) S+ [; {
  12.         }) d1 F) a4 h/ J" t& ?7 D/ L4 p" b) [
  13.         if( (mode & 0xF) && ((mode & 0xF) < 6)) //判断触摸点个数
    9 E0 Z5 V$ \/ X; G
  14.         {$ e& G( n; X( U3 n+ s& X* P* ~) k6 @5 b
  15.             for(i = 0; i < (mode & 0xF); i++)
      u* x' x7 b9 {
  16.             {
    - x7 H& `9 ]4 x& @/ W
  17.                 GT9147_RD_Reg(GT9147_TPX_TBL<i>, buf, 4);        //读取XY坐标值% m6 F8 r, n0 p& A' _# a3 C4 O
  18.                 </i>x = (((uint16_t)buf[1] << 8) + buf[0]);
    / w# Y6 z. m9 |# V- O; T# |
  19.                 y = (((uint16_t)buf[3] << 8) + buf[2]);
    5 C7 J/ s! r- p1 ^4 X. @- W
  20.             }4 Q) ]5 r. q* z7 h1 s, B' m
  21.             touch_x = x[0];! }% X+ F, n% Y( r7 U2 K
  22.             touch_y = y[0];6 P- ~* Z/ d$ h* E. ?
  23.         }
    + }+ v$ c$ M# J; t& V6 T2 W8 @

  24. ! N5 W0 z% N! @8 Y
  25.         if((mode&0x8F)==0x80)//无触摸点按下,xy赋值为0xffff
    : u: ]0 [: y5 b
  26.         {
    ! ~( W3 x) I$ {, x+ K
  27.           touch_x = 0xffff;
    ' `. f" x1 Y  E: o
  28.           touch_y = 0xffff;8 O0 V# P8 [0 D9 b' t# f
  29.         }' b4 g( t& l* x! r, K5 N. t6 e. ]
  30.     }/ v) a( r! [8 M  C* Q5 F- w
  31. }
复制代码
4.主机 对 GT9147 进行读操作时序1 c9 Z1 u) x2 b5 x8 R; b
4 Q; p8 V8 p! @2 n$ D( k
20190621161601926.png

& N' s) F) B$ |5 m
  d1 S& _. `6 u' K7 {: D- T9 M根据该时序图编写读寄存器函数如下:
& ~" S" Q6 K! N1 g- T, h9 E. S6 j. b$ V) e$ {! ~/ ^' a0 ?3 l
  1. /***************************************************************************************
    6 r# V5 o/ Q$ O' ?- A0 g6 ]
  2.   * @brief   从GT9147读出一次数据
    ! g5 f0 X* L8 x1 R: d0 _) }
  3.   * @input   reg:起始寄存器地址
      j6 {, m5 V$ Q% r$ P4 G
  4.              buf:数据缓缓存区% O/ b9 e' e% x8 }. n" U
  5.              len:读数据长度        
    . i6 Q  ~* b) @1 T* r2 M
  6.   * @return  
    2 i. L! c5 ]; x' f0 i2 n; h* ^
  7. ***************************************************************************************/0 z' T0 r* D# d; s( w
  8. void GT9147_RD_Reg(uint16_t reg,uint8_t *buf,uint8_t len)
    9 Y" H. e# C7 E5 P3 e- M
  9. {  M: [2 }* @0 m- H8 y0 Q6 j" ?( h  A
  10.         uint8_t i;
    ! r* I4 t& [0 Q+ {4 C4 g
  11.          CT_IIC_Start();        
    , G) c) @5 d1 l" ]: }
  12.          CT_IIC_Send_Byte(GT_CMD_WR);   //发送写命令         
    4 r8 J0 F  o; a) W0 k! F5 S
  13.         CT_IIC_Wait_Ack();  r7 W9 M+ P& q
  14.          CT_IIC_Send_Byte(reg>>8);           //发送高8位地址
    $ r( h2 _, w' g; `+ V
  15.         CT_IIC_Wait_Ack();                                                                                                               
    5 {+ u; d2 [0 r
  16.          CT_IIC_Send_Byte(reg&0XFF);           //发送低8位地址
      X! Z) _! J% V4 |4 j" k4 D( ~
  17.         CT_IIC_Wait_Ack();  
    ! w# I& \5 _2 f$ |! {
  18.          CT_IIC_Start();                      5 G) W6 L+ f- ^6 s8 Z) L' S1 I
  19.         CT_IIC_Send_Byte(GT_CMD_RD);   //发送读命令                   : j6 a" R. R) {3 Z, N
  20.         CT_IIC_Wait_Ack();           
    9 b# U+ b! F% r/ Y1 P' Y
  21.         for(i=0;i<len;i++)9 W" {) H9 |6 x* S5 D0 y; b/ ~
  22.         {4 H# [" Y7 c8 t- m' T1 y$ U  I- k
  23.             buf<span style="font-style: italic;"><span style="font-style: normal;">=CT_IIC_Read_Byte(i==(len-1)?0:1); //发数据         
    7 s' j; W' [' |; S4 i& V' Y6 K
  24.         }3 y9 a8 B8 M; a' Y! r
  25.         CT_IIC_Stop();//产生一个停止条件   
    / Y7 C9 f% Q$ B, o
  26. }</span></span>
复制代码
6 b+ @/ h2 u$ Z  M2 F- s# Y
5.主机对 GT9147 进行写操作时序# p3 g7 L) y8 b% m8 P6 l) P) T
9 N3 b" @9 k0 T, t5 g
20190621161509843.png
6 Z& p0 Z8 C; y8 @" u# h
/ N$ P! x8 x% P! d2 `6 R
通过该时序图,编写写寄存器函数如下& J4 i+ |, }& k- ?
1 E8 |3 j1 r) Z# r8 Y
  1. /***************************************************************************************
    5 @6 H* W7 b3 ]3 _7 O9 s, k
  2.   * @brief   向GT9147写入一次数据
    0 H3 U* H& c* W4 w$ A: k& g6 k
  3.   * @input   reg:起始寄存器地址;
    9 {, M" I/ y& g+ d; u8 Q8 w
  4.              buf:数据缓缓存区
    ( c. t) i, e# W+ _" \6 R, t: {
  5.              len:写数据长度4 s  m/ n& T) @- \2 B  g% S
  6.   * @return  0,成功; 1,失败.9 U# F8 a5 L' R
  7. ***************************************************************************************/$ V4 W8 }( }1 h+ }6 g7 I" |
  8. uint8_t GT9147_WR_Reg(uint16_t reg,uint8_t *buf,uint8_t len), l4 M7 k) b* |* w4 ~5 h
  9. {
    / Z& ]  i* ^9 i- P/ u
  10.         uint8_t i;
    ) ]% E  T! E+ d/ J) ^. O( |2 D
  11.         uint8_t ret=0;
    7 c* q$ j# r) S
  12.         CT_IIC_Start();        
    8 Q( g! I9 a/ }* Z; o) A% N; x' s
  13.          CT_IIC_Send_Byte(GT_CMD_WR);           //发送写命令          : c7 w0 z5 n* Y( a8 x' u6 Y8 [' G
  14.         CT_IIC_Wait_Ack();2 m6 ]8 M; o4 q2 g
  15.         CT_IIC_Send_Byte(reg>>8);           //发送高8位地址
    % k& K: ?" ^! N* V( v
  16.         CT_IIC_Wait_Ack();                                                                                                               5 H/ i% w' _+ V4 l
  17.         CT_IIC_Send_Byte(reg&0XFF);           //发送低8位地址1 `  @! v! B' H; [  V
  18.         CT_IIC_Wait_Ack();  ' q4 v9 c, \8 p  W
  19.         for(i=0;i<len;i++)4 E+ }0 a5 A) b% W- V
  20.         {
    ) V4 p. s' t; c4 j9 n
  21.             CT_IIC_Send_Byte(buf<span style="font-style: italic;"><span style="font-style: normal;">);          //发数据) b- x& n+ Z$ t
  22.                 ret = CT_IIC_Wait_Ack();
    9 m& n$ S& u& j( w* e
  23.                 if(ret)break;  
    % J2 A9 j( h& `# \9 A9 l
  24.         }: Y3 z" @$ A6 N) k" H2 P
  25.     CT_IIC_Stop();                                        //产生一个停止条件            7 R! n& O  _- B1 r9 i
  26.         return ret; ) v5 c! Y' f7 l# Y$ V$ n/ X
  27. }</span></span>
复制代码

) Q% U& O) l8 c6. GT9147配置函数如下,GT9147_CFG_TBL针对分辨率480×272的触摸屏。0 a3 \* w( X* Y  K

2 D1 K& O4 E) ^" `2 {配置寄存器时是要注意以下几点:
' m- p) U3 Y( a5 H' E5 _7 F- W( r- J, O( g: {
新的版本号大于等于GT9147内部flash原有版本号,才会更新配置.
+ O( Y; x3 d5 f( X写完GT9147_CFG_TBL中的配置后,还需要往0x80FF寄存器中写入校验,0x8100寄存器中写1。
2 x' R3 w4 N: D" A* A关于配置更详细的信息可以参考GT9147编程参考手册
0 F$ O5 \" I$ c! o' a4 \
  1. const uint8_t GT9147_CFG_TBL[]=2 r9 \7 y4 r% |; }
  2. {- Z% N( M. V& @
  3.     0x60,0xe0,0x01,0x10,0x01,0x05,0x0C,0x00,0x01,0x08,
    $ f  F; k! @1 E, k
  4.     0x28,0x05,0x50,0x32,0x03,0x05,0x00,0x00,0xff,0xff,2 a4 q, C6 [7 O0 k8 T$ [; p
  5.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x89,0x28,0x0a,
    # t- p! E  w. k( G+ M- v4 f
  6.     0x17,0x15,0x31,0x0d,0x00,0x00,0x02,0x9b,0x03,0x25,1 p' }$ g$ x1 ]9 W( P& A
  7.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0x00,0x00,
    $ O$ m+ j4 S. o2 ~: C8 w
  8.     0x00,0x0f,0x94,0x94,0xc5,0x02,0x07,0x00,0x00,0x04,
    ; a* q5 \8 v% ?; v( x2 V2 d
  9.     0x8d,0x13,0x00,0x5c,0x1e,0x00,0x3c,0x30,0x00,0x29,0 C( Y6 h" @; U3 n/ R  {  J1 v5 Z; ^
  10.     0x4c,0x00,0x1e,0x78,0x00,0x1e,0x00,0x00,0x00,0x00,) }: m% i5 n$ W
  11.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    . M9 x( O0 ^; W. u
  12.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    ! @$ o+ ~8 @- C3 s" j6 Z8 y
  13.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    5 x: g+ Q7 B# J( A: v0 S
  14.     0x00,0x00,0x08,0x0a,0x0c,0x0e,0x10,0x12,0x14,0x16,. y4 n7 N" o6 ~& Z/ J
  15.     0x18,0x1a,0x00,0x00,0x00,0x00,0x1f,0xff,0xff,0xff,  ?9 e( Q$ O! l+ K# C' d% |
  16.     0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,) {' R' @. w6 F  E) v& s
  17.     0xff,0xff,0x00,0x02,0x04,0x05,0x06,0x08,0x0a,0x0c,
    3 y1 E  o7 ?+ d/ d
  18.     0x0e,0x1d,0x1e,0x1f,0x20,0x22,0x24,0x28,0x29,0xff,
    ) I7 D3 g5 m$ S- R2 I
  19.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,
    ' _8 H* P' V! L, s7 a) L" P' J7 y4 G
  20.     0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,' m) ^' V! }- P# a1 V
  21.     0xff,0xff,0xff,0xff,
    8 [, H6 ^2 l" N) Q
  22. };
    ; {& F2 W* Q, e& V5 U9 s

  23. * C  j: W9 X/ F1 a# O8 q1 l
  24. uint8_t GT9147_Send_Cfg(uint8_t mode), T) r/ d9 w- R; [
  25. {
    $ v7 B3 x: U$ M2 b- Z
  26.         uint8_t buf[2];/ i1 s% W9 o0 Z7 y* o  I
  27.         uint8_t i=0;
    6 ?6 s$ I& G" {
  28.         buf[0]=0;) ]- e3 y: W6 b/ i8 l
  29.         buf[1]=mode;        //是否写入到GT9147 FLASH?  即是否掉电保存
    ( n7 Q& p2 x- J6 I
  30.         for(i=0;i<sizeof(GT9147_CFG_TBL);i++)
    : W# N6 `6 G$ C$ K. J2 _0 ~
  31.             buf[0]+=GT9147_CFG_TBL<span style="font-style: italic;"><span style="font-style: normal;">;//计算校验和
    . A; _: k, P! k1 ~! T
  32.         buf[0]=(~buf[0])+1;
    $ g+ u; [/ u0 m
  33.         GT9147_WR_Reg(GT_CFGS_REG,(uint8_t*)GT9147_CFG_TBL,sizeof(GT9147_CFG_TBL));//发送寄存器配置
    & \/ n; j; u* X
  34.         GT9147_WR_Reg(GT_CHECK_REG,buf,2);//写入校验和,和配置更新标记
    9 m" ^* u( M& F: i' j6 n
  35.         return 0;7 g' u4 E5 b: i$ B  {( k' }" J
  36. }</span></span>
复制代码
- s# Q- U1 P8 ^1 w& ^
四 移植触摸屏驱动到STemWin0 f1 W2 r! H, G& _- t
这里假设已经成功移植了STemWin到STM32F7工程。+ i6 N$ Q$ u" ^' X

9 o! Z' A1 p2 u$ e/ e  r1. 在GUIConf打开STemWin触摸屏驱动宏
0 I9 @6 t) [$ C  S: J5 L7 E8 l7 d1 G" P1 N6 e
  1. #define GUI_SUPPORT_TOUCH       (1)  // Support touchscreen
复制代码
) P- w" D  e7 Q! a
2. 新建GUI_X_Touch_Analog.c文件实现以下四个函数,在第三章第3小节我们知道touch_x,touch_y表示当前触摸的xy坐标。整个文件的内容如下所示。
; g6 r/ R4 |/ \" j- x+ r: u7 d* N
0 ^6 `1 ?0 G/ n$ M9 x5 ]2 D- G) ]
  1. void GUI_TOUCH_X_ActivateX(void)
    ! K0 @8 r7 u! Q
  2. {9 b& ]) t9 N# Z9 K6 [" H2 b/ }5 t# C2 y4 b
  3. ( p- A6 _; l, E' @# C4 t
  4. }1 a3 U. D- t5 O! S; M

  5. 3 Q' v- e8 L2 p. E1 Z. h# V! A
  6. void GUI_TOUCH_X_ActivateY(void)
    5 ?) B1 N6 U3 T7 r5 c
  7. {
    8 z" l5 ?0 Y) u" S3 F$ d
  8. + v( C' T. ~2 J" z5 M# r
  9. }
    ! [$ V" l, \7 N: t" x6 Z

  10. 5 V* o4 y, E& f$ H, z
  11. /*获取x坐标*/8 ]; v' M# s' z8 j& G6 E' v
  12. int  GUI_TOUCH_X_MeasureX (void): J4 y: `( r5 y
  13. {3 H2 _/ S5 }* o/ t8 H8 U
  14.   return touch_x;. G- v, Z/ c' W4 y3 ?  Y, E8 B
  15. }9 e7 N" C- n' @- O! N

  16. 4 g  P1 y6 W( d- o1 O; {/ Y
  17. /*获取y坐标*/: B3 G6 ^, o. g8 J# K" o1 b/ H* B6 T
  18. int  GUI_TOUCH_X_MeasureY (void)
    0 L! I, p1 P% o+ j
  19. {1 M0 ?' n% t2 T2 @
  20.   return touch_y;
    7 w5 v+ G& u" ^4 t7 `
  21. }
复制代码

8 |. }9 r9 d# H7 Y" ^3. 使用GUI_TOUCH_Calibrate函数校准x与y值,然后才能调用GUI_TOUCH_Exec()函数处理触摸事件。' g0 d" k: b, w/ u% G8 F

' G  B  a# M3 M# P
  1. void StartTouchTask(void const * argument)
    5 D5 W, `4 H$ i$ _' d
  2. {
    ; C; P$ T% v  b# C
  3.   /* USER CODE BEGIN StartTouchTask */
    5 l# C6 }+ d+ \7 H: X2 U
  4.   GUI_CURSOR_Show();//显示鼠标指针& I+ \% A  ~$ U  u
  5.   GUI_TOUCH_Calibrate(GUI_COORD_X,0,LCD_WIDTH,0,LCD_WIDTH);   3 N1 t/ e5 h1 \* Z1 K) E$ X4 i; O
  6.   GUI_TOUCH_Calibrate(GUI_COORD_Y,0,LCD_HEIGHT,0,LCD_HEIGHT);$ h" a* J* E4 ?2 F$ A- {
  7.   /* Infinite loop */* p6 w+ F/ N& Z; {+ v( w. R
  8.   for(;;)
    , z! V8 _0 x' h1 g' w/ g
  9.   {
    ; W6 s- S) r- c7 J% Y$ ^
  10.     GUI_TOUCH_Exec();2 _% c$ m  W5 g
  11.     osDelay(5);' B, d1 C( T) Z, [2 U# b
  12.   }7 ~) R# Z3 E# E6 m
  13.   /* USER CODE END StartTouchTask */
    - y4 \2 M. P" [0 @/ {  ?( i
  14. }
复制代码

1 e9 D' w, I/ D, t8 z" T
& X) U9 X- f9 {6 A  ?* w0 D0 L
" S) Q/ M, K" |3 Y& H
: `9 t/ P4 l% N
收藏 评论0 发布时间:2021-12-17 12:05

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版