stm32 触摸屏 XPT2046

发布者:bdwhsc最新更新时间:2019-01-04 来源: eefocus关键字:stm32  触摸屏  XPT2046 手机看文章 扫描二维码
随时随地手机看文章

引脚功能描述 

1


控制字的控制位命令 

1


控制字节各位描述 

1


单端模式输入配置 

1


差分模式输入配置 

1


时序 

前8个时钟用来通过DIN引脚输入控制字节,接着的12个时钟周期将完成真正的模数转换,剩下的3个多时钟周期将用来完成被转换器忽略的最后字节(DOUT置低)


1


举例 

1 
2 
3


#define TOUCH_READ_TIMES    40 //读取次数

#define TOUCH_ERR_RANGE 20 //误差范围


#define TOUCH_X_CMD 0xD0 //读取X轴

#define TOUCH_Y_CMD 0x90 //读取Y轴

#define TOUCH_Continue_Read 0xFF

#define TOUCH_X_MAX 4000 //X最大值

#define TOUCH_X_MIN 100 //X最小值

#define TOUCH_Y_MAX 4000 //Y最大值

#define TOUCH_Y_MIN 100 //X最小值


#define LCD_CALx_MIN (10) //校准点最小值X

#define LCD_CALx_MAX (tftlcd_data.width - LCD_CALx_MIN) //校准点最大值X

#define LCD_CALy_MIN (10) //校准点最小值Y

#define LCD_CALy_MAX (tftlcd_data.height - LCD_CALy_MIN) //校准点最大值Y


#define LCD_CAL_X   (LCD_CALx_MAX - LCD_CALx_MIN) //方框的宽度

#define LCD_CAL_Y   (LCD_CALy_MAX - LCD_CALy_MIN) //方框的高度


#define TOUCH_CAL_OK        'Y' //校准OK标志

#define TOUCH_CAL_ADDR  200  //校准参数在at24c02的保存地址


typedef struct

{

    u8 flag; 

    short xoffset;

    short yoffset; 

    float xFactor;

    float yFactor;

} calibrate_t;


calibrate_t calibrate = {0};


u16 touchX;

u16 touchY;


void TOUCH_init()

{

    GPIO_InitTypeDef gpioa = 

    {

        GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7,

        GPIO_Speed_50MHz,

        GPIO_Mode_AF_PP

    };


    GPIO_InitTypeDef gpiod6 = 

    {

        GPIO_Pin_6,

        GPIO_Speed_50MHz,

        GPIO_Mode_Out_PP

    };

    GPIO_InitTypeDef gpiod7 = 

    {

        GPIO_Pin_7,

        GPIO_Speed_50MHz,

        GPIO_Mode_IPU

    };


    SPI_InitTypeDef spi = 

    {

        SPI_Direction_2Lines_FullDuplex,

        SPI_Mode_Master, //0x0104

        SPI_DataSize_8b,

        SPI_CPOL_High,

        SPI_CPHA_2Edge,

        SPI_NSS_Soft,

        SPI_BaudRatePrescaler_256,

        SPI_FirstBit_MSB,

        7

    };


    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOD, ENABLE);


    GPIO_Init(GPIOA, &gpioa);

    GPIO_Init(GPIOD, &gpiod6);

    GPIO_Init(GPIOD, &gpiod7);


    SPI_Init(SPI1, &spi); //初始化SPI


    SPI_Cmd(SPI1, ENABLE); //使能SPI

}


u16 TOUCH_read(u16 cmd)

{

    u8 i = 0, j = 0;

    u16 tmp;

    u16 value[TOUCH_READ_TIMES] = {0};

    u32 total_value = 0;


    SPI1_SetSpeed(SPI_BaudRatePrescaler_32); //设置SPI速度


    for(i = 0; i < TOUCH_READ_TIMES; i++) //读取次数

    {

        TOUCH_CS = 0;


        SPI1_read_write(cmd);


        value[i] = SPI1_read_write(TOUCH_Continue_Read) << 8; //详见时序

        value[i] |= SPI1_read_write(TOUCH_Continue_Read);

        value[i] >>= 3;


        TOUCH_CS = 1;

    }


    for (i = 0; i < TOUCH_READ_TIMES; i++) //排序

    {

        for (j = i + 1; j < TOUCH_READ_TIMES; j++)

        {

            if (value[i] < value[j])

            {

                tmp = value[i];

                value[i] = value[j];

                value[j] = tmp;

            }

        }

    }


    for (i = 1; i < TOUCH_READ_TIMES - 1; i++) //去掉一个最大值,一个最小值

    {

        total_value += value[i];

    }


    total_value /= (TOUCH_READ_TIMES - 2); //求平均值


    return total_value;

}


u8 TOUCH_readXY(u16 *x, u16 *y)

{

    u16 valueX1, valueY1, valueX2, valueY2;


    valueX1 = TOUCH_read(TOUCH_X_CMD); //读取触摸值

    valueY1 = TOUCH_read(TOUCH_Y_CMD);

    valueX2 = TOUCH_read(TOUCH_X_CMD);

    valueY2 = TOUCH_read(TOUCH_Y_CMD);


    *x = valueX1 > valueX2 ? (valueX1 - valueX2) : (valueX2 - valueX1); 

    *y = valueY1 > valueY2 ? (valueY1 - valueY2) : (valueY2 - valueY1);

    if((*x > TOUCH_ERR_RANGE) || (*y > TOUCH_ERR_RANGE)) //判断容错范围

    {

        return 0xFF;

    }


    *x = (valueX1 + valueX2) / 2;

    *y = (valueY1 + valueY2) / 2;


    if((*x < TOUCH_X_MIN || *x > TOUCH_X_MAX) || //判断边界范围

        (*y < TOUCH_Y_MIN || *y > TOUCH_Y_MAX))

    {

        return 0xFF;

    }


    return 0;

}


void TOUCH_start_calibrate(u16 x, u16 y, u16 *valueX,u16 *valueY) //开始校准

{

    u8 i = 0;


    LCD_Clear(BACK_COLOR); //清屏

    LCD_DrowSign(x, y, BACK_COLOR); //画十字


    while(1)

    {

        if(TOUCH_readXY(valueX, valueY) != 0xFF)

        {

            i++;

            if(i > 10)

            {

                LCD_DrowSign(x, y, BACK_COLOR);

                break;

            }

        }

    }

}


void TOUCH_calibrate()

{

    u16 px[2], py[2], valueX[4], valueY[4];

    float xFactor = 0, yFactor = 0;


    TOUCH_start_calibrate(LCD_CALx_MIN, LCD_CALy_MIN, &valueX[0], &valueY[0]); //第一次校准

    delay_ms(500);


    TOUCH_start_calibrate(LCD_CALx_MIN, LCD_CALy_MAX, &valueX[1], &valueY[1]);

    delay_ms(500);


    TOUCH_start_calibrate(LCD_CALx_MAX, LCD_CALy_MIN, &valueX[2], &valueY[2]);

    delay_ms(500);


    TOUCH_start_calibrate(LCD_CALx_MAX, LCD_CALy_MAX, &valueX[3], &valueY[3]);

    delay_ms(500);


    //整合成对角的两点

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

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

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

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


    //求出比例因子

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

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


    //求出偏移量

    calibrate.xoffset = (short)LCD_CALx_MAX - ((float)px[1] * xFactor);

    calibrate.yoffset = (short)LCD_CALy_MAX - ((float)py[1] * yFactor);


    calibrate.xFactor = xFactor ;

    calibrate.yFactor = yFactor ;


    printf("xoffset %d\n", calibrate.xoffset);

    printf("yoffset %d\n", calibrate.yoffset);

    printf("xFactor %f\n", calibrate.xFactor);

    printf("yFactor %f\n", calibrate.yFactor);


    //保存校准数据到at24c02

    calibrate.flag = TOUCH_CAL_OK;

    at24c02Write_buf((u8*)&calibrate, TOUCH_CAL_ADDR, sizeof(calibrate));   

}


u8 TOUCH_scan() //查看是否触摸

{

    u16 valueX;

    u16 valueY; 


    if(TOUCH_readXY(&valueX, &valueY) == 0xFF)

    {

        return 0xFF;

    }


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

    touchX = valueX * calibrate.xFactor + calibrate.xoffset;

    touchY = valueY * calibrate.yFactor + calibrate.yoffset;


    if((touchX > tftlcd_data.width) || (touchY > tftlcd_data.height))

    {

        return 0xFF;

    }


    return 0;

}


int main(void)

{

    I2C_init();

    TOUCH_init();


    at24c02Read_buf((u8*)&calibrate, TOUCH_CAL_ADDR, sizeof(calibrate));

    if(calibrate.flag != TOUCH_CAL_OK) //判断是否已经校准

    {

        TOUCH_calibrate();

    }

    LCD_ShowString(tftlcd_data.width-40,0,tftlcd_data.width,tftlcd_data.height,16,"clear");


    while(1)

    {

        if(TOUCH_scan() == 0)

        {

            LCD_Fill(touchX-1, touchY-1, touchX+2, touchY+2, FRONT_COLOR); //画粗线


            if((touchX > tftlcd_data.width-40) && (touchY < 20))

            {

                LCD_Fill(0, 0, tftlcd_data.width,tftlcd_data.height, BACK_COLOR); //清屏

                LCD_ShowString(tftlcd_data.width-40,0,tftlcd_data.width,tftlcd_data.height,16,"clear");

            }

        }

    }

}


关键字:stm32  触摸屏  XPT2046 引用地址:stm32 触摸屏 XPT2046

上一篇:教你使用stm32接收串口的一帧数据
下一篇:stm32 SysTick系统定时器

推荐阅读最新更新时间:2024-03-16 16:21

STM32启动过程启动文件分析
一、概述 1、说明   每一款芯片的启动文件都值得去研究,因为它可是你的程序跑的最初一段路,不可以不知道。通过了解启动文件,我们可以体会到处理器的架构、指令集、中断向量安排等内容,是非常值得玩味的。   STM32作为一款高端Cortex-M3系列单片机,有必要了解它的启动文件。打好基础,为以后优化程序,写出高质量的代码最准备。   本文以一个实际测试代码--START_TEST为例进行阐述。 2、整体过程概括   STM整个启动过程是指从上电开始,一直到运行到main函数之间的这段过程,步骤为(以使用微库为例): ①上电后硬件设置SP、PC ②设置系统时钟 ③软件设置SP ④加载.data、.bss,并初始化栈区
[单片机]
<font color='red'>STM32</font>启动过程启动文件分析
STM32 ADC转换时间
STM32F103XX的ADC的采样时钟最快14MHz,最快采样率1MHz。 ADC时钟: 这个ADC时钟是从哪来的呢。我们看下面这个STM32的时钟结构图: 我们大多使用STM32的最快PCLK2系统时钟72MHz。 ADCCLK的时钟由72MHz的6分频能瞒住14MHz以下的要求 为12MHz。 RCC_ADCCLKConfig(RCC_PCLK2_Div6); //72M/6=12,ADC最大时间不能超过14M ADC转换时间: 有如下公式: TCONV = 采样时间+ 12.5 个周期 其中12.5个周期是采集12位AD时间是固定的,另外一个采样时间可以取下面几个参数由SMPx 寄存器控制,每个通道可以单独配置
[单片机]
<font color='red'>STM32</font> ADC转换时间
STM32串口通信之超级终端控制LED灯
一、硬件介绍 本程序使用开发板:STM32-PZ6806L 1、GPIO控制LED 开发板中LED的硬件电路参看:直接通过寄存器地址操作控制LED灯 2、串口 开发板中连接了MCU的2个串口,分别为USART1和USART3,其中USART1通过CH340G接PC端USB口,实现USB转串口功能,可以用于程序下载和串口通信,但通过PC端的超级终端连接时不能连接,所以本程序使用开发板上的另一个串口USART3,该串口信号转换成RS232,通过直连串口线与PC端的COM口相连,可以实现与超级终端通信。 开发板串口的硬件连接图请参考:STM32串口通信之Hello 二、项目创建与配置 请参看《STM32串
[单片机]
<font color='red'>STM32</font>串口通信之超级终端控制LED灯
2023年 STM32中国峰会开启全新篇章
今年的STM32中国峰会已经圆满结束,我们诚挚感谢各位的持续支持和关注。下面就让一组关键数据带我们回顾本届峰会的精彩历程! • 2,600多名观众亲临2023 STM32中国峰会现场 • 75,000多名观众在线观看了2023 STM32中国峰会 • 截至5月17日,共收集2,433张直播图片,浏览量高达341,495次 • 围绕边缘AI&信息安全、连接、生态系统&开发者优先计划以及智能工业&高性能MCU/MPU四大主题,共计29场主题演讲和28场研讨会在峰会现场举办 • 现场展示200多款产品, 覆盖边缘AI,网络连接,信息安全,生态系统,开发者优先解决方案和STM32 垂直应用等广泛领域 • 11
[单片机]
2023年 <font color='red'>STM32</font>中国峰会开启全新篇章
STM32步进伺服电机梯形加速源程序 单轴简易运动控制器
步进电机梯形加速程序 单片机源程序如下: /*基于STM32的单轴简易运动控制器/脉冲发生器*/ /*脉冲+方向控制步进伺服电机*/ /* 优化记录: 增加急停GPIOC.0、正向极限GPIOC.1、负向极限GPIOC.2等输入IO接点 中断修改TIMx_PSC一个寄存器的值,而不是修改TIMx_ARR预加载寄存器+TIMx_CCRx比较值寄存器两个值,缩短中断处理时间 定位指令DRVI/DRVA中,目标频率设定过高、而实际输出脉冲数过少时,则不必加速到目标频率即进入减速区 */ /* DRVI(A);相对定位,输出A(A取绝对值)个脉冲 A不能为0 若A为正数,则方向为正、GPIOB.0为高电平 若A为负数,则
[单片机]
STM32学习笔记一时钟和定时器
由于近期在准备海洋航行器比赛,正好趁此机会学习一下ARM,看到周围很多同学都在使用32,所以我也买了一块STM32F103ZET6,准备好好地学习一下。 STM32的时钟系统相当的复杂,包含了5个时钟源,分别是HSI HSE LSI LSE PLL,HSI是高速内部时钟、RC振荡器,频率为8M,HSE是高速外部时钟,即晶振,我的核心板上晶振为8M。LSI为低速内部时钟、RC振荡器,频率40k,LSE为低速外部时钟,接32.768kHz晶振,作为RTC时钟源。PLL为锁相环倍频输出,最大不超过72M。 我在学习定时器时先看的是TIM3,它挂载在APB1分频器上,APB1上面挂载的是低速外设,APB2上挂载高速外设。 在
[单片机]
STM32 SysTick小结
SysTick简介 系统定时器,24位,只能递减,存在于内核,嵌套在 NVIC 中。其大部分内容可以查看 STM32F10xxx Cortex-M3编程手册-英文版。 SysTick工作过程 1.计数器在时钟驱动下从初值开始计数直到0。 2.为0时可以产生中断或置位 COUNTFLAG 标志位。 3.如果没有关闭,则初值再次开始计数,如此循环。 计数过程中,计数器的实时值可由 STK_VAL 位得到 SysTick寄存器 STK_CTRL 控制及状态寄存器,只有四个有效位: COUNTFLAG :如果计数器计到0,此位置1;如果软件读取这个位,这个位会置0; CLKSOURCE :时钟选择位;0=AHB/8;1=AHB
[单片机]
<font color='red'>STM32</font> SysTick小结
STM32的基本系统是怎样的?
电源 无论是否使用模拟部分和AD部分,MCU外围出去VCC和GND,VDDA、VSSA、Vref(如果封装有该引脚)都必需要连接,不可悬空 对于每组对应的VDD和GND都应至少放置一个104的陶瓷电容用于滤波,并接该电容应放置尽量靠近MCU 用万用表测试供电电压是否正确,调试时最好用数字电源供电,以便过压或过流烧坏板子,电压最好一步一步从进线端测试到芯片供电端 复位、启动选择 Boot引脚与JTAG无关。其仅是用于MCU启动后,判断执行代码的起始地址 在电路设计上可能Boot引脚不会使用,但要求一定要外部连接电阻到地或电源,切不可悬空;STM32三种启动模式对应的存储介质均是芯片内置的,它们是: 用户闪存 = 芯片内置的Fla
[单片机]
<font color='red'>STM32</font>的基本系统是怎样的?
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

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

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

换一换 更多 相关热搜器件
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved