stm32 触摸屏 XPT2046
引脚功能描述 
控制字的控制位命令 
控制字节各位描述 
单端模式输入配置 
差分模式输入配置 
时序 
前8个时钟用来通过DIN引脚输入控制字节,接着的12个时钟周期将完成真正的模数转换,剩下的3个多时钟周期将用来完成被转换器忽略的最后字节(DOUT置低)
举例 
 
 
#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的更多相关文章
- 第29章 	电容触摸屏—触摸画板—零死角玩转STM32-F429系列
		
第29章 电容触摸屏—触摸画板 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fir ...
 - 基于野火M3开发板(STM32F103VET6)的迷宫小球(重力感应控制)游戏开发
		
2013-03-03 这是研一上学期<实时嵌入式系统实验>课程的大作业,是利用野火板的资源,加上一个AHRS(Attitude and Heading Reference System,姿 ...
 - LVGL库入门教程01-移植到STM32(触摸屏)
		
LVGL库移植STM32 LVGL库简介 LVGL(Light and Versatile Graphics Library)是一个免费.开源的嵌入式图形库,可以创建丰富.美观的界面,具有许多可以自定 ...
 - STM32之触摸屏
		
一.触摸屏控制器简介 1.TSC2046概貌 2.TSC2046引脚描述 3.TSC2046应用电路 4.常见接线方法 YU=Y- YD=Y+ XL=X- XR=X+ 二.TSC2046编程注意事项 ...
 - (stm32学习总结)—LCD—液晶显示
		
显示器简介 显示器属于计算机的 I/O 设备,即输入输出设备.它是一种将特定电子信息输出到屏幕上再反射到人眼的显示工具.常见的有 CRT 显示器.液晶显示器.LED 点阵显示器及OLED 显示器 本章 ...
 - [stm32][ucos][ucgui] 2、LED闪烁、串口、滑块、文本编辑框简单例程
		
上一篇:[stm32][ucos] 1.基于ucos操作系统的LED闪烁.串口通信简单例程 * 内容简述: 本例程操作系统采用ucos2.86a版本, 建立了7个任务 任务名 ...
 - FreeModbus 移植于STM32 实现Modbus RTU通信
		
http://ntn314.blog.163.com/blog/static/161743584201233084434579/ 毕业设计自己要做个基于STM32的PLC能直接跑语句表的,现在看来好像 ...
 - STM32采集电阻触摸贴膜
		
今天为了解决一个测量电阻屏压力的问题,自己直接用STM32做了一个测量电阻屏的程序(直接把触摸屏的四根线接到单片机引脚上),通过AD切换采集,采集X轴电压,Y轴电压,和压力..最后附上自己的程序 先说 ...
 - 利用XPT2046制作一个电位器AD转换装置
		
XPT2046是一款四线制电阻触摸屏控制芯片,内含12位分辨率125KHz转换速率逐步逼近型A/D转换器,支持从1.5V到5.25V的低电压I/O接口. 所谓逐步逼近型,就是输入一个模拟量,其与100 ...
 
随机推荐
- Spring中好玩的注解和接口
			
测试中: 一.unit中集中基本注解,是必须掌握的. @BeforeClass – 表示在类中的任意public static void方法执行之前执行 @AfterClass – 表示在类中的任意p ...
 - Django ORM的继承关系
			
ORM中通常将对象引用映射到外键,但是对于继承,关系数据库中没有自然有效的方法来对应.从数据存储的角度来看,在映射继承关系时,可以采用几种方式(参考JPA中的InheritanceType.定义): ...
 - pcm、wav、amr说明
			
wav比pcm多44个字节(在文件头位置多)
 - iOS 给view,button,text filed,label等添加边框和颜色
			
self.tfaaa.layer.borderWidth = 2; self.tfaaa.layer.borderColor = [UIColor blueColor].CGColor;
 - 今天被这个BDE错误搞了半天,不过终于好了,分享一下
			
今天正编译程序时,突然就报了这个错误出来,重启电脑都没用,多亏网上高手指教,先把解决方案列于下,供受此累得朋友查阅,自己也留底供查找:"Shared memory conflict ($21 ...
 - 【物联网】esp8266
			
esp8266环境配置 https://www.jianshu.com/p/cb0274d612b5 https://www.cnblogs.com/zleiblogs/p/7126106.html ...
 - 修改ecshop的70种技巧
			
1.如何修改网站”欢迎惠临本店”答复(dafu):languages\zh_cn\common.php文件中,$_LANG['welcome']=’欢迎惠临本店’:将他修改成你需要的字样. 2.如何修 ...
 - 原生JavaScript常用本地浏览器存储方法五(LocalStorage+userData的一个浏览器兼容类)
			
基于LocalStorage+globalStorage+userData实现的一个本地存储类 userData用来兼容ie6 ie7 由userData模仿Session的方法:浏览器关闭删除保存的 ...
 - PHPStudy后门事件分析
			
PHP环境集成程序包phpStudy被公告疑似遭遇供应链攻击,程序包自带PHP的php_xmlrpc.dll模块隐藏有后门.经过分析除了有反向连接木马之外,还可以正向执行任意php代码. 影响版本 P ...
 - 龙六网络科技有限公司(Dragon six Network Technology Co., Ltd.)
			
龙六网络科技有限公司(Dragon six Network Technology Co., Ltd.)