STM32:编写XPT2046电阻触摸屏驱动(模拟SPI)

发布时间:2024-06-04  

一、环境介绍

单片机采用: STM32F103ZET6

编程软件: keil5

编程语言: C语言

编程风格: 寄存器开发.

目标芯片: XPT2046---标准SPI接口时序

二、XPT2046芯片介绍

2.1 功能

XPT2046是一颗12位的ADC芯片,可以当做普通的ADC芯片使用,但是一般都是用在电阻触摸屏上,方便定位触摸屏坐标。


poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

图1: XPT2046内部原理图

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png


图2:电阻触摸屏---引出的4条线就接在XPT2046的YNXNYPXP上

(XPT2046支持笔中断输出--低电平有效,这个引脚可以配置到单片机的中断脚上,或者轮询判断这个引脚状态,判断触摸屏是否已经按下)

可以单独买一个触摸屏+一个XPT2046就可以自己做手画板、触摸按键(自己用一张纸在下面画个模型就行)、等等很多小玩意。

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png


图3:采用的电阻触摸屏的LCD屏(上面盖的哪一层薄膜就是触摸用的)

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png


2.2 特性

1. 工作电压范围为 2.2V~5.25V
2. 支持 1.5V~5.25V 的数字 I/O 口
3. 内建 2.5V 参考电压源
4. 电源电压测量(0V~6)
5. 内建温度测量功能
6. 触摸压力测量
7. 采用 SPI 3线控制通信接口
8. 具有自动 power-down 功能
9. 封装:QFN-16、 TSSOP-16 和 VFBGA-48与 TSC2046、 AK4182A 完全兼容
10. XPT2046 在 125KHz 转换速率和 2.7V 电压下的功耗仅为750 µW。 XPT2046 11. 以其低功耗和高速率等特性,被广泛应用在采用电池供电的小型手持设备上,比如 PDA、手机等。
12. XPT2046 有 TSSOP-16、 QFN-16 和 VFBGA 三种封装形
式,温度范围是 - 40 ~ + 85℃ 。


2.3工作原理

XPT2046 是一种典型的逐次逼近型模数转换器(SAR ADC),包含了采样/保持、模数转换、串口数据输出等功能。同时芯片集成有一个 2.5V的内部参考电压源、温度检测电路,工作时使用外部时钟。 XPT2046 可以单电源供电,电源电压范围为 2.7V~5.5V。参考电压值直接决定ADC的输入范围,参考电压可以使用内部参考电压,也可以从外部直接输入1V~VCC范围内的参考电压(要求外部参考电压源输出阻抗低)。 X、 Y、 Z、 VBAT、 Temp和AUX模拟信号经过片内的
控制寄存器选择后进入ADC, ADC可以配置为单端或差分模式。选择VBAT、 Temp和AUX时可以配置为单端模式;作为触摸屏应用时,可以配置为差分模式,这可有效消除由于驱动开关的寄生电阻及外部的干扰带来的测量误差,提高转换准确度。

典型的应用:

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png


单端工作模式

SER/DFR置为高电平时, XPT2046 工作在为单端模式,单端工作模式的应用原理如下图所示。
单端模式简单,在采样过程完成后,转换过程中可以关闭驱动开关,降低功耗。但这种模式的缺点是精度直接受参考电压源的精度限制,同时由于内部驱动开关的导通电阻存在,导通电阻与触摸屏电阻的分压作用,也会带来测量误差。

(图片里的A2 A1 A0 ,还有上面说的SER/DFR就是XPT2046的配置命令,具体使用方法在后面会讲到)

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png


差分工作模式

SER/DFR置为低电平时, XPT2046 为差分工作模式.
差分模式的优点是: +REF 和-REF 的输入分别直接接到 YP、 YN 上,可消除由于驱动开关的导通电阻引入的坐标测量误差。
缺点是:无论是采样还是转换过程中,驱动开关都需要接通,相对单端模式而言,功耗增加了。
如果不考虑功耗的话,当前就选择差分工作模式了。

(图片里的A2 A1 A0 ,还有上面说的SER/DFR就是XPT2046的配置命令,具体使用方法在后面会讲到)

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png



2.3 XPT2046采集并转换一次数据的时序介绍

XPT2046 数据接口是串行接口,处理器和转换器之间的通信需要 8 个时钟周期,可采用 SPI、 SSI 和 Microwire 等同步串行接口。一次完整的转换需要 24 个串行同步时钟(DCLK)来完成。

前 8 个时钟用来通过DIN引脚输入控制字节。当转换器获取有关下一次转换的足够信息后,接着根据获得的信息设置输入多路选择器和参考源输入,并进入采样模式,如果需要,将启动触摸面板驱动器。 3 个多时钟周期后,控制字节设置完成,转换器进入转换状态。这时,输入采样-保持器进入保持状态,触摸面板驱动器停止工作(单端工作模式)。

接着的12 个时钟周期将完成真正的模数转换。如果是度量比率转换方式(SER/DFR ——=0),驱动器在转换过程中将一直工作,第13 个时钟将输出转换结果的最后一位。剩下的 3 个多时钟周期将用来完成被转换器忽略的最后字节(DOUT置低)。

时序图如下:


时序图里的控制命令字节:

位 7(MSB) 位 6 位 5 位 4 位 3 位 2 位 1 位 0(LSB)
S A2 A1 A0 MODE SER/DFR PD1 PD0

控制字节每个位的含义如下:

名称 功能描述
7 S 开始位。为 1 表示一个新的控制字节到来,为 0 则忽略 PIN 引脚上数据
6-4 A2-A0 通道选择位。这个在上面已经介绍过了
3 MODE 12 位/8 位转换分辨率选择位。为 1 选择 8 位为转换分辨率,为 0 选择 12 位分辨率
2 SER/DFR 单端输入方式/ 差分输入方式选择位。为 1 是单端输入方式,为 0 是差分输入方式
1-0 PD1-PD0 低功率模式选择位。若为11,器件总处于供电状态;若为00,器件在变换之间处于低
功率模式

注意: 差分模式仅用于 X 坐标、 Y 坐标和触摸压力的测量,其它测量要求采用单端模式。

根据上面表格的介绍,可以得到在差分模式下,选择12位分辨率,测量X和Y坐标的两个命令:0xD0 和 0x90

XPT2046还有其他模式,可以测量温度,笔中断的开关(默认是开着的),16时钟周期转换,15时钟周期转换,这些就不再介绍。 根据前面的介绍用在触摸屏上测量XY坐标的功能已经满足了。


2.4 SPI时序介绍

这里的XPT2046支持标准3线SPI接口,关于SPI时序的介绍,在前面文章里有介绍过。

参考这里:STM32入门开发: 介绍SPI总线、读写W25Q64(FLASH)(硬件+模拟时序)_DS小龙哥的专栏-CSDN博客_w25q64


2.5 物理坐标与屏幕坐标的转换

正常在LCD屏上使用触摸屏,肯定是需要将采集的原始X、Y值转为LCD屏的屏幕坐标才好使用。

转换的方法有很多,这里采用最简单的角系数计算方法转换。

比如,我使用的LCD屏是3.5寸的,分辨率是320*480。

1. 得到触摸屏左上角和右下角的坐标XY极限值
x=3831,y=3934
x=155,y=168

2. 转换坐标值
x坐标:3831~155 --> 3676~0
y坐标:3934~168 --> 3766~0

3. 计算斜率
x坐标的斜率: 3676/320=11.4875
y坐标的斜率: 3766/480=7.84583

4. 得到实际的像素坐标
x坐标: 320-(实时采集的当前X模拟量-155)/11.4875
y坐标: 480-(实时采集的当前Y模拟量-168)/7.84583

这里相减的原因: 因为我测试用的触摸屏采集出来的X、Y值大小和LCD屏的屏幕坐标值大小是反过来的。


三、示例代码

采用SPI模拟时序驱动,其他平台都可以移植。


3.1 xpt2046.c

#include "xpt2046_touch.h"

struct XPT2046_TOUCH xpt2046_touch;


/*

函数功能:  初始化

硬件连接:

T_MOSI--PF9

T_MISO--PB2

T_SCK---PB1

T_PEN---PF10

T_CS----PF11

*/

void XPT2046_TouchInit(void)

{

    /*1. 时钟初始化*/

    RCC->APB2ENR|=1<<3; //PB

    RCC->APB2ENR|=1<<7; //PF

    

   /*2. 初始化GPIO口*/

   GPIOB->CRL&=0xFFFFF00F;

   GPIOB->CRL|=0x00000830;

  

   GPIOF->CRH&=0xFFFF000F;

   GPIOF->CRH|=0x00003830;

  

   /*3. 上拉*/

   GPIOB->ODR|=0x3<<1;

   GPIOF->ODR|=0x7<<9;

}



/*

函数功能:  SPI底层写一个字节

*/

void XPT2046_SPI_WriteOneByte(u8 cmd)

{

    u8 i;

    for(i=0;i<8;i++)

    {

        XPT2046_SCK=0; //低电平写

        if(cmd&0x80)XPT2046_MOSI=1;

        else XPT2046_MOSI=0;

        cmd<<=1;

        XPT2046_SCK=1; //高电平读,保证数据线稳定

    }

}



/*

函数功能:  读2个字节

说明: 读取16位数据,最低4位数据无效,有效数据是高12位


*/

u16 XPT2046_ReadData(u8 cmd)

{

    u16 data;

    u8 i;

    XPT2046_CS=0;  //选中XPT2046

    XPT2046_MOSI=0;

    XPT2046_SCK=0;

    XPT2046_SPI_WriteOneByte(cmd);

    

    DelayUs(8); //0.008ms ,等待XPT2046转换完成。

    //消除忙信号

    XPT2046_SCK=0;

    DelayUs(1);

    XPT2046_SCK=1;

    

    //连续读取16位的数据

    for(i=0;i<16;i++)

    {

        XPT2046_SCK=0; //通知XPT2046,主机需要数据

        XPT2046_SCK=1; 

        data<<=1;

        if(XPT2046_MISO)data|=0x01;

    }

    data>>=4; //丢弃最低4位

    

    XPT2046_CS=1; //取消选中

    return data;

}


/*

XPT2046的命令:


10010000  :测试Y的坐标 0x90

11010000  :测试X的坐标 0xD0


返回值:  0表示没有读取到坐标,1表示读取到当前坐标


//1. 得到左上角和右下角的坐标XY极限值

  x=3831,y=3934

  x=155,y=168


//2. 转换坐标值

  x坐标:3831~155 -->  3676~0

  y坐标:3934~168 -->  3766~0


//3. 计算斜率

  x坐标的斜率: 3676/320=11.4875

  y坐标的斜率: 3766/480=7.84583


//4. 得到实际的像素坐标

  x坐标:  320-(模拟量-155)/11.4875

  y坐标:  480-(模拟量-168)/7.84583

*/

u8 XPT2046_ReadXY(void)

{

    if(XPT2046_PEN==0) //判断触摸屏是否按下

    {

        /*1. 得到物理坐标*/

        xpt2046_touch.x0=XPT2046_ReadData(0xD0);

        xpt2046_touch.y0=XPT2046_ReadData(0x90);

      

        /*2. 得到像素坐标*/

        xpt2046_touch.x=320-(xpt2046_touch.x0-155)/11.4875;

        xpt2046_touch.y=480-(xpt2046_touch.y0-168)/7.84583;

        return 1;

    }

    return 0;

}

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

3.2 xpt2046.h

#ifndef XPT2046_TOUCH_H

#define XPT2046_TOUCH_H

#include "stm32f10x.h"

#include "sys.h"

#include "delay.h"


//触摸屏引脚定义

#define XPT2046_MOSI PFout(9)

#define XPT2046_MISO PBin(2)

#define XPT2046_SCK PBout(1)

#define XPT2046_CS  PFout(11)

#define XPT2046_PEN PFin(10)


//函数声明

void XPT2046_TouchInit(void);

void XPT2046_SPI_WriteOneByte(u8 cmd);

u8 XPT2046_ReadXY(void);


//存放触摸屏信息的结构体

struct XPT2046_TOUCH

{

    u16 x0; //物理坐标x

    u16 y0; //物理坐标y

    u16 x;  //像素坐标x

    u16 y;  //像素坐标y

};

extern struct XPT2046_TOUCH xpt2046_touch;

#endif


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>