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

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

[复制链接]
STMCU小助手 发布时间:2021-12-17 12:05
一  电阻驱动与电容驱动原理
0 U: M& H9 ?. n! p9 T) g: w3 z' H! P1 p2 k( a) T. s( U
1. 电阻屏等效电路如下所示, 当产生按压时:
3 L# E# j% X0 K( H  c" m" G
X-接地,X+接电源,Y+接ADC输入.通过读取Y+的电压以及电阻分压原理,可以得出触点的x坐标/ w! J; X, z! Z2 s. K
Y-接地,Y+接电源,X+接ADC输入.通过读取X+的电压以及电阻分压原理,可以得出触点的y坐标
! o  H) Q$ J# |  w$ O' {5 d6 o9 f( f/ k7 d( V9 k
2019061911075212.png

% r% c6 A, S2 Y# X# R
( A+ b) p: b- n8 F2. 电容屏等效图如下所示, 检测原理类似矩阵按键, 当产生按压时:
! K+ U  u3 r1 J- N+ j6 L5 q: _. }+ K* z# c
X轴产生从上至下依次产生激励信号(AC交流信号), Y轴电极同时接受信号 (该激励信号是交流电,可以通过电容穿到Y轴).
8 a* {& j3 \4 d" N' L& n2 t( N5 ^& a$ g5 f6 I1 o
假设有如下两个按压点(分别位于(1,1)与(2,2)的位置),检测过程如下:+ G4 I5 y# M, t4 v; C
当X1产生激励信号时,Y1接受到的交流信号产生了变化, 所以可以确认(1,1)处有触摸.
/ Z" l) `0 r/ |2 W' ?& h接着当当X2产生激励信号时,Y2接受到的交流信号产生了变化, 所以可以确认(2,2)处也有有触摸.6 v. V1 h8 e) Z+ r# [7 K& P

5 b' G$ q/ ^9 x( o
20190619115448553.png

3 Z( W2 i1 P5 w/ {" y( L; Y1 h8 \  R. b. {2 l3 ~
二 软件模拟IIC4 C; p$ d  z6 [) e2 r8 _
由于stm32的硬件iic有各种各样的问题,所以采用软件模拟IIC的方式,主要实现IIC起始信号函数、IIC停止信号函数、等待ACK函数、产生ACK应答函数、不产生ACK应答函数、发送字节函数、读字节函数
4 y  N( B) W: j+ [  @+ b$ B. N" _( S' Q
1. 起始信号与停止信号! A1 j! M. c& x" p; `0 X/ j
" B4 ?/ t2 y9 V$ X' s. d. W
下图是IIC起始信号与停止信号时序图,通过观察该图编写起始信号与停止信号函数。
( N/ ?% G; ], J5 ]) @5 S1 s! q
( e7 Q3 K$ [% e2 h3 m% |5 I1 s
aHR0cHM6Ly9pbWFnZXMwLmNuYmxvZ3MuY29tL2Jsb2cvNDcwOTA5LzIwMTMwNS8yODE2MzczMy01MjE5.png

7 A0 S7 E5 R/ s, A; \
+ k4 N2 _  O; ^1 ]$ m' p* g起始信号:当SCL为高期间,SDA由高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号。9 {% `+ N# i! E* v; E. @; E0 O, \: X
  1. /***************************************************************************************1 l: h2 B9 _$ O: i
  2.   * @brief  产生IIC起始信号,当SCL为高期间,SDA由高到低的跳变
    . E4 m/ W) q3 m1 F
  3. ***************************************************************************************/
    0 \) r" S' p' ?) @2 K* r& _
  4. void CT_IIC_Start(void)
    - a; G0 c' W- F& n  R! H, g( O
  5. {
    9 N4 U4 {$ O4 B# d+ M! Y
  6.         CT_SDA_OUT();     //sda线输出* g2 p* g/ b1 U0 m# q: M6 J
  7.     CT_IIC_SCL(1);/ r: d) n- o" x7 u. m! W. O
  8.         CT_IIC_SDA(1);                    
    " p/ Q- J0 b0 |
  9.         CT_Delay();
    0 K9 a" e0 V3 Y) \+ m  J" Z. y
  10.          CT_IIC_SDA(0);
    ; j# I0 l% S$ A4 G* j
  11. }
复制代码

2 P# b' \4 X' @' _停止信号:当SCL为高期间,SDA由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。
' H$ n' B  e6 v/ V
  1. /***************************************************************************************7 _! n4 O# v  c5 z
  2.   * @brief  产生IIC停止信号,当SCL为高期间,SDA由低到高的跳变4 |6 R9 ]2 p! h* b% A! v+ D
  3. ***************************************************************************************/& D9 C) H$ ]* g
  4. void CT_IIC_Stop(void)
    , H* `0 M' ^1 r3 c" t/ W* L
  5. {; K, O; e; X$ T. g- D6 S5 \- o! W
  6.         CT_SDA_OUT();//sda线输出
    1 F/ O2 e' B( X% H
  7.         CT_IIC_SCL(1);5 ^8 R2 w" Q' B. L
  8.         CT_IIC_SDA(0);//STOP:when CLK is high DATA change form low to high+ W4 a# B3 `2 P2 C5 K' K
  9.         CT_Delay();; ]9 @) r2 B4 |3 y7 m9 ~
  10.         CT_IIC_SDA(1);
    $ e/ H( E/ U: z7 G6 A! z
  11. }
复制代码

7 F6 u3 j3 ~: A在GT9147数据手册中可以发现如下截图所示内容,SCL在低电平期间至少保持1.3us,其他电平最小保持0.6! ~' {" M- u# v- Y% t& v- E- _5 Q
$ n4 Q' w* B' l1 C% w
20190622160910729.png
8 T, k) {6 y, o% _

! F0 o& G' ~. k) N* Z所以将IIC延时函数定时为2us可以满足所有时序。(一般支持最高速度400k的IIC设备,基本都可以使用2us延时。)
' D9 M1 R8 g6 Q! P
2 Q' u% h& Y. ~& g, _9 s& E$ L
  1. //控制I2C速度的延时5 i8 |6 @  H/ e+ l) \8 G
  2. void CT_Delay(void)
    # k% X* Y% Q! `' y
  3. {, x/ O& k! w6 d! s
  4.         delay_us(2);
    - K0 y" {7 e' q' |# l. X
  5. }
复制代码
! j, v. w: N1 s1 F
2. 数据传输 与 ACK时序6 B# j: E9 m4 @, X, e
7 `! M$ c! F: ~5 n. u
下图是ACK时序与 传输数据0的时序图,这两种时序图是一样的,区别在于ACK是在8个数据时序后产生,且SDA电平是由接受数据端拉低的。& m2 |9 i1 l. q( C; n' _5 G. {! d
& Z: j# r1 r, ^) R" M5 w# T
20190622161607756.png

4 [" y* v5 U% u8 [; T
, O' }3 S) e! A; R3 ~( w产生ACK时序:在SCL高电平期间,SDA为低电平状态。' t9 H) X$ e9 B* u, u: O
  1. /***************************************************************************************
    ' W$ r3 q3 `+ s. ^- p8 Z
  2.   * @brief  产生ACK应答,2 u8 l, G  \7 ]" t
  3. ***************************************************************************************/* o8 T8 L* c& |
  4. void CT_IIC_Ack(void)* T( u& z% t9 x% ^% C) z
  5. {. q9 X4 q3 k; h
  6.         CT_IIC_SCL(0);
    3 z2 {+ R  v9 B# b+ c
  7.         CT_Delay();
    3 q1 Q! b- g* O) D
  8.         CT_SDA_OUT();
      ~. ]9 U  ~7 [4 p
  9.         CT_IIC_SDA(0);+ |7 s+ @( }# v5 Z
  10.         CT_IIC_SCL(1);9 W+ L1 r. y! f! u3 ~& o
  11.         CT_Delay();
    0 X# x9 S& l( {0 J8 @( K0 B
  12.         CT_IIC_SCL(0);3 X- t8 g2 b7 I9 c
  13. }
复制代码

* `+ y$ X+ l/ [) g等待ACK时序:拉高SCL与SDA后, 然后设置SDA为输入检测状态,等待接受数据端拉低SDA& E) Y8 J5 v5 \6 {
  1. /***************************************************************************************9 W( X# C4 V/ W) n8 ]; e
  2.   * @brief   等待应答信号到来,等待接受数据端拉低SDA
    1 a7 s8 p3 ~" y  W  e4 M3 d
  3.   * @input   6 b  l! ^! x! l* p+ F
  4.   * @return  1,接收应答失败 ; 0,接收应答成功' t" z5 P' L5 j* b7 A# b6 t6 S+ ]
  5. ***************************************************************************************/
    # Z$ @3 M$ S0 Z' h) L
  6. uint8_t CT_IIC_Wait_Ack(void)
    ; I; u7 Q7 m) r' U
  7. {6 D8 B3 E. e: |( {
  8.         uint8_t ucErrTime=0;+ e6 \! P; ~2 m1 h8 b. W
  9.         CT_IIC_SDA(1);           
    2 |  o$ R( q  B9 \9 C' Z; z5 Z
  10.         CT_IIC_SCL(1);8 l8 M+ N- k' o6 W
  11.         CT_SDA_IN();      //SDA设置为输入  * S- \. n. m+ N+ b9 I
  12.         while(CT_READ_SDA)
    2 L# y/ Z/ R; A$ y% J: W. C/ K6 I
  13.         {
    : z$ d& W5 T. o0 p8 B
  14.                 ucErrTime++;
    5 ^0 o6 ]' T' }+ A5 ]0 s
  15.                 if(ucErrTime>250){$ I7 Q8 r3 q: M; M. x' |
  16.                         CT_IIC_Stop();
    ) q" A( Q% v+ v' U% d  G
  17.                         return 1;& U4 w! [0 a; j
  18.                 }" c5 v! }$ C7 C; X) S
  19.                 CT_Delay();4 V$ w* W0 T" c! f# F9 t
  20.         }- I, I7 n- \1 i5 z1 a. f
  21.         CT_IIC_SCL(0);
    5 Z' I) T+ H  P; |
  22.         return 0;  
    4 B& Z6 z& ~7 O5 Y9 o7 y. l1 G' c
  23. }
复制代码
5 _: h) I2 p* n$ P
下图是nACK时序与 传输数据1的时序图,这两种时序图是一样的,区别在于ACK是在8个数据时序后产生,且SDA电平是由接受数据端拉低的。
1 H6 E8 H; q8 u$ e* L- w: B& r  `
& z. T- d. W( F6 G, ~! z7 Z
20190622164227486.png
0 B5 p9 Y. O2 \7 F2 q/ S  h
8 o8 p3 P+ Y) `  K5 L: u! `" X
产生ACK时序:在SCL高电平期间,SDA为高电平状态。
: g  a" i7 H+ g; e* {
  1. /***************************************************************************************  [0 _4 M) G9 H2 u
  2.   * @brief  不产生ACK应答        7 R, v6 t3 n" H1 Q" _) ]6 B
  3. ***************************************************************************************/( Z: K4 @! i' r! @# i& f* l, `* l# n
  4. void CT_IIC_NAck(void)
    6 V/ V- ~7 [  D, d4 A
  5. {) ]; t) ?& n- o: M
  6.         CT_IIC_SCL(0);
    : }  L  |) c' T' _
  7.         CT_Delay();
    " X7 O0 L0 `+ z$ ^
  8.         CT_SDA_OUT();, X' C  `- [, \% h6 t! w" X
  9.         CT_IIC_SDA(1);
    " b& X: s/ W' ]* b6 o4 T/ J8 S
  10.         CT_IIC_SCL(1);$ z+ p2 }; F/ P1 v# B: Z/ f2 k
  11.         CT_Delay();% U- M, p/ ~3 v+ [  L
  12.         CT_IIC_SCL(0);
    + a4 a( |. |8 m0 k5 K, K4 v
  13. }
复制代码
1 u& \  w; h* [: |3 N
发送一个字节函数,优先发送高位,即从bit7开始发送。
: J4 F7 C! n8 n( G& [3 L+ N
  1. /***************************************************************************************
    0 l& @' h# L1 `& Q4 X: s
  2.   * @brief   IIC发送一个字节,6 E- `( I6 d8 \5 k, V
  3.   * @input   
    8 I. y" x% j% M- P) ~0 W
  4.   * @return  
    * s0 Z7 w. g1 y! ]
  5. ***************************************************************************************/
    2 V+ V+ a! S  d" Q6 ~
  6. void CT_IIC_Send_Byte(uint8_t txd)1 E! X8 z7 B, }
  7. {' W3 D/ p# g/ |% R1 D; f! r3 c
  8.     uint8_t t;   
    * b* t" T. k  y. }" b. f3 i% R$ J
  9.     CT_SDA_OUT();            
    4 e/ X5 [: B8 n
  10.     CT_IIC_SCL(0);//拉低时钟开始数据传输
    3 W; B/ `, }5 y# B! C
  11.     CT_Delay();
    ; D, k" Y3 ?0 m3 q; v" a' T  p
  12.     for(t=0;t<8;t++)
    ' o2 g4 z7 p* s+ `4 s' n
  13.     {7 a: ?* t. d/ \5 S  t
  14.         CT_IIC_SDA((txd&0x80)>>7);//发送bit7位
    ; D! b3 W% D1 q( ~6 I; S( G
  15.         txd<<=1; //将txd的次高位左移到最高位              
    ) J/ L. w2 `  C; Y( ~
  16.         CT_IIC_SCL(1);
    2 u8 }( M& V! z4 j$ q
  17.         CT_Delay();) e3 L* r) @. f9 I
  18.         CT_IIC_SCL(0);        : @8 t! |4 b2 u7 j6 w
  19.         CT_Delay();) V- A% L) g: z! H4 H; Q
  20.     }5 Y3 t- H3 x$ m: M5 }. o5 E, t4 ^# y
  21. }
复制代码

6 |; \2 T' q7 T- A2 F. r7 r读字一个字节函数,接受到1bit数据后,将该bit放在bit0位置(通过receive++实现),如果还要继续接受数据,则将之前接受到的数据左移一位(通过receive<<=1实现),留出bit0位置接受新的数据。
5 j% T/ H3 C) t: o* g
  1. /***************************************************************************************
    $ N% z: }9 u$ G6 l9 T
  2.   * @brief   读1个字节/ F" \5 E1 {8 |; o0 i' L
  3.   * @input   ack=1时,发送ACK,ack=0,发送nACK
    " E. H/ D2 _6 l
  4.   * @return  8 R7 i0 r" a9 ]+ D/ ]: a4 Z
  5. ***************************************************************************************/" z$ p. F- x6 F3 n
  6. uint8_t CT_IIC_Read_Byte(unsigned char ack)
    # n# [0 ~+ f) d5 ]" t
  7. {$ J5 o* T4 i/ ]' [
  8.         uint8_t i,receive=0;8 q$ {3 ?0 C( N: n: K
  9.          CT_SDA_IN();//SDA设置为输入! o4 ^) E; ~0 W0 `1 [- x
  10.         CT_Delay();
      \9 F8 r, q. @0 a0 d- v5 w
  11.         for(i=0;i<8;i++ )
    9 r1 O$ {- s2 y* x  r$ D
  12.         {
    5 K. e2 D9 z% X$ ~' l# I
  13.                 CT_IIC_SCL(0);                        
    ; _# W+ H* j6 q: C) W/ k) n7 G
  14.                 CT_Delay();& y+ g9 [3 C* I0 Z0 k/ |
  15.                 CT_IIC_SCL(1);         - Y4 D+ P! R+ V% `! m- `- Y% n
  16.                 receive<<=1;
    1 e; U& j9 p/ m% o! O
  17.                 if(CT_READ_SDA)receive++;   5 l! g) @2 ^# a$ o; T1 o9 [
  18.         }                                          
    ) H+ X- K; j9 M1 }) I6 a
  19.         if (!ack)) M% Y1 n2 o& Q' n+ [
  20.         CT_IIC_NAck();//发送nACK/ W6 P- C2 O4 B
  21.         else
    * z8 v5 y( r) g0 e. I5 l. Z9 r
  22.         CT_IIC_Ack(); //发送ACK   
    ' I/ ]/ a+ t/ ~9 e: \2 P3 f
  23.          return receive;
    + ]: ~5 u) y1 J- c& y7 V" M- _! x/ U
  24. }
复制代码
; G  M( Q( B) H2 X
三 GT9147电容触摸屏控制芯片驱动
! {/ v  x7 R$ z7 _/ Y1. GT914内部结构框图如下图所示
- T6 j" f- K: T( s" J8 L3 e4 E6 h" m' W- Y1 s2 w: c
2019061913180610.png
5 |0 \* D* q# I1 F6 o$ k3 i

8 K, K9 g' `; H1 L5 T
5L5)3BWQK[DM1E_`8%S}J0F.png

* z7 k7 ~) c5 \2 o. t. s* i1 v2 x+ d: }! a5 i  ^: m, ?4 C+ ^0 Y( t' _
2. 上电流程/ X4 X& o- L' t- P) d$ x! O
4 j9 M' {* ?/ @! N8 T
GT9147上电初始化流程如下所示:. v6 d+ {9 r& O! l$ r

/ A) \9 u5 I# }; ^+ k' H配置RST输出低电平,INT输出低(或者高)电平后,位置100us以上,此阶段配置IIC地址为 0xBA/0xBB(或者0x28/0x29)4 h' |6 Y& T& J- L* F; m. G, e
接着配置RST输出高电平并维持5ms以上后,可以配置INT引脚为悬浮输入模式。" G9 F6 Y2 ?9 f( c
等待50ms以上后,可以发送配置信息。* Q( j( U/ v: p0 W( L% n$ S2 h

& u+ q8 s( a7 O. E: d/ P/ R1 _$ _
2019062113491579.png

4 l* ]9 P2 e* g
; R8 i; P$ Q3 W: \8 {代码参考原子例程编写,贴上代码:* v! ]; U" L/ H+ C
* k$ X# H$ @5 x7 n2 }  D
  1. uint8_t GT9147_Init(void)
    9 q/ y5 R- b7 G8 d- r
  2. {
    6 j, ^: `9 P) r1 v1 p
  3.     uint8_t temp[5];
    + A$ t; `" l) j. }
  4. 0 _  j  A. L& c  \/ N% Y4 C. P. ?
  5.     GPIO_InitTypeDef GPIO_Initure;
    " i3 I3 d& j( n8 t4 b% A

  6. ' F+ o6 q  w9 r4 t* p' V6 R  V6 s
  7.     GPIO_Initure.Pin = GPIO_PIN_7;          //PH7
    6 y- g/ e6 e; s9 P6 b
  8.     GPIO_Initure.Mode = GPIO_MODE_INPUT;    //输出
    : ]% v4 O7 h7 ~; G
  9.     GPIO_Initure.Pull = GPIO_PULLUP;        //上拉
    , y+ q$ \4 _6 w( v. K4 b, T
  10.     GPIO_Initure.Speed = GPIO_SPEED_HIGH;   //高速
    ) u$ N! b" e' E' A3 w) _
  11.     HAL_GPIO_Init(GPIOH, &GPIO_Initure);    //初始化
    7 d, F& P; g+ j& u, M3 O7 S: i
  12. * P# M; w2 I8 I+ l4 ~( J
  13.     GPIO_Initure.Pin = GPIO_PIN_8;           //PI85 n1 i6 h- }& ?. ]2 r
  14.     GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP; //推挽输出5 C" O  x" V% P; X" h2 u8 C
  15.     HAL_GPIO_Init(GPIOI, &GPIO_Initure);     //初始化$ H3 f. @6 w/ G9 C
  16. & [0 O) y% Y+ C
  17.     CT_IIC_Init();              //初始化电容屏的I2C总线% K- k6 [. M& _$ A
  18. ) @3 j6 h( y( O0 h2 q5 b9 B! G! B
  19.     GT_RST(0);                                //复位
    ( G% M  m1 u% U% r1 j
  20.     delay_ms(1);            //INT引脚电平维持100us以上+ V3 R, j4 D, R. Q9 L, C
  21.     GT_RST(1);                                //释放复位
    - O3 Z6 k' q, w. Z( y
  22.     delay_ms(10);           //释放复位后维持5ms以上,设置INT为悬浮输入. N0 L; K$ |5 l9 m$ H, X7 a5 h9 L: I
  23.     GPIO_Initure.Pin = GPIO_PIN_7;
    + d" q( ?. h" O6 ]" G# N
  24.     GPIO_Initure.Mode = GPIO_MODE_IT_RISING;' a2 }" a* c* J  K' ?8 x
  25.     GPIO_Initure.Pull = GPIO_NOPULL;. s( F/ E+ L, w, Y# k7 b
  26.     HAL_GPIO_Init(GPIOH, &GPIO_Initure);    //初始化$ `; y' _2 @3 n
  27.     delay_ms(60);$ P2 H( P0 x& Y' q

  28. : M5 T* ~5 K& s' Y( _
  29.     GT9147_RD_Reg(GT_PID_REG, temp, 4); //读取产品ID1 a- c4 v8 P% W2 ?: g2 a* C* y
  30.     temp[4] = 0;$ E. Y& {" g5 v0 u( X. L+ [* \
  31.     printf("CTP ID:0x%s\r\n", temp);        //打印ID
    $ g2 |$ {4 H9 q& b  e: I( I

  32. - _+ s3 ^' z' l4 @, h; L0 z9 I3 Z
  33.     GT9147_Send_Cfg(1);//更新并保存配置/ V/ T; j* Z2 F" `8 s. w

  34. . l+ \' \6 R, P
  35.     return 1;
    & J3 d* L# R, Q+ L" I0 B
  36. }
复制代码

4 W& h, s# M- F- m- N3. 读取坐标流程  E5 j, J# r  Z

, R) L& ]& ?/ Z使用中断方式读取坐标,需要注意的是,如果不及时读取坐标信息会一直产生中断。GT9147的中断脚与STM32的LINE7中断线相连,中断回调函数如下所示。当按下触摸屏时,touch_x与touch_y分别保存触摸时的xy坐标;当松开触摸屏时,touch_x,touch_y赋值0xffff: V' \& z9 L  n4 f! m0 u) p+ T6 |

( J; {" W- V+ D8 }8 ?' Y
  1. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
    " n8 ^# w0 Y$ G9 e& t& L8 y5 e
  2. {
    ; M- o% Z2 R  ]( l- ^  y
  3.     uint8_t buf[4];
    . C; R3 J8 R$ t" W
  4.     uint8_t i = 0, mode = 0, temp = 0;" P$ ]2 K9 A0 H" g6 _0 D- k& p
  5.     uint16_t x[5], y[5];& |" q  a7 e4 I- C+ C8 E2 q( K$ Q; W
  6.     if(GPIO_Pin == GPIO_PIN_7) { //读取坐标, 否则会一直有INT脉冲7 q  V6 R5 g5 j
  7.         GT9147_RD_Reg(GT_GSTID_REG, &mode, 1);        //读取触摸点的状态
    + B( N+ P' W3 b* |6 T
  8.         if(mode & 0X80 && ((mode & 0XF) < 6)) //有坐标可读取- }0 P5 L7 S9 x8 }2 i" H" U+ R* j
  9.         {$ D; K/ ~1 f+ S& K* |/ }( j; O; B
  10.             temp = 0;
    ! H, u1 C! [! j- Q; J
  11.             GT9147_WR_Reg(GT_GSTID_REG, &temp, 1);//清标志
    ! Z4 J& Z* G& `8 U4 n
  12.         }  p8 L+ H6 T+ A* ]
  13.         if( (mode & 0xF) && ((mode & 0xF) < 6)) //判断触摸点个数, f. I9 m3 H8 J, m; E
  14.         {! C, _6 G5 [, y9 x
  15.             for(i = 0; i < (mode & 0xF); i++)
    & @: n8 Z5 K, ?% v
  16.             {
    & C- g9 Y- {" R0 J) D$ W
  17.                 GT9147_RD_Reg(GT9147_TPX_TBL<i>, buf, 4);        //读取XY坐标值, K6 |3 {" h9 N+ o5 M( ^+ [
  18.                 </i>x = (((uint16_t)buf[1] << 8) + buf[0]);
    ' b# T4 N) p; K
  19.                 y = (((uint16_t)buf[3] << 8) + buf[2]);( P  Y& Z5 \8 r1 P6 H& s
  20.             }$ A# U9 x0 m; t9 u- M. k
  21.             touch_x = x[0];- O' `" s% I2 A* ~
  22.             touch_y = y[0];
    # M7 q. K& R3 w* D( _! T4 m' L& K) @
  23.         }
    ) `3 Z3 k4 [, }. C* u: `" T6 m
  24. " w, `5 L2 s- s0 n! y) D
  25.         if((mode&0x8F)==0x80)//无触摸点按下,xy赋值为0xffff; o6 A: W& E) |3 o9 }
  26.         {
    $ E9 D1 y) T+ `1 @5 t- \' v
  27.           touch_x = 0xffff;: C2 M. y  C& [& f" h
  28.           touch_y = 0xffff;% ~2 `6 f) Z* c: W  W
  29.         }
    2 R+ [6 i( ~4 W
  30.     }
    , f1 R: n4 [( O+ A8 }, H7 I
  31. }
复制代码
4.主机 对 GT9147 进行读操作时序8 m# X* n; H; T' V: F. Q& @

! o/ u% q6 w1 K9 }4 [7 i8 n1 y  C
20190621161601926.png

5 n. d3 P& }3 A0 T& y0 h# J: d1 @2 [% |1 ]9 g- c# X$ A. x6 j
根据该时序图编写读寄存器函数如下:
" B$ p/ ~* h$ \0 U6 t" o! Z. a+ X
6 F4 m4 V2 ^' v( ]8 G
  1. /***************************************************************************************% U# s' I$ N0 t/ B
  2.   * @brief   从GT9147读出一次数据
    ' S: v4 B/ H8 W: s# Z4 A0 h9 f; H1 e
  3.   * @input   reg:起始寄存器地址/ ]* L6 B# H7 q3 Y
  4.              buf:数据缓缓存区2 G, @' u; Z; {9 y+ I3 a% n  M
  5.              len:读数据长度        ( u# A% x$ O1 n0 U9 |
  6.   * @return    x: A; t. J: B: q& N# F% W
  7. ***************************************************************************************/
    4 k8 y. E% z. `2 k" P- i$ w. ]
  8. void GT9147_RD_Reg(uint16_t reg,uint8_t *buf,uint8_t len)
    0 D0 Z- i  y9 ^5 }. |. ^! P
  9. {
    . h  o' X% w2 Q' F
  10.         uint8_t i;
    7 \7 K5 i8 P. p  d! W9 u
  11.          CT_IIC_Start();        9 f, \8 G$ I8 h: J8 h, e( Z% G
  12.          CT_IIC_Send_Byte(GT_CMD_WR);   //发送写命令         
    0 O# P/ r' j% w$ B
  13.         CT_IIC_Wait_Ack();
    ) c+ H8 T9 h, I$ e
  14.          CT_IIC_Send_Byte(reg>>8);           //发送高8位地址
    : I% [! ]; x( r9 l
  15.         CT_IIC_Wait_Ack();                                                                                                               9 H" {0 c) d3 P5 |6 R' D4 y
  16.          CT_IIC_Send_Byte(reg&0XFF);           //发送低8位地址+ b. O; p" F: W% D% t+ x
  17.         CT_IIC_Wait_Ack();  
    ( Z, z8 U9 [5 }6 Z
  18.          CT_IIC_Start();                     
    6 b& G* q( Z! Z& A- \3 ?# w" a
  19.         CT_IIC_Send_Byte(GT_CMD_RD);   //发送读命令                   0 Z2 k- m$ T1 ?8 b9 T$ E, x# o
  20.         CT_IIC_Wait_Ack();           2 |) N  j: S6 n7 Z/ W- y
  21.         for(i=0;i<len;i++)
      ~; F! Y' r: Z1 J5 x, U
  22.         {
    % R6 J# ^: T# _/ p; j: R
  23.             buf<span style="font-style: italic;"><span style="font-style: normal;">=CT_IIC_Read_Byte(i==(len-1)?0:1); //发数据         
    / k2 E: Z" q  n7 G2 r$ X6 X
  24.         }
    + _$ u& |1 Q& t# S  y: S9 R
  25.         CT_IIC_Stop();//产生一个停止条件    ) b2 m; b7 I0 F% t3 E
  26. }</span></span>
复制代码

  h  }# o" E4 d  O: E5.主机对 GT9147 进行写操作时序
. t9 E% a$ d9 n
! v  k8 M* G* p
20190621161509843.png
) x  ?6 q; T8 N) N$ @& ]3 p+ `

  p$ X# G6 _" Q, ~7 A* p通过该时序图,编写写寄存器函数如下2 U9 i# N% [8 g
9 Y) _" ^4 s+ M
  1. /***************************************************************************************
    % i* v; H2 @2 {- }
  2.   * @brief   向GT9147写入一次数据$ P# ?( e) s* ^: [. I
  3.   * @input   reg:起始寄存器地址;
    7 m3 P0 a2 \# w* d0 i( G% i
  4.              buf:数据缓缓存区
    1 K. g4 L7 [, ^5 k" {0 Z' h" @$ {
  5.              len:写数据长度
    * k8 N4 X/ r& f2 q6 w# ]
  6.   * @return  0,成功; 1,失败./ q) L5 I( W* S! o+ t
  7. ***************************************************************************************/
    " u- D. R$ W. Y8 o6 k( k& |2 Y
  8. uint8_t GT9147_WR_Reg(uint16_t reg,uint8_t *buf,uint8_t len)! ^) T9 ?! K( ]$ W: d# I- }
  9. {. U9 W# C8 O0 A  X: T1 J' x1 c5 w
  10.         uint8_t i;8 t6 }9 V; M1 e& i3 ~) c6 Z" B' L
  11.         uint8_t ret=0;% G- e; k  q# j$ [6 b
  12.         CT_IIC_Start();        0 }$ F$ i0 y$ c0 x% i! ?7 a& P
  13.          CT_IIC_Send_Byte(GT_CMD_WR);           //发送写命令          7 `" s4 ^+ O. ^# N+ f3 }1 y' m
  14.         CT_IIC_Wait_Ack();
    / j, w1 E; k0 b9 `/ l1 R# y! y
  15.         CT_IIC_Send_Byte(reg>>8);           //发送高8位地址5 s  h+ Y" u: D0 G
  16.         CT_IIC_Wait_Ack();                                                                                                               7 T4 F# j0 o! z! M- C7 {! l2 s
  17.         CT_IIC_Send_Byte(reg&0XFF);           //发送低8位地址
    , \7 v* C7 L, \8 ?; ?
  18.         CT_IIC_Wait_Ack();  
    ; s  g- q- y4 V$ B# L
  19.         for(i=0;i<len;i++)
    1 T- m& M% m! b- |: \3 P
  20.         {+ Y1 O  B4 P6 p+ `
  21.             CT_IIC_Send_Byte(buf<span style="font-style: italic;"><span style="font-style: normal;">);          //发数据
    ( w" \8 s. r5 J8 T9 \
  22.                 ret = CT_IIC_Wait_Ack();
    ! F% z8 W. t- y7 `! l+ q( e7 {- }
  23.                 if(ret)break;  
    4 f& F# I: S4 C% K7 f
  24.         }; g/ j: ?  t8 G" s! c5 i
  25.     CT_IIC_Stop();                                        //产生一个停止条件            
    5 T, L( X" W* |3 U
  26.         return ret; ' A1 S/ C" W: f- ^9 k5 f
  27. }</span></span>
复制代码

* f+ f" p3 @9 N; ?5 k+ V6. GT9147配置函数如下,GT9147_CFG_TBL针对分辨率480×272的触摸屏。
! g( v3 {' n$ |4 f9 N4 l
# L0 c4 I/ h2 N7 o% ]5 i配置寄存器时是要注意以下几点:
  g- |5 n0 {4 a8 I+ F3 N1 t) `; ?7 r% m- O  f# d
新的版本号大于等于GT9147内部flash原有版本号,才会更新配置.
) h& A6 v* h; P0 H, N, E写完GT9147_CFG_TBL中的配置后,还需要往0x80FF寄存器中写入校验,0x8100寄存器中写1。7 a# V$ ^& S! n
关于配置更详细的信息可以参考GT9147编程参考手册' O# \7 |  c6 |' Z. `4 V4 ]  M8 P. A
  1. const uint8_t GT9147_CFG_TBL[]=! {( \. M- c, F5 y1 y
  2. {
    5 V. r1 c  T( Z! g
  3.     0x60,0xe0,0x01,0x10,0x01,0x05,0x0C,0x00,0x01,0x08,7 Q% n6 T3 m5 w: D# m) |* Y- h# L
  4.     0x28,0x05,0x50,0x32,0x03,0x05,0x00,0x00,0xff,0xff,
    ( Y" _$ s9 e- {, X) z. Q
  5.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x89,0x28,0x0a,
    3 B7 A% _8 t7 B
  6.     0x17,0x15,0x31,0x0d,0x00,0x00,0x02,0x9b,0x03,0x25,
    " T; `; |: a( w( D) D
  7.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0x00,0x00,
    , s) f% S8 c- g9 ]( |
  8.     0x00,0x0f,0x94,0x94,0xc5,0x02,0x07,0x00,0x00,0x04,# ^9 c+ Q8 h& U$ C$ d7 r
  9.     0x8d,0x13,0x00,0x5c,0x1e,0x00,0x3c,0x30,0x00,0x29,* O- l$ m5 r9 @! x- h% s& Z
  10.     0x4c,0x00,0x1e,0x78,0x00,0x1e,0x00,0x00,0x00,0x00,2 }5 x' r, F! w4 R& r  {0 B; {
  11.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,3 g( d& V, n" V1 A9 r4 B; ?
  12.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    , P; L$ t) e) m* H  `+ I4 X" R/ O' C
  13.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    2 W# v8 x  f0 J0 Q
  14.     0x00,0x00,0x08,0x0a,0x0c,0x0e,0x10,0x12,0x14,0x16,
    ) x1 G/ K  C5 Q
  15.     0x18,0x1a,0x00,0x00,0x00,0x00,0x1f,0xff,0xff,0xff,
    - s) s, U- q0 E* q  h9 g( f" x
  16.     0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,3 o! D' {9 T/ `+ s) U2 p
  17.     0xff,0xff,0x00,0x02,0x04,0x05,0x06,0x08,0x0a,0x0c,
    * S) K& O4 n, ]1 c% Y5 y' U% ?0 }% D
  18.     0x0e,0x1d,0x1e,0x1f,0x20,0x22,0x24,0x28,0x29,0xff,
    / H3 I9 z  i4 J* t6 L* i
  19.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,
    # _. K5 c  k1 ~9 o+ {$ W8 U+ `
  20.     0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
    ' L8 A+ x9 S! r: b+ u/ w& V# Y2 \; ^
  21.     0xff,0xff,0xff,0xff,1 g# S6 D! q+ a( t2 y0 D, [+ f
  22. };
    $ v! e# @! n- p5 }6 Z4 H
  23. - D, O- h4 j- S; X2 a1 s( S
  24. uint8_t GT9147_Send_Cfg(uint8_t mode)& Z+ e  \4 @- p+ C& v
  25. {$ g. ^$ z! l; i( ~0 i5 ]3 z. n
  26.         uint8_t buf[2];' T7 y2 i) e( V8 M' X
  27.         uint8_t i=0;
    % {) c/ s! Q3 E1 X9 R4 I  X; d
  28.         buf[0]=0;4 D4 P( J: E" V2 y4 o
  29.         buf[1]=mode;        //是否写入到GT9147 FLASH?  即是否掉电保存
    9 F& P1 K4 S2 X; r4 l2 h! @1 y, {1 \
  30.         for(i=0;i<sizeof(GT9147_CFG_TBL);i++)
    4 g4 y; r! {) b
  31.             buf[0]+=GT9147_CFG_TBL<span style="font-style: italic;"><span style="font-style: normal;">;//计算校验和
    # n; c( O6 E8 M) U- M! |! v# e6 o
  32.         buf[0]=(~buf[0])+1;2 |7 d$ ?/ q  Q3 G7 q1 D
  33.         GT9147_WR_Reg(GT_CFGS_REG,(uint8_t*)GT9147_CFG_TBL,sizeof(GT9147_CFG_TBL));//发送寄存器配置9 t% U1 i9 R) `
  34.         GT9147_WR_Reg(GT_CHECK_REG,buf,2);//写入校验和,和配置更新标记
    * f7 A( m9 M4 |* \0 s5 a4 D- a: h; C7 \
  35.         return 0;
    + Y" H% a$ M( I0 p1 l. {
  36. }</span></span>
复制代码
, Y5 `( f5 W) F
四 移植触摸屏驱动到STemWin) H) t4 Y/ O8 J* d8 _( L" e
这里假设已经成功移植了STemWin到STM32F7工程。7 [; A3 \: n' T+ j: U0 C
( K7 V# S: G; ]0 c7 s
1. 在GUIConf打开STemWin触摸屏驱动宏4 f8 N9 p4 s" \$ _* z- \
# D/ [4 l; }4 e: x$ h  Y/ p8 U8 q
  1. #define GUI_SUPPORT_TOUCH       (1)  // Support touchscreen
复制代码

+ G) B& N% Q8 n' g1 T2. 新建GUI_X_Touch_Analog.c文件实现以下四个函数,在第三章第3小节我们知道touch_x,touch_y表示当前触摸的xy坐标。整个文件的内容如下所示。
# q, q4 K6 f% x' |4 r. y
/ I2 K8 G# r' H/ Y
  1. void GUI_TOUCH_X_ActivateX(void)
    $ o% y2 C& }2 a" R- u4 V1 y4 n
  2. {6 t8 [7 H! Q, A( u' f

  3. 9 h* `; B  e2 W9 D; n& a
  4. }
    $ b* k& h- M, L9 f

  5. 9 }. z9 g9 c0 Z8 v: g
  6. void GUI_TOUCH_X_ActivateY(void)
    8 E) y5 d% P" h% G# q$ y  p
  7. {
    + {, ]) `% _0 v5 b! c  z$ C2 X

  8. . z1 d: [( h: W
  9. }
    % b6 J! Y& E' b- R& b" L

  10. 1 S. {  K5 r7 N5 V/ d- l6 ^
  11. /*获取x坐标*/
    & X( Q, C* P! v! u
  12. int  GUI_TOUCH_X_MeasureX (void)
    . i5 l& E# n8 W* k5 c
  13. {- L# M1 {4 P4 c6 j: Y1 y! M, }
  14.   return touch_x;8 B5 ?3 o: a/ e' j" T0 s
  15. }' n# k" [2 A+ j$ K) f
  16. 4 \: k9 p% [2 p: a1 e
  17. /*获取y坐标*/
    1 \/ s! M/ s6 x; T
  18. int  GUI_TOUCH_X_MeasureY (void)8 O- T; w. ^/ r1 E1 g/ ^; _5 d
  19. {/ H( s  _! e( S0 {; r. @" [* o+ M: }* V
  20.   return touch_y;
    % B: W: L3 V2 U
  21. }
复制代码

, `2 X) N) I2 X3 _9 q8 q3. 使用GUI_TOUCH_Calibrate函数校准x与y值,然后才能调用GUI_TOUCH_Exec()函数处理触摸事件。3 L0 v2 D4 H' V/ Y& f4 A; a
, ^1 O5 h& W1 n0 b& @) a1 r) Y
  1. void StartTouchTask(void const * argument)( @* P' \8 A' y* ^/ i1 S  O) T1 k
  2. {
    : k- t, A$ k4 m' |! d4 j
  3.   /* USER CODE BEGIN StartTouchTask */
    1 K: ~) e3 z! c" l% ]
  4.   GUI_CURSOR_Show();//显示鼠标指针% p$ k, F* k; e" E9 L2 Z
  5.   GUI_TOUCH_Calibrate(GUI_COORD_X,0,LCD_WIDTH,0,LCD_WIDTH);   
    4 }  p% ]7 d0 x4 C* o* p1 y1 g% C) G- M
  6.   GUI_TOUCH_Calibrate(GUI_COORD_Y,0,LCD_HEIGHT,0,LCD_HEIGHT);2 y- N* q. F- E( U) z
  7.   /* Infinite loop */& \( c$ x+ q* a! J) H' q; U3 K
  8.   for(;;)
    0 _  [9 J( W9 C$ [
  9.   {
    : c$ ]3 ~8 K- }3 L7 r  O+ }9 s' S
  10.     GUI_TOUCH_Exec();
    . c3 D. ^& j1 o5 A# p2 O* z; g
  11.     osDelay(5);( B2 s# x0 R* _# a6 a; C% U
  12.   }
      U$ q7 ^. {2 E: E7 k' d- H" K
  13.   /* USER CODE END StartTouchTask */
    3 V6 l1 C- Y* Z& \! g& @
  14. }
复制代码
% G- [5 L+ ~) e, n7 }5 O0 s
! {+ l6 R) c$ w
. T4 e# }0 h5 g3 _+ E# j+ l
8 p4 T& q; U* Q* t8 g& h1 f
收藏 评论0 发布时间:2021-12-17 12:05

举报

0个回答

所属标签

相似技术帖

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