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