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

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

[复制链接]
STMCU小助手 发布时间:2021-12-17 12:05
一  电阻驱动与电容驱动原理
9 J+ j9 q$ q8 A9 w( n& H# v
8 Z) \7 Y. k/ V" f3 y* W+ S1. 电阻屏等效电路如下所示, 当产生按压时:
& |  Z& }. w' p
X-接地,X+接电源,Y+接ADC输入.通过读取Y+的电压以及电阻分压原理,可以得出触点的x坐标+ [/ [& @7 r- I, A) o: X
Y-接地,Y+接电源,X+接ADC输入.通过读取X+的电压以及电阻分压原理,可以得出触点的y坐标
# `# {. P! m6 d" Q  s! d/ z+ p  {# {+ \- n
2019061911075212.png
2 Y3 K8 F% {* P
" R" i+ E- W9 p; Y/ U) d4 t1 W3 m$ c
2. 电容屏等效图如下所示, 检测原理类似矩阵按键, 当产生按压时:
( J8 |9 }6 q- Y% q0 d* O" H
( T' @5 g/ q7 tX轴产生从上至下依次产生激励信号(AC交流信号), Y轴电极同时接受信号 (该激励信号是交流电,可以通过电容穿到Y轴).
8 X0 Y7 J! ^! Q4 n" i7 l  X7 ?1 w1 ^  o- |+ s
假设有如下两个按压点(分别位于(1,1)与(2,2)的位置),检测过程如下:, q, e, j5 C. B  Y: I' R4 [" `6 k
当X1产生激励信号时,Y1接受到的交流信号产生了变化, 所以可以确认(1,1)处有触摸.5 H5 H& p0 U  ~+ q, j8 Y$ n
接着当当X2产生激励信号时,Y2接受到的交流信号产生了变化, 所以可以确认(2,2)处也有有触摸., U9 `/ l& B, c8 q
, p5 U% M7 S3 C3 N
20190619115448553.png

( d4 j) F9 L0 A/ d4 L0 q" F- S) r! S
$ {  P: k% M, |" D  V- w- z二 软件模拟IIC
% a) b' W; U" s) F1 z; {7 _由于stm32的硬件iic有各种各样的问题,所以采用软件模拟IIC的方式,主要实现IIC起始信号函数、IIC停止信号函数、等待ACK函数、产生ACK应答函数、不产生ACK应答函数、发送字节函数、读字节函数3 W1 z' E7 ^( N- @
2 Z9 I7 b% U. y( E1 c$ N4 A7 I
1. 起始信号与停止信号
, {  ~2 i, I3 C5 S. A2 D& Z% e) L' w8 b) H4 z& b; r8 B: @
下图是IIC起始信号与停止信号时序图,通过观察该图编写起始信号与停止信号函数。
+ K' d8 w( Y. \
% |; Q8 X8 l8 l: L) }
aHR0cHM6Ly9pbWFnZXMwLmNuYmxvZ3MuY29tL2Jsb2cvNDcwOTA5LzIwMTMwNS8yODE2MzczMy01MjE5.png

. p! H& A% {; ]3 o$ n
, ?! n# I3 v+ G起始信号:当SCL为高期间,SDA由高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号。
5 o$ ^; Q; Z( C& E: Y# m' y5 d
  1. /***************************************************************************************
    ! V% B' ]( }- D- x: Y% g2 U
  2.   * @brief  产生IIC起始信号,当SCL为高期间,SDA由高到低的跳变7 @& F  S4 B1 U& A, I( A
  3. ***************************************************************************************/- F  x+ j# i7 Z; Z
  4. void CT_IIC_Start(void)
    , A$ C5 V# ]( K
  5. {( L: y/ m8 o5 ]; D: ?- f1 N
  6.         CT_SDA_OUT();     //sda线输出
    ; K$ j* Y# x& r  z  Z% A
  7.     CT_IIC_SCL(1);
    9 a+ n" T3 n. _6 B& R2 N* b$ Q
  8.         CT_IIC_SDA(1);                    
    0 x' C5 D( \& H& G* C
  9.         CT_Delay();
    ' M+ `- ^1 a1 ]7 S; L. ^
  10.          CT_IIC_SDA(0);
    ; P3 j! ~4 N$ m. i, j" w
  11. }
复制代码

* }% Z# T: L$ H: e; Q( a停止信号:当SCL为高期间,SDA由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。" j! k: E7 Q" z' z8 i8 X& ?
  1. /***************************************************************************************
    / o; S; d6 Y; E/ W! Y2 R2 V& N
  2.   * @brief  产生IIC停止信号,当SCL为高期间,SDA由低到高的跳变/ M# H& m; H  \2 e# K- {& C6 ?2 i
  3. ***************************************************************************************/8 O3 S4 B4 n( g( X8 ^2 y  R
  4. void CT_IIC_Stop(void)/ s6 e. o4 M/ U* D
  5. {
    8 C8 O" L0 d# H9 E: [; P
  6.         CT_SDA_OUT();//sda线输出- E+ c6 h" v5 H! |$ I/ a' s" P
  7.         CT_IIC_SCL(1);
    , s5 n6 |8 g& \8 q& B: I
  8.         CT_IIC_SDA(0);//STOP:when CLK is high DATA change form low to high
    8 n, M$ e. U8 [% R( s/ @
  9.         CT_Delay();
    8 E6 n) I" ^7 c2 U8 }6 V1 i
  10.         CT_IIC_SDA(1);/ q9 P1 C+ l  m+ l
  11. }
复制代码
. J  Z7 @2 N# t( ^: a& x6 m
在GT9147数据手册中可以发现如下截图所示内容,SCL在低电平期间至少保持1.3us,其他电平最小保持0.63 @) ]1 ?( T) b, D# j
* a1 `& \1 v, e# R# l" O. j* D
20190622160910729.png
' t: p) J# G6 |9 T* w4 w* J
6 [) r1 q6 c8 L
所以将IIC延时函数定时为2us可以满足所有时序。(一般支持最高速度400k的IIC设备,基本都可以使用2us延时。)
$ M  ^' Y# D( [% c
% h& S( ^0 A' l/ y' ^  C
  1. //控制I2C速度的延时
    4 }- |4 P$ I- W6 B" u6 `1 V
  2. void CT_Delay(void)- r  a" W" [$ c
  3. {* v* S# K; X( O) Q) |+ }
  4.         delay_us(2);9 j5 H0 r; x! L. e3 t# O
  5. }
复制代码
9 r/ C) R8 _4 o* m6 L
2. 数据传输 与 ACK时序' d3 t; B1 N' U, a0 M' p

) i5 Y. B, N( ]5 s/ M8 ~下图是ACK时序与 传输数据0的时序图,这两种时序图是一样的,区别在于ACK是在8个数据时序后产生,且SDA电平是由接受数据端拉低的。  |' L' [; f- O3 C) M# G

. Y+ r7 C" Q* X  b" c) Z% ~# G
20190622161607756.png

3 b7 w6 C% n! w+ K  j+ }  m0 E1 o$ c# L+ _* v3 y
产生ACK时序:在SCL高电平期间,SDA为低电平状态。
9 s8 s( [# e6 q# y% v
  1. /***************************************************************************************
    ) G' M) y- Y! d
  2.   * @brief  产生ACK应答,- P  Z2 N4 n" {3 b, y
  3. ***************************************************************************************/; v1 U0 n% r7 _8 y9 A# Z
  4. void CT_IIC_Ack(void)
    $ ]5 T/ V# k6 E  X* X
  5. {
    5 n/ j7 h9 h5 o3 f! G  Y0 G" Y
  6.         CT_IIC_SCL(0);$ m) ]  m$ [) |2 ?
  7.         CT_Delay();! o  g. Y2 k- {+ \& A1 o
  8.         CT_SDA_OUT();
    # ^7 B2 q1 n1 u5 Z. v, I
  9.         CT_IIC_SDA(0);) }8 L' D: T  [
  10.         CT_IIC_SCL(1);: q6 W* ^; `8 `1 P
  11.         CT_Delay();  H& r2 o2 k1 D6 @
  12.         CT_IIC_SCL(0);7 V+ p# h7 c: q- n
  13. }
复制代码

5 Y; X, H' n& Q' B5 T等待ACK时序:拉高SCL与SDA后, 然后设置SDA为输入检测状态,等待接受数据端拉低SDA" s& x4 N5 ^' V" X) q6 e  q
  1. /***************************************************************************************
      r& ~& z/ K/ I) Z
  2.   * @brief   等待应答信号到来,等待接受数据端拉低SDA
    # I! |2 @) m  N$ w3 W0 a  W  ?. ^
  3.   * @input   
    : H) }- p5 v' l& y7 {
  4.   * @return  1,接收应答失败 ; 0,接收应答成功  ]1 d# y0 B1 ?6 A3 w0 k. e; H& C
  5. ***************************************************************************************/: F+ ~$ ~; x7 _4 y' ?9 u
  6. uint8_t CT_IIC_Wait_Ack(void)
    + u# s6 |; e) f3 R; T
  7. {; h) T% a( O7 j. q, \
  8.         uint8_t ucErrTime=0;
    8 Q4 {3 e" |" a8 @$ p
  9.         CT_IIC_SDA(1);           
    - a- p. n) w& j
  10.         CT_IIC_SCL(1);' D9 P# x: @! X* v9 T) P
  11.         CT_SDA_IN();      //SDA设置为输入  1 z& ^1 u* s+ Y1 F! q8 ~
  12.         while(CT_READ_SDA)" F! s& v, j. r) S6 N, C
  13.         {
    ( B- P9 f5 k& B% i& d- t
  14.                 ucErrTime++;, q# B$ U( j2 h: x
  15.                 if(ucErrTime>250){) C: I! [; l3 v- Q. Q7 F2 {
  16.                         CT_IIC_Stop();1 Z7 D; }$ f$ J5 {' {' D) ]
  17.                         return 1;
    : n. Y3 X* ~) S6 U! h; G4 }
  18.                 }
    6 ?# l' Q% j  _( y/ M& P# W; q( h
  19.                 CT_Delay();
    4 F5 e9 r% }+ L3 G3 T% I6 R% ^: `3 H
  20.         }- r6 r7 _4 j$ j, j! F3 O4 P
  21.         CT_IIC_SCL(0);; c0 O5 q9 o" ~5 v, [* C5 W
  22.         return 0;  $ M9 g8 @4 m9 M# n& p, h* p
  23. }
复制代码
/ J' P9 ]0 Z5 o8 T4 j! Y1 t: J
下图是nACK时序与 传输数据1的时序图,这两种时序图是一样的,区别在于ACK是在8个数据时序后产生,且SDA电平是由接受数据端拉低的。
$ T$ F7 [; \: U
" \/ b- N' t7 h4 K. Y! `
20190622164227486.png

* `$ K) f' L: l7 A$ _1 y3 t$ e0 S: Q- ^6 ~% \( ?; }$ S
产生ACK时序:在SCL高电平期间,SDA为高电平状态。
- d+ o  M# Q$ p7 ]
  1. /***************************************************************************************
    0 g# b. y; M: O7 e. S6 K
  2.   * @brief  不产生ACK应答        
    4 D$ E$ A+ T: T* y+ M( }
  3. ***************************************************************************************/
    9 Q$ M8 J" t- v! |: G5 o
  4. void CT_IIC_NAck(void); O0 d8 X/ n  z# }
  5. {2 L! M. j7 L  Y* z& L! P+ W
  6.         CT_IIC_SCL(0);( x( M& r2 [% X$ \, R
  7.         CT_Delay();
    * k; q+ r  j! V" {+ _$ _- m
  8.         CT_SDA_OUT();
      t1 Q. g3 ]. F0 _( `0 E; S$ L
  9.         CT_IIC_SDA(1);1 I8 F% U/ A2 n5 g; B  Z
  10.         CT_IIC_SCL(1);6 n: B2 C7 ?. J4 R  ^8 o
  11.         CT_Delay();
    . S5 i8 b& }1 @' W; r+ l% o8 I
  12.         CT_IIC_SCL(0);5 \4 d, I+ W9 j2 j4 [
  13. }
复制代码
9 n% \. s8 S8 q! C$ g
发送一个字节函数,优先发送高位,即从bit7开始发送。0 Q. Z3 Q% l9 f. T+ }7 ^8 b
  1. /***************************************************************************************% ~, c  l. G# z1 w6 T" @0 b+ ^
  2.   * @brief   IIC发送一个字节,2 ^9 [# P( }6 @, b6 ]( I6 b0 u
  3.   * @input   
    + t: D, o- y3 F9 A2 j! A$ l) o
  4.   * @return  
    1 K6 ^. n" X7 ]- d% g5 x5 K" v8 E
  5. ***************************************************************************************/) ]) q( C; U6 a2 {4 G
  6. void CT_IIC_Send_Byte(uint8_t txd)
    ( Z$ W. h/ o/ l, \7 R& H
  7. {3 w, @9 d, }; b  L. M: a: }
  8.     uint8_t t;   
    % n# H" }% s, m2 r' \
  9.     CT_SDA_OUT();             * C$ ^( o/ n6 V" P) O( ~
  10.     CT_IIC_SCL(0);//拉低时钟开始数据传输
    0 v7 ]- \5 P% @" @% k8 s0 B
  11.     CT_Delay();# N+ D  k5 R; W( x6 a$ i, L" L5 z
  12.     for(t=0;t<8;t++)
    ) E( U3 w8 e7 Q- c' l+ a" E
  13.     {( S7 c# o) q4 C; ^! s
  14.         CT_IIC_SDA((txd&0x80)>>7);//发送bit7位* g3 u6 w3 x" C: h1 z
  15.         txd<<=1; //将txd的次高位左移到最高位              
    5 J% w, D. U+ q$ k2 `: n
  16.         CT_IIC_SCL(1); , k# L! z% R" }! x' E( x. ^
  17.         CT_Delay();
    # T( v/ ^0 t$ |
  18.         CT_IIC_SCL(0);        
    2 {* V6 Y& n# R& E3 }% M/ Q: j
  19.         CT_Delay();: L1 X1 M( C; L8 F3 W6 c. Y
  20.     }: h8 l3 e# N5 \. X) k; H8 p3 a1 W
  21. }
复制代码
2 ]" S/ I2 e$ |2 P8 o1 G. Q4 W. w2 U- N
读字一个字节函数,接受到1bit数据后,将该bit放在bit0位置(通过receive++实现),如果还要继续接受数据,则将之前接受到的数据左移一位(通过receive<<=1实现),留出bit0位置接受新的数据。
& D; r& y! M/ Z- _' I; R# T% i
  1. /***************************************************************************************& [! H6 A( h3 s6 J% p* r8 S
  2.   * @brief   读1个字节/ ^6 b+ N# l" }) R
  3.   * @input   ack=1时,发送ACK,ack=0,发送nACK: }; Q0 F. q2 B& ]
  4.   * @return  " H- W) l* o' s2 d$ N
  5. ***************************************************************************************/
    , J$ }9 }' w: H5 Y& Z/ U
  6. uint8_t CT_IIC_Read_Byte(unsigned char ack)
    $ D" y, K+ u8 T" _! m0 P9 }
  7. {
    ) @1 j5 }% W* J. T8 |
  8.         uint8_t i,receive=0;2 |+ V1 a/ q7 ^
  9.          CT_SDA_IN();//SDA设置为输入6 f& w+ Z! A5 g- m
  10.         CT_Delay();
    ( D# f. u8 b' ~' ~
  11.         for(i=0;i<8;i++ ), ?* V. P" M/ v
  12.         {
    3 s; ~) ^, `* m' q5 |5 }
  13.                 CT_IIC_SCL(0);                        ) C5 f) I; ~' p6 @' f8 g
  14.                 CT_Delay();( @% l  O' B; d" w/ B; }
  15.                 CT_IIC_SCL(1);         ! P, w7 }6 d! V9 K, _7 p. y7 T2 K
  16.                 receive<<=1;
    5 W/ R2 R* D" C# W8 q2 t; l
  17.                 if(CT_READ_SDA)receive++;   7 Z: L( }) v; ^" O
  18.         }                                          
    ; Z$ J) t8 D2 g. v5 E
  19.         if (!ack)$ m5 l, _! @- D' o
  20.         CT_IIC_NAck();//发送nACK
    , Z" g$ ^( C& R0 K) u/ g
  21.         else # m2 I. h2 O0 c2 i. e4 _
  22.         CT_IIC_Ack(); //发送ACK   
    6 i7 a% Q8 ^0 [+ ?# c
  23.          return receive;
    : E  U0 p% g  ~- P2 }0 Y9 m; [
  24. }
复制代码

: h9 z9 |: R) M% s; J0 Z三 GT9147电容触摸屏控制芯片驱动: d2 }6 C4 ^* T
1. GT914内部结构框图如下图所示
& X. X* s7 m% J, ^8 p  \6 ?. G- S9 n5 ~/ {  u" `" B3 k: _3 _2 Q6 L
2019061913180610.png

$ K/ c& Q# X/ V5 C7 I1 [* @0 J8 C- T/ M/ f
5L5)3BWQK[DM1E_`8%S}J0F.png

" b/ P3 m+ O8 e4 f5 _6 B& \& ?. i7 V: M4 L
2. 上电流程% D( f, E- [, C6 ]' Y' h

5 m( J6 Z( G$ x# N- K, n* g; SGT9147上电初始化流程如下所示:' n# W. v+ Q5 ?0 w% Q0 h
* q' s; e0 f1 U  [2 y& |# h
配置RST输出低电平,INT输出低(或者高)电平后,位置100us以上,此阶段配置IIC地址为 0xBA/0xBB(或者0x28/0x29)5 f! l6 ~( O: t+ T$ O6 m5 k
接着配置RST输出高电平并维持5ms以上后,可以配置INT引脚为悬浮输入模式。
5 t0 i6 r1 k3 B( ]4 S等待50ms以上后,可以发送配置信息。4 w# _! S7 u  V  {$ l
8 ~- a0 t. v, N" v+ i) U" n
2019062113491579.png
/ y5 C, T6 e* V3 A( D3 X6 T" t

0 ]! x4 X4 V4 W8 G代码参考原子例程编写,贴上代码:
& M  y: U* N0 |) t' r7 Y$ k) J2 W" M/ v' M0 k" J9 T0 e9 K: I
  1. uint8_t GT9147_Init(void)
    % N; u5 ]6 Z8 q7 I+ Q' z: m) b
  2. {
    0 R( d: L5 I" h3 J
  3.     uint8_t temp[5];! S- N7 v# I6 \6 ]4 X
  4. ' s/ e' a: ~- {
  5.     GPIO_InitTypeDef GPIO_Initure;0 w7 S: j2 \! W8 I5 f

  6. 3 z4 T8 x& }) W6 |+ l. ]
  7.     GPIO_Initure.Pin = GPIO_PIN_7;          //PH78 b- h1 K# \+ d9 ~8 }" C
  8.     GPIO_Initure.Mode = GPIO_MODE_INPUT;    //输出9 f5 S8 Q5 A0 Z& x6 u
  9.     GPIO_Initure.Pull = GPIO_PULLUP;        //上拉8 Z5 [5 E3 R8 y. E. T! S2 _; k: G
  10.     GPIO_Initure.Speed = GPIO_SPEED_HIGH;   //高速
    # u# S2 e2 [# n3 E# C
  11.     HAL_GPIO_Init(GPIOH, &GPIO_Initure);    //初始化
    8 K/ }9 \4 i- a# B0 G

  12. 8 W. [- _2 J# F  R! W" X
  13.     GPIO_Initure.Pin = GPIO_PIN_8;           //PI88 _7 g+ x: Q7 X5 g" F
  14.     GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP; //推挽输出6 G/ _! s# v' g- X9 y* U
  15.     HAL_GPIO_Init(GPIOI, &GPIO_Initure);     //初始化- B" _; B# j$ X! O$ g

  16. , g3 \3 [( x4 l0 K4 f9 @1 K2 e
  17.     CT_IIC_Init();              //初始化电容屏的I2C总线0 a3 [& `: Z! s+ i0 i: t

  18. $ X3 [9 `7 i% n- c$ C
  19.     GT_RST(0);                                //复位& W' A+ v9 s, |4 f* q/ R5 ^5 M0 C
  20.     delay_ms(1);            //INT引脚电平维持100us以上4 \1 O7 X. b- T( m5 h
  21.     GT_RST(1);                                //释放复位
    3 i" Y5 u6 X3 F* ]$ t: v, l
  22.     delay_ms(10);           //释放复位后维持5ms以上,设置INT为悬浮输入$ w; N% W  E- W7 n& Y
  23.     GPIO_Initure.Pin = GPIO_PIN_7;. ?# R* h, b0 M7 ?9 J8 X5 {
  24.     GPIO_Initure.Mode = GPIO_MODE_IT_RISING;3 n. h% d- z: e% d' x9 }/ N0 m: `
  25.     GPIO_Initure.Pull = GPIO_NOPULL;
    5 G5 M9 U; w3 M7 Z* `9 A
  26.     HAL_GPIO_Init(GPIOH, &GPIO_Initure);    //初始化9 L. L9 O0 z$ c- D2 B8 w
  27.     delay_ms(60);
    ( G' w+ k  U- }  y& A, g' I
  28. + F' o. S& \: P& a* h( `" {2 E9 U
  29.     GT9147_RD_Reg(GT_PID_REG, temp, 4); //读取产品ID1 L0 Q& }9 D, M% I  n: j
  30.     temp[4] = 0;; D7 T2 W9 t) A6 K! L0 T) m
  31.     printf("CTP ID:0x%s\r\n", temp);        //打印ID+ ~8 P9 K9 v8 K; q* ]1 x, q

  32. # L4 Q. }7 |; \; Z6 }
  33.     GT9147_Send_Cfg(1);//更新并保存配置
    + W7 i6 s' I, r5 D& }

  34. " l0 f) @; i  n" S  v
  35.     return 1;
    ( F3 o) f% ~, u9 R
  36. }
复制代码

# D% a7 }/ O" \, @( I3. 读取坐标流程, C: B7 F" l9 ^6 |7 ~

7 g2 g  j9 j. h& A8 r- S使用中断方式读取坐标,需要注意的是,如果不及时读取坐标信息会一直产生中断。GT9147的中断脚与STM32的LINE7中断线相连,中断回调函数如下所示。当按下触摸屏时,touch_x与touch_y分别保存触摸时的xy坐标;当松开触摸屏时,touch_x,touch_y赋值0xffff
: F8 }; n' M  I4 e: P
- _: r) t! K& z6 b  a% T+ I7 w
  1. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
    2 U' R: z8 m# G1 n1 s
  2. {5 q: j  A  i6 x: N  y6 [3 b& `
  3.     uint8_t buf[4];% x7 u3 Z" b! c
  4.     uint8_t i = 0, mode = 0, temp = 0;
    / }7 ]5 w! l- Y6 h4 ^
  5.     uint16_t x[5], y[5];" w5 h+ \$ p9 {: F; F0 ?2 s! u# n7 o* F
  6.     if(GPIO_Pin == GPIO_PIN_7) { //读取坐标, 否则会一直有INT脉冲' o/ z! i) D, Q& L
  7.         GT9147_RD_Reg(GT_GSTID_REG, &mode, 1);        //读取触摸点的状态8 Q4 q% X3 n! C8 c* ^" B9 K
  8.         if(mode & 0X80 && ((mode & 0XF) < 6)) //有坐标可读取) A8 _5 f2 f- K$ T5 g
  9.         {1 V+ _/ @5 ^3 Y  V# w" E( V
  10.             temp = 0;
    0 z% G2 J+ t4 B. D4 X1 W
  11.             GT9147_WR_Reg(GT_GSTID_REG, &temp, 1);//清标志
    % [# o; H' j' k
  12.         }8 N& n. u8 M& o$ J. w, ?3 v% ]$ _
  13.         if( (mode & 0xF) && ((mode & 0xF) < 6)) //判断触摸点个数2 S, i+ g9 [( L( @4 w/ ?
  14.         {. c) K$ w9 E: S+ [4 [5 V4 m8 B
  15.             for(i = 0; i < (mode & 0xF); i++)
    8 x% M. U$ R8 Y0 H7 |2 L
  16.             {# k: E8 j  {# F9 {* ], T* l
  17.                 GT9147_RD_Reg(GT9147_TPX_TBL<i>, buf, 4);        //读取XY坐标值9 }& g" j+ R! N2 K7 p+ n( s
  18.                 </i>x = (((uint16_t)buf[1] << 8) + buf[0]);
    / b  W  j7 L0 R! @, E& Y
  19.                 y = (((uint16_t)buf[3] << 8) + buf[2]);( A1 o1 e7 x! ?+ F* ]
  20.             }" `* N) J  p# `* G8 h3 o. v
  21.             touch_x = x[0];( a# t2 m2 F0 L
  22.             touch_y = y[0];
    5 b7 T: {4 h. `) l9 Q
  23.         }
    ; Q9 ^2 H% E! V, l& v2 P
  24. 8 e5 n' c1 r- k$ {; ?. N% r" n) I8 ^
  25.         if((mode&0x8F)==0x80)//无触摸点按下,xy赋值为0xffff! t$ {- U+ {, E
  26.         {( v, t7 i9 o- b% o4 |$ @
  27.           touch_x = 0xffff;0 z' z! \; d) c9 h- R
  28.           touch_y = 0xffff;
    , a/ m, T* j9 w* ?2 _
  29.         }4 z$ C/ R0 L: {% r& ~& y3 R  N
  30.     }: z0 G* l1 I5 H( X) ~. F
  31. }
复制代码
4.主机 对 GT9147 进行读操作时序
# L+ O3 U- A1 M/ e  @. \2 ]
' o+ R. m* y4 [; Y* D) j
20190621161601926.png
! K" M& l$ z( C
3 V  C4 A4 M& i+ t: m
根据该时序图编写读寄存器函数如下:
9 X, Y  g- t* @0 w8 A6 I. q' ^; g
* e9 H$ `: ]- d( s7 _" v) T" ]
  1. /***************************************************************************************
    3 g. d; g( N6 z2 q& D
  2.   * @brief   从GT9147读出一次数据6 [! {! x1 V8 e2 X2 G+ M; t
  3.   * @input   reg:起始寄存器地址5 T" P1 d1 V  S
  4.              buf:数据缓缓存区
    $ ^! b, P; J( L( ?  J9 _, F
  5.              len:读数据长度        
    5 \1 b( J9 w0 Z1 \- m3 [
  6.   * @return  
    # |+ H% @( J6 X2 a& Z. |, S/ U
  7. ***************************************************************************************/
    ; I5 ^$ U; P* G. I1 f
  8. void GT9147_RD_Reg(uint16_t reg,uint8_t *buf,uint8_t len)! @" V% s5 F9 n6 u( w+ E
  9. {
    4 d) P; k& L! p
  10.         uint8_t i; / J6 i9 j  q/ Z  }1 V% _
  11.          CT_IIC_Start();        8 E% e9 x7 \% C, _, {
  12.          CT_IIC_Send_Byte(GT_CMD_WR);   //发送写命令         
    7 `. E2 W% C" ]6 \$ M; ^8 G
  13.         CT_IIC_Wait_Ack();
    , A  T: Q+ u7 Z% _. {5 f% V
  14.          CT_IIC_Send_Byte(reg>>8);           //发送高8位地址# ^( t+ M( U5 M! V( O
  15.         CT_IIC_Wait_Ack();                                                                                                               / ~$ o9 v: o6 s" O$ \
  16.          CT_IIC_Send_Byte(reg&0XFF);           //发送低8位地址3 y; d  f/ z2 q1 k( B7 |* `7 P) g
  17.         CT_IIC_Wait_Ack();  3 }' d$ [+ q& H+ l+ S9 q* n
  18.          CT_IIC_Start();                     
    : n9 D, U" J7 m- Z
  19.         CT_IIC_Send_Byte(GT_CMD_RD);   //发送读命令                   ; l' T1 k$ H. B
  20.         CT_IIC_Wait_Ack();           , E% k7 \7 J; A- D. p% \3 A
  21.         for(i=0;i<len;i++)2 M( U2 B( c6 p, k5 U4 k
  22.         {
    5 ~: O- C* u2 J% |" C
  23.             buf<span style="font-style: italic;"><span style="font-style: normal;">=CT_IIC_Read_Byte(i==(len-1)?0:1); //发数据         
    + i" W% _5 G" N( |, K  K6 U
  24.         }
    , c' c& ^0 q3 l
  25.         CT_IIC_Stop();//产生一个停止条件   
    " A+ Q4 l' e8 D0 Z
  26. }</span></span>
复制代码
7 R" {+ B) e  s9 l& w: {% Y8 A' j
5.主机对 GT9147 进行写操作时序
4 O8 w0 M; O1 x/ T& [( M! U9 a  m$ _* m1 w
20190621161509843.png

5 |# x# J  c: ^# p, W  B8 c* h* I9 {: n- T8 D  S/ e2 W
通过该时序图,编写写寄存器函数如下
: i- |, {( ~4 S, H1 ?' ]- \9 q, A1 i% W& p/ |% w
  1. /***************************************************************************************
    " z2 A: A- ]. q4 H/ {- H# r! F
  2.   * @brief   向GT9147写入一次数据
    9 r  l; i  ?( o+ \. M
  3.   * @input   reg:起始寄存器地址;
    ! o4 F- j8 o5 U- r
  4.              buf:数据缓缓存区
    0 b. u9 @! H" R% ]3 y% N3 W
  5.              len:写数据长度
    ( ?4 l  _4 G! q' ]0 V& h% G
  6.   * @return  0,成功; 1,失败.
    : w% g" z& q1 ~
  7. ***************************************************************************************/
    , l* H, c6 G4 Q( A; J6 z. ]
  8. uint8_t GT9147_WR_Reg(uint16_t reg,uint8_t *buf,uint8_t len)
    : K% \1 k; w0 W! l" `* U9 w' j
  9. {5 R" K$ N* J# _' r1 d$ U; W. r
  10.         uint8_t i;
    2 h: W8 T$ d: w: o' W* S8 B' I! f
  11.         uint8_t ret=0;
    , r6 i5 H: M9 ^! c- e
  12.         CT_IIC_Start();        ; V3 I" _1 X/ M- @8 e
  13.          CT_IIC_Send_Byte(GT_CMD_WR);           //发送写命令          . g0 o* c$ E8 L/ S  j$ J  ?7 c, w) Y
  14.         CT_IIC_Wait_Ack();
    5 g; P% h+ U7 O- Y+ O5 f
  15.         CT_IIC_Send_Byte(reg>>8);           //发送高8位地址
    6 V; }( ~6 z3 D
  16.         CT_IIC_Wait_Ack();                                                                                                               
    . c: X* }# D/ i5 l9 ], G
  17.         CT_IIC_Send_Byte(reg&0XFF);           //发送低8位地址
    , P* J2 N0 r. C- w
  18.         CT_IIC_Wait_Ack();  $ P7 e9 d( g" V/ Q- }4 S2 h
  19.         for(i=0;i<len;i++)
    9 Y& b$ u% }/ L% K7 H" i
  20.         {
    8 `, c2 x+ s9 p( R  @: c
  21.             CT_IIC_Send_Byte(buf<span style="font-style: italic;"><span style="font-style: normal;">);          //发数据6 Q; |; F7 e% o( }6 r3 a
  22.                 ret = CT_IIC_Wait_Ack();+ \; v1 B9 q# n: \! N0 z
  23.                 if(ret)break;  9 d: @. R" Q+ i$ Z- s* ?: D6 Y% y
  24.         }
    / W4 s0 V# d9 p$ n: l; N
  25.     CT_IIC_Stop();                                        //产生一个停止条件            . Q. T/ {' _: n2 H. H
  26.         return ret;
    : c; L5 ?3 R% N) q7 e. s
  27. }</span></span>
复制代码
* h* B7 g* C3 n1 N; [
6. GT9147配置函数如下,GT9147_CFG_TBL针对分辨率480×272的触摸屏。1 F$ i4 |$ V% r" r# U' {) J' b5 u
, O. H( O+ \& `/ x2 q! M
配置寄存器时是要注意以下几点:
6 e+ q$ G8 |3 e& G" S7 B7 b
' L) L8 t, v. z新的版本号大于等于GT9147内部flash原有版本号,才会更新配置.
! y! X( n, c* r" B1 {写完GT9147_CFG_TBL中的配置后,还需要往0x80FF寄存器中写入校验,0x8100寄存器中写1。
: f# Y, p# C3 \4 @关于配置更详细的信息可以参考GT9147编程参考手册9 p0 X* ?' ?) J) ?
  1. const uint8_t GT9147_CFG_TBL[]=
    $ i+ H) p& X, ?' Z4 ~5 T
  2. {
    ( F/ }1 r  H' T" K
  3.     0x60,0xe0,0x01,0x10,0x01,0x05,0x0C,0x00,0x01,0x08,$ e/ }0 T; b+ D
  4.     0x28,0x05,0x50,0x32,0x03,0x05,0x00,0x00,0xff,0xff,
    ' f6 T( U: c- [$ i3 W
  5.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x89,0x28,0x0a,
    ; K; d0 V- |; V4 k' k  c
  6.     0x17,0x15,0x31,0x0d,0x00,0x00,0x02,0x9b,0x03,0x25,5 u. t) t3 e8 Y* z8 Y
  7.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0x00,0x00,& C. K& l4 I7 n( h! t
  8.     0x00,0x0f,0x94,0x94,0xc5,0x02,0x07,0x00,0x00,0x04,- @/ b$ V2 H$ w6 M$ g) [
  9.     0x8d,0x13,0x00,0x5c,0x1e,0x00,0x3c,0x30,0x00,0x29,( {. }3 F. i, @$ @* G! @" o
  10.     0x4c,0x00,0x1e,0x78,0x00,0x1e,0x00,0x00,0x00,0x00,9 I& W0 |- D2 i
  11.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,% r( u  a5 b+ e* W6 w- d) x4 m
  12.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    & V: |! W5 S4 F3 N/ R$ `7 a
  13.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    4 \1 J$ z& x/ G& L- z7 ]
  14.     0x00,0x00,0x08,0x0a,0x0c,0x0e,0x10,0x12,0x14,0x16,
    3 @' H" N  t& L' e
  15.     0x18,0x1a,0x00,0x00,0x00,0x00,0x1f,0xff,0xff,0xff,
      O% Y" e, u; ~: P* v4 R0 a* C
  16.     0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
    / Y+ `+ [  X8 e; H" i
  17.     0xff,0xff,0x00,0x02,0x04,0x05,0x06,0x08,0x0a,0x0c,
    1 U6 H! _' K7 R2 f. i
  18.     0x0e,0x1d,0x1e,0x1f,0x20,0x22,0x24,0x28,0x29,0xff,
    # j0 s: D; z  j, ^
  19.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,! u& ?% N7 I- P5 `' a: o
  20.     0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,. t, J9 K$ t, e0 {2 A" n
  21.     0xff,0xff,0xff,0xff,
      F. Z$ N& H  K, y/ J+ @
  22. };2 G" u) |: {/ J* t
  23. / }% P( r) a2 Y- Y
  24. uint8_t GT9147_Send_Cfg(uint8_t mode); x& \5 Z; ^  b4 R7 g
  25. {
    1 _. Z5 I0 U5 f
  26.         uint8_t buf[2];" c( e' \/ o3 i' m
  27.         uint8_t i=0;
    6 |" |  T. B' N; k3 P
  28.         buf[0]=0;
    2 d( P0 r- Y* x) r0 @
  29.         buf[1]=mode;        //是否写入到GT9147 FLASH?  即是否掉电保存
    9 N8 L& S# k, M2 B, s
  30.         for(i=0;i<sizeof(GT9147_CFG_TBL);i++)" ]$ ?# L2 g, Y4 p, I; i1 v6 `
  31.             buf[0]+=GT9147_CFG_TBL<span style="font-style: italic;"><span style="font-style: normal;">;//计算校验和
    # y. q& ?* @& ~) D, v
  32.         buf[0]=(~buf[0])+1;: X5 x# s; V+ h, I" V1 Z4 q
  33.         GT9147_WR_Reg(GT_CFGS_REG,(uint8_t*)GT9147_CFG_TBL,sizeof(GT9147_CFG_TBL));//发送寄存器配置
      g; n. f8 x& |* p  N9 O9 T
  34.         GT9147_WR_Reg(GT_CHECK_REG,buf,2);//写入校验和,和配置更新标记9 \5 |+ `9 I2 N$ T+ X) |( [
  35.         return 0;
    ! Y4 `) H; H( ~. I
  36. }</span></span>
复制代码

" b4 W/ N% `, S1 A5 `- f3 E
四 移植触摸屏驱动到STemWin
0 |' D. M) N) K. }9 K这里假设已经成功移植了STemWin到STM32F7工程。, w3 F5 u/ p) T

$ Y: O- a4 p% z4 }" v# P1. 在GUIConf打开STemWin触摸屏驱动宏
( p, v; e3 e4 z
$ Q8 Z( P6 }* h2 o9 V
  1. #define GUI_SUPPORT_TOUCH       (1)  // Support touchscreen
复制代码
9 S) D7 C& r0 e! A( X0 k5 D; X  R7 z& r
2. 新建GUI_X_Touch_Analog.c文件实现以下四个函数,在第三章第3小节我们知道touch_x,touch_y表示当前触摸的xy坐标。整个文件的内容如下所示。
) ~8 V$ Y7 W6 @& Z6 t* X# u& b" e! j( T+ a+ W+ A0 S
  1. void GUI_TOUCH_X_ActivateX(void) 7 @+ f  z: s1 S9 ?, G3 g
  2. {! w& n8 g1 \- J3 W0 O( V/ \
  3. 2 P4 \5 G+ [, u" r; G% Y  T
  4. }3 ^: e! b; o! n$ i( }
  5. 5 k( s3 D) c/ i$ T. C
  6. void GUI_TOUCH_X_ActivateY(void)
    ) u; ]$ Z7 i- L8 `2 W
  7. {0 V0 S5 I) P4 P  k: Z
  8. ) b& T7 j- s6 e: ?) b) u
  9. }  M/ N6 ^: q) ?* c( ]* C

  10. / i/ c) ?" K2 Y. h/ q* O3 ^
  11. /*获取x坐标*/
    : Z  z( p. s+ @* X, {& ]1 F/ \3 I' b7 L
  12. int  GUI_TOUCH_X_MeasureX (void)9 u- ?1 V: a, j' Y
  13. {
    # X/ k' u* ]: @: `1 d2 L
  14.   return touch_x;
    0 M: i3 B/ d7 K, U% S
  15. }
    9 f4 U9 H( r) W$ E! r

  16. 8 @3 A8 T. u# r1 t: [! U" Y2 N
  17. /*获取y坐标*/+ A2 g: k. U8 \7 a! C/ W
  18. int  GUI_TOUCH_X_MeasureY (void)
    0 N4 ^$ h8 O9 U3 U$ T
  19. {
    9 V& f( H4 P8 i
  20.   return touch_y;
    : h3 e4 q3 H, P3 I+ o' \! Q
  21. }
复制代码
' }. X% B5 g- X/ ]( C8 V9 R
3. 使用GUI_TOUCH_Calibrate函数校准x与y值,然后才能调用GUI_TOUCH_Exec()函数处理触摸事件。
9 j8 [  c' h0 p3 m1 q* \" {/ O1 ^  s" K9 X: b1 m
  1. void StartTouchTask(void const * argument)
    4 z: o9 c7 E$ B$ {! v8 f
  2. {
    0 E; j6 n0 M- |+ n; b$ {
  3.   /* USER CODE BEGIN StartTouchTask */
    2 j5 X* b( A' r% j3 ^. L
  4.   GUI_CURSOR_Show();//显示鼠标指针
    ! c$ Y0 c$ u/ w$ b) j9 }) n- `
  5.   GUI_TOUCH_Calibrate(GUI_COORD_X,0,LCD_WIDTH,0,LCD_WIDTH);   
    " y  N0 O* j- A, L1 A2 R
  6.   GUI_TOUCH_Calibrate(GUI_COORD_Y,0,LCD_HEIGHT,0,LCD_HEIGHT);- _( P9 D2 B/ l; N. T3 p! A
  7.   /* Infinite loop */
    ) ?0 o  O. f3 J1 B6 r
  8.   for(;;)
    * G& ^$ X! r7 h0 m  p9 |0 ~5 z8 e
  9.   {' U# M+ {# l+ g' m1 R
  10.     GUI_TOUCH_Exec();8 }, c& n5 k2 a; h5 j8 p
  11.     osDelay(5);
    $ i* V/ h" k& j. T
  12.   }
    9 q5 ~' c+ U: h3 L: |
  13.   /* USER CODE END StartTouchTask */
    # O4 r9 t, O- A& ]* a2 k( W9 b; b& d
  14. }
复制代码
- v* B/ }, W0 ~2 }: t
0 k' d# c5 S& r# m; l# u* [
/ v! K3 e) \  Q
+ ~' ]- w) f; q" D* v
收藏 评论0 发布时间:2021-12-17 12:05

举报

0个回答

所属标签

相似技术帖

官网相关资源

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