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