|
STM32f103的触摸屏的设置与使用
) z/ Y' m6 }" C- t3 n7 V1 {& l6 e4 K5 [, o7 W/ H' k7 k
多功能采集显示平台的人机交互采用的触屏方案. Y- i/ C- _8 W) w
# q! F1 _/ P- V* I8 }1 S6 j6 o" F4 X% `! L* z# b9 C
触屏功能主要是依赖电阻触摸屏的主要部分是一块与显示器表面非常配合的电阻薄膜屏,这是一种多层的复合薄膜,它以一层玻璃或硬塑料平板作为基层,表面涂有一层透明氧化金属(透明的导电电阻)导电层,上面再盖有一层外表面硬化处理、光滑防擦的塑料层、它的内表面也涂有一层涂层、在他们之间有许多细小的(小于 1/1000 英寸)的透明隔离点把两层导电层隔开绝缘。当手指触摸屏幕时,两层导电层在触摸点位置就有了接触,电阻发生变化,在 X 和 Y 两个方向上产生信号,然后送触摸屏控制器。控制器侦测到这一接触并计算出(X,Y)的位置,再根据获得的位置模拟鼠标的方式运作。这就是电阻技术触摸屏的最基本的原理。
4 D7 M" D' }. ~: j- |1 B q) V( S. f$ o% c7 k$ }6 U& f8 n
. h, a5 d( I* Y7 F
电阻触摸屏的优点:精度高、价格便宜、抗干扰能力强、稳定性好。
; Y6 N! y% W% u3 z) F( I6 m; f( u2 t3 q9 D$ T
5 e# {' I9 }# a( ~! r 电阻触摸屏的缺点:容易被划伤、透光性不太好、不支持多点触摸。
# S' T5 L. @9 P( a7 r" n4 c
( B& E# T- ~1 d
7 f: n# x6 _& f% ] 多功能采集显示平台采用了触摸屏控制芯片为 XPT2046。 XPT2046 是一款 4 导线制触摸屏控制器,内含 12 位分辨率 125KHz 转换速率逐步逼近型 A/D 转换器。 XPT2046 支持从 1.5V到 5.25V 的低电压 I/O 接口。XPT2046 能通过执行两次 A/D 转换查出被按的屏幕位置, 除此之外,还可以测量加在触摸屏上的压力。
' q% x& {) P. T) b! ?# P( {! P5 x
5 y* }6 I4 C5 K( u- g$ B0 Z4 D9 C/ p+ @ s/ d
硬件设计方面,多功能采集显示平台采用SPI的方式读取XPT2046所存储的XY的逻辑电压值,同时采用了外部中断的方式响应电阻触摸屏的点击事件。SPI接口使用片上资源的SPI2,占用PB 13~15,片选信号线占用IO口PB12,触摸响应信号线占用PG7,使用外部中断模式,并且中断级别高于显示刷新定时中断。# X0 Z+ T' p& i
) {! v, Z0 T6 B( ^- m
软件设计方面有以下3点
- [2 D9 g+ a N3 F& _/ X* R
' p# i7 R: C8 a) z W3 N, e/ C+ | z
第一,初始化XPT2046芯片,初始化SPI功能,并设置外部中断事件,同时使能XPT2046芯片和IO内部时钟。
; ^8 z4 E" z* c r z% V0 d4 @, T) g4 ]( U+ B
9 D, `1 k( z! x1 x) P 第二,电阻触摸屏的点击中断事件,编写中断服务函数,进行对点击的位置的获取,并且根据获取的位置进行区域判定,经行相应的操作。
" z3 B7 E7 |# x. t3 z
; f7 P9 [( g/ p% x' U+ m5 E$ H6 N! K1 D9 {, ^. [' K& `* J
' G1 Q, m. Q l8 ?: d! k8 w
第三,对于电阻触摸屏的特性,点击电阻触摸屏后驱动芯片可以产生一个中断信号提示触摸动作,同时在寄存器存放这X和Y轴两个逻辑电压值,这两个逻辑电压值的精度是12位的,与TFTLCD的物理坐标值(320*240)是有一定相关性的,但是便于程序的编写,我们需要使得逻辑电压值和物理坐标值相同。所以编写了电阻触摸屏的校正程序,校正的算法是改进的五点校正法
7 o/ u( a! w: \9 Z, \. h
8 p9 Q! G2 j# {; bXPT2046触摸屏初始化代码如下:
# m% r: A% r4 L/ D! T3 l- [cpp] view plain copy2 `4 |5 l$ f4 @% V$ D
- void Touch_Init(void) / }9 m' `$ g4 @* [. y# W8 v, L
- { 5 [/ }% X- v/ @ d# Q9 I6 V
- GPIO_InitTypeDef GPIO_InitStructure; # G8 A- g9 w u
- NVIC_InitTypeDef NVIC_InitStructure;
) F# E# m1 r' n0 c& O - EXTI_InitTypeDef EXTI_InitStructure;
! E& v# X3 K4 H7 J - 9 v( @% X, P: e! d. [
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG | RCC_APB2Periph_AFIO,ENABLE);
- g" K- U6 d, f" h# J8 ~ n - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
$ P# |8 m) e `9 x: p" p - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
* B @' J: ]: o* F, y - //GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);//关闭jtag,使能SWD,可以用SWD模式调试 * i) [4 i0 p5 C4 I& g2 y
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; 5 }0 @# Q9 ~. Z6 _+ @5 y5 O# r
- GPIO_Init(GPIOG,&GPIO_InitStructure); 0 v- ]( Q6 E$ \* r
- GPIO_EXTILineConfig(GPIO_PortSourceGPIOG, GPIO_PinSource7); //设置管较为外部中断管脚
' @- }6 N/ R* ^' O7 [: l - EXTI_InitStructure.EXTI_Line = EXTI_Line7; " _1 U5 n! J8 t+ g# F
- EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //为中断请求
/ R1 _ H& Q E5 X( b' z - EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//Falling下降沿 Rising上升 , O/ j6 S8 V4 Q% B: y3 i
- EXTI_InitStructure.EXTI_LineCmd = ENABLE;
/ \' l9 G! ~4 i2 d) l) s - EXTI_Init(&EXTI_InitStructure);
; w; X1 N6 n$ I( _ q( q/ f1 \ - EXTI_ClearITPendingBit(EXTI_Line7); //清除线路挂起位 3 H1 ^' B8 S2 p% h( }
- /* Enable the EXTI4 Interrupt */
6 y4 M' _; y3 J0 x - NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn ; 8 [" q8 y/ D, @! s+ K
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
$ V4 K. q) V$ z8 h- ?) k8 o+ j - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
) K- U: {! f8 {0 Q# w - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 3 \- S: J! T3 ]. N! f
- NVIC_Init(&NVIC_InitStructure); & p' h) R& O) {/ T
-
3 _1 D- T: V. M/ p5 t9 }. h - SPI2_Init(); $ z8 ~+ [/ U5 g5 e: V1 e2 M) S r% a" ^5 O
- CSPin_init();
6 x! o9 l5 f- q' R - }
复制代码 读取XY坐标函数:% k0 _( y4 q* w1 i1 p+ j
- [cpp] view plain copy
3 b* U8 W% Y! r3 G# d/ }1 ? - u16 ADS_Read(u8 CMD) + w* j3 d' P. T8 \, I; g: c
- {
" k1 e( w7 |6 E: t0 r# Y - u16 Num=0,temp;
& F( u9 V) _! N: ` - TCS_LOW;
+ `' t9 h. f- W1 @ - SPI2_ReadWriteByte(CMD);
; T3 _& p* l( W" ]; `( B - delay_us(6); " W) R n3 N6 h! M( A5 }& k- A
- temp=SPI2_ReadWriteByte(0x00);
1 j4 m& J9 j5 y1 h4 ^. P8 w - Num=temp<<8;
, R1 k1 l# g. I/ p/ | - delay_us(1); 3 A; K! H) J! A% j% d5 M0 j2 N
- temp=SPI2_ReadWriteByte(0x00); # V" N9 J( q: a0 \; X$ x7 ^
- Num|=temp; % h% S; V+ G; D/ l& }
- Num>>=4;
1 M) H* q- o1 b0 X. h6 Q- a( I - TCS_HIGH; 0 \/ c' V$ |0 |/ Y
- return(Num); ) u& v3 C( o3 V% v
- }
/ k" u/ V% ]0 @+ q; }% R - ' x/ B- j' @. j5 t S( f B5 S
- u16 Read_XY(u8 CMD) 8 B/ h! n) l. n
- {
6 d7 ^1 k: Y* u' t S D! C. u - u16 i, j; 3 D/ |% ?5 [% Q0 U8 Y! Y
- u16 buf[10]; 6 r+ s( q6 o5 @) N6 J
- u16 sum=0; 5 j/ n* @( u7 P+ T. U/ y9 U2 K* u
- u16 temp;
[0 O* S8 @7 Y3 r! l8 D - for(i=0;i<10;i++)buf[i]=ADS_Read(CMD);
( X* }( d a- b( s e - for(i=0;i<9; i++) 6 ~7 d' A8 Q8 U+ @- o
- { + }3 R, k, U+ W# z9 x4 x* @& Z
- for(j=i+1;j<10;j++) ) [. |/ n9 }0 ?0 K
- {
! A6 `" e3 g4 |' t; Q; v' l - if(buf[i]>buf[j]) , J# p4 ]3 U. P2 k0 ?8 k
- {
. N+ w |1 V3 Q) t3 x" r4 \) t0 ] - temp=buf[i];
( x, m; D. o* o$ { - buf[i]=buf[j];
. I- o: D) A% V( j: [ - buf[j]=temp; - F" ? Q( g; x/ s2 K" }
- }
* E/ q9 M& x! Y) Z - }
1 \/ B" H$ @- K) p, N - }
) J4 j( X9 D v' m8 p6 { - for(i=3;i<7;i++)sum+=buf[i];
! `$ l c* Y: w: _ - temp=sum/(4); 4 n6 l2 Q/ ~9 Y$ N7 ^' y
- return temp; " {) U# ?2 J1 `9 W* B
- } 4 f! D, O4 o6 b/ m! Z% w8 K5 }
- $ U5 h! }; V* u5 q9 N/ R$ d, m
- u16 Read_X(void)
% h+ @, u7 b) u, N - {
3 z* u( h6 r$ O# p' s) N- P' O7 } - u16 tempx;
7 U- x$ i+ ?0 z9 k- p- y - tempx = (Read_XY(CMD_RDX)-XLC)/(KX) + XC; - M' @& {4 \- Y" j0 Z, p) J
- return tempx; 3 s, ^5 V1 l* t9 e3 k) L( p- o
- }
9 _( R% T. \2 E! T1 c- f1 K) o, k$ @ - u16 Read_Y(void)
! d" D4 F' w( I( q' E# l - { + e: G" e+ B: m4 O9 X' K
- u16 tempy; / B# \0 H6 N3 n2 y* n
- tempy = (Read_XY(CMD_RDY)-YLC)/(KY) + YC;
` x% y2 l7 `+ p9 e - return tempy; 2 i9 v6 a4 k) d8 ^) V/ Q
- }
复制代码 这里的 KX KY XLC YLC XC YC 都是用于校正电阻屏的系数,缺省值为1.00。
4 K% X/ x; D% v* O1 C( h% L, E | e a! w5 M3 ^! ]7 U9 z+ m4 _- z9 Z
|