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

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

[复制链接]
STMCU小助手 发布时间:2021-12-17 12:05
一  电阻驱动与电容驱动原理
* c" w: X4 |2 F" b+ o) w* r/ W* i5 P- [! g+ u5 P% a! w
1. 电阻屏等效电路如下所示, 当产生按压时:
) P- \3 L5 ^9 C2 s. X, L+ q
X-接地,X+接电源,Y+接ADC输入.通过读取Y+的电压以及电阻分压原理,可以得出触点的x坐标
9 r9 y' L/ C2 W) e$ s6 oY-接地,Y+接电源,X+接ADC输入.通过读取X+的电压以及电阻分压原理,可以得出触点的y坐标7 |+ @  L* k9 Z- [3 N
+ S$ T4 \! x  h# {( z+ ?$ T
2019061911075212.png
; l, @* V! r. D/ L
& J" S+ ?7 }+ l' p! K
2. 电容屏等效图如下所示, 检测原理类似矩阵按键, 当产生按压时:
5 u/ p7 }. [3 E6 E4 J5 K
% `% D: L! Z+ gX轴产生从上至下依次产生激励信号(AC交流信号), Y轴电极同时接受信号 (该激励信号是交流电,可以通过电容穿到Y轴).
5 Z- l) Z, C1 \+ q( ?  {8 f7 r& g( S( ^  ?# x
假设有如下两个按压点(分别位于(1,1)与(2,2)的位置),检测过程如下:
+ m+ b! E0 m+ x9 W6 h+ b当X1产生激励信号时,Y1接受到的交流信号产生了变化, 所以可以确认(1,1)处有触摸.
3 }4 m9 g+ ~/ T) [; K$ v接着当当X2产生激励信号时,Y2接受到的交流信号产生了变化, 所以可以确认(2,2)处也有有触摸.! B1 N" c$ f4 O( h8 I

- B) a1 `% \" z0 C* y9 r& O
20190619115448553.png

, A7 u$ c, H- @# E7 R" [
, y/ J7 _* b0 ~二 软件模拟IIC
# M* o: D0 I: I# }由于stm32的硬件iic有各种各样的问题,所以采用软件模拟IIC的方式,主要实现IIC起始信号函数、IIC停止信号函数、等待ACK函数、产生ACK应答函数、不产生ACK应答函数、发送字节函数、读字节函数
; S0 f3 ]0 h8 C( v5 y7 F
$ X' D" U% J) }1. 起始信号与停止信号
4 ]3 Y$ `8 G+ Z% y. D+ ?1 F
& e* [# i* `4 B# {0 r" E3 A6 {下图是IIC起始信号与停止信号时序图,通过观察该图编写起始信号与停止信号函数。
& O4 j' `( K6 t& O  Y/ L; |$ M+ g- {
aHR0cHM6Ly9pbWFnZXMwLmNuYmxvZ3MuY29tL2Jsb2cvNDcwOTA5LzIwMTMwNS8yODE2MzczMy01MjE5.png

* I0 v/ m# y  ^2 o9 }, W& h8 w* Z0 i* p8 N2 z
起始信号:当SCL为高期间,SDA由高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号。
# e$ w' p/ ?4 \7 w# Y% F$ ^& M$ |8 Q; [
  1. /***************************************************************************************
    . O' }' g* `! n9 d
  2.   * @brief  产生IIC起始信号,当SCL为高期间,SDA由高到低的跳变
    : x( Z) H* k7 j
  3. ***************************************************************************************/* N& C5 ~% o8 e% B$ l5 F
  4. void CT_IIC_Start(void)
    + z/ o+ K  g- @- g0 a
  5. {, _2 H- s0 ^; b0 Z( k
  6.         CT_SDA_OUT();     //sda线输出' j  n0 g: J7 @$ l5 z* V& P. P! C( s3 m
  7.     CT_IIC_SCL(1);1 N* I3 R! P/ `
  8.         CT_IIC_SDA(1);                    
    ) T0 \( Q9 @- `3 i3 G0 e5 R
  9.         CT_Delay();% x0 s7 y6 B9 Z& Q$ t- W* E
  10.          CT_IIC_SDA(0);
    . d9 u6 N% f3 v2 s/ t
  11. }
复制代码

: ~4 w6 C8 }% K3 T停止信号:当SCL为高期间,SDA由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。
. F5 b' X7 I3 ~+ ~0 W! ^  E# t
  1. /***************************************************************************************9 R+ m/ f0 c& z+ @1 S  h
  2.   * @brief  产生IIC停止信号,当SCL为高期间,SDA由低到高的跳变
    - F5 Q2 `" x5 ]7 ?' V4 k
  3. ***************************************************************************************/- U, P8 R" x1 ]; b' v: A2 ~8 `
  4. void CT_IIC_Stop(void)* a2 ]9 Y4 e4 h/ F
  5. {
    6 k; {$ ?7 z8 t: K/ T/ u7 J. t
  6.         CT_SDA_OUT();//sda线输出
    7 s0 p! j7 N5 B  d+ f) ]5 x$ Z2 F
  7.         CT_IIC_SCL(1);; v7 d" j6 }+ U" E
  8.         CT_IIC_SDA(0);//STOP:when CLK is high DATA change form low to high" m- S+ \4 M+ ~/ Q9 X# ^
  9.         CT_Delay();. }! y8 g7 S7 N( c! m, D9 L% ~
  10.         CT_IIC_SDA(1);0 _( V3 u  P. h, r( q
  11. }
复制代码
/ ^* C* V; {  Q  M. d; }
在GT9147数据手册中可以发现如下截图所示内容,SCL在低电平期间至少保持1.3us,其他电平最小保持0.6
& X; L. R! K# g& q
+ h3 U& D0 L; R2 r3 ^8 m2 h- m, [* B% a
20190622160910729.png
8 p3 q4 V6 {# {

' H6 j3 p( U0 B; k$ U! @% E' ?, e所以将IIC延时函数定时为2us可以满足所有时序。(一般支持最高速度400k的IIC设备,基本都可以使用2us延时。)
% m4 Z; W7 L+ E1 O9 _9 e' m$ J5 n  u4 a* H+ X7 g# m3 J
  1. //控制I2C速度的延时
    1 P9 p, n2 z, N6 K
  2. void CT_Delay(void)
      Z+ d* R+ u. y1 Z0 e2 q7 c( t( R
  3. {
    ; B; D# e) x, q3 t& Q
  4.         delay_us(2);
      Y) |2 |/ F2 V2 o. }
  5. }
复制代码

5 [" Q: h7 |" S& f+ i: u/ c2. 数据传输 与 ACK时序: y! x, S# f# [/ k# j1 L/ [
4 I( s4 U& c% z  c4 n
下图是ACK时序与 传输数据0的时序图,这两种时序图是一样的,区别在于ACK是在8个数据时序后产生,且SDA电平是由接受数据端拉低的。8 u* C) N! s. u8 X* n

6 _- ~. T2 f5 C0 J
20190622161607756.png
6 b% ?7 U, O( l
2 h  p. H3 H% Q! S2 f2 [( j5 E8 R9 P
产生ACK时序:在SCL高电平期间,SDA为低电平状态。
' d' j9 U, r/ {( A. K
  1. /***************************************************************************************% ^- F* c( c% n) J) \: N
  2.   * @brief  产生ACK应答,: ?# \9 g6 `1 t  C# t
  3. ***************************************************************************************/; E3 e5 T  W9 B) M, o1 z
  4. void CT_IIC_Ack(void)
    / K* B+ N, N% e
  5. {
    ; N" z3 [7 B3 o. V2 a2 n6 `
  6.         CT_IIC_SCL(0);4 T0 b! }0 n1 n  A# y
  7.         CT_Delay();% I- }4 v, W4 v  `7 l4 @' q* F0 i6 ^
  8.         CT_SDA_OUT();
    # U9 N' {8 ]: M2 F
  9.         CT_IIC_SDA(0);! M& H& Z- A8 z3 w1 F
  10.         CT_IIC_SCL(1);% k, Y, p( H' ]1 W
  11.         CT_Delay();
    8 @2 N' l5 X  h6 J
  12.         CT_IIC_SCL(0);7 |% s( L; s$ j7 H( X) @
  13. }
复制代码
8 o+ R/ U% T) U$ I
等待ACK时序:拉高SCL与SDA后, 然后设置SDA为输入检测状态,等待接受数据端拉低SDA
. J0 i5 C/ r. S% B- `/ H: L
  1. /***************************************************************************************
    8 U4 T- {, e2 t! E" Q) w* ]
  2.   * @brief   等待应答信号到来,等待接受数据端拉低SDA: B+ Q7 d; n7 {+ s+ Z. `$ U
  3.   * @input     y2 D1 i, t' J
  4.   * @return  1,接收应答失败 ; 0,接收应答成功
    + }9 o7 d4 ^  J+ y' v* u* V
  5. ***************************************************************************************/
    : ]1 B6 e4 J9 O2 |6 m! K
  6. uint8_t CT_IIC_Wait_Ack(void)
    7 l, O% h9 h3 {( H
  7. {
    # W! w) N* u1 j2 r4 a+ M
  8.         uint8_t ucErrTime=0;( x" h! W: U: @1 E$ h
  9.         CT_IIC_SDA(1);           
    5 j- i2 c8 j* c' |) e3 Z; h+ @
  10.         CT_IIC_SCL(1);! Z9 n1 i4 A1 {9 h' n! O
  11.         CT_SDA_IN();      //SDA设置为输入  
    ! R" @" u& V2 P# I
  12.         while(CT_READ_SDA)' ^. T5 d4 ~  M" K, k% Z! G
  13.         {% a! N8 ]  \; L3 F7 x6 y9 {
  14.                 ucErrTime++;! U/ F: K5 B* }$ z2 i! h% i$ o4 w* ]
  15.                 if(ucErrTime>250){* \: g- b. t4 o& f9 A9 Q
  16.                         CT_IIC_Stop();
    # z1 H# k# P/ v  o1 H0 D
  17.                         return 1;* C6 \2 m* y; ~1 {6 s9 P
  18.                 }
    0 \) @$ k% x- y, p# \" i
  19.                 CT_Delay();" D# X2 p% y4 Z/ C$ a) O- ~5 W
  20.         }- H& W- e8 ]0 M* ^3 {. d3 |5 N5 w, M
  21.         CT_IIC_SCL(0);
    # R* ^* l" @( w9 ^
  22.         return 0;  
    - k. Z0 O7 ^  G1 Y3 v. ^! H
  23. }
复制代码

& t" x& W5 x1 \/ _$ b5 d7 k( q下图是nACK时序与 传输数据1的时序图,这两种时序图是一样的,区别在于ACK是在8个数据时序后产生,且SDA电平是由接受数据端拉低的。
7 ?- x0 A9 |# A# H
( Q) |4 F# Z+ }
20190622164227486.png
; |9 j# |+ h' S  |. O( B

( A/ v" r& ]$ w% w产生ACK时序:在SCL高电平期间,SDA为高电平状态。
# n+ K! ?9 l" ]  A5 G2 f- l8 |7 d
  1. /**************************************************************************************** p; ~& Q9 }& y$ i! V
  2.   * @brief  不产生ACK应答        ( X: v: v' G% G6 |% r8 t: @
  3. ***************************************************************************************/
    2 ?4 L9 I* J9 f' j0 V, _- i( k
  4. void CT_IIC_NAck(void)( m  \; }0 h" u7 r6 w
  5. {
    8 t& S: i+ j4 s% y% D- Q
  6.         CT_IIC_SCL(0);
    9 P& E+ }" i" y; q" I6 q, ?" e2 H
  7.         CT_Delay();
    9 i2 S5 Q( K. |" ]
  8.         CT_SDA_OUT();
    / v! ^9 c# ]  m. q
  9.         CT_IIC_SDA(1);
    ( O! W; T% T) c( ]; Q
  10.         CT_IIC_SCL(1);* j! R6 T2 D! r! G9 ?9 d
  11.         CT_Delay();! U1 N, ^6 z* ~) r$ L8 p& u
  12.         CT_IIC_SCL(0);) n3 b  F' b, ~
  13. }
复制代码
+ z! v3 `0 {* v8 o9 W) d( L" ?) \
发送一个字节函数,优先发送高位,即从bit7开始发送。
" i; |! i+ d' e: R% x4 ]5 j+ Y
  1. /***************************************************************************************7 |" s; p. A; ^7 [
  2.   * @brief   IIC发送一个字节,9 p8 C7 o2 B3 z
  3.   * @input     G0 h/ u1 i/ B( [8 t2 j
  4.   * @return  
    . z, b" X7 I: d  R7 R5 b, j, t% B
  5. ***************************************************************************************/& x2 K/ N* N! Y6 M# m6 c
  6. void CT_IIC_Send_Byte(uint8_t txd)* z/ s; F# I; b8 @
  7. {% i5 z6 Z+ f9 d% E2 h
  8.     uint8_t t;   , s- r$ C. L6 _
  9.     CT_SDA_OUT();             3 g! X4 A9 N4 w2 r; n5 G% H) P2 B
  10.     CT_IIC_SCL(0);//拉低时钟开始数据传输
    ) }- Q+ D* ]6 O/ {2 I* p' q
  11.     CT_Delay();
    & e) d2 g% A1 }+ Z* A/ P
  12.     for(t=0;t<8;t++)
    5 t$ o' K3 V; b3 }
  13.     {
    6 [& s8 ]! r$ o# q: D# A
  14.         CT_IIC_SDA((txd&0x80)>>7);//发送bit7位3 V( i4 ]& j6 s3 N# V
  15.         txd<<=1; //将txd的次高位左移到最高位              
    " q: P% L3 ?1 P* Z" F5 V1 Q0 A! h- C
  16.         CT_IIC_SCL(1);
    ' @- b  {0 t) ^' X
  17.         CT_Delay();
    ; p4 n" W6 G6 H! s( L% G
  18.         CT_IIC_SCL(0);        
    1 x9 W$ E3 y6 ^8 n1 w
  19.         CT_Delay();" y1 y0 {8 m2 G! `
  20.     }
    * g$ y7 `' P  i8 s
  21. }
复制代码

. f% C) r/ g( a4 J2 k/ M. Q读字一个字节函数,接受到1bit数据后,将该bit放在bit0位置(通过receive++实现),如果还要继续接受数据,则将之前接受到的数据左移一位(通过receive<<=1实现),留出bit0位置接受新的数据。7 c; ^, Z+ ^1 P2 b; C
  1. /***************************************************************************************: q% Q1 W( R! U- r! n. o
  2.   * @brief   读1个字节5 s% `7 R" R  V3 h+ Y
  3.   * @input   ack=1时,发送ACK,ack=0,发送nACK
    1 F. V5 z1 w! }
  4.   * @return  4 a% c" w, H4 \: [; J
  5. ***************************************************************************************/
    , ^2 R0 ~$ i# D3 `: I- d. I. \6 |  w
  6. uint8_t CT_IIC_Read_Byte(unsigned char ack)
    2 J7 D$ H2 h, K" h- ]/ ~
  7. {
    2 H; T5 [! D6 ]6 K8 Y+ ^5 Q3 h
  8.         uint8_t i,receive=0;$ T/ i% _" b" C, ]& O' e, F" G
  9.          CT_SDA_IN();//SDA设置为输入
    , B+ Q4 s3 i8 U; g: ~
  10.         CT_Delay();$ K5 W0 c7 g3 u* G0 M% n; `5 ~
  11.         for(i=0;i<8;i++ ). ]) t4 e, S1 X- P
  12.         { 6 ?! H, ~0 B' v# C  ^, W6 r
  13.                 CT_IIC_SCL(0);                        6 q: R) N, s  ]8 b7 x& ?& g& j, ^$ _
  14.                 CT_Delay();/ c5 D0 ~6 u# Z1 f) ]
  15.                 CT_IIC_SCL(1);         % h9 @2 v& }5 @9 Q" u* C+ d  G
  16.                 receive<<=1;
    & v5 k& V8 }# ^; ~! T# Z. p
  17.                 if(CT_READ_SDA)receive++;   0 J* V; _& a5 l, ]/ c; W, s
  18.         }                                           3 T7 X  }' P- d6 F
  19.         if (!ack)- [5 P& D5 J# ^( Q  q4 i1 W# |+ _
  20.         CT_IIC_NAck();//发送nACK
    7 c- @; w" W/ l: ~1 B* i$ I
  21.         else
    ; F7 Z) e& M# n; e* O
  22.         CT_IIC_Ack(); //发送ACK   ; ^# S4 O3 j' H" M( R% a8 c, Z
  23.          return receive;
    6 t+ r- H9 C0 ?# R! `
  24. }
复制代码
' e/ E; V, ?$ z0 H( i/ C: D5 _
三 GT9147电容触摸屏控制芯片驱动- V( u1 P) [( N8 O( {$ M
1. GT914内部结构框图如下图所示* \4 q- e6 a- u& S5 h* b' y
, Y' Q; Y) w. Z  c. E, a% h
2019061913180610.png

( B; F  y! |$ V4 I( b+ ?+ g4 H( b
. n1 K- o1 M. Q/ E0 _6 D" C
5L5)3BWQK[DM1E_`8%S}J0F.png

% \# m2 e. w1 s" @6 I
% v  b- m/ ~! Q( U2. 上电流程! P* {' j; l8 L& q4 ?0 O( y' U
& B& m% C+ a2 @" q
GT9147上电初始化流程如下所示:; L1 D; l% F' C& _6 R

5 H1 Y* L) [" D6 ?8 {: Y配置RST输出低电平,INT输出低(或者高)电平后,位置100us以上,此阶段配置IIC地址为 0xBA/0xBB(或者0x28/0x29)
: g( w# o6 }7 d接着配置RST输出高电平并维持5ms以上后,可以配置INT引脚为悬浮输入模式。
% ^! R, |0 t. {* x) `等待50ms以上后,可以发送配置信息。( @1 q, g7 w% I) j
, ^2 I/ M& [1 p. p
2019062113491579.png
+ `) k4 q' x5 Y# m
0 o9 o5 e' `, t: \$ v- K
代码参考原子例程编写,贴上代码:
) {' {% q( w- ^' S, @
1 b6 o, B- m. {4 |1 i- [9 Y* K
  1. uint8_t GT9147_Init(void)
    - N" ]0 D1 w' z4 y9 U
  2. {/ Z% H; f2 H3 {
  3.     uint8_t temp[5];/ i/ u! C/ b$ {* m
  4. : U, O# `9 D* ?' E; u
  5.     GPIO_InitTypeDef GPIO_Initure;
    2 f* u  p  e# a2 X/ u- M
  6. - @& \/ \+ m# c* |- u7 i9 F
  7.     GPIO_Initure.Pin = GPIO_PIN_7;          //PH74 y, v1 i& }0 f
  8.     GPIO_Initure.Mode = GPIO_MODE_INPUT;    //输出/ [) E6 C. m' M; n" k- @
  9.     GPIO_Initure.Pull = GPIO_PULLUP;        //上拉  ]% K2 u, k0 u1 `# f  n
  10.     GPIO_Initure.Speed = GPIO_SPEED_HIGH;   //高速- W) |5 x/ \5 G+ M' T- h( y8 G7 v
  11.     HAL_GPIO_Init(GPIOH, &GPIO_Initure);    //初始化9 C1 Y8 \/ i/ c3 e! d

  12. * }" z/ c7 c, W6 e% b
  13.     GPIO_Initure.Pin = GPIO_PIN_8;           //PI8
    ' c: N% W; J6 r" l+ R3 W, [
  14.     GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP; //推挽输出
    ) z2 ^5 q! [) l; Q
  15.     HAL_GPIO_Init(GPIOI, &GPIO_Initure);     //初始化
    2 F1 f: M1 M5 x: l, q7 @

  16. ; [/ n6 N- o$ M3 o: h) W  ?6 {6 P
  17.     CT_IIC_Init();              //初始化电容屏的I2C总线' ?0 i6 N/ A" B7 {. a. d

  18. + G: S! r0 C- ^
  19.     GT_RST(0);                                //复位! C: ]) q; g! H, H5 o; _% x9 [
  20.     delay_ms(1);            //INT引脚电平维持100us以上/ z) H2 v" o; O* }0 ]1 q
  21.     GT_RST(1);                                //释放复位# H; o" f2 \5 i7 l; _
  22.     delay_ms(10);           //释放复位后维持5ms以上,设置INT为悬浮输入
    . g# f. L+ l+ A8 T
  23.     GPIO_Initure.Pin = GPIO_PIN_7;: r8 W# M" Y& r% f+ ], [' A
  24.     GPIO_Initure.Mode = GPIO_MODE_IT_RISING;! U! F- l2 j; w+ ~6 ]# q# a
  25.     GPIO_Initure.Pull = GPIO_NOPULL;
    - m1 H& |5 u/ U1 w4 K5 C
  26.     HAL_GPIO_Init(GPIOH, &GPIO_Initure);    //初始化; p7 A1 p8 c1 m2 Y4 ~
  27.     delay_ms(60);
    , ?5 S/ F' E. p: |! R

  28. . u. t; C, X3 N2 X- X5 s  h9 _  ^! Y
  29.     GT9147_RD_Reg(GT_PID_REG, temp, 4); //读取产品ID: }1 Y8 y$ W# T% f# Q! J+ a. B" n
  30.     temp[4] = 0;& u1 c, x! h6 w, b
  31.     printf("CTP ID:0x%s\r\n", temp);        //打印ID
    : E6 M" b7 H# A. t' u

  32. : {  i+ {) P* d# V$ x5 d
  33.     GT9147_Send_Cfg(1);//更新并保存配置8 `. U9 b, u+ V  @* ]

  34. ) U% e& \- _, O0 d
  35.     return 1;! M5 H3 x' d1 H5 ~; F
  36. }
复制代码
2 S" `$ m4 W% L# h
3. 读取坐标流程
. Z) D# C& d8 Q1 I! [7 t" c' l* X
2 K: X8 z4 O+ w: _; J8 [' U0 P使用中断方式读取坐标,需要注意的是,如果不及时读取坐标信息会一直产生中断。GT9147的中断脚与STM32的LINE7中断线相连,中断回调函数如下所示。当按下触摸屏时,touch_x与touch_y分别保存触摸时的xy坐标;当松开触摸屏时,touch_x,touch_y赋值0xffff
0 Z. }  R8 _, W8 g; `( B& u: t2 o; P6 ]. F: A
  1. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)& ~0 V3 Q+ Z6 J' m
  2. {% S% {" M* X; t: p
  3.     uint8_t buf[4];- `( j( f6 N6 e7 K8 M, s
  4.     uint8_t i = 0, mode = 0, temp = 0;7 \/ j9 X6 c4 l3 a- d0 `+ X
  5.     uint16_t x[5], y[5];+ Z7 m  C; o, G8 Q
  6.     if(GPIO_Pin == GPIO_PIN_7) { //读取坐标, 否则会一直有INT脉冲( Y! A; d* F8 K% i' J
  7.         GT9147_RD_Reg(GT_GSTID_REG, &mode, 1);        //读取触摸点的状态0 |* B; k) B5 l. `
  8.         if(mode & 0X80 && ((mode & 0XF) < 6)) //有坐标可读取: N9 T$ A% J$ i) {4 t4 s
  9.         {
    8 B! m$ e0 ?7 {. \: B3 h
  10.             temp = 0;7 Q0 A3 z/ ]' j7 C
  11.             GT9147_WR_Reg(GT_GSTID_REG, &temp, 1);//清标志( `" c7 v% U) y+ r* h# C
  12.         }9 _/ s. P  Y9 ^, B) @6 {7 G
  13.         if( (mode & 0xF) && ((mode & 0xF) < 6)) //判断触摸点个数% M  G3 @( M) ~, Z  N: n
  14.         {7 q9 l( X4 k0 J$ h) K
  15.             for(i = 0; i < (mode & 0xF); i++)# a4 l" Z  P: U5 h+ A
  16.             {. B& g7 i" k$ ]! a& G
  17.                 GT9147_RD_Reg(GT9147_TPX_TBL<i>, buf, 4);        //读取XY坐标值4 Z' {/ P8 [5 y5 s1 O
  18.                 </i>x = (((uint16_t)buf[1] << 8) + buf[0]);
    $ d' T8 @5 A9 q4 }$ ^0 {7 e
  19.                 y = (((uint16_t)buf[3] << 8) + buf[2]);
    + z! w( v- d. K/ n0 v
  20.             }/ Y5 J& A1 l  `" W6 @- K
  21.             touch_x = x[0];) }& l' [; B3 ?2 _. }
  22.             touch_y = y[0];
    % t( l2 F( ^0 Z( J; y8 l
  23.         }- Z" A8 E0 T* U
  24. ; J7 \1 w0 [4 C9 T. |
  25.         if((mode&0x8F)==0x80)//无触摸点按下,xy赋值为0xffff
    0 r1 u( C4 K1 |
  26.         {, H7 b$ J; Q- r( f2 l) j# W
  27.           touch_x = 0xffff;
    * s5 ?) g8 W9 h% @8 `
  28.           touch_y = 0xffff;
      X' e5 a+ I6 G5 @: H
  29.         }9 k, z# c4 M- {& @/ R6 u1 \' ]7 O
  30.     }
    + t2 q$ H6 T  i+ m; ?6 `3 b
  31. }
复制代码
4.主机 对 GT9147 进行读操作时序
- q( E) U7 v/ l# t# l6 t7 e8 W! `& E' f/ w: H
20190621161601926.png

$ g, ~5 d% X: g* Z4 c6 v4 Q+ ~/ x5 S# `7 P' V0 Q
根据该时序图编写读寄存器函数如下:1 U1 I+ n' J  i* N+ O" `
3 F. n+ A8 y/ D! s9 B
  1. /***************************************************************************************  m$ W, N! F# ^, W7 l
  2.   * @brief   从GT9147读出一次数据
    ; h! t# D; |+ [# V# Z) {
  3.   * @input   reg:起始寄存器地址
    3 }0 |6 [* S) _% v) [. |+ j1 M( f; Y0 _
  4.              buf:数据缓缓存区
    : G, V" u4 x: q# @% A& L
  5.              len:读数据长度        " l2 G# W0 f/ ]. D, P
  6.   * @return  
    7 S/ [9 v) O7 k4 U& s: |) s' @& H
  7. ***************************************************************************************/8 m( V' S* e+ q; ~9 G& N# a2 U+ r( |" c
  8. void GT9147_RD_Reg(uint16_t reg,uint8_t *buf,uint8_t len)
      R% o8 _1 c0 y8 {6 l% |4 U8 l
  9. {; R3 P% \' N  G0 O* ]6 ]
  10.         uint8_t i; ; j$ M8 J$ L* j0 W3 q6 T5 Q% q
  11.          CT_IIC_Start();        
    6 G/ ^/ j+ K* B
  12.          CT_IIC_Send_Byte(GT_CMD_WR);   //发送写命令          & Z+ B! p  M3 u2 p5 b( z
  13.         CT_IIC_Wait_Ack();) h& u4 ^  B8 n% Z
  14.          CT_IIC_Send_Byte(reg>>8);           //发送高8位地址; C0 F/ _7 L2 w0 }; `
  15.         CT_IIC_Wait_Ack();                                                                                                               
    5 t( [0 }$ C: e; T
  16.          CT_IIC_Send_Byte(reg&0XFF);           //发送低8位地址7 }/ t6 h$ E! f! H1 M- ^
  17.         CT_IIC_Wait_Ack();  ) F2 v4 J: x6 l3 U0 H8 j, x
  18.          CT_IIC_Start();                     
    ! d% x+ l% b; }/ P2 G( u
  19.         CT_IIC_Send_Byte(GT_CMD_RD);   //发送读命令                   ! D) k/ V- v1 j6 x. H9 D4 l* V4 _
  20.         CT_IIC_Wait_Ack();           ! i' l( Y8 h) W( ?0 v. K5 j, z
  21.         for(i=0;i<len;i++)
    4 \2 S4 a, S$ f7 A2 C& [' b' u
  22.         {
    2 v9 n2 p2 V( M) W
  23.             buf<span style="font-style: italic;"><span style="font-style: normal;">=CT_IIC_Read_Byte(i==(len-1)?0:1); //发数据          * [  }  f) ]5 Q8 I$ |( ~( k
  24.         }
    7 F' C6 |) [# Y2 \
  25.         CT_IIC_Stop();//产生一个停止条件    - _5 K" r/ @  s6 R* J
  26. }</span></span>
复制代码

) J5 S/ {& S# [3 m& h$ i5.主机对 GT9147 进行写操作时序0 C0 p" t2 t8 M% Q
5 J; k, X, g/ k9 }1 k' p
20190621161509843.png

0 n  e, m. Q$ x; ], i0 q# F& v9 `/ m& h! i* K: e  q- w
通过该时序图,编写写寄存器函数如下
* _# f7 j* l4 f) @* w# y$ j7 A" r
  1. /***************************************************************************************  H6 e9 n, O  t' |6 ?
  2.   * @brief   向GT9147写入一次数据2 d# o8 V+ v4 w4 ?$ x& Q
  3.   * @input   reg:起始寄存器地址;
      h$ t0 I( A7 [) ~5 P: J! N
  4.              buf:数据缓缓存区5 U2 @3 ^( L+ z1 o8 Q
  5.              len:写数据长度
    7 c: Z) k- \$ |3 d  b' ^
  6.   * @return  0,成功; 1,失败.' P7 M/ r  H# Z
  7. ***************************************************************************************/
      j4 P1 y/ S: d, |' S0 `1 T2 A
  8. uint8_t GT9147_WR_Reg(uint16_t reg,uint8_t *buf,uint8_t len)9 v; z% C: Q6 i
  9. {1 [8 M' M) W( t; w; D5 d  K
  10.         uint8_t i;
    3 @# d0 N/ B7 f1 r$ j% p
  11.         uint8_t ret=0;0 |0 R) F* M) q/ U0 |$ ~
  12.         CT_IIC_Start();        9 u) F+ b( t4 y' V2 F# m
  13.          CT_IIC_Send_Byte(GT_CMD_WR);           //发送写命令         
    " v( Q3 @, x) Z# M
  14.         CT_IIC_Wait_Ack();4 }' S$ ?/ [4 L0 t) w
  15.         CT_IIC_Send_Byte(reg>>8);           //发送高8位地址
    4 v  i4 |2 a2 I# j+ D3 S0 Q
  16.         CT_IIC_Wait_Ack();                                                                                                               + b' @$ P2 s! E2 |
  17.         CT_IIC_Send_Byte(reg&0XFF);           //发送低8位地址3 ?5 w9 a$ c+ G
  18.         CT_IIC_Wait_Ack();  
    3 H# ?( V  d5 n+ m% D1 u7 s" `1 m
  19.         for(i=0;i<len;i++)
    ' x  E8 z9 u. ~6 G  L2 }; T
  20.         {0 b+ v8 b+ Z% @) Q, T1 l
  21.             CT_IIC_Send_Byte(buf<span style="font-style: italic;"><span style="font-style: normal;">);          //发数据# d2 E' N0 C  G( N2 ^0 z1 ~. z* e
  22.                 ret = CT_IIC_Wait_Ack();
    3 O' o" n3 n  k$ i
  23.                 if(ret)break;  
    + ]2 V2 x, C6 p2 {
  24.         }8 {6 P+ N& \9 }3 Z0 Y2 A. r5 t3 K
  25.     CT_IIC_Stop();                                        //产生一个停止条件            * _$ A# Q) W% s; T- v; S+ W! o
  26.         return ret;
    ( f3 \; w4 V. I2 Q1 H' ^1 O! V
  27. }</span></span>
复制代码
: ?" J9 Z1 O5 T7 g. h* c
6. GT9147配置函数如下,GT9147_CFG_TBL针对分辨率480×272的触摸屏。1 d, Z" _4 J4 f

0 L6 p4 K' c7 z配置寄存器时是要注意以下几点:
' ]4 q7 a: n* a4 w1 r" \- [3 i# D+ r0 }) t7 R& g
新的版本号大于等于GT9147内部flash原有版本号,才会更新配置.0 i0 k9 {. m( Y3 l* f! g8 i- h
写完GT9147_CFG_TBL中的配置后,还需要往0x80FF寄存器中写入校验,0x8100寄存器中写1。; q: ^+ {0 o% L  R- L
关于配置更详细的信息可以参考GT9147编程参考手册
1 J* }0 }  X* X; o7 d2 ?
  1. const uint8_t GT9147_CFG_TBL[]=
    * A7 o- k% V& F% s* `! X9 k0 D) {
  2. {  Q; v% M3 D) i6 d# _  X5 S' [
  3.     0x60,0xe0,0x01,0x10,0x01,0x05,0x0C,0x00,0x01,0x08,: M) Z  K5 u+ I  }2 p+ X/ ]% F2 j. p
  4.     0x28,0x05,0x50,0x32,0x03,0x05,0x00,0x00,0xff,0xff,8 E' \# f* E1 [& [1 A* q9 C
  5.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x89,0x28,0x0a,
    4 |' n2 f* t9 M+ s+ b# D
  6.     0x17,0x15,0x31,0x0d,0x00,0x00,0x02,0x9b,0x03,0x25,& Y! ~: E; @7 }" o
  7.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0x00,0x00,
    , ?6 ]; b" Q6 J" y4 V" O
  8.     0x00,0x0f,0x94,0x94,0xc5,0x02,0x07,0x00,0x00,0x04,- g  l! `0 f8 D6 p( ^1 ]
  9.     0x8d,0x13,0x00,0x5c,0x1e,0x00,0x3c,0x30,0x00,0x29,6 {& |3 O  r* u$ h) r4 ?
  10.     0x4c,0x00,0x1e,0x78,0x00,0x1e,0x00,0x00,0x00,0x00,# F4 H2 }% I* N: F2 P  L
  11.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,% @5 V5 f  E0 r! @; x- A
  12.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,: e" V" P2 T; q  r
  13.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  X3 P* ^5 B  r* b; D
  14.     0x00,0x00,0x08,0x0a,0x0c,0x0e,0x10,0x12,0x14,0x16,: C. m- K/ s/ |5 D
  15.     0x18,0x1a,0x00,0x00,0x00,0x00,0x1f,0xff,0xff,0xff,
    " x8 V  E) \# A! F$ u/ i3 w
  16.     0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
    , Z' p6 Z! \& h. s# t& M2 m: {3 g
  17.     0xff,0xff,0x00,0x02,0x04,0x05,0x06,0x08,0x0a,0x0c,
    9 F- B( Z) w7 y" W4 `+ P9 h, i
  18.     0x0e,0x1d,0x1e,0x1f,0x20,0x22,0x24,0x28,0x29,0xff,
    4 ^1 l; E6 f" \$ ?( w
  19.     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,  E. \0 I. G3 _
  20.     0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
    ( A* }! e$ e: f" A) v, J
  21.     0xff,0xff,0xff,0xff,' u# e  c! w5 k
  22. };
    / [0 L. I. {, h* z

  23. 2 m/ [% n; x* e2 O- L/ A) f" _
  24. uint8_t GT9147_Send_Cfg(uint8_t mode), ?- F' B. o( s: z& u% e
  25. {, N. c% u( W( D7 q* ^
  26.         uint8_t buf[2];
    1 t! L2 i) H+ C$ h
  27.         uint8_t i=0;
    $ C( d$ c! b: J! u7 f5 A
  28.         buf[0]=0;$ E% B! v2 @( f' T7 Z9 t1 I7 D
  29.         buf[1]=mode;        //是否写入到GT9147 FLASH?  即是否掉电保存  W" T+ \& O* t) Q8 b5 W, ~
  30.         for(i=0;i<sizeof(GT9147_CFG_TBL);i++)
    % G+ T2 @6 `* Y6 x' @
  31.             buf[0]+=GT9147_CFG_TBL<span style="font-style: italic;"><span style="font-style: normal;">;//计算校验和) D! ~( d* M: o6 w
  32.         buf[0]=(~buf[0])+1;2 Z- n  X* |+ m8 x8 j
  33.         GT9147_WR_Reg(GT_CFGS_REG,(uint8_t*)GT9147_CFG_TBL,sizeof(GT9147_CFG_TBL));//发送寄存器配置
    7 \8 l9 O2 g! S0 `8 ~5 x
  34.         GT9147_WR_Reg(GT_CHECK_REG,buf,2);//写入校验和,和配置更新标记
    % w! Z: b, a: k
  35.         return 0;  L$ h) U% E8 Y- v; Z+ x) g
  36. }</span></span>
复制代码

3 V' b/ f( |7 {; C
四 移植触摸屏驱动到STemWin" ]( `/ f9 S4 A; q
这里假设已经成功移植了STemWin到STM32F7工程。6 {5 l* n9 s/ g+ I3 r9 w
' f+ S! e: g- A# O" m
1. 在GUIConf打开STemWin触摸屏驱动宏% G: u5 S3 A) x9 a
  j; N) c+ z+ q9 ^4 j2 M
  1. #define GUI_SUPPORT_TOUCH       (1)  // Support touchscreen
复制代码

  w6 i8 m+ t) _2. 新建GUI_X_Touch_Analog.c文件实现以下四个函数,在第三章第3小节我们知道touch_x,touch_y表示当前触摸的xy坐标。整个文件的内容如下所示。/ q% j% D, C( H! [' I
8 r4 r$ e+ H3 c) C' m5 V
  1. void GUI_TOUCH_X_ActivateX(void) . t/ R: }6 O1 M: b1 |: C, l3 b
  2. {
    # |' K9 ]. s3 s1 A+ y

  3. 6 \1 J* y0 v4 Q: `
  4. }' W9 d1 {2 O% U; R' x
  5. $ ^1 n# b' B: _
  6. void GUI_TOUCH_X_ActivateY(void)0 e" a  _. r( A
  7. {  W/ c0 C0 K6 }

  8. . f* c2 L/ p- q8 i
  9. }
    / }1 T7 E3 c$ \

  10. 0 i% V# z& k+ x% n3 V
  11. /*获取x坐标*/. S1 ~2 K9 P) w7 Z: H
  12. int  GUI_TOUCH_X_MeasureX (void)5 |; X/ h& Q, u4 x! R7 Q4 k
  13. {
    & q9 O, |2 b1 i! j% ?2 ?6 s- Q
  14.   return touch_x;& d' f- u6 P' [
  15. }6 w% X8 m9 h& E8 s9 D  O
  16. ; k# [" T3 I! s. Q
  17. /*获取y坐标*/
    0 w% m" H, {* q8 H
  18. int  GUI_TOUCH_X_MeasureY (void)3 U2 e) P- T/ R8 H4 v% M0 @
  19. {5 t0 h" ?3 r5 S9 L
  20.   return touch_y;
    # z6 P& K0 d5 y( G9 i
  21. }
复制代码

4 S$ `9 L. ]5 n5 M! J3. 使用GUI_TOUCH_Calibrate函数校准x与y值,然后才能调用GUI_TOUCH_Exec()函数处理触摸事件。
/ D/ {; \" H4 b2 p% g& V& t6 i# i6 c$ L+ }# g+ K: K0 w
  1. void StartTouchTask(void const * argument)
    - L, ~3 O% z/ @( D# I
  2. {0 M: x6 P7 H# i/ G+ j* R
  3.   /* USER CODE BEGIN StartTouchTask */8 p' e- s+ Y% V/ @
  4.   GUI_CURSOR_Show();//显示鼠标指针
    2 s: Q' {2 Q: g/ G
  5.   GUI_TOUCH_Calibrate(GUI_COORD_X,0,LCD_WIDTH,0,LCD_WIDTH);   % I( U$ y4 K' S) A* l, p$ S& g, ]
  6.   GUI_TOUCH_Calibrate(GUI_COORD_Y,0,LCD_HEIGHT,0,LCD_HEIGHT);- p& v* z; Q6 e8 Q
  7.   /* Infinite loop */& B8 k5 O7 d9 b) z6 C3 {
  8.   for(;;)9 Z" |" i$ i- }8 r: e) F+ N. L
  9.   {
    ) H4 F7 Y0 b: A7 Q$ s
  10.     GUI_TOUCH_Exec();% ^1 W7 `8 \% j: ~
  11.     osDelay(5);2 L. }4 g" C4 V% ?$ i) K
  12.   }
    0 j+ Q/ \# i' s7 o
  13.   /* USER CODE END StartTouchTask */& ^' a% r2 D* M# ]7 `
  14. }
复制代码
$ j% b' M& o+ A9 A* o7 v

+ Y) {+ p# \& E, c
/ S) y8 k$ z) k) ~. p! U1 ], Z# u7 V/ D0 o/ c% c; Z  e/ i0 z
收藏 评论0 发布时间:2021-12-17 12:05

举报

0个回答

所属标签

相似技术帖

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