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

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

[复制链接]
STMCU小助手 发布时间:2021-12-17 12:05
一  电阻驱动与电容驱动原理3 V) ]% {& H9 ~) \( c0 ^9 e
2 G9 r, O9 n" U  ?
1. 电阻屏等效电路如下所示, 当产生按压时:

% R3 X$ d. z% f) C" S7 @X-接地,X+接电源,Y+接ADC输入.通过读取Y+的电压以及电阻分压原理,可以得出触点的x坐标" Z3 a6 a4 j- e- h( @% a
Y-接地,Y+接电源,X+接ADC输入.通过读取X+的电压以及电阻分压原理,可以得出触点的y坐标
3 ~) D" N. T" `1 _, m: Q; Y, R8 K( q4 S) B/ b) G
2019061911075212.png
0 @% I; L/ P/ g( A* h

2 a* v  H" @# `& t2. 电容屏等效图如下所示, 检测原理类似矩阵按键, 当产生按压时:1 u9 b" c% T& Q6 y
: i0 A0 c+ ]2 I" E
X轴产生从上至下依次产生激励信号(AC交流信号), Y轴电极同时接受信号 (该激励信号是交流电,可以通过电容穿到Y轴).8 b$ @% G0 ^; E# M$ a3 u
+ R2 b0 x* M4 u& U& _; o. f
假设有如下两个按压点(分别位于(1,1)与(2,2)的位置),检测过程如下:
# l6 j1 D2 h/ L2 @当X1产生激励信号时,Y1接受到的交流信号产生了变化, 所以可以确认(1,1)处有触摸.7 s( `( g' W' H. t8 @
接着当当X2产生激励信号时,Y2接受到的交流信号产生了变化, 所以可以确认(2,2)处也有有触摸.
2 x# O+ ?: i2 \3 R* _* H1 k( q* }$ R
20190619115448553.png
6 n; G+ |7 _, \$ A3 i8 \# n
- G) a3 Z; u, u0 ^, Q' C2 L
二 软件模拟IIC
+ w% z- X/ t: z由于stm32的硬件iic有各种各样的问题,所以采用软件模拟IIC的方式,主要实现IIC起始信号函数、IIC停止信号函数、等待ACK函数、产生ACK应答函数、不产生ACK应答函数、发送字节函数、读字节函数
& k7 {) T9 d& y' n" v7 a
* Q% N2 a0 W; j2 k. V  E1. 起始信号与停止信号; V! D. k  n* [& p2 W- S

( \0 k8 `; g) ~+ f. W下图是IIC起始信号与停止信号时序图,通过观察该图编写起始信号与停止信号函数。
/ i6 e  I1 X# ]% }( e# c
, Q2 I, J& n- h$ m- c
aHR0cHM6Ly9pbWFnZXMwLmNuYmxvZ3MuY29tL2Jsb2cvNDcwOTA5LzIwMTMwNS8yODE2MzczMy01MjE5.png
) [8 J  s* F' G* f1 Y
: Z  v2 r( H/ n5 w5 ]
起始信号:当SCL为高期间,SDA由高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号。
3 M- U" f! s5 |1 P: U( a
  1. /***************************************************************************************
    2 s, Z  B; k  q
  2.   * @brief  产生IIC起始信号,当SCL为高期间,SDA由高到低的跳变, Y4 z. N0 g2 S  U/ C0 O* p7 d# {
  3. ***************************************************************************************/
    8 v$ I* ~3 C0 g1 s% [8 N) H
  4. void CT_IIC_Start(void)7 }( N+ t: s- H  W9 @
  5. {, q+ {! N9 Q1 ~0 M! P% z& d3 M
  6.         CT_SDA_OUT();     //sda线输出
    5 D7 B/ E: J9 _- C* d+ C7 Z3 p
  7.     CT_IIC_SCL(1);& y# ]5 C* C+ S' E2 |: y3 f9 R! ^  v: [
  8.         CT_IIC_SDA(1);                    
    + N! X+ |8 G  Q2 u
  9.         CT_Delay();% T5 @! X5 c0 [9 A- @
  10.          CT_IIC_SDA(0);
    6 H( Q8 a$ _. }' R6 g9 k/ h
  11. }
复制代码
* Y1 ?- ]; \/ Q$ O& ?8 o1 o
停止信号:当SCL为高期间,SDA由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。
' e( D; \3 v2 ?: x
  1. /***************************************************************************************
    ; i' ~' }( ~5 }2 Z, t$ g
  2.   * @brief  产生IIC停止信号,当SCL为高期间,SDA由低到高的跳变
    ; H& M. b2 n. s* V/ z; T4 Y9 E( P
  3. ***************************************************************************************/
    0 \+ F- \) T3 j9 ~
  4. void CT_IIC_Stop(void)
    8 o; ^7 V) O" S: Z) x
  5. {
    % t8 t! {$ h1 [
  6.         CT_SDA_OUT();//sda线输出
    # q: X$ @% G* f- g3 }" M7 M+ O
  7.         CT_IIC_SCL(1);6 s( ^  v  H. {6 V% k+ I
  8.         CT_IIC_SDA(0);//STOP:when CLK is high DATA change form low to high2 i6 C$ \9 l" v# N. y% T; c; w# {
  9.         CT_Delay();0 o: E8 t/ W# W7 c- |2 ~
  10.         CT_IIC_SDA(1);+ |( J4 [- s$ I, l# S( q
  11. }
复制代码

& C$ r8 H6 a' u- h. m$ p在GT9147数据手册中可以发现如下截图所示内容,SCL在低电平期间至少保持1.3us,其他电平最小保持0.6* O' h' ?: p* W# B' f2 k

( p8 h; x/ T+ I) `5 l, l, W5 x
20190622160910729.png
. a3 d& w: \# A

% K0 J6 g- m# c; o3 }8 L所以将IIC延时函数定时为2us可以满足所有时序。(一般支持最高速度400k的IIC设备,基本都可以使用2us延时。)! \' O8 }& N0 m: v5 C

- w7 N" g' J% \
  1. //控制I2C速度的延时
    : [; p6 p- R! g. }
  2. void CT_Delay(void)) O1 e: R2 I4 s- c8 Z
  3. {* N7 ^* v- L' V: M
  4.         delay_us(2);9 c# Y7 F. o1 F+ B
  5. }
复制代码
) y8 \6 h2 M1 {, G
2. 数据传输 与 ACK时序
& E" _# b% u/ @& B8 e5 A% w- [: L1 |& n+ E: ~( f2 e' C$ O
下图是ACK时序与 传输数据0的时序图,这两种时序图是一样的,区别在于ACK是在8个数据时序后产生,且SDA电平是由接受数据端拉低的。
7 U; W6 l3 a, |
0 Y% w# i9 U3 _6 B4 Z' C- b
20190622161607756.png

0 f( c; G1 Z# z- h9 i3 K) h9 Y( C+ q& ^6 a: g+ y" i8 s8 a6 l
产生ACK时序:在SCL高电平期间,SDA为低电平状态。
( G/ h3 H3 p$ I  k9 P  D
  1. /***************************************************************************************) q8 j: ~' h- h* R3 L
  2.   * @brief  产生ACK应答,
    # m. s0 E* J; ?. S" V0 M
  3. ***************************************************************************************/' P; O: }9 ^2 P- k2 D( b5 l
  4. void CT_IIC_Ack(void)
    & |& W, l0 P/ `4 h* \4 b1 C* w2 L. k; h
  5. {+ P3 g. P3 g8 P. P
  6.         CT_IIC_SCL(0);
    1 Q! k$ |* b2 ?3 ]9 X
  7.         CT_Delay();0 Y$ o2 y) a8 i5 x5 U$ J
  8.         CT_SDA_OUT();
    0 ]- K8 w8 t4 w; q4 T1 g( ]
  9.         CT_IIC_SDA(0);
      @$ G" _* H' n: v
  10.         CT_IIC_SCL(1);1 f0 w0 M( ]; P
  11.         CT_Delay();
    ' ]2 K# e, y2 p, h
  12.         CT_IIC_SCL(0);0 b' @2 E$ D( e+ J! I7 E4 L
  13. }
复制代码

$ f! ^. ?1 W0 I" K& W等待ACK时序:拉高SCL与SDA后, 然后设置SDA为输入检测状态,等待接受数据端拉低SDA
, v+ V) X+ b) q' O
  1. /***************************************************************************************
    ( P! b+ X; z7 o
  2.   * @brief   等待应答信号到来,等待接受数据端拉低SDA/ v. t5 N6 I3 v1 X
  3.   * @input   
    : {6 \: O) Y4 z7 G2 z# g* `! k
  4.   * @return  1,接收应答失败 ; 0,接收应答成功$ F4 P/ @5 E3 K4 a5 r; A5 h$ M
  5. ***************************************************************************************/
    4 }  ?  C; x( N' g7 r
  6. uint8_t CT_IIC_Wait_Ack(void)
    4 w1 Y: [1 K7 Q' a& w, k' ^: I( [
  7. {2 a5 ^9 L! ]! a, Q" F+ H
  8.         uint8_t ucErrTime=0;
    , x) }1 N2 f3 ^% g
  9.         CT_IIC_SDA(1);           - V2 I. N# f" A0 N& U
  10.         CT_IIC_SCL(1);
    / k/ \1 b% L$ l
  11.         CT_SDA_IN();      //SDA设置为输入  
    % i, f6 k7 Z. v" y4 o
  12.         while(CT_READ_SDA)4 t! ?2 B: N" r+ @
  13.         {- T* {6 }% L" v5 R
  14.                 ucErrTime++;
    # f% R7 F  w- Z! D
  15.                 if(ucErrTime>250){1 g4 K. q7 J6 g- I* E; Y1 z- V7 {
  16.                         CT_IIC_Stop();
    2 K9 ^( C4 ?( h
  17.                         return 1;
    ) n) ^6 `! d. Y$ x3 t: ~
  18.                 }& F6 d3 X: u/ h4 @. s
  19.                 CT_Delay();
    ( r8 r3 `1 M% b" a
  20.         }; @: X, X! J( f
  21.         CT_IIC_SCL(0);
    ) |0 D- T1 z, {7 I
  22.         return 0;  
    ' j/ ^' y4 n+ Z0 ?$ ]9 g2 F
  23. }
复制代码

! k2 o# a/ f9 h! F! j4 `下图是nACK时序与 传输数据1的时序图,这两种时序图是一样的,区别在于ACK是在8个数据时序后产生,且SDA电平是由接受数据端拉低的。
% h7 Y5 ?+ I9 K( j5 `
' w, s8 ]+ z: X: l. T: M/ T- p
20190622164227486.png
) E, M; C7 }+ N2 ~% f* @* N' F* j

9 e: Q% t( ~# p) ?9 T" Q; y产生ACK时序:在SCL高电平期间,SDA为高电平状态。( @* r4 e" k. v9 e
  1. /***************************************************************************************" l, r" w! A3 _
  2.   * @brief  不产生ACK应答        2 `9 n" F+ }( u% n. z. d
  3. ***************************************************************************************/) u2 s# r+ W6 X# K. U( U8 Q1 q
  4. void CT_IIC_NAck(void)9 u. s% g! K; [' q+ ~* ]
  5. {
    * g+ b) a4 O* Q- O- j1 v& j/ g
  6.         CT_IIC_SCL(0);+ x% c8 U) j7 k0 ]3 Z' Q
  7.         CT_Delay();# q# K/ D4 K4 U8 a& T1 Z$ l% p
  8.         CT_SDA_OUT();! r+ N( @2 i# w! s2 k  E& ^3 M. m, i
  9.         CT_IIC_SDA(1);0 _( L/ t, w- o2 i6 d, h
  10.         CT_IIC_SCL(1);7 _# |9 G  P3 X& i! a) }
  11.         CT_Delay();
    ( D1 k- L3 Z- G$ F/ C; a- l3 X
  12.         CT_IIC_SCL(0);+ m5 \+ C$ L2 `% }3 M7 M& u; O7 ?
  13. }
复制代码
5 H4 f) r* R/ N& N
发送一个字节函数,优先发送高位,即从bit7开始发送。8 U9 E, ~6 _/ p, ]% M6 n5 m2 l% n" R
  1. /***************************************************************************************
    + ~" ?2 a- x6 d
  2.   * @brief   IIC发送一个字节,
    2 n' z' _; K- f( u8 r: T
  3.   * @input   
    & s2 r0 D1 }7 h
  4.   * @return    B6 n6 U" A: X& z
  5. ***************************************************************************************/2 f. U% Q3 N& T+ y7 T7 F
  6. void CT_IIC_Send_Byte(uint8_t txd)
    2 U) e1 `% E+ g8 b
  7. {
    & r, ^; n1 n& g. N/ n9 g( t1 f3 t
  8.     uint8_t t;   9 w9 D: r: r* I/ Y7 y+ ], G  D& i' z) B3 ?
  9.     CT_SDA_OUT();             0 x# V4 O% j. B: ?
  10.     CT_IIC_SCL(0);//拉低时钟开始数据传输
    . R4 \( i8 _, c" m! i
  11.     CT_Delay();+ Q* G& K3 h' F0 f
  12.     for(t=0;t<8;t++)8 k; H/ Q: M) @( z1 t
  13.     {
    ; p% V% w7 F  y5 D  N
  14.         CT_IIC_SDA((txd&0x80)>>7);//发送bit7位+ x* e6 Y. a5 U& A) E
  15.         txd<<=1; //将txd的次高位左移到最高位              
    8 t' i* M2 \+ t' {, U
  16.         CT_IIC_SCL(1); # U. X& H3 ~. s! S, N5 Y% }' a
  17.         CT_Delay();
    ( P8 P% w+ T' g, _) K
  18.         CT_IIC_SCL(0);        
    ) Z: B" y; j4 F9 d* U* l! T
  19.         CT_Delay();1 H  [& c3 T! O# Q2 E2 W4 T
  20.     }5 q! u! `- x  _( [5 M& B
  21. }
复制代码

# K& G! E* D  ^+ P读字一个字节函数,接受到1bit数据后,将该bit放在bit0位置(通过receive++实现),如果还要继续接受数据,则将之前接受到的数据左移一位(通过receive<<=1实现),留出bit0位置接受新的数据。
! d9 Q' _  A3 G7 a6 D- U; y
  1. /***************************************************************************************
    4 w3 i: s' ]7 X! p7 g2 Q
  2.   * @brief   读1个字节" p# ]8 @! T* p4 d" \+ o
  3.   * @input   ack=1时,发送ACK,ack=0,发送nACK
    ' r% \% S2 `; Y# G
  4.   * @return  ( M! M' ]. g& M& O  O
  5. ***************************************************************************************/( k$ O; y. U4 B
  6. uint8_t CT_IIC_Read_Byte(unsigned char ack)
    5 X) B, X& _  l7 k
  7. {0 r4 \* e' a6 a& h, K
  8.         uint8_t i,receive=0;
    . T& y* H, Z; j4 L$ ^0 R
  9.          CT_SDA_IN();//SDA设置为输入
    % R: I& f% w' N7 `; t- q
  10.         CT_Delay();8 I6 [1 a+ ^* [
  11.         for(i=0;i<8;i++ )5 h" v5 T; B9 E& y, ]
  12.         {
    + l( a$ W$ Q  u* C2 t
  13.                 CT_IIC_SCL(0);                        
    ! @, b9 W, ~5 y/ P" S/ f% \
  14.                 CT_Delay();
    0 q1 |0 P) Q- `: ~6 O* o4 N5 Y
  15.                 CT_IIC_SCL(1);         
    ; L( L+ V" K3 p2 X4 e
  16.                 receive<<=1;8 X' ?* ?: ~3 d: G3 ^, W
  17.                 if(CT_READ_SDA)receive++;   % |- ^. e2 e" N
  18.         }                                          
    ; g0 b, o6 D, o" h4 E( h
  19.         if (!ack)
    + w5 ?7 o1 s  e6 y* |
  20.         CT_IIC_NAck();//发送nACK6 k5 I! q/ P% V9 l7 ~' B' J
  21.         else 8 J# |: l- g2 C5 R+ ?2 f: E
  22.         CT_IIC_Ack(); //发送ACK   & d: ^! s+ R, b' _( `- P! I# K
  23.          return receive;* t4 j; E! [+ C% I( W" [3 e
  24. }
复制代码

) h! z: `: j  U6 b8 a三 GT9147电容触摸屏控制芯片驱动/ ^0 e" K7 }  K# z4 K5 I
1. GT914内部结构框图如下图所示
2 O# H( S4 B6 m0 b! Z! M. t4 Y- p4 s& g5 M- i
2019061913180610.png

1 z3 r& r- M/ `
* }6 a  n7 B9 q# ?
5L5)3BWQK[DM1E_`8%S}J0F.png

& i( P; C3 {- X: b% h5 G
4 V, P0 g' s# S: X4 _; ]1 K2. 上电流程
; X, g4 q. p1 {% h
( f( M. D0 U" F$ dGT9147上电初始化流程如下所示:
# R9 s! m! P5 [( \5 s
1 b  W0 _* x7 C- p& s6 j3 @配置RST输出低电平,INT输出低(或者高)电平后,位置100us以上,此阶段配置IIC地址为 0xBA/0xBB(或者0x28/0x29)- \9 ~) ]4 S) l/ M+ U1 ?2 H8 |' _
接着配置RST输出高电平并维持5ms以上后,可以配置INT引脚为悬浮输入模式。
) R) b) f$ _( O( H等待50ms以上后,可以发送配置信息。( ]' q& o' t4 Y9 ?

- a8 j" D( J' d, G& f2 f' f
2019062113491579.png

+ I6 C, a, ?9 v2 E' r
8 }0 @$ Z+ \$ R4 L! z代码参考原子例程编写,贴上代码:
7 }  Z, k3 b2 F3 q6 I( o1 u8 [
1 `: T6 c+ Q$ ]6 z
  1. uint8_t GT9147_Init(void)0 z+ C- D% W. \: S; P9 d! E! \  Q) s
  2. {
    ( Q5 S  e7 @7 H; U" ?  d
  3.     uint8_t temp[5];
      P3 d4 V5 U7 Y' O. k8 Q

  4. & h9 y0 h7 Q8 F8 O4 ?! Q
  5.     GPIO_InitTypeDef GPIO_Initure;" T: V) R' r+ Q- q: B% o* m
  6. , e. N% D" v8 F) t* W5 Z& T* ~% K
  7.     GPIO_Initure.Pin = GPIO_PIN_7;          //PH7
    ' w4 k2 m9 T2 a7 w
  8.     GPIO_Initure.Mode = GPIO_MODE_INPUT;    //输出6 a6 P5 h2 ]6 H- I5 S
  9.     GPIO_Initure.Pull = GPIO_PULLUP;        //上拉
    ' _/ X; `+ ~/ K) d
  10.     GPIO_Initure.Speed = GPIO_SPEED_HIGH;   //高速
    6 Y8 C& A- |+ n* B! g$ I+ y
  11.     HAL_GPIO_Init(GPIOH, &GPIO_Initure);    //初始化* I0 }9 X) U, o$ U5 U. Z
  12. ' S& V: n" U# f# j& W
  13.     GPIO_Initure.Pin = GPIO_PIN_8;           //PI87 z4 k% N! e$ e" @: t- i! V
  14.     GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP; //推挽输出" {, \6 K6 ~- w5 m& q! u
  15.     HAL_GPIO_Init(GPIOI, &GPIO_Initure);     //初始化
    5 g) p# v  |5 F4 K7 |- x$ D

  16. ! J( n2 h7 W7 P" M
  17.     CT_IIC_Init();              //初始化电容屏的I2C总线
    & o/ O& G2 V0 Q8 ?4 M
  18. 4 n4 ~4 B+ M4 c3 A1 i# R
  19.     GT_RST(0);                                //复位. Q* \/ n( ?/ E6 l
  20.     delay_ms(1);            //INT引脚电平维持100us以上
    9 U  N7 f( {8 G( }% q  I( y
  21.     GT_RST(1);                                //释放复位/ N0 |" T* e# r
  22.     delay_ms(10);           //释放复位后维持5ms以上,设置INT为悬浮输入
    . Y% g$ N2 {. g- p
  23.     GPIO_Initure.Pin = GPIO_PIN_7;
    ( N$ Y, |# n. K+ [3 M6 }& q
  24.     GPIO_Initure.Mode = GPIO_MODE_IT_RISING;3 D! u1 B8 Y/ ~- u1 T" D# O
  25.     GPIO_Initure.Pull = GPIO_NOPULL;
    / p/ N) s. {8 D% ]% l9 M) ^
  26.     HAL_GPIO_Init(GPIOH, &GPIO_Initure);    //初始化, A1 b6 I2 T) u: j8 Z- B  _$ d4 [( P
  27.     delay_ms(60);& s: c4 `' ~0 R+ Z; j/ X/ A/ R

  28. 1 ^  e) R6 w9 T) W7 Z) S4 N
  29.     GT9147_RD_Reg(GT_PID_REG, temp, 4); //读取产品ID
    ' v& I' J# y: l
  30.     temp[4] = 0;
    7 d& a. o8 S; \/ h$ P" V7 O
  31.     printf("CTP ID:0x%s\r\n", temp);        //打印ID
    7 f! g+ c/ d9 L) @  K' A( W( \+ z( N

  32. 3 {7 `' t* \+ E& f! h
  33.     GT9147_Send_Cfg(1);//更新并保存配置
    3 q: {: C0 `) i7 M4 z5 W
  34. - A0 J- [4 y4 A" w5 F6 M  O
  35.     return 1;8 r: j' `4 @, ]  {
  36. }
复制代码
( w3 w& `* N; \4 d- U
3. 读取坐标流程/ S& P0 s5 a9 c/ F( n$ |

, g) n3 v9 D! q" E& X6 h) i6 Y使用中断方式读取坐标,需要注意的是,如果不及时读取坐标信息会一直产生中断。GT9147的中断脚与STM32的LINE7中断线相连,中断回调函数如下所示。当按下触摸屏时,touch_x与touch_y分别保存触摸时的xy坐标;当松开触摸屏时,touch_x,touch_y赋值0xffff
, ~4 T8 }9 `: t& `7 h5 k, K/ @* M% \& X8 d  e% t* F4 y
  1. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
    3 {/ F. _. J2 \/ G5 d/ E1 ^, y
  2. {; X* i+ g7 [# y# x
  3.     uint8_t buf[4];7 I. P; M0 w1 _( Z$ s
  4.     uint8_t i = 0, mode = 0, temp = 0;
    ) X* f3 D  w. r1 Z8 d0 t8 _
  5.     uint16_t x[5], y[5];; [  t. q" I- C  |7 K
  6.     if(GPIO_Pin == GPIO_PIN_7) { //读取坐标, 否则会一直有INT脉冲- b: M$ L& E' b' ?1 W
  7.         GT9147_RD_Reg(GT_GSTID_REG, &mode, 1);        //读取触摸点的状态
    $ [# i$ v3 x+ q- q. B4 z# K$ J
  8.         if(mode & 0X80 && ((mode & 0XF) < 6)) //有坐标可读取+ ~% u2 F9 y1 N1 ~+ K3 \
  9.         {
    7 [# O! d+ e' y4 w- ]( r: M6 N2 m9 W
  10.             temp = 0;
    ! L1 @% G0 [! y6 e
  11.             GT9147_WR_Reg(GT_GSTID_REG, &temp, 1);//清标志+ K" Z2 L! z+ m: h5 a; X) `
  12.         }; ?$ Z! q/ c+ }; S: _7 T1 Q
  13.         if( (mode & 0xF) && ((mode & 0xF) < 6)) //判断触摸点个数
    2 ^& P. O- C% |1 p6 I
  14.         {" V+ y- [% U. @* k  ]( N$ c
  15.             for(i = 0; i < (mode & 0xF); i++)
    8 v; W9 s+ h* z# ?$ X3 w' X1 D# `
  16.             {
    5 n* D! L# |. ?" I
  17.                 GT9147_RD_Reg(GT9147_TPX_TBL<i>, buf, 4);        //读取XY坐标值
    ' }$ o; y) Z# e! ?" |
  18.                 </i>x = (((uint16_t)buf[1] << 8) + buf[0]);" V" V" V: a$ i
  19.                 y = (((uint16_t)buf[3] << 8) + buf[2]);
    / p9 g: }2 T( o: z
  20.             }
    4 j- s' H# D5 ]5 y! `1 i
  21.             touch_x = x[0];6 {. ^7 n, {# x+ B% @* i& C' C5 T
  22.             touch_y = y[0];
    ! @0 T1 h0 l+ j2 H* Q6 M7 R3 u% S
  23.         }
    6 }& B. v% `8 i5 R4 u) z1 j
  24.   ?; r1 l- g  n3 n# R" \4 h* _
  25.         if((mode&0x8F)==0x80)//无触摸点按下,xy赋值为0xffff
    6 l! N5 h# F' \8 a* P
  26.         {& Q$ W9 ^  @  {1 y
  27.           touch_x = 0xffff;& Z5 \5 P6 e  r
  28.           touch_y = 0xffff;
    9 A6 Y8 K! {, u
  29.         }& v. J* [/ `2 B# _/ N
  30.     }( Z3 m2 b7 u! |- s
  31. }
复制代码
4.主机 对 GT9147 进行读操作时序
. D8 {1 x# ?. H" p# Z
( S( F9 P# I, J8 h6 g
20190621161601926.png
. t5 j, P9 o3 S; Z+ X9 v3 v

2 d9 |: X5 x) G8 ?' O( u根据该时序图编写读寄存器函数如下:+ m5 f; ]3 i+ [7 S$ P4 \1 ]* P
# |4 Q0 [/ J: S0 o
  1. /***************************************************************************************3 o8 P1 Q4 a( F) K. T- N1 G% `
  2.   * @brief   从GT9147读出一次数据4 g+ Z$ q  D  @, a" t; I
  3.   * @input   reg:起始寄存器地址
    , S& N. r* v2 ~) E! `# X
  4.              buf:数据缓缓存区
    : T0 I& a' y5 I$ b# S  m
  5.              len:读数据长度        8 k2 p' q( R) x9 H
  6.   * @return  + ^# H, H8 Y' `" K
  7. ***************************************************************************************/+ G# @) T/ T" l/ B5 ^
  8. void GT9147_RD_Reg(uint16_t reg,uint8_t *buf,uint8_t len)3 l6 M; \/ h, o, x* P, m! ]+ E
  9. {
    * ~( f3 p& y( s4 N
  10.         uint8_t i; 6 c. C2 Q+ \. v* F% e! o: A
  11.          CT_IIC_Start();        
    + u7 y: o' R0 l* u0 t7 p( y
  12.          CT_IIC_Send_Byte(GT_CMD_WR);   //发送写命令         
      p! d) n3 s+ j
  13.         CT_IIC_Wait_Ack();
    % [- h4 b" m( \
  14.          CT_IIC_Send_Byte(reg>>8);           //发送高8位地址
    7 }- U9 @- w$ Q% i) f- `' G4 x
  15.         CT_IIC_Wait_Ack();                                                                                                               # q' x4 i% [% b. d; X+ u
  16.          CT_IIC_Send_Byte(reg&0XFF);           //发送低8位地址8 @# B* |* X' f
  17.         CT_IIC_Wait_Ack();  7 D5 ^' s% e  x. C$ n
  18.          CT_IIC_Start();                     
    ! Z/ Y* Y  Q& c: f/ y
  19.         CT_IIC_Send_Byte(GT_CMD_RD);   //发送读命令                  
    3 q. M3 B+ P3 S4 T: g
  20.         CT_IIC_Wait_Ack();           
    9 i: m6 [( S( B/ W* A5 @1 ^
  21.         for(i=0;i<len;i++)$ o& H. [% }; R$ ~
  22.         {/ c/ u# O8 ]# _8 l" |! r: B
  23.             buf<span style="font-style: italic;"><span style="font-style: normal;">=CT_IIC_Read_Byte(i==(len-1)?0:1); //发数据          9 v, E2 u5 L/ i: `8 N; r
  24.         }- o% _3 e3 j, F) @
  25.         CT_IIC_Stop();//产生一个停止条件    1 `& }* N9 G+ m+ _. e+ r  P
  26. }</span></span>
复制代码

# f. F0 V3 j1 ^* K5.主机对 GT9147 进行写操作时序7 _  Y/ s# x! B% W6 \

0 p8 X% a( C% e( }) _+ T4 q* C
20190621161509843.png
3 s7 {- i( d$ v" u6 W5 X

- ?; U3 ]4 T3 c- s3 V通过该时序图,编写写寄存器函数如下
8 e- D, D' h5 G. C; n+ \3 k7 I4 n0 R$ f2 y0 B7 H  S* k7 M
  1. /***************************************************************************************  W( j# q+ u" W5 x& z( Z! D
  2.   * @brief   向GT9147写入一次数据8 |8 N2 W  b( R) K, w
  3.   * @input   reg:起始寄存器地址;
    1 ~$ p8 ^$ M; _) Y+ r4 L! t- `; B; k
  4.              buf:数据缓缓存区
    - J1 ^) d4 i% ~4 n: K3 U; Q1 k
  5.              len:写数据长度( @8 L0 Y5 y! s% a' g) a
  6.   * @return  0,成功; 1,失败." N1 T) J9 W. ?7 D% E
  7. ***************************************************************************************/3 E- @- m3 z  L' ?: [# F
  8. uint8_t GT9147_WR_Reg(uint16_t reg,uint8_t *buf,uint8_t len)1 u4 T/ @2 ]2 t6 J+ e4 E
  9. {9 W7 |3 B9 A- R; u. `  d% E
  10.         uint8_t i;/ }+ o) I+ q) c+ |% `1 `
  11.         uint8_t ret=0;0 ^! D& S; e1 {3 [/ ]4 E6 O! W: t% H
  12.         CT_IIC_Start();        
    ( J6 F' @: c$ ?) U
  13.          CT_IIC_Send_Byte(GT_CMD_WR);           //发送写命令         
    : f; E5 n" A2 r: _# ]  Y! L* Z4 K
  14.         CT_IIC_Wait_Ack();9 t& z( z4 E; O) V+ g& ]
  15.         CT_IIC_Send_Byte(reg>>8);           //发送高8位地址# Q# n7 u' M. W( ]) `
  16.         CT_IIC_Wait_Ack();                                                                                                               
    1 `: M/ ]% g! u) _1 X  f8 U$ b
  17.         CT_IIC_Send_Byte(reg&0XFF);           //发送低8位地址$ h% R# ~! E. r% w$ p" ~2 f
  18.         CT_IIC_Wait_Ack();  
    7 U6 G' E' y+ H1 q
  19.         for(i=0;i<len;i++)
    * K1 a4 f' X- e2 z# w
  20.         {5 h0 B+ `- u5 q$ E
  21.             CT_IIC_Send_Byte(buf<span style="font-style: italic;"><span style="font-style: normal;">);          //发数据
    4 ~# A1 W% m4 v! D
  22.                 ret = CT_IIC_Wait_Ack();
    ( ]1 d+ w* d* G; S+ F
  23.                 if(ret)break;  / Q6 X* @& @1 f& v0 H
  24.         }
    ; S! W+ B  X4 l, T/ m
  25.     CT_IIC_Stop();                                        //产生一个停止条件            8 v, k  [0 I) U% o- T
  26.         return ret;
    9 f9 h9 V7 ^/ z" M% I$ b5 n8 O
  27. }</span></span>
复制代码

2 A2 C8 H) l) B, T: D% Z' c6. GT9147配置函数如下,GT9147_CFG_TBL针对分辨率480×272的触摸屏。
; l; `$ X# k. }9 d& _6 b
( {9 L) i! I+ b- ^配置寄存器时是要注意以下几点:0 j: r* Z- K" L6 G0 W( u, p

* M' r7 e8 l) \  y新的版本号大于等于GT9147内部flash原有版本号,才会更新配置.0 }) X; {1 r2 [" A( e% b! A. |
写完GT9147_CFG_TBL中的配置后,还需要往0x80FF寄存器中写入校验,0x8100寄存器中写1。
: b; m1 t1 q+ D3 @关于配置更详细的信息可以参考GT9147编程参考手册
( @8 |3 s2 [( z0 X& \( \7 {
  1. const uint8_t GT9147_CFG_TBL[]=
    7 j5 K$ u3 E# q& q1 {0 j
  2. {& V0 R( l; _4 R' Q8 A. y' P/ @
  3.     0x60,0xe0,0x01,0x10,0x01,0x05,0x0C,0x00,0x01,0x08,
    $ U9 e, E% B6 `! Y1 J( J
  4.     0x28,0x05,0x50,0x32,0x03,0x05,0x00,0x00,0xff,0xff,
    % ]# {- Z' c9 q+ A& O1 ~* z% X
  5.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x89,0x28,0x0a,
    9 `. s$ e" \  v9 I  N! U
  6.     0x17,0x15,0x31,0x0d,0x00,0x00,0x02,0x9b,0x03,0x25,' o& b$ j0 G$ f7 j
  7.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0x00,0x00,
    ' V+ V+ g2 h" ]' x/ Y8 X8 x
  8.     0x00,0x0f,0x94,0x94,0xc5,0x02,0x07,0x00,0x00,0x04,0 k2 q. O0 x' O3 I; f
  9.     0x8d,0x13,0x00,0x5c,0x1e,0x00,0x3c,0x30,0x00,0x29,
    5 ?3 p' W# }9 I2 d" N' i4 p8 Q
  10.     0x4c,0x00,0x1e,0x78,0x00,0x1e,0x00,0x00,0x00,0x00,3 J  y6 z* G! i8 h
  11.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,, s$ W# K% @" ~. N/ ~4 O
  12.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    - _" D+ K; f# c( {- N# i5 v
  13.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,. K  O9 ?* q* ~( K. B3 A
  14.     0x00,0x00,0x08,0x0a,0x0c,0x0e,0x10,0x12,0x14,0x16,
    & d3 ^3 f, i% r0 |( A" L
  15.     0x18,0x1a,0x00,0x00,0x00,0x00,0x1f,0xff,0xff,0xff,# G( P& V4 k. P9 x8 K$ i; f
  16.     0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
      f4 k* ]# T8 N1 e- _' M' h/ X6 @
  17.     0xff,0xff,0x00,0x02,0x04,0x05,0x06,0x08,0x0a,0x0c,
    - D- f( G4 c) U3 _5 `- @8 g" S
  18.     0x0e,0x1d,0x1e,0x1f,0x20,0x22,0x24,0x28,0x29,0xff,
    . W2 b$ B: d4 B3 C8 r
  19.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,! t* m1 r# g! ?, u5 J$ H
  20.     0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,; L' n3 f* _3 A0 J- ^" g& s
  21.     0xff,0xff,0xff,0xff,5 U3 S( p; d! o* ~, x. h
  22. };& L2 k- g! G5 G1 a5 Y

  23. $ g6 [7 c: b, I1 w8 b' q
  24. uint8_t GT9147_Send_Cfg(uint8_t mode)2 ?: {0 J& Q" d/ Y2 }. ^
  25. {8 G8 R5 {2 d8 t" |. Y* [  a/ M
  26.         uint8_t buf[2];. S, d! Z8 g; M
  27.         uint8_t i=0;' e3 b# @2 K# u6 w0 `0 Z3 W, Q
  28.         buf[0]=0;' T# A- i. M5 f' f. y5 T& A( @5 X6 N
  29.         buf[1]=mode;        //是否写入到GT9147 FLASH?  即是否掉电保存, z( |. d4 Q; r) I) n" B7 \- N
  30.         for(i=0;i<sizeof(GT9147_CFG_TBL);i++)
    2 y) c# O2 c# m, Z
  31.             buf[0]+=GT9147_CFG_TBL<span style="font-style: italic;"><span style="font-style: normal;">;//计算校验和
    1 ]2 v& B9 `, h) H3 d0 O
  32.         buf[0]=(~buf[0])+1;
    : N. h; u* ]8 v+ F- [5 M
  33.         GT9147_WR_Reg(GT_CFGS_REG,(uint8_t*)GT9147_CFG_TBL,sizeof(GT9147_CFG_TBL));//发送寄存器配置9 y, W0 N' [8 d+ @  f
  34.         GT9147_WR_Reg(GT_CHECK_REG,buf,2);//写入校验和,和配置更新标记) e# I6 V2 s2 c6 z/ |
  35.         return 0;5 Y- K  J8 G% G3 a
  36. }</span></span>
复制代码

: ?3 w7 V3 T! n) L' l( n
四 移植触摸屏驱动到STemWin
& F& [* @2 h7 g+ a, Z. [这里假设已经成功移植了STemWin到STM32F7工程。
" d' P# \  g% w/ \1 d" c" Z% o; b) p
1. 在GUIConf打开STemWin触摸屏驱动宏
5 N4 b& X7 H6 e, w  K
6 J, S! k* v- R$ z1 h0 @# |- Y
  1. #define GUI_SUPPORT_TOUCH       (1)  // Support touchscreen
复制代码

8 d, G* G" ?# Y: l2. 新建GUI_X_Touch_Analog.c文件实现以下四个函数,在第三章第3小节我们知道touch_x,touch_y表示当前触摸的xy坐标。整个文件的内容如下所示。: t: F& O( x5 H- R9 R, A* q
8 D) `2 z* E  Z
  1. void GUI_TOUCH_X_ActivateX(void) 3 X5 R- q/ Y+ Q: M
  2. {# d" t2 |2 u% J* c
  3. 2 m) V- H. I4 b- j2 @* ^7 X
  4. }
    7 r* G2 J- H+ N/ S, ~1 m

  5. , G& L: J$ M' h* l2 a) \* G
  6. void GUI_TOUCH_X_ActivateY(void): x- g2 k& Q9 x% K9 L+ k7 J& B0 [+ u
  7. {
    % y/ {& ~' v- k

  8. $ V* `* w: j! B3 x3 Z$ d
  9. }
    8 m2 _, w  F) G; ~* J

  10. $ ]* Y1 d, v% f5 d7 i3 n
  11. /*获取x坐标*/
    ) y$ s8 [5 |- D
  12. int  GUI_TOUCH_X_MeasureX (void)# R! K/ B3 @7 N
  13. {' j0 |, p3 T, g% g
  14.   return touch_x;
    ; [4 V3 i6 A. q5 x' Y( h$ L
  15. }( @# o* ?% Y& S' s* D
  16. 6 i; Z2 |" H( ^7 W0 v! F
  17. /*获取y坐标*/6 e# a2 ]/ t; Z0 r
  18. int  GUI_TOUCH_X_MeasureY (void)' B0 g3 \% h: D- N+ k! _, x, O
  19. {
    5 d( a4 ~6 p& K% K! u
  20.   return touch_y;
      [% t- v$ d7 k, o
  21. }
复制代码
& e4 U& Y  E8 J5 _
3. 使用GUI_TOUCH_Calibrate函数校准x与y值,然后才能调用GUI_TOUCH_Exec()函数处理触摸事件。( L4 X+ W/ U  s
" j& p$ l$ y6 `6 I6 r
  1. void StartTouchTask(void const * argument)
    , H3 h; g" g( [, X. C' o0 ]% B4 q
  2. {8 _( N7 X0 ]9 h; r
  3.   /* USER CODE BEGIN StartTouchTask */
    7 v4 N5 a3 g$ O1 }# w
  4.   GUI_CURSOR_Show();//显示鼠标指针
    # n5 A- }$ z+ E$ u9 J
  5.   GUI_TOUCH_Calibrate(GUI_COORD_X,0,LCD_WIDTH,0,LCD_WIDTH);   
    3 l7 @8 Q( D3 ?! R+ c
  6.   GUI_TOUCH_Calibrate(GUI_COORD_Y,0,LCD_HEIGHT,0,LCD_HEIGHT);
    8 I  ^0 z( S. L& A" G5 ]' W6 }
  7.   /* Infinite loop */4 L! R* f( X* I$ r  f
  8.   for(;;)+ R5 n# e5 \1 A6 G
  9.   {
    7 }' X5 l! }* |/ h
  10.     GUI_TOUCH_Exec();( X. S" ]  t6 p9 Y
  11.     osDelay(5);
    . X4 v& _. _% j$ o
  12.   }- z# H$ F3 X1 W, ^1 ^+ E
  13.   /* USER CODE END StartTouchTask */
    - E; l8 ~) I$ u& q( L3 D
  14. }
复制代码

' m3 Q1 ~) L) O* W9 a( G6 k: v3 P, \  _7 T8 O
7 v, i; Z1 x7 A4 J

4 M7 y! h' Z" W1 f8 ~
赞 收藏 评论0 发布时间:2021-12-17 12:05

举报

0个回答

所属标签

相似技术帖

官网相关资源

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