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