一 电阻驱动与电容驱动原理
3 [. V; \( J5 R; m: v2 b! F0 e3 s! T' }, E
1. 电阻屏等效电路如下所示, 当产生按压时:! l$ Z: a5 ]0 W1 d5 ^& r" C
X-接地,X+接电源,Y+接ADC输入.通过读取Y+的电压以及电阻分压原理,可以得出触点的x坐标
; t0 K, o/ V' p) g/ ~Y-接地,Y+接电源,X+接ADC输入.通过读取X+的电压以及电阻分压原理,可以得出触点的y坐标. R% B: X9 V6 b( r# q# k+ P7 k
( M7 G7 V, T! \& o$ K
/ X1 W0 e* I' X& ?# c1 Z
2 N7 f6 M( O( e# O8 F
2. 电容屏等效图如下所示, 检测原理类似矩阵按键, 当产生按压时:
" q$ D4 I5 X9 ^( g- p: c. A( J8 {* P" @' o
X轴产生从上至下依次产生激励信号(AC交流信号), Y轴电极同时接受信号 (该激励信号是交流电,可以通过电容穿到Y轴)./ y# D4 n% a; _6 ]7 U! S y
5 ?; r9 `/ S$ B2 \) m+ q: }- A
假设有如下两个按压点(分别位于(1,1)与(2,2)的位置),检测过程如下:
+ W1 i& Z; m- ^+ z: d$ {; ?0 A当X1产生激励信号时,Y1接受到的交流信号产生了变化, 所以可以确认(1,1)处有触摸.
7 T0 Q+ d* g5 |% Q; o* `$ D) x接着当当X2产生激励信号时,Y2接受到的交流信号产生了变化, 所以可以确认(2,2)处也有有触摸.1 R9 l* z2 O7 u( \
; ` T, u9 T' i% b* r
/ ^5 \/ n t Q7 i$ j: K
( A" W: t0 b D- w5 K' j+ z0 Y二 软件模拟IIC6 a$ q/ i5 Q$ T
由于stm32的硬件iic有各种各样的问题,所以采用软件模拟IIC的方式,主要实现IIC起始信号函数、IIC停止信号函数、等待ACK函数、产生ACK应答函数、不产生ACK应答函数、发送字节函数、读字节函数) l7 D& m F- v
* k0 R1 m9 Y3 ]8 w" D1. 起始信号与停止信号4 S8 M, _$ M; z4 I0 Y
+ ]/ X+ `+ R! s/ Q8 K8 h$ i
下图是IIC起始信号与停止信号时序图,通过观察该图编写起始信号与停止信号函数。
+ @! b* B: `- ^( B% D1 w% f/ i8 L" I/ Z' |3 Q5 j+ y, z
! k& S% d* |% G0 E! k" a
" K1 i3 N" C% d* L# b
起始信号:当SCL为高期间,SDA由高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号。
* l- P0 m5 K/ l+ u B# r' C3 _ J- /***************************************************************************************
$ M! M7 P& C; {6 L - * @brief 产生IIC起始信号,当SCL为高期间,SDA由高到低的跳变% h! P8 ~1 z* f! c! {) F3 M
- ***************************************************************************************/" ]! k9 s6 V0 v; z5 ? S
- void CT_IIC_Start(void)
3 ?: @. @) D- m: L* R - {
9 Y' G) R- F& T$ r: X - CT_SDA_OUT(); //sda线输出4 A4 @! L( U0 \
- CT_IIC_SCL(1);) ?9 K S0 r8 x
- CT_IIC_SDA(1); # |9 V- `' S( K$ m3 {
- CT_Delay();! I @* L& q4 y$ ]! X, c0 B
- CT_IIC_SDA(0);- r2 Y0 \/ F2 a( Y' ]
- }
复制代码 ' T1 K* G. h1 q3 D; E
停止信号:当SCL为高期间,SDA由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。6 V2 X5 t. ]9 |
- /***************************************************************************************6 O9 d6 ^1 k7 W& e, @
- * @brief 产生IIC停止信号,当SCL为高期间,SDA由低到高的跳变
* \! j; i- }1 y/ C6 d. G - ***************************************************************************************/
3 u: w0 }0 c4 U- a B. G - void CT_IIC_Stop(void)' Z/ f) K, h% D0 b
- {% C' w' D4 P) ?2 |& N
- CT_SDA_OUT();//sda线输出# E, {( h; O. n7 V7 O4 r4 m* m
- CT_IIC_SCL(1);
& M0 b' n( ` w& h - CT_IIC_SDA(0);//STOP:when CLK is high DATA change form low to high+ L9 N1 ]; E, S& d) f
- CT_Delay();1 g) k0 t3 `2 w6 _! d
- CT_IIC_SDA(1);: P D$ s+ h& V
- }
复制代码
6 N4 Q4 p: z& e- F在GT9147数据手册中可以发现如下截图所示内容,SCL在低电平期间至少保持1.3us,其他电平最小保持0.60 L: i& P* H0 {$ r; m; T( k- y
; X- {8 J" p' T2 r: P
) R! U0 Y6 \9 O* Z* G9 S# V3 C/ s$ e0 k0 B$ M
所以将IIC延时函数定时为2us可以满足所有时序。(一般支持最高速度400k的IIC设备,基本都可以使用2us延时。)
3 h( p7 k5 l4 I8 T' h
3 d- N! a* s# x7 [7 B- //控制I2C速度的延时
& P" |8 J$ e7 H% e0 {0 W - void CT_Delay(void), F( K: u+ c5 |, N* i
- {
8 {% q5 A( f4 s5 f! G7 b - delay_us(2);- j: h' D: \9 c) }4 F2 D7 ]# q, v
- }
复制代码 ! Y1 V3 P4 J- F9 o9 r" R, N4 }
2. 数据传输 与 ACK时序
1 w- u9 H" J" Y
4 B! f3 C @% A$ n( R下图是ACK时序与 传输数据0的时序图,这两种时序图是一样的,区别在于ACK是在8个数据时序后产生,且SDA电平是由接受数据端拉低的。2 @$ [, n. t( ^
; I! K" y% c0 o6 m* `( B; ~
- j& h2 i' b# m3 X4 w7 c7 u) B
7 t' d. G: V# {9 K$ C产生ACK时序:在SCL高电平期间,SDA为低电平状态。" R @; k% K2 W! n( J
- /***************************************************************************************- D. q5 I/ n- F$ {* L9 u! d% P. r
- * @brief 产生ACK应答,
' C# _$ J) b; B. ~2 w& f8 ~- m - ***************************************************************************************/
) K: f; O6 H7 \) |- }9 M A/ Z% C4 d - void CT_IIC_Ack(void)3 Y' Q5 A( \7 ~$ N ^* k/ Y9 X
- {
o* h, y2 b: r. U. Z2 A - CT_IIC_SCL(0);
+ N7 C7 {' b# c/ a, W - CT_Delay();
& _/ e, s; ^+ X1 [ - CT_SDA_OUT();
" l1 t# ?6 n6 W3 |# T - CT_IIC_SDA(0);
* A) k5 C! [( B) [9 u a$ J9 ^$ W - CT_IIC_SCL(1);8 D* r% C. T. F: r6 j
- CT_Delay();
" x' e4 o! \" m3 O2 n/ D. ^ - CT_IIC_SCL(0);
3 h u, A2 {' P2 l0 J. U - }
复制代码
5 d1 y7 d9 i( |6 W等待ACK时序:拉高SCL与SDA后, 然后设置SDA为输入检测状态,等待接受数据端拉低SDA" ? U7 B1 ^ X' w' {2 s! m
- /***************************************************************************************+ ~! g# d1 I/ F/ Q, V2 G9 O
- * @brief 等待应答信号到来,等待接受数据端拉低SDA2 x" k+ ]6 p: D# W
- * @input
- F! _! Z6 j1 ]9 k$ Q - * @return 1,接收应答失败 ; 0,接收应答成功
$ Y! w/ V3 d# x' T9 T0 W" @ - ***************************************************************************************/* |5 A+ L' }1 [* c! L! Q$ p
- uint8_t CT_IIC_Wait_Ack(void)2 r$ m7 d8 D! E/ t( R8 p
- {
; `" W% _8 e8 O e! q# c - uint8_t ucErrTime=0;0 e i/ U4 W5 ]
- CT_IIC_SDA(1);
: j2 |+ r) h% ?8 @ - CT_IIC_SCL(1);
2 }3 G$ A; L0 [$ {, d' \0 f - CT_SDA_IN(); //SDA设置为输入 $ I4 D! u9 x2 j- o% J q# g
- while(CT_READ_SDA)+ B! N# @8 j+ ?0 {
- {# P( b& }7 y# g" ?; T9 k' f- }
- ucErrTime++;
$ ?1 A; c8 P: k - if(ucErrTime>250){" l1 A/ W% e7 B2 v& v2 |
- CT_IIC_Stop();
" G# c& u& S7 v8 u - return 1;+ m8 y6 o9 ~3 s$ `
- }
! x. R& ~+ H% ]" j - CT_Delay();- s6 X2 o1 X$ e0 o) E" K
- }6 ^) y* x& y- i$ P( K
- CT_IIC_SCL(0);! \9 s: N' v `2 P9 j
- return 0;
U- E. D- w( `' e1 C/ J; { - }
复制代码 - K* e' H# e/ R _
下图是nACK时序与 传输数据1的时序图,这两种时序图是一样的,区别在于ACK是在8个数据时序后产生,且SDA电平是由接受数据端拉低的。3 v5 T6 r) _9 m6 a# I' A6 e
& c' m! s8 a# f
; u; x+ W" S7 Z# Q, X9 u1 `
6 d% b* L! R* @产生ACK时序:在SCL高电平期间,SDA为高电平状态。/ R" N$ k( |# ~2 u: v$ I4 R
- /***************************************************************************************
5 _; R' f: a0 e, p% D0 Z - * @brief 不产生ACK应答
v, M) {, m% B( c2 U6 f* y6 m% k - ***************************************************************************************/* R) N# n- p/ f, L. O- A
- void CT_IIC_NAck(void)
) V, ^6 n, O1 _2 M! ^0 B$ j5 _1 O - {7 h) o+ M1 Q) i- M# R
- CT_IIC_SCL(0);1 o( K. \8 e$ }, F- Z( e0 x7 N0 F
- CT_Delay();
$ {* S ^6 D% S# P! u' q8 S2 ` - CT_SDA_OUT();
' a* S! y5 R* x( @! Z - CT_IIC_SDA(1);7 f6 X, S3 A V* X
- CT_IIC_SCL(1);3 K( e9 G' k3 h
- CT_Delay();9 X# o/ j& f! S
- CT_IIC_SCL(0);
* } O' }; H' i8 W. N+ u" h" T, ] - }
复制代码 ( x) P& J! X8 O' U
发送一个字节函数,优先发送高位,即从bit7开始发送。$ c; N4 [. w; c3 ^
- /***************************************************************************************
% U" \: S9 m5 _7 k+ [ - * @brief IIC发送一个字节,* L/ K' {8 g3 t6 J# Y
- * @input 6 b" O' e' Y8 f9 B
- * @return / ^8 }" Q3 _( W4 U" Z) V1 ^
- ***************************************************************************************/
4 l$ q. p7 }+ X# R - void CT_IIC_Send_Byte(uint8_t txd)$ T+ }0 O. ^) V) y/ b9 q
- {; M/ B- L& ^) D1 e7 h% Q4 Z8 J( V9 P" z
- uint8_t t; 7 V7 f$ m4 `2 q: z
- CT_SDA_OUT(); * G- D$ u. Y1 g# J! A$ x" I5 b9 [
- CT_IIC_SCL(0);//拉低时钟开始数据传输9 S' {: i4 f- @. g6 {* `
- CT_Delay();: G2 D+ x* g/ ~6 T/ f1 o
- for(t=0;t<8;t++)! ]+ @* v' E( `9 U
- {0 A' S" b. k$ i4 G9 |# ]& V
- CT_IIC_SDA((txd&0x80)>>7);//发送bit7位+ E" \# V* s- W* E% z( P5 N. i
- txd<<=1; //将txd的次高位左移到最高位 : I. J! k% d4 g2 | U
- CT_IIC_SCL(1); 1 R/ k0 f' v4 Y" l( g
- CT_Delay();
* K# e) ], Z( w0 r; m - CT_IIC_SCL(0);
; Z( }* ]2 m; _+ h0 m3 ] - CT_Delay();/ T; I1 I! W) Z6 f
- }
9 n% h2 o3 r% U6 m3 u' R* j - }
复制代码
7 r. I$ k- {# M" G: O/ x* t3 A读字一个字节函数,接受到1bit数据后,将该bit放在bit0位置(通过receive++实现),如果还要继续接受数据,则将之前接受到的数据左移一位(通过receive<<=1实现),留出bit0位置接受新的数据。4 ?) J( @" E/ D0 w. K4 u
- /***************************************************************************************
4 r! O4 z6 ~" i: b* o" P - * @brief 读1个字节- k' ~% k) z5 Z8 \
- * @input ack=1时,发送ACK,ack=0,发送nACK( N h/ i$ J- E6 p9 {
- * @return
# A9 y1 f! Y8 J% [ - ***************************************************************************************/
' ]8 R2 \; Y1 @/ T$ a6 ` - uint8_t CT_IIC_Read_Byte(unsigned char ack)% I& Z- {" G( O5 w) z0 E
- {8 }) Y* P3 I) R7 l$ j9 @; b
- uint8_t i,receive=0;7 w5 c% ^ L& i) H. E, U% Z
- CT_SDA_IN();//SDA设置为输入
: h, N% \" l: j - CT_Delay();+ x! n! K2 a$ H Y. ?
- for(i=0;i<8;i++ )
, |; O( q" S& b - {
, C4 G- B/ Z% x' u2 P# \" [9 N5 z - CT_IIC_SCL(0); - L0 ?- h5 D. U. a
- CT_Delay();
% T- Q% G" Q8 m8 S. e- R+ ?) {1 \ - CT_IIC_SCL(1); # e" W- u) I3 c2 a
- receive<<=1;
& j7 J% P& Z8 B( | - if(CT_READ_SDA)receive++;
, h" [9 S" T2 z& w0 y7 v2 x - } : z( x9 Y6 t# L+ |4 q8 E* z
- if (!ack); a, |0 C. @ c. y5 @
- CT_IIC_NAck();//发送nACK3 U \& ?( Y q( B3 l
- else - K* L4 q5 {3 H1 U& A. q2 A* \' Y
- CT_IIC_Ack(); //发送ACK
6 H& Y3 Z- m k - return receive;
8 G" q" S, \6 p5 e& r( D( g - }
复制代码
. J/ `) d O! Y1 z( G: F三 GT9147电容触摸屏控制芯片驱动
" K. A. b+ B/ W1 R$ o/ a" ]1. GT914内部结构框图如下图所示
3 Q" L$ J( `% u" \6 l0 l+ ~' `( R
2 {( R; J7 x* X0 n! L
! n- h* W$ ?. d: @7 Q: @& _% l" O( Z) U* U
c; m e' ], {# z+ |- ^5 }' g6 L4 o/ r/ a9 J! l3 G
2. 上电流程" s0 u, z$ D: G3 s' A2 O
& Z( s- I+ p- f4 H+ f- o& t5 ]- G/ G
GT9147上电初始化流程如下所示:
. y0 f3 Y" l1 I" G: y5 B1 d; f$ v& }3 O4 t
配置RST输出低电平,INT输出低(或者高)电平后,位置100us以上,此阶段配置IIC地址为 0xBA/0xBB(或者0x28/0x29)' p5 o8 f. z1 D E& I. \8 i+ n
接着配置RST输出高电平并维持5ms以上后,可以配置INT引脚为悬浮输入模式。& u# H* A- B# T+ T: D: e
等待50ms以上后,可以发送配置信息。4 k; s. Y7 ?7 H m
4 p# \. ?) t% z& @7 O
( }$ W7 v4 q* [3 k: I- I n; ~" u7 J( Y: I' h' c
代码参考原子例程编写,贴上代码: r$ x/ n5 C6 Y( E% ?$ q, @% ~8 w( y
1 z# F0 A2 T/ x3 e( K% p ^' Y- uint8_t GT9147_Init(void)
4 _" g2 t7 B/ o& x( W( K% Z% X - {' V0 o3 `8 ^% s4 u
- uint8_t temp[5];
+ ^( a$ j7 H' U
& N& Z: ^/ i0 m6 j7 {! N, ~; u- GPIO_InitTypeDef GPIO_Initure;
) B3 u2 s, Y# ^% X - ( \4 K6 c9 B% `0 b1 x( t" o
- GPIO_Initure.Pin = GPIO_PIN_7; //PH7" n+ N4 x* U' d* @' k! C8 w4 U
- GPIO_Initure.Mode = GPIO_MODE_INPUT; //输出
7 L9 u, G: P, Y! {* T+ Y( p - GPIO_Initure.Pull = GPIO_PULLUP; //上拉
; u, [3 t4 B: o/ ?. E! w - GPIO_Initure.Speed = GPIO_SPEED_HIGH; //高速
; h g5 Q3 e+ [# z- f3 } - HAL_GPIO_Init(GPIOH, &GPIO_Initure); //初始化
" T/ L6 j, E7 B+ O" V3 E7 E
" h$ ^! K3 `, T2 @7 M/ Y! q- GPIO_Initure.Pin = GPIO_PIN_8; //PI8
) ^' a; Y: u- @5 Z R - GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP; //推挽输出
7 ]* e5 |, R1 K4 |% O e9 x$ e - HAL_GPIO_Init(GPIOI, &GPIO_Initure); //初始化
4 s; H* _7 K& m3 |/ _
& X' E1 H" D: F. i0 h- `# y1 b- CT_IIC_Init(); //初始化电容屏的I2C总线
7 N/ I' f0 H5 r' U% R- s$ |% [
2 N: Z* v5 j3 H5 W6 B N: ^4 n- GT_RST(0); //复位. ^1 X% M0 N' I4 f" i* R
- delay_ms(1); //INT引脚电平维持100us以上
& P# f* a. {3 {, s - GT_RST(1); //释放复位
- j/ `, h! G) O; z7 ` - delay_ms(10); //释放复位后维持5ms以上,设置INT为悬浮输入
/ q4 H( u! d2 q) w; K5 L4 } - GPIO_Initure.Pin = GPIO_PIN_7;
* w9 H: \8 I: D- X - GPIO_Initure.Mode = GPIO_MODE_IT_RISING;# v3 {: M1 e. y) S8 k# L
- GPIO_Initure.Pull = GPIO_NOPULL;) A0 |7 B6 j' Q3 ?
- HAL_GPIO_Init(GPIOH, &GPIO_Initure); //初始化
: z6 m: {, ?! E ~: \ - delay_ms(60);
5 @; }1 G4 Y9 V1 G
t6 N! y0 ^) r0 X) { ^5 s- GT9147_RD_Reg(GT_PID_REG, temp, 4); //读取产品ID
: c) m, U- `2 [7 c) d2 H( W* V - temp[4] = 0;
9 E6 B1 h: e* h% O. ]2 X - printf("CTP ID:0x%s\r\n", temp); //打印ID- Z$ D' L3 N$ ?% J
- 7 s) y! ]3 P j8 B& H
- GT9147_Send_Cfg(1);//更新并保存配置
D" m: r! W& I6 e
! }1 M6 }3 V0 T8 X U: f- return 1; C* b) I/ S/ d: y
- }
复制代码
$ s' G# `, k1 R3 W6 b7 W! }, G* D0 b( i3. 读取坐标流程. p$ R8 o1 S! i& x) ?3 K1 F
1 q# o* g3 E5 w. @2 }使用中断方式读取坐标,需要注意的是,如果不及时读取坐标信息会一直产生中断。GT9147的中断脚与STM32的LINE7中断线相连,中断回调函数如下所示。当按下触摸屏时,touch_x与touch_y分别保存触摸时的xy坐标;当松开触摸屏时,touch_x,touch_y赋值0xffff! g) i! T0 B, ^8 W
; [( S" j8 h5 T% _6 W
- void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)0 b, ]4 u g* C% h; L- e
- {
* t; N4 k) w( B) B4 t! C- I. E4 E - uint8_t buf[4]; O, _" a& |% G$ v6 [
- uint8_t i = 0, mode = 0, temp = 0;! }) ~8 p2 Z" d5 _ x
- uint16_t x[5], y[5];
/ H9 e6 d% d2 o6 A7 ?2 M - if(GPIO_Pin == GPIO_PIN_7) { //读取坐标, 否则会一直有INT脉冲% t0 H. `8 V3 H* y* r# L
- GT9147_RD_Reg(GT_GSTID_REG, &mode, 1); //读取触摸点的状态2 @# {' U/ \; r6 X+ Q, N) w
- if(mode & 0X80 && ((mode & 0XF) < 6)) //有坐标可读取
/ c2 K' W* \& M. W' |0 | - {) Q2 T: {2 M- G4 O+ [7 k7 U
- temp = 0;: S% P; S1 u+ z
- GT9147_WR_Reg(GT_GSTID_REG, &temp, 1);//清标志% }, P6 m' t4 B9 w
- }* S% O% d) M' _% G' D8 Y
- if( (mode & 0xF) && ((mode & 0xF) < 6)) //判断触摸点个数
" \- |) Y5 i# g4 M - {
/ T. F( J( r# ]' z) }+ G - for(i = 0; i < (mode & 0xF); i++)
$ J) p4 D* O- l - {, w6 Z) ~, G+ ^' J1 v0 S
- GT9147_RD_Reg(GT9147_TPX_TBL<i>, buf, 4); //读取XY坐标值& P; s# l, P: Z8 M
- </i>x = (((uint16_t)buf[1] << 8) + buf[0]);' m3 p( L% j d. P
- y = (((uint16_t)buf[3] << 8) + buf[2]);. \! S: ~9 F4 d$ E* C( c* c
- }
% [; n# X. _) A- o9 }* m - touch_x = x[0];9 i7 H0 ?" ^6 q* O* ^. K
- touch_y = y[0];, [% s* I8 B# t' y+ g) y7 X
- }
, L4 d1 d+ H4 j8 ^6 P2 |
: [5 E: j# J$ _& w# p. m' C! j- if((mode&0x8F)==0x80)//无触摸点按下,xy赋值为0xffff# t2 N0 N g. v% Q* w- F9 k* k- p
- {
4 S5 L( A s+ [' t( e - touch_x = 0xffff;7 ?; T8 E4 o5 [- t* [, j$ z2 C. B* E
- touch_y = 0xffff;
0 b. `: _; w, t1 L- ]7 l2 R - }
' ]% A/ \1 e: N5 \/ G3 U - }- I" m8 `* M5 P; x& q
- }
复制代码 4.主机 对 GT9147 进行读操作时序8 L0 ^* k8 x5 X1 x2 X
7 f3 g' F4 c" h" b
! o7 a6 F) n' G0 T8 X4 j. \
, q/ ^! S- V& B/ |/ q" y I$ i根据该时序图编写读寄存器函数如下:
3 |1 K3 z; J6 y, u: J- W K# {# q4 F8 T5 A* n8 S
- /***************************************************************************************) B0 j: Z H1 C) S! j ?
- * @brief 从GT9147读出一次数据
' m5 R9 l9 k! M - * @input reg:起始寄存器地址
3 K( v' V5 A: I! \( y - buf:数据缓缓存区9 W8 j: g- U% S
- len:读数据长度
% C! H. b4 i$ z7 x - * @return
! ^/ l) R6 o( L7 p5 E- o- o$ m - ***************************************************************************************/
: g8 |9 _0 O, E) s: n/ } - void GT9147_RD_Reg(uint16_t reg,uint8_t *buf,uint8_t len)
% f3 F& l' d8 [) E3 \; h - {
# R- g# f g9 z% H - uint8_t i; {) h1 @( H: F, B4 C, \0 @
- CT_IIC_Start(); ! }$ A `! ]3 c0 N9 F* v- N& m+ q( S0 g
- CT_IIC_Send_Byte(GT_CMD_WR); //发送写命令
3 o2 l5 P: Z) R+ q% @5 E5 s - CT_IIC_Wait_Ack();- j B6 K4 h- E; D% `) \# b
- CT_IIC_Send_Byte(reg>>8); //发送高8位地址
; r7 A$ v6 Y% i - CT_IIC_Wait_Ack(); 2 P* M; r8 T4 j
- CT_IIC_Send_Byte(reg&0XFF); //发送低8位地址
& A& f, Z, X7 V& m7 a - CT_IIC_Wait_Ack(); ( w% b; I$ L0 y* B3 X7 ^
- CT_IIC_Start(); / t) ?0 c n o% H, m4 l7 F* d
- CT_IIC_Send_Byte(GT_CMD_RD); //发送读命令 ! |; j" {+ e( S9 m$ p: m0 M
- CT_IIC_Wait_Ack(); ) X5 i' k+ ?7 ~* M# Q0 `, N
- for(i=0;i<len;i++)
, s4 b' ^0 K5 {5 g* m; j w - {
2 J; O/ [+ H( k" L; |+ e- Z - buf<span style="font-style: italic;"><span style="font-style: normal;">=CT_IIC_Read_Byte(i==(len-1)?0:1); //发数据
7 W, U; I( ~2 I8 O. T - } I4 @/ C! u2 b/ B/ B6 b& o3 G) t
- CT_IIC_Stop();//产生一个停止条件
7 J" B1 C3 n7 ^& `& P, H! e+ m# q, h7 X - }</span></span>
复制代码 " m# z+ a# f$ ]
5.主机对 GT9147 进行写操作时序
5 e$ Z. ~& Z) ^1 G
& x A, q% ~& M( E
8 R) j$ w; u- k7 A- K/ \; x( M' o- ^) r1 M
通过该时序图,编写写寄存器函数如下2 C8 @+ h$ N. j5 D8 o: Z1 [
% V: y+ W: Y' |) w( T$ J' v- /***************************************************************************************% F2 K; Q3 L4 W# R
- * @brief 向GT9147写入一次数据
5 o* W; m8 q! s - * @input reg:起始寄存器地址;
( E$ E* {! S- N1 X - buf:数据缓缓存区6 f) [+ Y h3 E) G S! c) c& L' r
- len:写数据长度$ r3 B" z( A! ^, F
- * @return 0,成功; 1,失败.
9 E, p; `5 A% q( ]7 y" J - ***************************************************************************************/4 ?; G0 \. E( _8 V9 ~ s' P9 I
- uint8_t GT9147_WR_Reg(uint16_t reg,uint8_t *buf,uint8_t len)9 P7 ^9 N9 I# y( W
- {: h* N0 B! p' ]( Y0 Q) F
- uint8_t i;
. o+ p/ H% S8 K" t: m3 y; l+ O* h - uint8_t ret=0;
( W7 x' i: @, E( Q; }7 f, J - CT_IIC_Start(); # t5 O, y9 d1 v* z
- CT_IIC_Send_Byte(GT_CMD_WR); //发送写命令
" ~$ N- R" u2 b7 a7 j - CT_IIC_Wait_Ack();) ~- \4 C4 l, e+ Q, N$ b
- CT_IIC_Send_Byte(reg>>8); //发送高8位地址
9 y; u3 x9 M: a+ B I3 b5 f2 v( v - CT_IIC_Wait_Ack(); 2 L' J8 v$ v2 r/ m+ T7 `' l
- CT_IIC_Send_Byte(reg&0XFF); //发送低8位地址( ?, Z) p" E( u4 k# H7 b
- CT_IIC_Wait_Ack();
3 [. h- [' v* d3 o4 f5 K- A. t9 G - for(i=0;i<len;i++)
5 a/ q6 G3 v+ N+ Y9 M W5 X4 N, Q - {
# }, x h1 N+ L4 r6 S2 a) S* Q8 p - CT_IIC_Send_Byte(buf<span style="font-style: italic;"><span style="font-style: normal;">); //发数据
7 P9 L* T9 b9 s! \3 n, g0 x - ret = CT_IIC_Wait_Ack();
- Y3 q |3 e' u0 D3 V) M0 N' U+ ~ - if(ret)break; 0 C& ]) p- x; {7 g
- }
% x7 v7 r7 e/ q - CT_IIC_Stop(); //产生一个停止条件
5 ] M$ e. I3 { - return ret;
* H0 u1 w( W8 {3 Z - }</span></span>
复制代码 $ j% a0 @, X3 N$ u
6. GT9147配置函数如下,GT9147_CFG_TBL针对分辨率480×272的触摸屏。9 r/ N0 H# J v% _
. F! l) p" b1 J* N; Z2 B, d) J- k配置寄存器时是要注意以下几点:3 u( S- k W7 m% r( K3 K
; m/ M0 S" v% w9 L新的版本号大于等于GT9147内部flash原有版本号,才会更新配置.0 ]$ J7 d, F- ]% u2 j) s" u
写完GT9147_CFG_TBL中的配置后,还需要往0x80FF寄存器中写入校验,0x8100寄存器中写1。9 _( @ g( p0 P( h4 D: M
关于配置更详细的信息可以参考GT9147编程参考手册: \2 M( l: [ ~9 M- T
- const uint8_t GT9147_CFG_TBL[]=2 @) V8 u6 d- ]6 z
- {
# y$ i. H5 f: \7 N5 Q9 ^. a6 n- i - 0x60,0xe0,0x01,0x10,0x01,0x05,0x0C,0x00,0x01,0x08,2 U0 g$ _' P8 P. ^9 I1 g
- 0x28,0x05,0x50,0x32,0x03,0x05,0x00,0x00,0xff,0xff,
4 A7 l; |; d0 v) ]9 M' T - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x89,0x28,0x0a,: W9 ]) E! V3 E
- 0x17,0x15,0x31,0x0d,0x00,0x00,0x02,0x9b,0x03,0x25," ^$ {, S& Q, n h: W
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0x00,0x00,* Y b }- e- q9 a# |( o$ w
- 0x00,0x0f,0x94,0x94,0xc5,0x02,0x07,0x00,0x00,0x04,. C6 P' C# [# l, [; t- |# t
- 0x8d,0x13,0x00,0x5c,0x1e,0x00,0x3c,0x30,0x00,0x29,
% P9 _' U8 G, R5 p( | - 0x4c,0x00,0x1e,0x78,0x00,0x1e,0x00,0x00,0x00,0x00,
9 b. {" G* ~1 R' C - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0 F; p4 T* V3 W2 G1 N+ F; `4 ^- Q
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
# _8 _9 n2 v" q) L" F - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
: G7 L/ ^: O/ o+ ?" o - 0x00,0x00,0x08,0x0a,0x0c,0x0e,0x10,0x12,0x14,0x16,
7 U! y: @. r' S8 g2 M" M2 D9 { - 0x18,0x1a,0x00,0x00,0x00,0x00,0x1f,0xff,0xff,0xff,! O2 }1 k. x* b* e4 [* A( I& e5 E
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
# E' n/ U; |0 |; _6 S8 i( K5 M z, ]. x - 0xff,0xff,0x00,0x02,0x04,0x05,0x06,0x08,0x0a,0x0c,2 d' ^% ^0 i5 Q- G/ q: ?, u$ T) G/ h _
- 0x0e,0x1d,0x1e,0x1f,0x20,0x22,0x24,0x28,0x29,0xff,
8 l2 B* d; W$ |+ g( L9 S& E - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff," {5 m. A3 v7 J, K$ p9 E9 y! g
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,& a! _ ]* x$ R+ ?
- 0xff,0xff,0xff,0xff,
6 ~, ~! `7 v; v - };
: M1 A" h4 U! E' W - ' z; `( Y/ ]& B/ c* j' r6 c
- uint8_t GT9147_Send_Cfg(uint8_t mode)
9 [9 d. f: g' d) G( J) i+ m) x( ^. L( `' j - {
$ x0 I: p6 Y! C, c) N: ]9 m6 L - uint8_t buf[2];7 V: N# {4 R& r# J2 q$ ]: h2 F0 G$ U
- uint8_t i=0;8 h6 a$ o% B Q2 O+ z# B% }
- buf[0]=0;
. X% g: D) H3 x6 B& o. B - buf[1]=mode; //是否写入到GT9147 FLASH? 即是否掉电保存2 N$ u% }& S; S7 u0 h/ g& u
- for(i=0;i<sizeof(GT9147_CFG_TBL);i++)/ ~" q; L+ {4 U1 r" b
- buf[0]+=GT9147_CFG_TBL<span style="font-style: italic;"><span style="font-style: normal;">;//计算校验和$ `; g: d: N* \ l6 A% r
- buf[0]=(~buf[0])+1;, U( L$ F K9 O. E% }
- GT9147_WR_Reg(GT_CFGS_REG,(uint8_t*)GT9147_CFG_TBL,sizeof(GT9147_CFG_TBL));//发送寄存器配置
% S. I2 U3 D. }$ d - GT9147_WR_Reg(GT_CHECK_REG,buf,2);//写入校验和,和配置更新标记0 Y! \1 K% V4 `& `( F
- return 0;0 K4 b$ k, \" @+ T" Q3 ?% G( T5 [
- }</span></span>
复制代码 4 s+ ]3 I" t: m8 Y' @3 L3 l
四 移植触摸屏驱动到STemWin% u' g+ v1 ?# I+ D
这里假设已经成功移植了STemWin到STM32F7工程。4 s5 V0 \' b& g% i/ S
0 t5 S7 j Z' p
1. 在GUIConf打开STemWin触摸屏驱动宏" ^) @% q2 `6 h4 w) Y
+ B7 v4 @- c5 ^1 u/ z9 v$ P* V
- #define GUI_SUPPORT_TOUCH (1) // Support touchscreen
复制代码 . E% Q6 U5 C x1 d
2. 新建GUI_X_Touch_Analog.c文件实现以下四个函数,在第三章第3小节我们知道touch_x,touch_y表示当前触摸的xy坐标。整个文件的内容如下所示。
5 ^6 v7 G3 H4 a& N
; _, J* u7 i5 D8 ?8 }- void GUI_TOUCH_X_ActivateX(void)
9 b7 q1 `8 `9 f* M) [9 T - {: H/ v) n+ e( J2 n/ E
/ y7 D4 O* d; D& S* m- `- }
" Z) A- L2 P' I& F7 E* a' n7 ] - 1 y& F% g3 h5 c) B
- void GUI_TOUCH_X_ActivateY(void)
* Z& Z" d1 d, R! V - {* T# c2 }& n' i) l# H
w+ a+ Q4 P2 e7 p- }
$ [/ F, _5 m& g( r! {8 D
* @; i, h: b& Q8 K- /*获取x坐标*/! e0 N7 K" [1 j( e
- int GUI_TOUCH_X_MeasureX (void)
# Q3 ?5 M* N' _* M$ n, z - {
- W6 |) z4 \8 ?& H3 C - return touch_x;
7 ]7 S; n; i; ]5 G - }* o7 z& R: [2 [+ e9 I X
- 8 F6 G4 A) c. O! c, P% Z4 Z% I
- /*获取y坐标*/* j+ M( S1 W2 n# j r( T" J$ s
- int GUI_TOUCH_X_MeasureY (void)+ K$ k* [+ \# _) Y2 D' H
- {
. ]8 U4 T6 B$ Q* d. t5 x9 Z" N - return touch_y;" ^7 l0 Y4 {' O8 n, Y1 ]
- }
复制代码
) ]7 i$ ~' q% ~8 ?* m3. 使用GUI_TOUCH_Calibrate函数校准x与y值,然后才能调用GUI_TOUCH_Exec()函数处理触摸事件。
( r! {( x* A$ J0 F5 \2 a8 d( D0 S: G4 x; L
- void StartTouchTask(void const * argument)* ]7 N/ D0 Z/ B+ ]# |$ a- S
- {) X) h1 A; e. l) J( y/ J0 n
- /* USER CODE BEGIN StartTouchTask */2 \! W+ c1 _# A
- GUI_CURSOR_Show();//显示鼠标指针
2 e8 E8 L$ X- _* ?0 q - GUI_TOUCH_Calibrate(GUI_COORD_X,0,LCD_WIDTH,0,LCD_WIDTH); ' W& L# L# a8 q7 J
- GUI_TOUCH_Calibrate(GUI_COORD_Y,0,LCD_HEIGHT,0,LCD_HEIGHT);
' ?/ y; O; F/ ]! M( i1 } - /* Infinite loop */
" Y8 U* ^6 x+ g$ p3 I - for(;;)
; o8 J( k& R/ k- V; C# S0 ` - {
) C* U2 C; c- [. K' r5 r9 ~+ ~* P6 _ - GUI_TOUCH_Exec();
0 D3 t; _8 ?9 {: f h9 d V9 A - osDelay(5);
3 b( h$ z Q% P. ?6 k - }
* @9 G2 D3 G( ^" z' q/ E - /* USER CODE END StartTouchTask */: m$ L) \& Y+ X5 b/ c1 e
- }
复制代码
! v7 j4 L( n1 f* v7 |9 V8 y
" J. S- X0 d# Y& E$ \4 ?
. e: S; K* q: h( w9 I6 _! \* i3 q. m1 ^5 @
|