一 电阻驱动与电容驱动原理
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
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
( 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) }
. p! H& A% {; ]3 o$ n
, ?! n# I3 v+ G起始信号:当SCL为高期间,SDA由高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号。
5 o$ ^; Q; Z( C& E: Y# m' y5 d- /***************************************************************************************
! V% B' ]( }- D- x: Y% g2 U - * @brief 产生IIC起始信号,当SCL为高期间,SDA由高到低的跳变7 @& F S4 B1 U& A, I( A
- ***************************************************************************************/- F x+ j# i7 Z; Z
- void CT_IIC_Start(void)
, A$ C5 V# ]( K - {( L: y/ m8 o5 ]; D: ?- f1 N
- CT_SDA_OUT(); //sda线输出
; K$ j* Y# x& r z Z% A - CT_IIC_SCL(1);
9 a+ n" T3 n. _6 B& R2 N* b$ Q - CT_IIC_SDA(1);
0 x' C5 D( \& H& G* C - CT_Delay();
' M+ `- ^1 a1 ]7 S; L. ^ - CT_IIC_SDA(0);
; P3 j! ~4 N$ m. i, j" w - }
复制代码
* }% Z# T: L$ H: e; Q( a停止信号:当SCL为高期间,SDA由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。" j! k: E7 Q" z' z8 i8 X& ?
- /***************************************************************************************
/ o; S; d6 Y; E/ W! Y2 R2 V& N - * @brief 产生IIC停止信号,当SCL为高期间,SDA由低到高的跳变/ M# H& m; H \2 e# K- {& C6 ?2 i
- ***************************************************************************************/8 O3 S4 B4 n( g( X8 ^2 y R
- void CT_IIC_Stop(void)/ s6 e. o4 M/ U* D
- {
8 C8 O" L0 d# H9 E: [; P - CT_SDA_OUT();//sda线输出- E+ c6 h" v5 H! |$ I/ a' s" P
- CT_IIC_SCL(1);
, s5 n6 |8 g& \8 q& B: I - CT_IIC_SDA(0);//STOP:when CLK is high DATA change form low to high
8 n, M$ e. U8 [% R( s/ @ - CT_Delay();
8 E6 n) I" ^7 c2 U8 }6 V1 i - CT_IIC_SDA(1);/ q9 P1 C+ l m+ l
- }
复制代码 . 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
' 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- //控制I2C速度的延时
4 }- |4 P$ I- W6 B" u6 `1 V - void CT_Delay(void)- r a" W" [$ c
- {* v* S# K; X( O) Q) |+ }
- delay_us(2);9 j5 H0 r; x! L. e3 t# O
- }
复制代码 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
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- /***************************************************************************************
) G' M) y- Y! d - * @brief 产生ACK应答,- P Z2 N4 n" {3 b, y
- ***************************************************************************************/; v1 U0 n% r7 _8 y9 A# Z
- void CT_IIC_Ack(void)
$ ]5 T/ V# k6 E X* X - {
5 n/ j7 h9 h5 o3 f! G Y0 G" Y - CT_IIC_SCL(0);$ m) ] m$ [) |2 ?
- CT_Delay();! o g. Y2 k- {+ \& A1 o
- CT_SDA_OUT();
# ^7 B2 q1 n1 u5 Z. v, I - CT_IIC_SDA(0);) }8 L' D: T [
- CT_IIC_SCL(1);: q6 W* ^; `8 `1 P
- CT_Delay(); H& r2 o2 k1 D6 @
- CT_IIC_SCL(0);7 V+ p# h7 c: q- n
- }
复制代码
5 Y; X, H' n& Q' B5 T等待ACK时序:拉高SCL与SDA后, 然后设置SDA为输入检测状态,等待接受数据端拉低SDA" s& x4 N5 ^' V" X) q6 e q
- /***************************************************************************************
r& ~& z/ K/ I) Z - * @brief 等待应答信号到来,等待接受数据端拉低SDA
# I! |2 @) m N$ w3 W0 a W ?. ^ - * @input
: H) }- p5 v' l& y7 { - * @return 1,接收应答失败 ; 0,接收应答成功 ]1 d# y0 B1 ?6 A3 w0 k. e; H& C
- ***************************************************************************************/: F+ ~$ ~; x7 _4 y' ?9 u
- uint8_t CT_IIC_Wait_Ack(void)
+ u# s6 |; e) f3 R; T - {; h) T% a( O7 j. q, \
- uint8_t ucErrTime=0;
8 Q4 {3 e" |" a8 @$ p - CT_IIC_SDA(1);
- a- p. n) w& j - CT_IIC_SCL(1);' D9 P# x: @! X* v9 T) P
- CT_SDA_IN(); //SDA设置为输入 1 z& ^1 u* s+ Y1 F! q8 ~
- while(CT_READ_SDA)" F! s& v, j. r) S6 N, C
- {
( B- P9 f5 k& B% i& d- t - ucErrTime++;, q# B$ U( j2 h: x
- if(ucErrTime>250){) C: I! [; l3 v- Q. Q7 F2 {
- CT_IIC_Stop();1 Z7 D; }$ f$ J5 {' {' D) ]
- return 1;
: n. Y3 X* ~) S6 U! h; G4 } - }
6 ?# l' Q% j _( y/ M& P# W; q( h - CT_Delay();
4 F5 e9 r% }+ L3 G3 T% I6 R% ^: `3 H - }- r6 r7 _4 j$ j, j! F3 O4 P
- CT_IIC_SCL(0);; c0 O5 q9 o" ~5 v, [* C5 W
- return 0; $ M9 g8 @4 m9 M# n& p, h* p
- }
复制代码 / J' P9 ]0 Z5 o8 T4 j! Y1 t: J
下图是nACK时序与 传输数据1的时序图,这两种时序图是一样的,区别在于ACK是在8个数据时序后产生,且SDA电平是由接受数据端拉低的。
$ T$ F7 [; \: U
" \/ b- N' t7 h4 K. Y! `
* `$ K) f' L: l7 A$ _1 y3 t$ e0 S: Q- ^6 ~% \( ?; }$ S
产生ACK时序:在SCL高电平期间,SDA为高电平状态。
- d+ o M# Q$ p7 ]- /***************************************************************************************
0 g# b. y; M: O7 e. S6 K - * @brief 不产生ACK应答
4 D$ E$ A+ T: T* y+ M( } - ***************************************************************************************/
9 Q$ M8 J" t- v! |: G5 o - void CT_IIC_NAck(void); O0 d8 X/ n z# }
- {2 L! M. j7 L Y* z& L! P+ W
- CT_IIC_SCL(0);( x( M& r2 [% X$ \, R
- CT_Delay();
* k; q+ r j! V" {+ _$ _- m - CT_SDA_OUT();
t1 Q. g3 ]. F0 _( `0 E; S$ L - CT_IIC_SDA(1);1 I8 F% U/ A2 n5 g; B Z
- CT_IIC_SCL(1);6 n: B2 C7 ?. J4 R ^8 o
- CT_Delay();
. S5 i8 b& }1 @' W; r+ l% o8 I - CT_IIC_SCL(0);5 \4 d, I+ W9 j2 j4 [
- }
复制代码 9 n% \. s8 S8 q! C$ g
发送一个字节函数,优先发送高位,即从bit7开始发送。0 Q. Z3 Q% l9 f. T+ }7 ^8 b
- /***************************************************************************************% ~, c l. G# z1 w6 T" @0 b+ ^
- * @brief IIC发送一个字节,2 ^9 [# P( }6 @, b6 ]( I6 b0 u
- * @input
+ t: D, o- y3 F9 A2 j! A$ l) o - * @return
1 K6 ^. n" X7 ]- d% g5 x5 K" v8 E - ***************************************************************************************/) ]) q( C; U6 a2 {4 G
- void CT_IIC_Send_Byte(uint8_t txd)
( Z$ W. h/ o/ l, \7 R& H - {3 w, @9 d, }; b L. M: a: }
- uint8_t t;
% n# H" }% s, m2 r' \ - CT_SDA_OUT(); * C$ ^( o/ n6 V" P) O( ~
- CT_IIC_SCL(0);//拉低时钟开始数据传输
0 v7 ]- \5 P% @" @% k8 s0 B - CT_Delay();# N+ D k5 R; W( x6 a$ i, L" L5 z
- for(t=0;t<8;t++)
) E( U3 w8 e7 Q- c' l+ a" E - {( S7 c# o) q4 C; ^! s
- CT_IIC_SDA((txd&0x80)>>7);//发送bit7位* g3 u6 w3 x" C: h1 z
- txd<<=1; //将txd的次高位左移到最高位
5 J% w, D. U+ q$ k2 `: n - CT_IIC_SCL(1); , k# L! z% R" }! x' E( x. ^
- CT_Delay();
# T( v/ ^0 t$ | - CT_IIC_SCL(0);
2 {* V6 Y& n# R& E3 }% M/ Q: j - CT_Delay();: L1 X1 M( C; L8 F3 W6 c. Y
- }: h8 l3 e# N5 \. X) k; H8 p3 a1 W
- }
复制代码 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- /***************************************************************************************& [! H6 A( h3 s6 J% p* r8 S
- * @brief 读1个字节/ ^6 b+ N# l" }) R
- * @input ack=1时,发送ACK,ack=0,发送nACK: }; Q0 F. q2 B& ]
- * @return " H- W) l* o' s2 d$ N
- ***************************************************************************************/
, J$ }9 }' w: H5 Y& Z/ U - uint8_t CT_IIC_Read_Byte(unsigned char ack)
$ D" y, K+ u8 T" _! m0 P9 } - {
) @1 j5 }% W* J. T8 | - uint8_t i,receive=0;2 |+ V1 a/ q7 ^
- CT_SDA_IN();//SDA设置为输入6 f& w+ Z! A5 g- m
- CT_Delay();
( D# f. u8 b' ~' ~ - for(i=0;i<8;i++ ), ?* V. P" M/ v
- {
3 s; ~) ^, `* m' q5 |5 } - CT_IIC_SCL(0); ) C5 f) I; ~' p6 @' f8 g
- CT_Delay();( @% l O' B; d" w/ B; }
- CT_IIC_SCL(1); ! P, w7 }6 d! V9 K, _7 p. y7 T2 K
- receive<<=1;
5 W/ R2 R* D" C# W8 q2 t; l - if(CT_READ_SDA)receive++; 7 Z: L( }) v; ^" O
- }
; Z$ J) t8 D2 g. v5 E - if (!ack)$ m5 l, _! @- D' o
- CT_IIC_NAck();//发送nACK
, Z" g$ ^( C& R0 K) u/ g - else # m2 I. h2 O0 c2 i. e4 _
- CT_IIC_Ack(); //发送ACK
6 i7 a% Q8 ^0 [+ ?# c - return receive;
: E U0 p% g ~- P2 }0 Y9 m; [ - }
复制代码
: 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
$ K/ c& Q# X/ V5 C7 I1 [* @0 J8 C- T/ M/ f
" 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
/ 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
- uint8_t GT9147_Init(void)
% N; u5 ]6 Z8 q7 I+ Q' z: m) b - {
0 R( d: L5 I" h3 J - uint8_t temp[5];! S- N7 v# I6 \6 ]4 X
- ' s/ e' a: ~- {
- GPIO_InitTypeDef GPIO_Initure;0 w7 S: j2 \! W8 I5 f
3 z4 T8 x& }) W6 |+ l. ]- GPIO_Initure.Pin = GPIO_PIN_7; //PH78 b- h1 K# \+ d9 ~8 }" C
- GPIO_Initure.Mode = GPIO_MODE_INPUT; //输出9 f5 S8 Q5 A0 Z& x6 u
- GPIO_Initure.Pull = GPIO_PULLUP; //上拉8 Z5 [5 E3 R8 y. E. T! S2 _; k: G
- GPIO_Initure.Speed = GPIO_SPEED_HIGH; //高速
# u# S2 e2 [# n3 E# C - HAL_GPIO_Init(GPIOH, &GPIO_Initure); //初始化
8 K/ }9 \4 i- a# B0 G
8 W. [- _2 J# F R! W" X- GPIO_Initure.Pin = GPIO_PIN_8; //PI88 _7 g+ x: Q7 X5 g" F
- GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP; //推挽输出6 G/ _! s# v' g- X9 y* U
- HAL_GPIO_Init(GPIOI, &GPIO_Initure); //初始化- B" _; B# j$ X! O$ g
, g3 \3 [( x4 l0 K4 f9 @1 K2 e- CT_IIC_Init(); //初始化电容屏的I2C总线0 a3 [& `: Z! s+ i0 i: t
$ X3 [9 `7 i% n- c$ C- GT_RST(0); //复位& W' A+ v9 s, |4 f* q/ R5 ^5 M0 C
- delay_ms(1); //INT引脚电平维持100us以上4 \1 O7 X. b- T( m5 h
- GT_RST(1); //释放复位
3 i" Y5 u6 X3 F* ]$ t: v, l - delay_ms(10); //释放复位后维持5ms以上,设置INT为悬浮输入$ w; N% W E- W7 n& Y
- GPIO_Initure.Pin = GPIO_PIN_7;. ?# R* h, b0 M7 ?9 J8 X5 {
- GPIO_Initure.Mode = GPIO_MODE_IT_RISING;3 n. h% d- z: e% d' x9 }/ N0 m: `
- GPIO_Initure.Pull = GPIO_NOPULL;
5 G5 M9 U; w3 M7 Z* `9 A - HAL_GPIO_Init(GPIOH, &GPIO_Initure); //初始化9 L. L9 O0 z$ c- D2 B8 w
- delay_ms(60);
( G' w+ k U- } y& A, g' I - + F' o. S& \: P& a* h( `" {2 E9 U
- GT9147_RD_Reg(GT_PID_REG, temp, 4); //读取产品ID1 L0 Q& }9 D, M% I n: j
- temp[4] = 0;; D7 T2 W9 t) A6 K! L0 T) m
- printf("CTP ID:0x%s\r\n", temp); //打印ID+ ~8 P9 K9 v8 K; q* ]1 x, q
# L4 Q. }7 |; \; Z6 }- GT9147_Send_Cfg(1);//更新并保存配置
+ W7 i6 s' I, r5 D& }
" l0 f) @; i n" S v- return 1;
( F3 o) f% ~, u9 R - }
复制代码
# 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- void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
2 U' R: z8 m# G1 n1 s - {5 q: j A i6 x: N y6 [3 b& `
- uint8_t buf[4];% x7 u3 Z" b! c
- uint8_t i = 0, mode = 0, temp = 0;
/ }7 ]5 w! l- Y6 h4 ^ - uint16_t x[5], y[5];" w5 h+ \$ p9 {: F; F0 ?2 s! u# n7 o* F
- if(GPIO_Pin == GPIO_PIN_7) { //读取坐标, 否则会一直有INT脉冲' o/ z! i) D, Q& L
- GT9147_RD_Reg(GT_GSTID_REG, &mode, 1); //读取触摸点的状态8 Q4 q% X3 n! C8 c* ^" B9 K
- if(mode & 0X80 && ((mode & 0XF) < 6)) //有坐标可读取) A8 _5 f2 f- K$ T5 g
- {1 V+ _/ @5 ^3 Y V# w" E( V
- temp = 0;
0 z% G2 J+ t4 B. D4 X1 W - GT9147_WR_Reg(GT_GSTID_REG, &temp, 1);//清标志
% [# o; H' j' k - }8 N& n. u8 M& o$ J. w, ?3 v% ]$ _
- if( (mode & 0xF) && ((mode & 0xF) < 6)) //判断触摸点个数2 S, i+ g9 [( L( @4 w/ ?
- {. c) K$ w9 E: S+ [4 [5 V4 m8 B
- for(i = 0; i < (mode & 0xF); i++)
8 x% M. U$ R8 Y0 H7 |2 L - {# k: E8 j {# F9 {* ], T* l
- GT9147_RD_Reg(GT9147_TPX_TBL<i>, buf, 4); //读取XY坐标值9 }& g" j+ R! N2 K7 p+ n( s
- </i>x = (((uint16_t)buf[1] << 8) + buf[0]);
/ b W j7 L0 R! @, E& Y - y = (((uint16_t)buf[3] << 8) + buf[2]);( A1 o1 e7 x! ?+ F* ]
- }" `* N) J p# `* G8 h3 o. v
- touch_x = x[0];( a# t2 m2 F0 L
- touch_y = y[0];
5 b7 T: {4 h. `) l9 Q - }
; Q9 ^2 H% E! V, l& v2 P - 8 e5 n' c1 r- k$ {; ?. N% r" n) I8 ^
- if((mode&0x8F)==0x80)//无触摸点按下,xy赋值为0xffff! t$ {- U+ {, E
- {( v, t7 i9 o- b% o4 |$ @
- touch_x = 0xffff;0 z' z! \; d) c9 h- R
- touch_y = 0xffff;
, a/ m, T* j9 w* ?2 _ - }4 z$ C/ R0 L: {% r& ~& y3 R N
- }: z0 G* l1 I5 H( X) ~. F
- }
复制代码 4.主机 对 GT9147 进行读操作时序
# L+ O3 U- A1 M/ e @. \2 ]
' o+ R. m* y4 [; Y* D) j! 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" ]- /***************************************************************************************
3 g. d; g( N6 z2 q& D - * @brief 从GT9147读出一次数据6 [! {! x1 V8 e2 X2 G+ M; t
- * @input reg:起始寄存器地址5 T" P1 d1 V S
- buf:数据缓缓存区
$ ^! b, P; J( L( ? J9 _, F - len:读数据长度
5 \1 b( J9 w0 Z1 \- m3 [ - * @return
# |+ H% @( J6 X2 a& Z. |, S/ U - ***************************************************************************************/
; I5 ^$ U; P* G. I1 f - void GT9147_RD_Reg(uint16_t reg,uint8_t *buf,uint8_t len)! @" V% s5 F9 n6 u( w+ E
- {
4 d) P; k& L! p - uint8_t i; / J6 i9 j q/ Z }1 V% _
- CT_IIC_Start(); 8 E% e9 x7 \% C, _, {
- CT_IIC_Send_Byte(GT_CMD_WR); //发送写命令
7 `. E2 W% C" ]6 \$ M; ^8 G - CT_IIC_Wait_Ack();
, A T: Q+ u7 Z% _. {5 f% V - CT_IIC_Send_Byte(reg>>8); //发送高8位地址# ^( t+ M( U5 M! V( O
- CT_IIC_Wait_Ack(); / ~$ o9 v: o6 s" O$ \
- CT_IIC_Send_Byte(reg&0XFF); //发送低8位地址3 y; d f/ z2 q1 k( B7 |* `7 P) g
- CT_IIC_Wait_Ack(); 3 }' d$ [+ q& H+ l+ S9 q* n
- CT_IIC_Start();
: n9 D, U" J7 m- Z - CT_IIC_Send_Byte(GT_CMD_RD); //发送读命令 ; l' T1 k$ H. B
- CT_IIC_Wait_Ack(); , E% k7 \7 J; A- D. p% \3 A
- for(i=0;i<len;i++)2 M( U2 B( c6 p, k5 U4 k
- {
5 ~: O- C* u2 J% |" C - 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 - }
, c' c& ^0 q3 l - CT_IIC_Stop();//产生一个停止条件
" A+ Q4 l' e8 D0 Z - }</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
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
- /***************************************************************************************
" z2 A: A- ]. q4 H/ {- H# r! F - * @brief 向GT9147写入一次数据
9 r l; i ?( o+ \. M - * @input reg:起始寄存器地址;
! o4 F- j8 o5 U- r - buf:数据缓缓存区
0 b. u9 @! H" R% ]3 y% N3 W - len:写数据长度
( ?4 l _4 G! q' ]0 V& h% G - * @return 0,成功; 1,失败.
: w% g" z& q1 ~ - ***************************************************************************************/
, l* H, c6 G4 Q( A; J6 z. ] - uint8_t GT9147_WR_Reg(uint16_t reg,uint8_t *buf,uint8_t len)
: K% \1 k; w0 W! l" `* U9 w' j - {5 R" K$ N* J# _' r1 d$ U; W. r
- uint8_t i;
2 h: W8 T$ d: w: o' W* S8 B' I! f - uint8_t ret=0;
, r6 i5 H: M9 ^! c- e - CT_IIC_Start(); ; V3 I" _1 X/ M- @8 e
- CT_IIC_Send_Byte(GT_CMD_WR); //发送写命令 . g0 o* c$ E8 L/ S j$ J ?7 c, w) Y
- CT_IIC_Wait_Ack();
5 g; P% h+ U7 O- Y+ O5 f - CT_IIC_Send_Byte(reg>>8); //发送高8位地址
6 V; }( ~6 z3 D - CT_IIC_Wait_Ack();
. c: X* }# D/ i5 l9 ], G - CT_IIC_Send_Byte(reg&0XFF); //发送低8位地址
, P* J2 N0 r. C- w - CT_IIC_Wait_Ack(); $ P7 e9 d( g" V/ Q- }4 S2 h
- for(i=0;i<len;i++)
9 Y& b$ u% }/ L% K7 H" i - {
8 `, c2 x+ s9 p( R @: c - CT_IIC_Send_Byte(buf<span style="font-style: italic;"><span style="font-style: normal;">); //发数据6 Q; |; F7 e% o( }6 r3 a
- ret = CT_IIC_Wait_Ack();+ \; v1 B9 q# n: \! N0 z
- if(ret)break; 9 d: @. R" Q+ i$ Z- s* ?: D6 Y% y
- }
/ W4 s0 V# d9 p$ n: l; N - CT_IIC_Stop(); //产生一个停止条件 . Q. T/ {' _: n2 H. H
- return ret;
: c; L5 ?3 R% N) q7 e. s - }</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) ?
- const uint8_t GT9147_CFG_TBL[]=
$ i+ H) p& X, ?' Z4 ~5 T - {
( F/ }1 r H' T" K - 0x60,0xe0,0x01,0x10,0x01,0x05,0x0C,0x00,0x01,0x08,$ e/ }0 T; b+ D
- 0x28,0x05,0x50,0x32,0x03,0x05,0x00,0x00,0xff,0xff,
' f6 T( U: c- [$ i3 W - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x89,0x28,0x0a,
; K; d0 V- |; V4 k' k c - 0x17,0x15,0x31,0x0d,0x00,0x00,0x02,0x9b,0x03,0x25,5 u. t) t3 e8 Y* z8 Y
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0x00,0x00,& C. K& l4 I7 n( h! t
- 0x00,0x0f,0x94,0x94,0xc5,0x02,0x07,0x00,0x00,0x04,- @/ b$ V2 H$ w6 M$ g) [
- 0x8d,0x13,0x00,0x5c,0x1e,0x00,0x3c,0x30,0x00,0x29,( {. }3 F. i, @$ @* G! @" o
- 0x4c,0x00,0x1e,0x78,0x00,0x1e,0x00,0x00,0x00,0x00,9 I& W0 |- D2 i
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,% r( u a5 b+ e* W6 w- d) x4 m
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
& V: |! W5 S4 F3 N/ R$ `7 a - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
4 \1 J$ z& x/ G& L- z7 ] - 0x00,0x00,0x08,0x0a,0x0c,0x0e,0x10,0x12,0x14,0x16,
3 @' H" N t& L' e - 0x18,0x1a,0x00,0x00,0x00,0x00,0x1f,0xff,0xff,0xff,
O% Y" e, u; ~: P* v4 R0 a* C - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
/ Y+ `+ [ X8 e; H" i - 0xff,0xff,0x00,0x02,0x04,0x05,0x06,0x08,0x0a,0x0c,
1 U6 H! _' K7 R2 f. i - 0x0e,0x1d,0x1e,0x1f,0x20,0x22,0x24,0x28,0x29,0xff,
# j0 s: D; z j, ^ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,! u& ?% N7 I- P5 `' a: o
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,. t, J9 K$ t, e0 {2 A" n
- 0xff,0xff,0xff,0xff,
F. Z$ N& H K, y/ J+ @ - };2 G" u) |: {/ J* t
- / }% P( r) a2 Y- Y
- uint8_t GT9147_Send_Cfg(uint8_t mode); x& \5 Z; ^ b4 R7 g
- {
1 _. Z5 I0 U5 f - uint8_t buf[2];" c( e' \/ o3 i' m
- uint8_t i=0;
6 |" | T. B' N; k3 P - buf[0]=0;
2 d( P0 r- Y* x) r0 @ - buf[1]=mode; //是否写入到GT9147 FLASH? 即是否掉电保存
9 N8 L& S# k, M2 B, s - for(i=0;i<sizeof(GT9147_CFG_TBL);i++)" ]$ ?# L2 g, Y4 p, I; i1 v6 `
- buf[0]+=GT9147_CFG_TBL<span style="font-style: italic;"><span style="font-style: normal;">;//计算校验和
# y. q& ?* @& ~) D, v - buf[0]=(~buf[0])+1;: X5 x# s; V+ h, I" V1 Z4 q
- GT9147_WR_Reg(GT_CFGS_REG,(uint8_t*)GT9147_CFG_TBL,sizeof(GT9147_CFG_TBL));//发送寄存器配置
g; n. f8 x& |* p N9 O9 T - GT9147_WR_Reg(GT_CHECK_REG,buf,2);//写入校验和,和配置更新标记9 \5 |+ `9 I2 N$ T+ X) |( [
- return 0;
! Y4 `) H; H( ~. I - }</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- #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
- void GUI_TOUCH_X_ActivateX(void) 7 @+ f z: s1 S9 ?, G3 g
- {! w& n8 g1 \- J3 W0 O( V/ \
- 2 P4 \5 G+ [, u" r; G% Y T
- }3 ^: e! b; o! n$ i( }
- 5 k( s3 D) c/ i$ T. C
- void GUI_TOUCH_X_ActivateY(void)
) u; ]$ Z7 i- L8 `2 W - {0 V0 S5 I) P4 P k: Z
- ) b& T7 j- s6 e: ?) b) u
- } M/ N6 ^: q) ?* c( ]* C
/ i/ c) ?" K2 Y. h/ q* O3 ^- /*获取x坐标*/
: Z z( p. s+ @* X, {& ]1 F/ \3 I' b7 L - int GUI_TOUCH_X_MeasureX (void)9 u- ?1 V: a, j' Y
- {
# X/ k' u* ]: @: `1 d2 L - return touch_x;
0 M: i3 B/ d7 K, U% S - }
9 f4 U9 H( r) W$ E! r
8 @3 A8 T. u# r1 t: [! U" Y2 N- /*获取y坐标*/+ A2 g: k. U8 \7 a! C/ W
- int GUI_TOUCH_X_MeasureY (void)
0 N4 ^$ h8 O9 U3 U$ T - {
9 V& f( H4 P8 i - return touch_y;
: h3 e4 q3 H, P3 I+ o' \! Q - }
复制代码 ' }. 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
- void StartTouchTask(void const * argument)
4 z: o9 c7 E$ B$ {! v8 f - {
0 E; j6 n0 M- |+ n; b$ { - /* USER CODE BEGIN StartTouchTask */
2 j5 X* b( A' r% j3 ^. L - GUI_CURSOR_Show();//显示鼠标指针
! c$ Y0 c$ u/ w$ b) j9 }) n- ` - GUI_TOUCH_Calibrate(GUI_COORD_X,0,LCD_WIDTH,0,LCD_WIDTH);
" y N0 O* j- A, L1 A2 R - GUI_TOUCH_Calibrate(GUI_COORD_Y,0,LCD_HEIGHT,0,LCD_HEIGHT);- _( P9 D2 B/ l; N. T3 p! A
- /* Infinite loop */
) ?0 o O. f3 J1 B6 r - for(;;)
* G& ^$ X! r7 h0 m p9 |0 ~5 z8 e - {' U# M+ {# l+ g' m1 R
- GUI_TOUCH_Exec();8 }, c& n5 k2 a; h5 j8 p
- osDelay(5);
$ i* V/ h" k& j. T - }
9 q5 ~' c+ U: h3 L: | - /* USER CODE END StartTouchTask */
# O4 r9 t, O- A& ]* a2 k( W9 b; b& d - }
复制代码 - v* B/ }, W0 ~2 }: t
0 k' d# c5 S& r# m; l# u* [
/ v! K3 e) \ Q
+ ~' ]- w) f; q" D* v
|