STM32CubeMX系列 | 触摸屏

发布者:心满意足最新更新时间:2023-03-23 来源: zhihu关键字:STM32CubeMX系列  触摸屏 手机看文章 扫描二维码
随时随地手机看文章

1.触摸屏简介

目前最常用的触摸屏有两种:电阻式触摸屏和电容式触摸屏

1.1 电阻式触摸屏

电阻式的触摸屏结构如下图示,它主要由表面硬涂层、两个ITO层、间隔点以及玻璃底层构成,这些结构层都是透明的,整个触摸屏覆盖在液晶面板上,透过触摸屏可看到液晶面板。表面涂层起到保护作用,玻璃底层起承载的作用,而两个ITO层是触摸屏的关键结构,它们是涂有铟锡金属氧化物的导电层。两个ITO层之间使用间隔点使两层分开,当触摸屏表面受到压力时,表面弯曲使得上层ITO与下层ITO接触,在触点处连通电路。

两个ITO涂层的两端分别引出X-、X+、Y-、Y+四个电极,这是电阻屏最常见的四线结构,通过这些电极,外部电路向这两个涂层可以施加匀强电场或检测电压。

电阻触摸屏的校准:确定位置和对应的电压值之间的比例关系

X0 = Xfac * ADC_X + Xoff
Y0 = Yfac * ADC_Y + Yoff

电阻触摸屏的优缺点

- 优点:精度高、价格便宜、抗干扰能力强、稳定性好
- 缺点:容易被划伤、透光性不太好、不支持多点触控

触摸屏都需要一个AD转换器来将电压变化读取出来,供主机算出触摸的位置。本例程中的TFTLCD模块使用的是四线电阻式触摸屏,触摸屏控制芯片为XPT2046,XPT2046是一款4导线制触摸屏控制器,采用SPI模式进行通讯,内含12位分辨率125KHz转换速率逐步逼近型A/D转换器。XPT2046引脚图(SOP-16封装)及引脚说明如下图示

1.2 电容式触摸屏

与电阻式触摸屏不同,电容式触摸屏不需要通过压力使触点变形。它的基本原理是利用充电时间检测电容大小,若手指触摸屏幕,会影响触摸点附近两个电极之间的耦合,从而改变两个电极之间的电容量,若检测到某电容的电容量发生了改变,即可获知该电容处有触摸动作从而通过检测出电容值的变化来获知触摸信号。

由于本例程使用的是电阻式触摸屏,这里电容式触摸屏不做详细介绍

2. 硬件设计

D1指示灯用来提示系统运行状态,K_UP按键用来强制校准电阻触摸屏(电容屏无需校准),AT24C02用来存储电阻触摸屏校准数据,TFTLCD模块用来显示触摸

  • D1指示灯

  • K_UP按键

  • TFTLCD模块

  • AT24C02

  • USART1

3. 软件设计

3.1 STM32CubeMX设置

  • RCC设置外接HSE,时钟设置为72M

  • PC0设置为GPIO推挽输出模式、上拉、高速、默认输出电平为高电平

  • PA0设置为GPIO输入模式、下拉模式

  • PD6设置为GPIO输出模式(TOUCH_CS);PD7设置为GPIO输入模式(TOUCH_PEN)

  • USART1选择为异步通讯方式,波特率设置为115200Bits/s,传输数据长度为8Bit,无奇偶校验,1位停止位

  • 激活I2C2,选择标准传输模式,选择7位寻址地址,其余默认设置

  • 激活FSMC,详细请参考TFTLCD显示章节的设置

  • 激活SPI1,不开启NSS,数据长度8位,MSB先输出,分频因子16,CPOL为HIGH,CPHA为第二个边沿,不开启CRC检验,NSS为软件控制

  • 输入工程名,选择工程路径(不要有中文),选择MDK-ARM V5;勾选Generated periphera initialization as a pair of ‘.c/.h’ files per IP ;点击GENERATE CODE,生成工程代码

3.2 MDK-ARM编程

  • 添加按键驱动文件key.c和key.h,参考按键输入例程

  • 添加AT24C02驱动文件24cxx.c和24cxx.h,参考I2C总线例程

  • 添加TFTLCD驱动文件tftlcd.c 和tftlcd.h,参考TFTLCD显示例程

  • 添加XPT2046触摸芯片驱动文件touch.c和touch.h 两个重要的结构体:

typedef struct{     /*存储触点读取到的数据*/

    uint16_t x;     //x轴物理坐标值

    uint16_t y;     //y轴物理坐标值

    uint16_t lcdx;  //x轴彩屏坐标值

    uint16_t lcdy;  //y轴彩屏坐标值

}TouchTypeDef;


typedef struct{     /*保存校正因素*/

  uint8_t posState; //校正参数标志

  int16_t xOffset;  //x轴偏移量

  int16_t yOffset;  //y轴偏移量

  float   xFactor;  //x轴比例因数

  float   yFactor;  //y轴比例因数

}PosTypeDef;

触摸屏初始化及读取物理坐标(ADC值)函数:

void TOUCH_Init(void){

    //读取AT24C02的TOUCH_ADJ_ADDR地址处的值

    HAL_I2C_Mem_Read(&hi2c2,ADDR_24CXX_READ,TOUCH_ADJ_ADDR,I2C_MEMADD_SIZE_8BIT,&TouchAdj.posState,sizeof(TouchAdj),0xff);  

    if(TouchAdj.posState != TOUCH_ADJ_OK){  //检查是否有校正数据

        TOUCH_Adjust(); //如果没有校正数据,则启动校正函数  

    }

}

/*封装SPI读取数据函数*/

uint8_t WR_Cmd(uint8_t cmd){

    uint8_t Tx_DATA = cmd;

    uint8_t Rx_DATA = 0;

    HAL_SPI_TransmitReceive(&hspi1,&Tx_DATA,&Rx_DATA,1,500);

    return Rx_DATA;     

}

/*读取X轴或Y轴的ADC值,并进行滤波处理*/

uint16_t TOUCH_Read_AD(uint8_t cmd){

    uint8_t i, j;

    uint16_t NUMH,NUML;

    uint16_t NUM[TOUCH_READ_TIMES] = {0};

    uint16_t temp,value;

    uint32_t totalValue;    //注意数据类型


    for(i=0; i        TOUCH_CS_LOW(); //开始SPI通讯   

        WR_Cmd(cmd);

        NUMH = WR_Cmd(0XFF);

        NUML = WR_Cmd(0XFF);

        NUM[i] = (NUMH<<8)+ NUML;

        NUM[i] >>= 3;   //最低三位无用    

        TOUCH_CS_HIGH();    //结束SPI通讯

    }

    //滤波处理:1.从大到小排序

    for(i=0; i<(TOUCH_READ_TIMES - 1); i++){

        for(j=i+1; j            if(NUM[i] < NUM[j]){

                temp = NUM[i];

                NUM[i] = NUM[j];

                NUM[j] = temp;

            }   

        }       

    }

    //滤波处理:2.去掉最大值和最小值,求余下的平均值

    j = TOUCH_READ_TIMES - 1;

    totalValue = 0;

    for(i=1; i        totalValue += NUM[i];

    }

    value = totalValue/(TOUCH_READ_TIMES - 2);  

    return value;

}

/*读取X轴和Y轴的ADC值,再次进行滤波*/

uint8_t TOUCH_ReadXY(uint16_t *xValue, uint16_t *yValue){   

    uint16_t xValue1, yValue1, xValue2, yValue2;

    xValue1 = TOUCH_Read_AD(TOUCH_X_CMD);

    yValue1 = TOUCH_Read_AD(TOUCH_Y_CMD);

    xValue2 = TOUCH_Read_AD(TOUCH_X_CMD);

    yValue2 = TOUCH_Read_AD(TOUCH_Y_CMD);

    //计算两点之间的采样差值

    if(xValue1 > xValue2)

        *xValue = xValue1 - xValue2;

    else

        *xValue = xValue2 - xValue1;


    if(yValue1 > yValue2)

        *yValue = yValue1 - yValue2;

    else

        *yValue = yValue2 - yValue1;

    //判断采样差值是否在可控范围内

    if((*xValue > TOUCH_MAX+0) || (*yValue > TOUCH_MAX+0))  

        return 0xFF;

    //求平均值

    *xValue = (xValue1 + xValue2) / 2;

    *yValue = (yValue1 + yValue2) / 2;

    //判断得到的值,是否在取指范围内,避免出现飞点现象  

    if((*xValue > TOUCH_X_MAX+0) || (*xValue < TOUCH_X_MIN) || (*yValue > TOUCH_Y_MAX+0) || (*yValue < TOUCH_Y_MIN))                 

        return 0xFF;


    return 0; 

}

触摸屏校准函数:

/*读校准点的物理坐标*/

uint8_t TOUCH_ReadAdjust(uint16_t x, uint16_t y, uint16_t *xValue, uint16_t *yValue){

    uint8_t i;

    uint32_t timeCont;


    LCD_Clear(BACK_COLOR);

    LCD_DrowSign(x, y, RED);    //x和y为指定的校准点的彩屏坐标值

    i = 0;

    while(1){   //读该指定校准点的物理坐标值

        if(!TOUCH_ReadXY(xValue, yValue)){

            i++;

            if(i > 10){

                LCD_DrowSign(x, y, BACK_COLOR);

                return 0;

            }               

        }


        timeCont++;

        if(timeCont > 0xFFFFFFFE){  //超时退出 

            LCD_DrowSign(x, y, BACK_COLOR); 

            return 0xFF;

        } 

    }       

}

/*触摸屏校准函数*/

void TOUCH_Adjust(void){

    uint16_t px[2], py[2], xPot[4], yPot[4];

    float xFactor, yFactor;

    //读取4个校准点的物理坐标值

    if(TOUCH_ReadAdjust(LCD_ADJX_MIN, LCD_ADJY_MIN, &xPot[0], &yPot[0]))

        return;

    HAL_Delay(500);

    if(TOUCH_ReadAdjust(LCD_ADJX_MIN, LCD_ADJY_MAX, &xPot[1], &yPot[1]))

        return;

    HAL_Delay(500);

    if(TOUCH_ReadAdjust(LCD_ADJX_MAX, LCD_ADJY_MIN, &xPot[2], &yPot[2]))

        return;

    HAL_Delay(500);

    if(TOUCH_ReadAdjust(LCD_ADJX_MAX, LCD_ADJY_MAX, &xPot[3], &yPot[3]))

        return; 

    HAL_Delay(500);

    //处理读取到的四个点的数据,整合成对角的两个点

    px[0] = (xPot[0] + xPot[1]) / 2;

    py[0] = (yPot[0] + yPot[2]) / 2;

    px[1] = (xPot[3] + xPot[2]) / 2;

    py[1] = (yPot[3] + yPot[1]) / 2;

    //求出比例因数

    xFactor = (float)LCD_ADJ_X / (px[1] - px[0]);

    yFactor = (float)LCD_ADJ_Y / (py[1] - py[0]);  

    //求出偏移量

    TouchAdj.xOffset = (int16_t)LCD_ADJX_MAX - ((float)px[1] * xFactor);

    TouchAdj.yOffset = (int16_t)LCD_ADJY_MAX - ((float)py[1] * yFactor);

    //将比例因数进行数据处理,并保存

    TouchAdj.xFactor = xFactor ;

    TouchAdj.yFactor = yFactor ;        

    TouchAdj.posState = TOUCH_ADJ_OK;

    //将得出的校正因数保存到AT24C02中的TOUCH_ADJ_ADDR地址处

    HAL_I2C_Mem_Write(&hi2c2,ADDR_24CXX_WRITE,TOUCH_ADJ_ADDR,I2C_MEMADD_SIZE_8BIT,&TouchAdj.posState,sizeof(TouchAdj),0xff);    

}

触摸屏扫描函数:

uint8_t TOUCH_Scan(void){

    if(TOUCH_ReadXY(&TouchData.x, &TouchData.y)) 

        return 0xFF;    //没有触摸,直接返回0xFF

    //根据物理坐标值,计算出彩屏坐标值

    TouchData.lcdx = TouchData.x * TouchAdj.xFactor + TouchAdj.xOffset;

    TouchData.lcdy = TouchData.y * TouchAdj.yFactor + TouchAdj.yOffset;

    //查看彩屏坐标值是否超过彩屏大小

    if(TouchData.lcdx > tftlcd_data.width)

        TouchData.lcdx = tftlcd_data.width;

    if(TouchData.lcdy > tftlcd_data.height)

        TouchData.lcdy = tftlcd_data.height;

    return 0;     

}

在main.c文件下编写触摸屏测试代码

int main(void){

    uint8_t key;

    uint16_t penColor = BLUE;

    HAL_Init();

    SystemClock_Config();

    MX_GPIO_Init();

    MX_FSMC_Init();

    MX_I2C2_Init();

    MX_SPI1_Init();

    MX_USART1_UART_Init();

  /* USER CODE BEGIN 2 */

    TFTLCD_Init();

    AT24CXX_Init();

    HAL_Delay(2000);    

    LCD_Clear(WHITE);

    TOUCH_Init();

  /* USER CODE END 2 */

  while (1){

    key=KEY_Scan(0);

    if(key==KEY_UP_PRES){   //按下KEY_UP键进入校准函数

        TOUCH_Adjust(); 

    }       


    if(TOUCH_Scan() == 0){   

        if(TouchData.lcdy > tftlcd_data.height - 18){

[1] [2]
关键字:STM32CubeMX系列  触摸屏 引用地址:STM32CubeMX系列 | 触摸屏

上一篇:STM32CubeMX系列 | TFTLCD显示
下一篇:STM32CubeMX系列 | ADXL345传感器

推荐阅读最新更新时间:2024-10-29 22:09

ADS7843/XPT2046触摸屏芯片8051单片机驱动程序
我的彩屏的大小是240*320~ 以下是代码 //common.h #ifndef __COMMON_H__ #define __COMMON_H__ #include reg52.h #include intrins.h typedef unsigned int uint; typedef unsigned char uchar; #endif// !__COMMON_H__ //TouchPad.c #define __TOUCHPAD_C__ #include TouchPad.h //我的屏幕接口 //#include gdi.h sbit TP_CLK = P1^4; //时钟 sbit TP
[单片机]
单片机的液晶显示触摸屏控制系统的工作方案介绍
1 引 言 嵌入式触摸屏装置是人机交互设备,一般将触摸屏安装在液晶显示屏上面,利用微处理器对触摸屏与液晶显示屏进行控制,实现触摸屏对液晶显示屏的控制,方便、直观,取代了传统的键盘输入,成为嵌入式计算机系统的输入设备,广泛应用于电子产品与工业控制中。由于触摸屏边缘电阻不均匀,不易找到变化规律,难于实现触摸屏坐标与点阵式液晶显示屏相互对应,会出现触摸点与液晶显示屏显示信息错位,造成触摸控制信息不灵敏。本文基于AT89C51 单片机和ADS7846芯片,辅以点阵式液晶显示屏,进行嵌入式触摸屏输入与显示系统的软硬件设计,实现触点测量与液晶屏上像素相对应,实现预期的控制功能,提高触摸控制的灵敏度。 2 液晶显示触摸屏的硬件设计 液晶触
[单片机]
单片机的液晶显示<font color='red'>触摸屏</font>控制系统的工作方案介绍
四大神级功能加持,苹果智能戒指是要颠覆谁
最近曝光的一份苹果专利数据,这份专利文件显示,这个设备可能会带有一个小型的显示屏,将于苹果自家的其他设备配合使用。在文件中也提到,用户可以将这个带有触摸屏的戒指佩戴在食指上,并使用大拇指进行操作。 当然,正如加入了触摸屏的手表并不能就称之为智能手表一样,只是加入了触摸屏的戒指也不能称之为智能戒指。当然这个智能戒指仍然只存在于专利文件上,考 虑到苹果每年都会申请大量的专利,而其中很大一部分的专利都是没有转化为实际产品的,这个苹果牌智能戒指的命运将会如何,我们也不得而知。不过目前市场上 也没有太实用的智能戒指产品,或许我们也还是可以期待一下这枚苹果智能戒指的。    说到苹果的专利,其实在苹果申请的这大量的专利当中,
[嵌入式]
触摸屏和人机界面的区别
触摸屏是人机界面的一种,但是有区别的 人机界面(Human-ComputerInterface,简写HCI,又称用户界面或使用者界面):是人与计算机之间传递、交换信息的媒介和对话接口,是计算机系统的重要组成部分。它实现信息的内部形式与人类可以接受形式之间的转换。凡参与人机信息交流的领域都存在着人机界面。 系统和用户之间进行交互和信息交换的媒介,它实现信息的内部形式与人类可以接受形式之间的转换。凡参与人机信息交流的领域都存在着人机界面。 举个例子来说,在一座工厂里头,我们要搜集工厂各个区域的温度、湿度以及工厂中机器的状态等等的信息透过一台主控器监视并记录这些参数,并在一些意外状况发生的时候能够加以处理。这便是一个很
[工业控制]
三菱plc与威纶触摸屏的通信控制
触摸屏人机接口(Human Machine Interface,HMI),连接可编程序控制器(PLC)、变频器、直流调速器、仪表等工业控制设备,利用显示屏显示,通过输入单元(如触摸屏、键盘、鼠标等)写入工作参数或输入操作命令,实现人与机器信息交互的数字设备,由硬件和软件两部分组成. 举个简单的例子说明下HMI控制PLC。 写一个简答的控制两个电机正反转、调速、速度显示。 先写主界面: 主界面的编辑 文字/批注用来写标题或者按钮、开关的标注,手动界面和自动界面的进入用功能键来实现,新建两个窗口,一个是手动界面窗口和自动界面窗口, 功能键的属性 时间 在主界面的下面可添加时间显示。 手动界面 手动界面的编写包括
[嵌入式]
三菱plc与威纶<font color='red'>触摸屏</font>的通信控制
STM32CubeMX系列 | 定时器中断
1. 定时器中断简介 STM32的定时器功能十分强大,有高级定时器(TIM1和TIM8)、通用定时器(TIM2~TIM5)和基本定时器(TIM6和TIM7);本实验主要介绍难度适中的通用定时器,通用定时器是一个通过可编程预分频器驱动的16位自动装载计数器构成。 它适用于多种场合,包括测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和PWM)。 使用定时器预分频器和RCC时钟控制器预分频器,脉冲长度和波形周期可以在几个微秒到几个毫秒间调整。 每个定时器都是完全独立的,没有互相共享任何资源。 通用TIMx (TIM2、TIM3、TIM4和TIM5)定时器功能包括: 16位向上、向下、向上/向下自动装载计数器 16位
[单片机]
电容式触摸屏系统设计考虑问题
  随着消费移动通信设备越来越多地采用数字方式和集成更多的功能,对于设备的设计来说,开发直观的创新型用户接口(UI)方案变得更为重要。作为用户接口设计的一部分,投射式电容触摸屏有助于应对这一挑战。   要设计一款成功的投射式电容触摸屏系统,需要仔细考虑设备的机械设计、基底选择和用户接口,另外,在设计过程的所有阶段都不能忘记在成本和技术之间进行折衷。     与电阻式触摸屏技术不同,投射式电容触摸屏更易于处理手指的动作,特别是多点触摸的用户输入。电阻技术需要依靠手指压力使触摸屏的多个机械层产生电气接触。   这种操作方法会影响手指滑动的流畅性和手势操作的灵巧性。另外,电阻式触摸屏的多层机械结构易于因重复使用而较早产生磨损
[嵌入式]
新一代iPod将支持Wi-Fi和触摸屏
  本周三,投行Piper Jaffray表示,它对华尔街流行的观点有不同看法,即苹果iPod业务的增长将在今年戛然而 止。Piper Jaffray称,售价低于200美元、支持无线和触摸屏技术的产品将推动iPod业务在可预见的将来实现持续增长。   Piper Jaffray的分析师吉恩在一份报告中写道,尽管我们也不认为iPod业务是苹果增长的主要动力,但认为苹果iPod业务在今年将超过华尔街的预期。对于华尔街有关今年iPod销售量将为5300万部——与去年基本持平的预期,我们不敢苟同。我们认为苹果能够保持iPod销售量增长的趋势,并略微超过华尔街的预测。   吉恩承认,iPod销售量增长幅度达到20%以上是不大可能的,但他
[手机便携]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved