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