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

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

[复制链接]
STMCU小助手 发布时间:2021-12-17 12:05
一  电阻驱动与电容驱动原理
3 [. V; \( J5 R; m: v2 b! F0 e3 s! T' }, E
1. 电阻屏等效电路如下所示, 当产生按压时:
! l$ Z: a5 ]0 W1 d5 ^& r" C
X-接地,X+接电源,Y+接ADC输入.通过读取Y+的电压以及电阻分压原理,可以得出触点的x坐标
; t0 K, o/ V' p) g/ ~Y-接地,Y+接电源,X+接ADC输入.通过读取X+的电压以及电阻分压原理,可以得出触点的y坐标. R% B: X9 V6 b( r# q# k+ P7 k
( M7 G7 V, T! \& o$ K
2019061911075212.png
/ X1 W0 e* I' X& ?# c1 Z
2 N7 f6 M( O( e# O8 F
2. 电容屏等效图如下所示, 检测原理类似矩阵按键, 当产生按压时:
" q$ D4 I5 X9 ^( g- p: c. A( J8 {* P" @' o
X轴产生从上至下依次产生激励信号(AC交流信号), Y轴电极同时接受信号 (该激励信号是交流电,可以通过电容穿到Y轴)./ y# D4 n% a; _6 ]7 U! S  y
5 ?; r9 `/ S$ B2 \) m+ q: }- A
假设有如下两个按压点(分别位于(1,1)与(2,2)的位置),检测过程如下:
+ W1 i& Z; m- ^+ z: d$ {; ?0 A当X1产生激励信号时,Y1接受到的交流信号产生了变化, 所以可以确认(1,1)处有触摸.
7 T0 Q+ d* g5 |% Q; o* `$ D) x接着当当X2产生激励信号时,Y2接受到的交流信号产生了变化, 所以可以确认(2,2)处也有有触摸.1 R9 l* z2 O7 u( \
; `  T, u9 T' i% b* r
20190619115448553.png

/ ^5 \/ n  t  Q7 i$ j: K
( A" W: t0 b  D- w5 K' j+ z0 Y二 软件模拟IIC6 a$ q/ i5 Q$ T
由于stm32的硬件iic有各种各样的问题,所以采用软件模拟IIC的方式,主要实现IIC起始信号函数、IIC停止信号函数、等待ACK函数、产生ACK应答函数、不产生ACK应答函数、发送字节函数、读字节函数) l7 D& m  F- v

* k0 R1 m9 Y3 ]8 w" D1. 起始信号与停止信号4 S8 M, _$ M; z4 I0 Y
+ ]/ X+ `+ R! s/ Q8 K8 h$ i
下图是IIC起始信号与停止信号时序图,通过观察该图编写起始信号与停止信号函数。
+ @! b* B: `- ^( B% D1 w% f/ i8 L" I/ Z' |3 Q5 j+ y, z
aHR0cHM6Ly9pbWFnZXMwLmNuYmxvZ3MuY29tL2Jsb2cvNDcwOTA5LzIwMTMwNS8yODE2MzczMy01MjE5.png
! k& S% d* |% G0 E! k" a
" K1 i3 N" C% d* L# b
起始信号:当SCL为高期间,SDA由高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号。
* l- P0 m5 K/ l+ u  B# r' C3 _  J
  1. /***************************************************************************************
    $ M! M7 P& C; {6 L
  2.   * @brief  产生IIC起始信号,当SCL为高期间,SDA由高到低的跳变% h! P8 ~1 z* f! c! {) F3 M
  3. ***************************************************************************************/" ]! k9 s6 V0 v; z5 ?  S
  4. void CT_IIC_Start(void)
    3 ?: @. @) D- m: L* R
  5. {
    9 Y' G) R- F& T$ r: X
  6.         CT_SDA_OUT();     //sda线输出4 A4 @! L( U0 \
  7.     CT_IIC_SCL(1);) ?9 K  S0 r8 x
  8.         CT_IIC_SDA(1);                    # |9 V- `' S( K$ m3 {
  9.         CT_Delay();! I  @* L& q4 y$ ]! X, c0 B
  10.          CT_IIC_SDA(0);- r2 Y0 \/ F2 a( Y' ]
  11. }
复制代码
' T1 K* G. h1 q3 D; E
停止信号:当SCL为高期间,SDA由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。6 V2 X5 t. ]9 |
  1. /***************************************************************************************6 O9 d6 ^1 k7 W& e, @
  2.   * @brief  产生IIC停止信号,当SCL为高期间,SDA由低到高的跳变
    * \! j; i- }1 y/ C6 d. G
  3. ***************************************************************************************/
    3 u: w0 }0 c4 U- a  B. G
  4. void CT_IIC_Stop(void)' Z/ f) K, h% D0 b
  5. {% C' w' D4 P) ?2 |& N
  6.         CT_SDA_OUT();//sda线输出# E, {( h; O. n7 V7 O4 r4 m* m
  7.         CT_IIC_SCL(1);
    & M0 b' n( `  w& h
  8.         CT_IIC_SDA(0);//STOP:when CLK is high DATA change form low to high+ L9 N1 ]; E, S& d) f
  9.         CT_Delay();1 g) k0 t3 `2 w6 _! d
  10.         CT_IIC_SDA(1);: P  D$ s+ h& V
  11. }
复制代码

6 N4 Q4 p: z& e- F在GT9147数据手册中可以发现如下截图所示内容,SCL在低电平期间至少保持1.3us,其他电平最小保持0.60 L: i& P* H0 {$ r; m; T( k- y

; X- {8 J" p' T2 r: P
20190622160910729.png

) R! U0 Y6 \9 O* Z* G9 S# V3 C/ s$ e0 k0 B$ M
所以将IIC延时函数定时为2us可以满足所有时序。(一般支持最高速度400k的IIC设备,基本都可以使用2us延时。)
3 h( p7 k5 l4 I8 T' h
3 d- N! a* s# x7 [7 B
  1. //控制I2C速度的延时
    & P" |8 J$ e7 H% e0 {0 W
  2. void CT_Delay(void), F( K: u+ c5 |, N* i
  3. {
    8 {% q5 A( f4 s5 f! G7 b
  4.         delay_us(2);- j: h' D: \9 c) }4 F2 D7 ]# q, v
  5. }
复制代码
! Y1 V3 P4 J- F9 o9 r" R, N4 }
2. 数据传输 与 ACK时序
1 w- u9 H" J" Y
4 B! f3 C  @% A$ n( R下图是ACK时序与 传输数据0的时序图,这两种时序图是一样的,区别在于ACK是在8个数据时序后产生,且SDA电平是由接受数据端拉低的。2 @$ [, n. t( ^
; I! K" y% c0 o6 m* `( B; ~
20190622161607756.png
- j& h2 i' b# m3 X4 w7 c7 u) B

7 t' d. G: V# {9 K$ C产生ACK时序:在SCL高电平期间,SDA为低电平状态。" R  @; k% K2 W! n( J
  1. /***************************************************************************************- D. q5 I/ n- F$ {* L9 u! d% P. r
  2.   * @brief  产生ACK应答,
    ' C# _$ J) b; B. ~2 w& f8 ~- m
  3. ***************************************************************************************/
    ) K: f; O6 H7 \) |- }9 M  A/ Z% C4 d
  4. void CT_IIC_Ack(void)3 Y' Q5 A( \7 ~$ N  ^* k/ Y9 X
  5. {
      o* h, y2 b: r. U. Z2 A
  6.         CT_IIC_SCL(0);
    + N7 C7 {' b# c/ a, W
  7.         CT_Delay();
    & _/ e, s; ^+ X1 [
  8.         CT_SDA_OUT();
    " l1 t# ?6 n6 W3 |# T
  9.         CT_IIC_SDA(0);
    * A) k5 C! [( B) [9 u  a$ J9 ^$ W
  10.         CT_IIC_SCL(1);8 D* r% C. T. F: r6 j
  11.         CT_Delay();
    " x' e4 o! \" m3 O2 n/ D. ^
  12.         CT_IIC_SCL(0);
    3 h  u, A2 {' P2 l0 J. U
  13. }
复制代码

5 d1 y7 d9 i( |6 W等待ACK时序:拉高SCL与SDA后, 然后设置SDA为输入检测状态,等待接受数据端拉低SDA" ?  U7 B1 ^  X' w' {2 s! m
  1. /***************************************************************************************+ ~! g# d1 I/ F/ Q, V2 G9 O
  2.   * @brief   等待应答信号到来,等待接受数据端拉低SDA2 x" k+ ]6 p: D# W
  3.   * @input   
    - F! _! Z6 j1 ]9 k$ Q
  4.   * @return  1,接收应答失败 ; 0,接收应答成功
    $ Y! w/ V3 d# x' T9 T0 W" @
  5. ***************************************************************************************/* |5 A+ L' }1 [* c! L! Q$ p
  6. uint8_t CT_IIC_Wait_Ack(void)2 r$ m7 d8 D! E/ t( R8 p
  7. {
    ; `" W% _8 e8 O  e! q# c
  8.         uint8_t ucErrTime=0;0 e  i/ U4 W5 ]
  9.         CT_IIC_SDA(1);           
    : j2 |+ r) h% ?8 @
  10.         CT_IIC_SCL(1);
    2 }3 G$ A; L0 [$ {, d' \0 f
  11.         CT_SDA_IN();      //SDA设置为输入  $ I4 D! u9 x2 j- o% J  q# g
  12.         while(CT_READ_SDA)+ B! N# @8 j+ ?0 {
  13.         {# P( b& }7 y# g" ?; T9 k' f- }
  14.                 ucErrTime++;
    $ ?1 A; c8 P: k
  15.                 if(ucErrTime>250){" l1 A/ W% e7 B2 v& v2 |
  16.                         CT_IIC_Stop();
    " G# c& u& S7 v8 u
  17.                         return 1;+ m8 y6 o9 ~3 s$ `
  18.                 }
    ! x. R& ~+ H% ]" j
  19.                 CT_Delay();- s6 X2 o1 X$ e0 o) E" K
  20.         }6 ^) y* x& y- i$ P( K
  21.         CT_IIC_SCL(0);! \9 s: N' v  `2 P9 j
  22.         return 0;  
      U- E. D- w( `' e1 C/ J; {
  23. }
复制代码
- K* e' H# e/ R  _
下图是nACK时序与 传输数据1的时序图,这两种时序图是一样的,区别在于ACK是在8个数据时序后产生,且SDA电平是由接受数据端拉低的。3 v5 T6 r) _9 m6 a# I' A6 e
& c' m! s8 a# f
20190622164227486.png

; u; x+ W" S7 Z# Q, X9 u1 `
6 d% b* L! R* @产生ACK时序:在SCL高电平期间,SDA为高电平状态。/ R" N$ k( |# ~2 u: v$ I4 R
  1. /***************************************************************************************
    5 _; R' f: a0 e, p% D0 Z
  2.   * @brief  不产生ACK应答        
      v, M) {, m% B( c2 U6 f* y6 m% k
  3. ***************************************************************************************/* R) N# n- p/ f, L. O- A
  4. void CT_IIC_NAck(void)
    ) V, ^6 n, O1 _2 M! ^0 B$ j5 _1 O
  5. {7 h) o+ M1 Q) i- M# R
  6.         CT_IIC_SCL(0);1 o( K. \8 e$ }, F- Z( e0 x7 N0 F
  7.         CT_Delay();
    $ {* S  ^6 D% S# P! u' q8 S2 `
  8.         CT_SDA_OUT();
    ' a* S! y5 R* x( @! Z
  9.         CT_IIC_SDA(1);7 f6 X, S3 A  V* X
  10.         CT_IIC_SCL(1);3 K( e9 G' k3 h
  11.         CT_Delay();9 X# o/ j& f! S
  12.         CT_IIC_SCL(0);
    * }  O' }; H' i8 W. N+ u" h" T, ]
  13. }
复制代码
( x) P& J! X8 O' U
发送一个字节函数,优先发送高位,即从bit7开始发送。$ c; N4 [. w; c3 ^
  1. /***************************************************************************************
    % U" \: S9 m5 _7 k+ [
  2.   * @brief   IIC发送一个字节,* L/ K' {8 g3 t6 J# Y
  3.   * @input   6 b" O' e' Y8 f9 B
  4.   * @return  / ^8 }" Q3 _( W4 U" Z) V1 ^
  5. ***************************************************************************************/
    4 l$ q. p7 }+ X# R
  6. void CT_IIC_Send_Byte(uint8_t txd)$ T+ }0 O. ^) V) y/ b9 q
  7. {; M/ B- L& ^) D1 e7 h% Q4 Z8 J( V9 P" z
  8.     uint8_t t;   7 V7 f$ m4 `2 q: z
  9.     CT_SDA_OUT();             * G- D$ u. Y1 g# J! A$ x" I5 b9 [
  10.     CT_IIC_SCL(0);//拉低时钟开始数据传输9 S' {: i4 f- @. g6 {* `
  11.     CT_Delay();: G2 D+ x* g/ ~6 T/ f1 o
  12.     for(t=0;t<8;t++)! ]+ @* v' E( `9 U
  13.     {0 A' S" b. k$ i4 G9 |# ]& V
  14.         CT_IIC_SDA((txd&0x80)>>7);//发送bit7位+ E" \# V* s- W* E% z( P5 N. i
  15.         txd<<=1; //将txd的次高位左移到最高位              : I. J! k% d4 g2 |  U
  16.         CT_IIC_SCL(1); 1 R/ k0 f' v4 Y" l( g
  17.         CT_Delay();
    * K# e) ], Z( w0 r; m
  18.         CT_IIC_SCL(0);        
    ; Z( }* ]2 m; _+ h0 m3 ]
  19.         CT_Delay();/ T; I1 I! W) Z6 f
  20.     }
    9 n% h2 o3 r% U6 m3 u' R* j
  21. }
复制代码

7 r. I$ k- {# M" G: O/ x* t3 A读字一个字节函数,接受到1bit数据后,将该bit放在bit0位置(通过receive++实现),如果还要继续接受数据,则将之前接受到的数据左移一位(通过receive<<=1实现),留出bit0位置接受新的数据。4 ?) J( @" E/ D0 w. K4 u
  1. /***************************************************************************************
    4 r! O4 z6 ~" i: b* o" P
  2.   * @brief   读1个字节- k' ~% k) z5 Z8 \
  3.   * @input   ack=1时,发送ACK,ack=0,发送nACK( N  h/ i$ J- E6 p9 {
  4.   * @return  
    # A9 y1 f! Y8 J% [
  5. ***************************************************************************************/
    ' ]8 R2 \; Y1 @/ T$ a6 `
  6. uint8_t CT_IIC_Read_Byte(unsigned char ack)% I& Z- {" G( O5 w) z0 E
  7. {8 }) Y* P3 I) R7 l$ j9 @; b
  8.         uint8_t i,receive=0;7 w5 c% ^  L& i) H. E, U% Z
  9.          CT_SDA_IN();//SDA设置为输入
    : h, N% \" l: j
  10.         CT_Delay();+ x! n! K2 a$ H  Y. ?
  11.         for(i=0;i<8;i++ )
    , |; O( q" S& b
  12.         {
    , C4 G- B/ Z% x' u2 P# \" [9 N5 z
  13.                 CT_IIC_SCL(0);                        - L0 ?- h5 D. U. a
  14.                 CT_Delay();
    % T- Q% G" Q8 m8 S. e- R+ ?) {1 \
  15.                 CT_IIC_SCL(1);         # e" W- u) I3 c2 a
  16.                 receive<<=1;
    & j7 J% P& Z8 B( |
  17.                 if(CT_READ_SDA)receive++;   
    , h" [9 S" T2 z& w0 y7 v2 x
  18.         }                                           : z( x9 Y6 t# L+ |4 q8 E* z
  19.         if (!ack); a, |0 C. @  c. y5 @
  20.         CT_IIC_NAck();//发送nACK3 U  \& ?( Y  q( B3 l
  21.         else - K* L4 q5 {3 H1 U& A. q2 A* \' Y
  22.         CT_IIC_Ack(); //发送ACK   
    6 H& Y3 Z- m  k
  23.          return receive;
    8 G" q" S, \6 p5 e& r( D( g
  24. }
复制代码

. J/ `) d  O! Y1 z( G: F三 GT9147电容触摸屏控制芯片驱动
" K. A. b+ B/ W1 R$ o/ a" ]1. GT914内部结构框图如下图所示
3 Q" L$ J( `% u" \6 l0 l+ ~' `( R
2 {( R; J7 x* X0 n! L
2019061913180610.png

! n- h* W$ ?. d: @7 Q: @& _% l" O( Z) U* U
5L5)3BWQK[DM1E_`8%S}J0F.png

  c; m  e' ], {# z+ |- ^5 }' g6 L4 o/ r/ a9 J! l3 G
2. 上电流程" s0 u, z$ D: G3 s' A2 O
& Z( s- I+ p- f4 H+ f- o& t5 ]- G/ G
GT9147上电初始化流程如下所示:
. y0 f3 Y" l1 I" G: y5 B1 d; f$ v& }3 O4 t
配置RST输出低电平,INT输出低(或者高)电平后,位置100us以上,此阶段配置IIC地址为 0xBA/0xBB(或者0x28/0x29)' p5 o8 f. z1 D  E& I. \8 i+ n
接着配置RST输出高电平并维持5ms以上后,可以配置INT引脚为悬浮输入模式。& u# H* A- B# T+ T: D: e
等待50ms以上后,可以发送配置信息。4 k; s. Y7 ?7 H  m
4 p# \. ?) t% z& @7 O
2019062113491579.png

( }$ W7 v4 q* [3 k: I- I  n; ~" u7 J( Y: I' h' c
代码参考原子例程编写,贴上代码:  r$ x/ n5 C6 Y( E% ?$ q, @% ~8 w( y

1 z# F0 A2 T/ x3 e( K% p  ^' Y
  1. uint8_t GT9147_Init(void)
    4 _" g2 t7 B/ o& x( W( K% Z% X
  2. {' V0 o3 `8 ^% s4 u
  3.     uint8_t temp[5];
    + ^( a$ j7 H' U

  4. & N& Z: ^/ i0 m6 j7 {! N, ~; u
  5.     GPIO_InitTypeDef GPIO_Initure;
    ) B3 u2 s, Y# ^% X
  6. ( \4 K6 c9 B% `0 b1 x( t" o
  7.     GPIO_Initure.Pin = GPIO_PIN_7;          //PH7" n+ N4 x* U' d* @' k! C8 w4 U
  8.     GPIO_Initure.Mode = GPIO_MODE_INPUT;    //输出
    7 L9 u, G: P, Y! {* T+ Y( p
  9.     GPIO_Initure.Pull = GPIO_PULLUP;        //上拉
    ; u, [3 t4 B: o/ ?. E! w
  10.     GPIO_Initure.Speed = GPIO_SPEED_HIGH;   //高速
    ; h  g5 Q3 e+ [# z- f3 }
  11.     HAL_GPIO_Init(GPIOH, &GPIO_Initure);    //初始化
    " T/ L6 j, E7 B+ O" V3 E7 E

  12. " h$ ^! K3 `, T2 @7 M/ Y! q
  13.     GPIO_Initure.Pin = GPIO_PIN_8;           //PI8
    ) ^' a; Y: u- @5 Z  R
  14.     GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP; //推挽输出
    7 ]* e5 |, R1 K4 |% O  e9 x$ e
  15.     HAL_GPIO_Init(GPIOI, &GPIO_Initure);     //初始化
    4 s; H* _7 K& m3 |/ _

  16. & X' E1 H" D: F. i0 h- `# y1 b
  17.     CT_IIC_Init();              //初始化电容屏的I2C总线
    7 N/ I' f0 H5 r' U% R- s$ |% [

  18. 2 N: Z* v5 j3 H5 W6 B  N: ^4 n
  19.     GT_RST(0);                                //复位. ^1 X% M0 N' I4 f" i* R
  20.     delay_ms(1);            //INT引脚电平维持100us以上
    & P# f* a. {3 {, s
  21.     GT_RST(1);                                //释放复位
    - j/ `, h! G) O; z7 `
  22.     delay_ms(10);           //释放复位后维持5ms以上,设置INT为悬浮输入
    / q4 H( u! d2 q) w; K5 L4 }
  23.     GPIO_Initure.Pin = GPIO_PIN_7;
    * w9 H: \8 I: D- X
  24.     GPIO_Initure.Mode = GPIO_MODE_IT_RISING;# v3 {: M1 e. y) S8 k# L
  25.     GPIO_Initure.Pull = GPIO_NOPULL;) A0 |7 B6 j' Q3 ?
  26.     HAL_GPIO_Init(GPIOH, &GPIO_Initure);    //初始化
    : z6 m: {, ?! E  ~: \
  27.     delay_ms(60);
    5 @; }1 G4 Y9 V1 G

  28.   t6 N! y0 ^) r0 X) {  ^5 s
  29.     GT9147_RD_Reg(GT_PID_REG, temp, 4); //读取产品ID
    : c) m, U- `2 [7 c) d2 H( W* V
  30.     temp[4] = 0;
    9 E6 B1 h: e* h% O. ]2 X
  31.     printf("CTP ID:0x%s\r\n", temp);        //打印ID- Z$ D' L3 N$ ?% J
  32. 7 s) y! ]3 P  j8 B& H
  33.     GT9147_Send_Cfg(1);//更新并保存配置
      D" m: r! W& I6 e

  34. ! }1 M6 }3 V0 T8 X  U: f
  35.     return 1;  C* b) I/ S/ d: y
  36. }
复制代码

$ s' G# `, k1 R3 W6 b7 W! }, G* D0 b( i3. 读取坐标流程. p$ R8 o1 S! i& x) ?3 K1 F

1 q# o* g3 E5 w. @2 }使用中断方式读取坐标,需要注意的是,如果不及时读取坐标信息会一直产生中断。GT9147的中断脚与STM32的LINE7中断线相连,中断回调函数如下所示。当按下触摸屏时,touch_x与touch_y分别保存触摸时的xy坐标;当松开触摸屏时,touch_x,touch_y赋值0xffff! g) i! T0 B, ^8 W
; [( S" j8 h5 T% _6 W
  1. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)0 b, ]4 u  g* C% h; L- e
  2. {
    * t; N4 k) w( B) B4 t! C- I. E4 E
  3.     uint8_t buf[4];  O, _" a& |% G$ v6 [
  4.     uint8_t i = 0, mode = 0, temp = 0;! }) ~8 p2 Z" d5 _  x
  5.     uint16_t x[5], y[5];
    / H9 e6 d% d2 o6 A7 ?2 M
  6.     if(GPIO_Pin == GPIO_PIN_7) { //读取坐标, 否则会一直有INT脉冲% t0 H. `8 V3 H* y* r# L
  7.         GT9147_RD_Reg(GT_GSTID_REG, &mode, 1);        //读取触摸点的状态2 @# {' U/ \; r6 X+ Q, N) w
  8.         if(mode & 0X80 && ((mode & 0XF) < 6)) //有坐标可读取
    / c2 K' W* \& M. W' |0 |
  9.         {) Q2 T: {2 M- G4 O+ [7 k7 U
  10.             temp = 0;: S% P; S1 u+ z
  11.             GT9147_WR_Reg(GT_GSTID_REG, &temp, 1);//清标志% }, P6 m' t4 B9 w
  12.         }* S% O% d) M' _% G' D8 Y
  13.         if( (mode & 0xF) && ((mode & 0xF) < 6)) //判断触摸点个数
    " \- |) Y5 i# g4 M
  14.         {
    / T. F( J( r# ]' z) }+ G
  15.             for(i = 0; i < (mode & 0xF); i++)
    $ J) p4 D* O- l
  16.             {, w6 Z) ~, G+ ^' J1 v0 S
  17.                 GT9147_RD_Reg(GT9147_TPX_TBL<i>, buf, 4);        //读取XY坐标值& P; s# l, P: Z8 M
  18.                 </i>x = (((uint16_t)buf[1] << 8) + buf[0]);' m3 p( L% j  d. P
  19.                 y = (((uint16_t)buf[3] << 8) + buf[2]);. \! S: ~9 F4 d$ E* C( c* c
  20.             }
    % [; n# X. _) A- o9 }* m
  21.             touch_x = x[0];9 i7 H0 ?" ^6 q* O* ^. K
  22.             touch_y = y[0];, [% s* I8 B# t' y+ g) y7 X
  23.         }
    , L4 d1 d+ H4 j8 ^6 P2 |

  24. : [5 E: j# J$ _& w# p. m' C! j
  25.         if((mode&0x8F)==0x80)//无触摸点按下,xy赋值为0xffff# t2 N0 N  g. v% Q* w- F9 k* k- p
  26.         {
    4 S5 L( A  s+ [' t( e
  27.           touch_x = 0xffff;7 ?; T8 E4 o5 [- t* [, j$ z2 C. B* E
  28.           touch_y = 0xffff;
    0 b. `: _; w, t1 L- ]7 l2 R
  29.         }
    ' ]% A/ \1 e: N5 \/ G3 U
  30.     }- I" m8 `* M5 P; x& q
  31. }
复制代码
4.主机 对 GT9147 进行读操作时序8 L0 ^* k8 x5 X1 x2 X
7 f3 g' F4 c" h" b
20190621161601926.png

! o7 a6 F) n' G0 T8 X4 j. \
, q/ ^! S- V& B/ |/ q" y  I$ i根据该时序图编写读寄存器函数如下:
3 |1 K3 z; J6 y, u: J- W  K# {# q4 F8 T5 A* n8 S
  1. /***************************************************************************************) B0 j: Z  H1 C) S! j  ?
  2.   * @brief   从GT9147读出一次数据
    ' m5 R9 l9 k! M
  3.   * @input   reg:起始寄存器地址
    3 K( v' V5 A: I! \( y
  4.              buf:数据缓缓存区9 W8 j: g- U% S
  5.              len:读数据长度        
    % C! H. b4 i$ z7 x
  6.   * @return  
    ! ^/ l) R6 o( L7 p5 E- o- o$ m
  7. ***************************************************************************************/
    : g8 |9 _0 O, E) s: n/ }
  8. void GT9147_RD_Reg(uint16_t reg,uint8_t *buf,uint8_t len)
    % f3 F& l' d8 [) E3 \; h
  9. {
    # R- g# f  g9 z% H
  10.         uint8_t i;   {) h1 @( H: F, B4 C, \0 @
  11.          CT_IIC_Start();        ! }$ A  `! ]3 c0 N9 F* v- N& m+ q( S0 g
  12.          CT_IIC_Send_Byte(GT_CMD_WR);   //发送写命令         
    3 o2 l5 P: Z) R+ q% @5 E5 s
  13.         CT_IIC_Wait_Ack();- j  B6 K4 h- E; D% `) \# b
  14.          CT_IIC_Send_Byte(reg>>8);           //发送高8位地址
    ; r7 A$ v6 Y% i
  15.         CT_IIC_Wait_Ack();                                                                                                               2 P* M; r8 T4 j
  16.          CT_IIC_Send_Byte(reg&0XFF);           //发送低8位地址
    & A& f, Z, X7 V& m7 a
  17.         CT_IIC_Wait_Ack();  ( w% b; I$ L0 y* B3 X7 ^
  18.          CT_IIC_Start();                      / t) ?0 c  n  o% H, m4 l7 F* d
  19.         CT_IIC_Send_Byte(GT_CMD_RD);   //发送读命令                   ! |; j" {+ e( S9 m$ p: m0 M
  20.         CT_IIC_Wait_Ack();           ) X5 i' k+ ?7 ~* M# Q0 `, N
  21.         for(i=0;i<len;i++)
    , s4 b' ^0 K5 {5 g* m; j  w
  22.         {
    2 J; O/ [+ H( k" L; |+ e- Z
  23.             buf<span style="font-style: italic;"><span style="font-style: normal;">=CT_IIC_Read_Byte(i==(len-1)?0:1); //发数据         
    7 W, U; I( ~2 I8 O. T
  24.         }  I4 @/ C! u2 b/ B/ B6 b& o3 G) t
  25.         CT_IIC_Stop();//产生一个停止条件   
    7 J" B1 C3 n7 ^& `& P, H! e+ m# q, h7 X
  26. }</span></span>
复制代码
" m# z+ a# f$ ]
5.主机对 GT9147 进行写操作时序
5 e$ Z. ~& Z) ^1 G
& x  A, q% ~& M( E
20190621161509843.png

8 R) j$ w; u- k7 A- K/ \; x( M' o- ^) r1 M
通过该时序图,编写写寄存器函数如下2 C8 @+ h$ N. j5 D8 o: Z1 [

% V: y+ W: Y' |) w( T$ J' v
  1. /***************************************************************************************% F2 K; Q3 L4 W# R
  2.   * @brief   向GT9147写入一次数据
    5 o* W; m8 q! s
  3.   * @input   reg:起始寄存器地址;
    ( E$ E* {! S- N1 X
  4.              buf:数据缓缓存区6 f) [+ Y  h3 E) G  S! c) c& L' r
  5.              len:写数据长度$ r3 B" z( A! ^, F
  6.   * @return  0,成功; 1,失败.
    9 E, p; `5 A% q( ]7 y" J
  7. ***************************************************************************************/4 ?; G0 \. E( _8 V9 ~  s' P9 I
  8. uint8_t GT9147_WR_Reg(uint16_t reg,uint8_t *buf,uint8_t len)9 P7 ^9 N9 I# y( W
  9. {: h* N0 B! p' ]( Y0 Q) F
  10.         uint8_t i;
    . o+ p/ H% S8 K" t: m3 y; l+ O* h
  11.         uint8_t ret=0;
    ( W7 x' i: @, E( Q; }7 f, J
  12.         CT_IIC_Start();        # t5 O, y9 d1 v* z
  13.          CT_IIC_Send_Byte(GT_CMD_WR);           //发送写命令         
    " ~$ N- R" u2 b7 a7 j
  14.         CT_IIC_Wait_Ack();) ~- \4 C4 l, e+ Q, N$ b
  15.         CT_IIC_Send_Byte(reg>>8);           //发送高8位地址
    9 y; u3 x9 M: a+ B  I3 b5 f2 v( v
  16.         CT_IIC_Wait_Ack();                                                                                                               2 L' J8 v$ v2 r/ m+ T7 `' l
  17.         CT_IIC_Send_Byte(reg&0XFF);           //发送低8位地址( ?, Z) p" E( u4 k# H7 b
  18.         CT_IIC_Wait_Ack();  
    3 [. h- [' v* d3 o4 f5 K- A. t9 G
  19.         for(i=0;i<len;i++)
    5 a/ q6 G3 v+ N+ Y9 M  W5 X4 N, Q
  20.         {
    # }, x  h1 N+ L4 r6 S2 a) S* Q8 p
  21.             CT_IIC_Send_Byte(buf<span style="font-style: italic;"><span style="font-style: normal;">);          //发数据
    7 P9 L* T9 b9 s! \3 n, g0 x
  22.                 ret = CT_IIC_Wait_Ack();
    - Y3 q  |3 e' u0 D3 V) M0 N' U+ ~
  23.                 if(ret)break;  0 C& ]) p- x; {7 g
  24.         }
    % x7 v7 r7 e/ q
  25.     CT_IIC_Stop();                                        //产生一个停止条件            
    5 ]  M$ e. I3 {
  26.         return ret;
    * H0 u1 w( W8 {3 Z
  27. }</span></span>
复制代码
$ j% a0 @, X3 N$ u
6. GT9147配置函数如下,GT9147_CFG_TBL针对分辨率480×272的触摸屏。9 r/ N0 H# J  v% _

. F! l) p" b1 J* N; Z2 B, d) J- k配置寄存器时是要注意以下几点:3 u( S- k  W7 m% r( K3 K

; m/ M0 S" v% w9 L新的版本号大于等于GT9147内部flash原有版本号,才会更新配置.0 ]$ J7 d, F- ]% u2 j) s" u
写完GT9147_CFG_TBL中的配置后,还需要往0x80FF寄存器中写入校验,0x8100寄存器中写1。9 _( @  g( p0 P( h4 D: M
关于配置更详细的信息可以参考GT9147编程参考手册: \2 M( l: [  ~9 M- T
  1. const uint8_t GT9147_CFG_TBL[]=2 @) V8 u6 d- ]6 z
  2. {
    # y$ i. H5 f: \7 N5 Q9 ^. a6 n- i
  3.     0x60,0xe0,0x01,0x10,0x01,0x05,0x0C,0x00,0x01,0x08,2 U0 g$ _' P8 P. ^9 I1 g
  4.     0x28,0x05,0x50,0x32,0x03,0x05,0x00,0x00,0xff,0xff,
    4 A7 l; |; d0 v) ]9 M' T
  5.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x89,0x28,0x0a,: W9 ]) E! V3 E
  6.     0x17,0x15,0x31,0x0d,0x00,0x00,0x02,0x9b,0x03,0x25," ^$ {, S& Q, n  h: W
  7.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0x00,0x00,* Y  b  }- e- q9 a# |( o$ w
  8.     0x00,0x0f,0x94,0x94,0xc5,0x02,0x07,0x00,0x00,0x04,. C6 P' C# [# l, [; t- |# t
  9.     0x8d,0x13,0x00,0x5c,0x1e,0x00,0x3c,0x30,0x00,0x29,
    % P9 _' U8 G, R5 p( |
  10.     0x4c,0x00,0x1e,0x78,0x00,0x1e,0x00,0x00,0x00,0x00,
    9 b. {" G* ~1 R' C
  11.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0 F; p4 T* V3 W2 G1 N+ F; `4 ^- Q
  12.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    # _8 _9 n2 v" q) L" F
  13.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    : G7 L/ ^: O/ o+ ?" o
  14.     0x00,0x00,0x08,0x0a,0x0c,0x0e,0x10,0x12,0x14,0x16,
    7 U! y: @. r' S8 g2 M" M2 D9 {
  15.     0x18,0x1a,0x00,0x00,0x00,0x00,0x1f,0xff,0xff,0xff,! O2 }1 k. x* b* e4 [* A( I& e5 E
  16.     0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
    # E' n/ U; |0 |; _6 S8 i( K5 M  z, ]. x
  17.     0xff,0xff,0x00,0x02,0x04,0x05,0x06,0x08,0x0a,0x0c,2 d' ^% ^0 i5 Q- G/ q: ?, u$ T) G/ h  _
  18.     0x0e,0x1d,0x1e,0x1f,0x20,0x22,0x24,0x28,0x29,0xff,
    8 l2 B* d; W$ |+ g( L9 S& E
  19.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff," {5 m. A3 v7 J, K$ p9 E9 y! g
  20.     0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,& a! _  ]* x$ R+ ?
  21.     0xff,0xff,0xff,0xff,
    6 ~, ~! `7 v; v
  22. };
    : M1 A" h4 U! E' W
  23. ' z; `( Y/ ]& B/ c* j' r6 c
  24. uint8_t GT9147_Send_Cfg(uint8_t mode)
    9 [9 d. f: g' d) G( J) i+ m) x( ^. L( `' j
  25. {
    $ x0 I: p6 Y! C, c) N: ]9 m6 L
  26.         uint8_t buf[2];7 V: N# {4 R& r# J2 q$ ]: h2 F0 G$ U
  27.         uint8_t i=0;8 h6 a$ o% B  Q2 O+ z# B% }
  28.         buf[0]=0;
    . X% g: D) H3 x6 B& o. B
  29.         buf[1]=mode;        //是否写入到GT9147 FLASH?  即是否掉电保存2 N$ u% }& S; S7 u0 h/ g& u
  30.         for(i=0;i<sizeof(GT9147_CFG_TBL);i++)/ ~" q; L+ {4 U1 r" b
  31.             buf[0]+=GT9147_CFG_TBL<span style="font-style: italic;"><span style="font-style: normal;">;//计算校验和$ `; g: d: N* \  l6 A% r
  32.         buf[0]=(~buf[0])+1;, U( L$ F  K9 O. E% }
  33.         GT9147_WR_Reg(GT_CFGS_REG,(uint8_t*)GT9147_CFG_TBL,sizeof(GT9147_CFG_TBL));//发送寄存器配置
    % S. I2 U3 D. }$ d
  34.         GT9147_WR_Reg(GT_CHECK_REG,buf,2);//写入校验和,和配置更新标记0 Y! \1 K% V4 `& `( F
  35.         return 0;0 K4 b$ k, \" @+ T" Q3 ?% G( T5 [
  36. }</span></span>
复制代码
4 s+ ]3 I" t: m8 Y' @3 L3 l
四 移植触摸屏驱动到STemWin% u' g+ v1 ?# I+ D
这里假设已经成功移植了STemWin到STM32F7工程。4 s5 V0 \' b& g% i/ S
0 t5 S7 j  Z' p
1. 在GUIConf打开STemWin触摸屏驱动宏" ^) @% q2 `6 h4 w) Y
+ B7 v4 @- c5 ^1 u/ z9 v$ P* V
  1. #define GUI_SUPPORT_TOUCH       (1)  // Support touchscreen
复制代码
. E% Q6 U5 C  x1 d
2. 新建GUI_X_Touch_Analog.c文件实现以下四个函数,在第三章第3小节我们知道touch_x,touch_y表示当前触摸的xy坐标。整个文件的内容如下所示。
5 ^6 v7 G3 H4 a& N
; _, J* u7 i5 D8 ?8 }
  1. void GUI_TOUCH_X_ActivateX(void)
    9 b7 q1 `8 `9 f* M) [9 T
  2. {: H/ v) n+ e( J2 n/ E

  3. / y7 D4 O* d; D& S* m- `
  4. }
    " Z) A- L2 P' I& F7 E* a' n7 ]
  5. 1 y& F% g3 h5 c) B
  6. void GUI_TOUCH_X_ActivateY(void)
    * Z& Z" d1 d, R! V
  7. {* T# c2 }& n' i) l# H

  8.   w+ a+ Q4 P2 e7 p
  9. }
    $ [/ F, _5 m& g( r! {8 D

  10. * @; i, h: b& Q8 K
  11. /*获取x坐标*/! e0 N7 K" [1 j( e
  12. int  GUI_TOUCH_X_MeasureX (void)
    # Q3 ?5 M* N' _* M$ n, z
  13. {
    - W6 |) z4 \8 ?& H3 C
  14.   return touch_x;
    7 ]7 S; n; i; ]5 G
  15. }* o7 z& R: [2 [+ e9 I  X
  16. 8 F6 G4 A) c. O! c, P% Z4 Z% I
  17. /*获取y坐标*/* j+ M( S1 W2 n# j  r( T" J$ s
  18. int  GUI_TOUCH_X_MeasureY (void)+ K$ k* [+ \# _) Y2 D' H
  19. {
    . ]8 U4 T6 B$ Q* d. t5 x9 Z" N
  20.   return touch_y;" ^7 l0 Y4 {' O8 n, Y1 ]
  21. }
复制代码

) ]7 i$ ~' q% ~8 ?* m3. 使用GUI_TOUCH_Calibrate函数校准x与y值,然后才能调用GUI_TOUCH_Exec()函数处理触摸事件。
( r! {( x* A$ J0 F5 \2 a8 d( D0 S: G4 x; L
  1. void StartTouchTask(void const * argument)* ]7 N/ D0 Z/ B+ ]# |$ a- S
  2. {) X) h1 A; e. l) J( y/ J0 n
  3.   /* USER CODE BEGIN StartTouchTask */2 \! W+ c1 _# A
  4.   GUI_CURSOR_Show();//显示鼠标指针
    2 e8 E8 L$ X- _* ?0 q
  5.   GUI_TOUCH_Calibrate(GUI_COORD_X,0,LCD_WIDTH,0,LCD_WIDTH);   ' W& L# L# a8 q7 J
  6.   GUI_TOUCH_Calibrate(GUI_COORD_Y,0,LCD_HEIGHT,0,LCD_HEIGHT);
    ' ?/ y; O; F/ ]! M( i1 }
  7.   /* Infinite loop */
    " Y8 U* ^6 x+ g$ p3 I
  8.   for(;;)
    ; o8 J( k& R/ k- V; C# S0 `
  9.   {
    ) C* U2 C; c- [. K' r5 r9 ~+ ~* P6 _
  10.     GUI_TOUCH_Exec();
    0 D3 t; _8 ?9 {: f  h9 d  V9 A
  11.     osDelay(5);
    3 b( h$ z  Q% P. ?6 k
  12.   }
    * @9 G2 D3 G( ^" z' q/ E
  13.   /* USER CODE END StartTouchTask */: m$ L) \& Y+ X5 b/ c1 e
  14. }
复制代码

! v7 j4 L( n1 f* v7 |9 V8 y
" J. S- X0 d# Y& E$ \4 ?
. e: S; K* q: h( w9 I6 _! \* i3 q. m1 ^5 @
赞 收藏 评论0 发布时间:2021-12-17 12:05

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版