stm32(十九)触摸屏XPT2046
1、触摸屏介绍
触摸屏(touch screen)又称为“触控屏”、 “触摸面板”,是一种可接收触头等输入讯号的感应式液晶显示装置,
当接触了屏幕上的图形按钮时,屏幕上的触觉反馈系统可根据预先编程的程式驱动各种连结装置,可用以取代机
械式的按钮面板,并借由液晶显示画面制造出生动的影音效果。触摸屏作为一种最新的电脑输入设备,它是目前
最简单、方便、自然的一种人机交互方式。它赋予了多媒体以崭新的面貌,是极富吸引力的全新多媒体交互设备。
主要应用于公共信息的查询、领导办公、工业控制、军事指挥、电子游戏、点歌点菜、多媒体教学、房地产预售
等。
2、触摸屏的类型
触摸屏常见的类型有电阻式,电容式,红外线式以及表面声波式
2.1. 电阻触摸屏
电阻触摸屏的屏体部分是一块与显示器表面相匹配的多层复合薄膜,由一层玻璃或有机玻璃作为基层,表面
涂有一层透明的导电层,上面再该有一层外表面硬化处理,光滑防刮的塑料层,它的内表面也涂有一层透明到垫
层,在两层导电层之间 有许多细小的透明隔离点把它们隔离绝缘
当手指触摸屏幕时,平常相互绝缘的导电层就在触摸点位置有了一个接触,因其中一面导电层接触 Y 轴方向
的 5V 均匀电压场,使得侦测层的电压由零变为非零,这种接通状态倍控制器侦测后,进行 A/D 转换,并将得到
的电压值与 5V 相比即可得到触摸点的 Y 轴坐标,同理得出 X 轴的坐标,这就是所有电阻技术触摸屏共同的原理。
电阻屏根据引出线数多少,分为四线、五线、六线等多线电阻触摸屏
(1) 四线电阻屏
四线电阻屏模拟量技术的两层透明金属工作时每层均增加 5V 恒定电压,一个竖直方向,一个水平方向,总
共需要四根电缆。特点:高解析度,高速传输反应,表面硬度处理,减少擦伤,刮伤及防化学处理,具有光面及
雾面处理,一次校正,稳定性高,永不漂移。
(2) 五线电阻屏
五线电阻技术触摸屏的基层把两个方向的电压场通过精密电阻网络都加在玻璃的导电工作面上,我们可以简
单的理解为两个方向的电压场分时工作加在同一工作面上,而外层镍金导电层只仅仅用来当作纯导体,有触摸后
分时检测内层 ITO 接触点 X 轴和 Y 轴电压值的方法测得触摸点的位置,五线电阻触摸屏内层 ITO 需四条引线,外
层只作导体仅仅一条,触摸屏的引出线共有 5 条。特点:解析度高,高速传输反应,表面硬度高,减少擦伤,刮
伤及防化学处理,同点接触 3000 万次尚可使用。
2.2. 电容触摸屏
电容式触摸屏的构造主要是在玻璃屏幕上镀一层透明的薄膜体层,再在导体层外上一块保护玻璃,双玻璃设
计能彻底保护导体层及感应器。此外,在附加的触摸屏四边均镀上狭长的电极,在导电体内形成一个低电压交流
电场。
用户触摸屏幕时,由于人体电场,手指与导体层间会形成一个耦合电容,四边电极发出的电流会流向触电,
而其强弱与手指及电极的距离成正比,位于触摸屏后的控制器便会计算电流的比列及强弱,准确算出触摸点的位
置。电容触摸屏的双玻璃不但能保护导体及感应器,更有效地防止外在环境因素给触摸屏造成影响,就算屏幕沾
有污秽,尘埃或油渍,电容式触摸屏依然能准确算出触摸位置
3. 触摸屏的控制器
触摸屏控制器一般有:主控内部自带控制器和外置控制器两种,常见的外置控制器(电阻触摸屏): ADS7843,ADS7846,TSC2046,XPT2046 和 AK4182 等,
3.1. 触摸屏控制器 XPT2046
(1) 特点
- 采用 SPI 四线控制通信接口
- SPI 通信支持模式 0 和模式 3
- SPI 通信速度最快 2.5MHz
- ADC 分辨率 12 位
- ADC 转换周期最快 15 个时钟周期
- 支持命令切换测量方向
3.2、硬件连接
3.3. XPT2046 管脚说明
3.4、XPT2046 时序
3.5、控制位命令
3.6、差分模式输入配置
3.7、控制字节各位描述
3.8、掉电和内部参考电压选择
3.8、触摸屏校准
校准:使得触膜和LCD屏建立联系。当按下触膜的某一个AD坐标点时,获知当前AD坐标点所对应的LCD像素点。
建立触膜和LCD屏建立联系,需要有两条公式:
Xlcd = Xtouch*(320/4096);
Ylcd = Ytouch*(480/4096);
如果触摸和LCD可以100%工整贴合,则换算公式就是上面的公式。
但是,实际上,不可能100%工整贴合。此时我们需要校准。
校准的过程如下图所示,目的是为了求得“比例系数”和“像素点偏移”
4、软件设计
功能:校准:使得触膜和LCD屏建立联系。当按下触膜的某一个AD坐标点时,获知当前AD坐标点所对应的LCD像素点。
寄存器就配置不一样,不弄了,懒了,但是寄存器配置也在代码里,屏蔽了,其他就只有管脚拉低拉高
#include "stm32f4xx.h"
#include "stdio.h"
#include "math.h"
typedef struct
{u16 x;u16 y;
}TOUCH_XY_TYPEDEF;typedef struct
{float kx; //比例系数s16 offset_x; //偏移量float ky;s16 offset_y;
}TOUCH_ADJ_TYPEDEF;TOUCH_ADJ_TYPEDEF touch_adj;void Touch_Init(void);
void Touch_Adj_Init(void);
u16 Touch_Get_ADC(u8 common);
TOUCH_XY_TYPEDEF Touch_Get_XY(void);
TOUCH_XY_TYPEDEF Get_Touch_Lcd(void);
TOUCH_XY_TYPEDEF Touch_Scanf(void);
TOUCH_XY_TYPEDEF Get_Touch_Lcd_XY(void);void Delay_ms(u16 ms)
{SysTick->CTRL &=~(1<<2);//选择时钟源为21MHZSysTick->CTRL &=~(1<<1);//禁止滴答中断SysTick->LOAD = 21000*ms; //设置重装载寄存器的值SysTick->CTRL |= (1<<0);//使能滴答定时器while(!(SysTick->CTRL&(1<<16)));//阻塞判断定时时间是否到达,判断SysTick->CTRL的位
}void Delay_us(u16 us)
{SysTick->CTRL &=~(1<<2);//选择时钟源为21MHZSysTick->CTRL &=~(1<<1);//禁止滴答中断SysTick->LOAD = 21*us; //设置重装载寄存器的值SysTick->CTRL |= (1<<0);//使能滴答定时器while(!(SysTick->CTRL&(1<<16)));//阻塞判断定时时间是否到达,判断SysTick->CTRL的位
}
void usart_Init(void)
{GPIO_InitTypeDef GPIO_InitStructe;USART_InitTypeDef USART_InitStructe;NVIC_InitTypeDef NVIC_InitStructe;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能A端口RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); //使能串口端口GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //GPIO端口映射到USARTGPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIO端口映射到USART// USART_DeInit(USART1); //复位GPIO_InitStructe.GPIO_Mode =GPIO_Mode_AF; //配置为输出模式GPIO_InitStructe.GPIO_OType =GPIO_OType_PP; //配置为推挽输出GPIO_InitStructe.GPIO_Pin =GPIO_Pin_9|GPIO_Pin_10; //初始化GPIOA9/10;GPIO_InitStructe.GPIO_Speed =GPIO_Speed_50MHz; //速度设置为50MHzGPIO_Init(GPIOA,&GPIO_InitStructe);USART_InitStructe.USART_BaudRate =115200; //波特率USART_InitStructe.USART_HardwareFlowControl =USART_HardwareFlowControl_None;//无硬件流控制USART_InitStructe.USART_Mode =USART_Mode_Tx|USART_Mode_Rx; //接收模式,发送模式使能USART_InitStructe.USART_Parity =USART_Parity_No; //无奇偶校验USART_InitStructe.USART_StopBits =USART_StopBits_1; //一位停止位USART_InitStructe.USART_WordLength =USART_WordLength_8b;//8位数据位USART_Init(USART1,&USART_InitStructe);USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启相关中断NVIC_InitStructe.NVIC_IRQChannel= USART1_IRQn; //串口1中断NVIC_InitStructe.NVIC_IRQChannelCmd =ENABLE; //串口1使能NVIC_InitStructe.NVIC_IRQChannelPreemptionPriority =0; //抢占优先级设为0NVIC_InitStructe.NVIC_IRQChannelSubPriority =0; //子优先级设为0NVIC_Init(&NVIC_InitStructe);USART_Cmd(USART1,ENABLE); //使能串口
}
int fputc(int data,FILE *file)
{USART_SendData(USART1,data);while(!USART_GetFlagStatus(USART1,USART_FLAG_TC)){}return data;
}
/******************** LCD引脚初始化函数 *******************
LCD显示屏硬件管脚对应关系:
数据线:
DB0---PD14 DB1---PD15 DB2---PD0 DB3---PD1
DB4---PE7 DB5---PE8 DB6---PE9 DB7---PE10
DB8---PE11 DB9---PE12 DB10---PE13 DB11---PE14
DB12---PE15 DB13---PD8 DB14---PD9 DB15---PD10
控制线:
WR---PD5 RD---PD4 CS---PG12 BL--PB15 ,DC --PF12
**********************************************************/
void LCD_PinInit(void)
{GPIO_InitTypeDef GPIO_InitStructure;//使能PD,PE,PF,PG时钟 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_GPIOD|RCC_AHB1Periph_GPIOE|\RCC_AHB1Periph_GPIOF|RCC_AHB1Periph_GPIOG, ENABLE);GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_8|\GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_14|GPIO_Pin_15;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;GPIO_InitStructure.GPIO_Speed=GPIO_Fast_Speed;GPIO_Init(GPIOD, &GPIO_InitStructure); GPIO_SetBits(GPIOD,GPIO_Pin_4|GPIO_Pin_5);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;//PE7~15,AF OUTGPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Fast_Speed;GPIO_Init(GPIOE, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;GPIO_InitStructure.GPIO_Speed = GPIO_Fast_Speed;GPIO_Init(GPIOG, &GPIO_InitStructure);GPIO_SetBits(GPIOG,GPIO_Pin_12);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;GPIO_InitStructure.GPIO_Speed = GPIO_Fast_Speed;GPIO_Init(GPIOF, &GPIO_InitStructure); GPIO_SetBits(GPIOF,GPIO_Pin_12);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_ResetBits(GPIOB,GPIO_Pin_15);
}
/******************* LCD写命令函数 *********************************
参数:需要输入的命令
********************************************************************/
void LCD_ILI9486_CMD(u16 common)
{GPIO_ResetBits(GPIOG,GPIO_Pin_12);GPIO_ResetBits(GPIOF,GPIO_Pin_12);GPIO_ResetBits(GPIOD,GPIO_Pin_5);if(common&0x01) GPIO_SetBits(GPIOD,GPIO_Pin_14);else GPIO_ResetBits(GPIOD,GPIO_Pin_14);if(common&0x02) GPIO_SetBits(GPIOD,GPIO_Pin_15);else GPIO_ResetBits(GPIOD,GPIO_Pin_15);if(common&0x04) GPIO_SetBits(GPIOD,GPIO_Pin_0);else GPIO_ResetBits(GPIOD,GPIO_Pin_0);if(common&0x08) GPIO_SetBits(GPIOD,GPIO_Pin_1);else GPIO_ResetBits(GPIOD,GPIO_Pin_1);if(common&0x10) GPIO_SetBits(GPIOE,GPIO_Pin_7);else GPIO_ResetBits(GPIOE,GPIO_Pin_7);if(common&0x20) GPIO_SetBits(GPIOE,GPIO_Pin_8);else GPIO_ResetBits(GPIOE,GPIO_Pin_8);if(common&0x40) GPIO_SetBits(GPIOE,GPIO_Pin_9);else GPIO_ResetBits(GPIOE,GPIO_Pin_9);if(common&0x80) GPIO_SetBits(GPIOE,GPIO_Pin_10);else GPIO_ResetBits(GPIOE,GPIO_Pin_10);if(common&0x0100) GPIO_SetBits(GPIOE,GPIO_Pin_11);else GPIO_ResetBits(GPIOE,GPIO_Pin_11);if(common&0x0200) GPIO_SetBits(GPIOE,GPIO_Pin_12);else GPIO_ResetBits(GPIOE,GPIO_Pin_12);if(common&0x0400) GPIO_SetBits(GPIOE,GPIO_Pin_13);else GPIO_ResetBits(GPIOE,GPIO_Pin_13);if(common&0x0800) GPIO_SetBits(GPIOE,GPIO_Pin_14);else GPIO_ResetBits(GPIOE,GPIO_Pin_14);if(common&0x1000) GPIO_SetBits(GPIOE,GPIO_Pin_15);else GPIO_ResetBits(GPIOE,GPIO_Pin_15);if(common&0x2000) GPIO_SetBits(GPIOD,GPIO_Pin_8);else GPIO_ResetBits(GPIOD,GPIO_Pin_8);if(common&0x4000) GPIO_SetBits(GPIOD,GPIO_Pin_9);else GPIO_ResetBits(GPIOD,GPIO_Pin_9);if(common&0x8000) GPIO_SetBits(GPIOD,GPIO_Pin_10);else GPIO_ResetBits(GPIOD,GPIO_Pin_10);GPIO_SetBits(GPIOD,GPIO_Pin_5);GPIO_SetBits(GPIOG,GPIO_Pin_12);
}/******************* LCD写数据函数 *********************************
参数:需要输输入待写到LCD屏的数据
********************************************************************/
void LCD_ILI9486_Parameter(u16 data)
{GPIO_ResetBits(GPIOG,GPIO_Pin_12);GPIO_SetBits(GPIOF,GPIO_Pin_12);GPIO_ResetBits(GPIOD,GPIO_Pin_5);//发送 16 位数据if(data&0x01) GPIO_SetBits(GPIOD,GPIO_Pin_14);else GPIO_ResetBits(GPIOD,GPIO_Pin_14);if(data&0x02) GPIO_SetBits(GPIOD,GPIO_Pin_15);else GPIO_ResetBits(GPIOD,GPIO_Pin_15);if(data&0x04) GPIO_SetBits(GPIOD,GPIO_Pin_0);else GPIO_ResetBits(GPIOD,GPIO_Pin_0);if(data&0x08) GPIO_SetBits(GPIOD,GPIO_Pin_1);else GPIO_ResetBits(GPIOD,GPIO_Pin_1);if(data&0x10) GPIO_SetBits(GPIOE,GPIO_Pin_7);else GPIO_ResetBits(GPIOE,GPIO_Pin_7);if(data&0x20) GPIO_SetBits(GPIOE,GPIO_Pin_8);else GPIO_ResetBits(GPIOE,GPIO_Pin_8);if(data&0x40) GPIO_SetBits(GPIOE,GPIO_Pin_9);else GPIO_ResetBits(GPIOE,GPIO_Pin_9);if(data&0x80) GPIO_SetBits(GPIOE,GPIO_Pin_10);else GPIO_ResetBits(GPIOE,GPIO_Pin_10);if(data&0x0100) GPIO_SetBits(GPIOE,GPIO_Pin_11);else GPIO_ResetBits(GPIOE,GPIO_Pin_11);if(data&0x0200) GPIO_SetBits(GPIOE,GPIO_Pin_12);else GPIO_ResetBits(GPIOE,GPIO_Pin_12);if(data&0x0400) GPIO_SetBits(GPIOE,GPIO_Pin_13);else GPIO_ResetBits(GPIOE,GPIO_Pin_13);if(data&0x0800) GPIO_SetBits(GPIOE,GPIO_Pin_14);else GPIO_ResetBits(GPIOE,GPIO_Pin_14);if(data&0x1000) GPIO_SetBits(GPIOE,GPIO_Pin_15);else GPIO_ResetBits(GPIOE,GPIO_Pin_15);if(data&0x2000) GPIO_SetBits(GPIOD,GPIO_Pin_8);else GPIO_ResetBits(GPIOD,GPIO_Pin_8);if(data&0x4000) GPIO_SetBits(GPIOD,GPIO_Pin_9);else GPIO_ResetBits(GPIOD,GPIO_Pin_9);if(data&0x8000) GPIO_SetBits(GPIOD,GPIO_Pin_10);else GPIO_ResetBits(GPIOD,GPIO_Pin_10);GPIO_SetBits(GPIOD,GPIO_Pin_5);GPIO_SetBits(GPIOG,GPIO_Pin_12);
}
//以某个颜色清除整个LCD屏
void LCD_ClearTotalLCD(u16 color)
{u32 i;LCD_ILI9486_CMD(0x2A); //设置列地址LCD_ILI9486_Parameter(0>>8); LCD_ILI9486_Parameter(0&(0xFF));LCD_ILI9486_Parameter(319>>8); LCD_ILI9486_Parameter(319&(0xFF));LCD_ILI9486_CMD(0x2B); //设置行地址LCD_ILI9486_Parameter(0>>8); LCD_ILI9486_Parameter(0&(0xFF));LCD_ILI9486_Parameter(479>>8); LCD_ILI9486_Parameter(479&(0xFF));LCD_ILI9486_CMD(0x2C); //写显存的命令for(i=0;i<(320*480);i++){LCD_ILI9486_Parameter(color); }
}void LCD_ShowPoint(u16 x,u16 y,u16 color)
{//2A 确定横坐标 x的范围LCD_ILI9486_CMD(0X2a); LCD_ILI9486_Parameter (x>>8);//起始横坐标LCD_ILI9486_Parameter (x);LCD_ILI9486_Parameter (x>>8);//终止横坐标LCD_ILI9486_Parameter (x);//2b 确定纵坐标 y的范围LCD_ILI9486_CMD(0X2b); LCD_ILI9486_Parameter (y>>8);//起始纵坐标LCD_ILI9486_Parameter (y);LCD_ILI9486_Parameter (y>>8);//终止纵坐标LCD_ILI9486_Parameter (y);//2c 填充颜色LCD_ILI9486_CMD(0X2c);LCD_ILI9486_Parameter (color);}//显示十字
void LCD_Draw_SZ(u16 x, u16 y, u16 color)
{u16 i;for(i=x-10; i<x+10; i++){LCD_ShowPoint(i, y, color);}for(i=y-10; i<y+10; i++){LCD_ShowPoint( x,i, color);}
}
/**********************
LCD初始化函数
***********************/
void LCD_Init(void)
{LCD_PinInit();//************* Reset LCD Driver ****************//Delay_ms(120); // Delay 120 ms//************* Start Initial Sequence **********//LCD_ILI9486_CMD(0x01); //软件复位LCD_ILI9486_CMD(0x13); //开启正常模式LCD_ILI9486_CMD(0xB4); LCD_ILI9486_Parameter(0x00); LCD_ILI9486_CMD(0XF2);LCD_ILI9486_Parameter(0x18);LCD_ILI9486_Parameter(0xA3);LCD_ILI9486_Parameter(0x12);LCD_ILI9486_Parameter(0x02);LCD_ILI9486_Parameter(0XB2);LCD_ILI9486_Parameter(0x12);LCD_ILI9486_Parameter(0xFF);LCD_ILI9486_Parameter(0x10);LCD_ILI9486_Parameter(0x00);LCD_ILI9486_CMD(0XF8);LCD_ILI9486_Parameter(0x21);LCD_ILI9486_Parameter(0x04);LCD_ILI9486_CMD(0XF9);LCD_ILI9486_Parameter(0x00);LCD_ILI9486_Parameter(0x08);LCD_ILI9486_CMD(0x3A);LCD_ILI9486_Parameter(0x05); //设置16位BPPLCD_ILI9486_CMD(0xB4);LCD_ILI9486_Parameter(0x01);//0x00LCD_ILI9486_CMD(0xB6);LCD_ILI9486_Parameter(0x02);LCD_ILI9486_Parameter(0x22);LCD_ILI9486_CMD(0xC1);LCD_ILI9486_Parameter(0x41);LCD_ILI9486_CMD(0xC5);LCD_ILI9486_Parameter(0x00);LCD_ILI9486_Parameter(0x07);//0X18LCD_ILI9486_CMD(0xE0);LCD_ILI9486_Parameter(0x0F);LCD_ILI9486_Parameter(0x1F);LCD_ILI9486_Parameter(0x1C);LCD_ILI9486_Parameter(0x0C);LCD_ILI9486_Parameter(0x0F);LCD_ILI9486_Parameter(0x08);LCD_ILI9486_Parameter(0x48);LCD_ILI9486_Parameter(0x98);LCD_ILI9486_Parameter(0x37);LCD_ILI9486_Parameter(0x0A);LCD_ILI9486_Parameter(0x13);LCD_ILI9486_Parameter(0x04);LCD_ILI9486_Parameter(0x11);LCD_ILI9486_Parameter(0x0D);LCD_ILI9486_Parameter(0x00);LCD_ILI9486_CMD(0xE1);LCD_ILI9486_Parameter(0x0F);LCD_ILI9486_Parameter(0x32);LCD_ILI9486_Parameter(0x2E);LCD_ILI9486_Parameter(0x0B);LCD_ILI9486_Parameter(0x0D);LCD_ILI9486_Parameter(0x05);LCD_ILI9486_Parameter(0x47);LCD_ILI9486_Parameter(0x75);LCD_ILI9486_Parameter(0x37);LCD_ILI9486_Parameter(0x06);LCD_ILI9486_Parameter(0x10);LCD_ILI9486_Parameter(0x03);LCD_ILI9486_Parameter(0x24);LCD_ILI9486_Parameter(0x20);LCD_ILI9486_Parameter(0x00);LCD_ILI9486_CMD(0x11); //退出睡眠LCD_ILI9486_CMD(0x36);
// LCD_ILI9486_Parameter(0x08); //设置RGB,含排线的屏LCD_ILI9486_Parameter(0x00); //设置RGB,不含排线的屏LCD_ILI9486_CMD(0x36);
// LCD_ILI9486_Parameter(0x08); //设置RGB,含排线的屏LCD_ILI9486_Parameter(0x00); //设置RGB,不含排线的屏LCD_ILI9486_CMD(0x36);
// LCD_ILI9486_Parameter(0x08); //设置RGB,含排线的屏LCD_ILI9486_Parameter(0x00); //设置RGB,不含排线的屏Delay_ms(120);LCD_ILI9486_CMD(0x29); //开启显示/* 以下由用户按实际编写 */LCD_ILI9486_CMD(0x20); //关闭颜色反转LCD_ILI9486_CMD(0x3A); //发送命令设置液晶屏颜色位深LCD_ILI9486_Parameter(0x05); //设置颜色位深16BPPLCD_ILI9486_CMD(0x36); //发送命令设置LCD扫描方向LCD_ILI9486_Parameter(0x08);//LCD_Clear(0,319,0,479,RED); //清屏GPIOB->ODR |= 1 << 15; //开LCD背光灯// GPIO_SetBits(GPIOB,GPIO_Pin_15); //开LCD背光灯
}/*
硬件连接
XTP2046 LCD屏 MCU
CLK T_CLK PB0 输出
CS T_CS PC13 输出
DIN T_MOSI PF11 输出
DOUT T_MISO PB2 输入
PEN T_PEN PB1 输入
*/
#define T_PEN (!!(GPIOB->IDR &(1<<1)))
#define T_CS_LOW (GPIOC->ODR &=~(1<<13))
#define T_CS_HIGH (GPIOC->ODR |=(1<<13))
#define T_MOSI_HIGH (GPIOF->ODR |=(1<<11))
#define T_MOSI_LOW (GPIOF->ODR &=~(1<<11))
#define T_CLK_HIGH (GPIOB->ODR |=(1<<0))
#define T_CLK_LOW (GPIOB->ODR &=~(1<<0))
#define T_MISO (GPIOB->IDR &(1<<2))
void Touch_Init()
{GPIO_InitTypeDef TOUCH_InitTypeDef;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE); //使能F端口RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE); //使能C端口RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE); //使能F端口/*PB0 输出**/TOUCH_InitTypeDef.GPIO_Mode =GPIO_Mode_OUT; //配置为输出模式TOUCH_InitTypeDef.GPIO_OType =GPIO_OType_PP; //配置为推挽输出TOUCH_InitTypeDef.GPIO_Pin =GPIO_Pin_0; //初始化GPIOB0;TOUCH_InitTypeDef.GPIO_PuPd =GPIO_PuPd_NOPULL; //配置为无上下拉状态TOUCH_InitTypeDef.GPIO_Speed =GPIO_Speed_2MHz; //速度设置为2MHzGPIO_Init(GPIOB,&TOUCH_InitTypeDef);/*PC13 输出*/TOUCH_InitTypeDef.GPIO_Mode =GPIO_Mode_OUT; //配置为输出模式TOUCH_InitTypeDef.GPIO_OType =GPIO_OType_PP; //配置为推挽输出TOUCH_InitTypeDef.GPIO_Pin =GPIO_Pin_13; //初始化GPIOC0;TOUCH_InitTypeDef.GPIO_PuPd =GPIO_PuPd_NOPULL; //配置为无上下拉状态TOUCH_InitTypeDef.GPIO_Speed =GPIO_Speed_2MHz; //速度设置为2MHzGPIO_Init(GPIOC,&TOUCH_InitTypeDef); /*PF11 输出*/TOUCH_InitTypeDef.GPIO_Mode =GPIO_Mode_OUT; //配置为输出模式TOUCH_InitTypeDef.GPIO_OType =GPIO_OType_PP; //配置为推挽输出TOUCH_InitTypeDef.GPIO_Pin =GPIO_Pin_11; //初始化GPIOF11;TOUCH_InitTypeDef.GPIO_PuPd =GPIO_PuPd_NOPULL; //配置为无上下拉状态TOUCH_InitTypeDef.GPIO_Speed =GPIO_Speed_2MHz; //速度设置为2MHzGPIO_Init(GPIOF,&TOUCH_InitTypeDef); /*PB2 输入*/TOUCH_InitTypeDef.GPIO_Mode =GPIO_Mode_IN; //配置为输出模式TOUCH_InitTypeDef.GPIO_Pin =GPIO_Pin_2; //初始化GPIOF11;TOUCH_InitTypeDef.GPIO_PuPd =GPIO_PuPd_NOPULL; //配置为无上下拉状态GPIO_Init(GPIOB,&TOUCH_InitTypeDef); /*PB1 输入*/TOUCH_InitTypeDef.GPIO_Mode =GPIO_Mode_IN; //配置为输出模式TOUCH_InitTypeDef.GPIO_Pin =GPIO_Pin_1; //初始化GPIOF11;TOUCH_InitTypeDef.GPIO_PuPd =GPIO_PuPd_NOPULL; //配置为无上下拉状态GPIO_Init(GPIOB,&TOUCH_InitTypeDef); GPIO_SetBits(GPIOF,GPIO_Pin_11); //DIN空闲状态为高电平GPIO_SetBits(GPIOC,GPIO_Pin_13); //CS拉高GPIO_ResetBits(GPIOB,GPIO_Pin_0);
// RCC->AHB1ENR |= (1<<1)|(1<<2)|(1<<5); //打开PB PC PF时钟
//
// //CLK--PB0 通用推挽 50M
// GPIOB->MODER &=~(0X3<<0); //清零
// GPIOB->MODER |=(0X1<<0); //配置成通用输出
// GPIOB->OTYPER &=~(1<<0); //配置成输出推挽
// GPIOB->OSPEEDR &=~(0X3<<0); //清零
// GPIOB->OSPEEDR |=(0X2<<0); //配置成输出速率50M
//
// //CS--PC13 通用推挽 50M
// GPIOC->MODER &= ~(0X3<<26); //清零
// GPIOC->MODER |= (0X1<<26); //配置成通用输出
// GPIOC->OTYPER &= ~(1<<13); //配置成输出推挽
// GPIOC->OSPEEDR &=~(0X3<<26); //清零
// GPIOC->OSPEEDR |=(0X2<<26); //配置成输出速率50M
//
// //DIN--MOSI PF11 通用推挽 50M
// GPIOF->MODER &= ~(0X3<<22); //清零
// GPIOF->MODER |= (0X1<<22); //配置成通用输出
// GPIOF->OTYPER &= ~(1<<11); //配置成输出推挽
// GPIOF->OSPEEDR &= ~(0X3<<22); //清零
// GPIOF->OSPEEDR |= (0X2<<22); //配置成输出速率50M
//
// /* DOUT--T_MISO--PB2 输入 */
// GPIOB->MODER &= ~(0X3<<4); //清零
// GPIOB->MODER |= (0X0<<4); //配置成输入模式
// GPIOB->PUPDR &=~(0X3<<4); //配置成无上下拉-浮空
//
// /* PEN--T_PEN--PB1 输入 */
// GPIOB->MODER &= ~(0X3<<2); //清零
// GPIOB->MODER |= (0X0<<2); //配置成输入模式
// GPIOB->PUPDR &= ~(0X3<<2); //配置成无上下拉-浮空
}
/*******************************************************************
* 函数名: Touch_Get_ADC()
* 功能描述 : 触摸屏数据时序函数
*******************************************************************/
u16 Touch_Get_ADC(u8 common)
{u8 i;u16 data = 0;GPIO_ResetBits(GPIOC,GPIO_Pin_13); //拉低片选/* 发送控制字节 */for(i = 0; i < 8; i++){GPIO_ResetBits(GPIOB,GPIO_Pin_0); //拉低时钟线,准备数据if(common & 0x80){GPIO_SetBits(GPIOF,GPIO_Pin_11); //拉高MOSI数据线,输出1}else{GPIO_ResetBits(GPIOF,GPIO_Pin_11); //拉高MOSI数据线,输出1}Delay_us(1);GPIO_SetBits(GPIOB,GPIO_Pin_0); //时钟产生上升沿,发出数据Delay_us(1);common <<= 1;}/* 产生一个空闲时钟 */GPIO_SetBits(GPIOB,GPIO_Pin_0); Delay_us(1); GPIO_ResetBits(GPIOB,GPIO_Pin_0);Delay_us(1);GPIO_SetBits(GPIOB,GPIO_Pin_0); /* 读数据 */for(i = 0; i < 12; i++){data <<= 1;GPIO_ResetBits(GPIOB,GPIO_Pin_0);Delay_us(1);GPIO_SetBits(GPIOB,GPIO_Pin_0); if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_2)){data |= 1;}Delay_us(1);}/* 空闲状态 */GPIO_SetBits(GPIOB,GPIO_Pin_0); //拉低时钟线GPIO_SetBits(GPIOB,GPIO_Pin_0); //拉高片选 GPIO_SetBits(GPIOB,GPIO_Pin_0); //拉低数据线return data;
}/*******************************************************************
* 函数名: Touch_Get_XY()
* 功能描述 : 触摸屏获取坐标参数函数
*******************************************************************/
TOUCH_XY_TYPEDEF Touch_Get_XY(void)
{TOUCH_XY_TYPEDEF touch;u16 buff[10],temp;u8 i,j;/* 获取X轴坐标AD值 */for(i = 0; i < 10; i++){buff[i] = Touch_Get_ADC(0xD0); //读取X轴AD值}/* 数据排序 */for(i = 1; i < 9; i++){for(j = i; j < 10; j++){if(buff[i] < buff[j]){temp = buff[i];buff[i] = buff[j];buff[j] = temp;}}}temp = 0;for(i = 1; i < 9; i++){temp += buff[i];}touch.x = temp / 8; /* 求平均数 *//* 获取Y轴坐标AD值 */for(i = 0; i < 10; i++){buff[i] = Touch_Get_ADC(0x90); //读取Y轴AD值}/* 数据排序 */for(i = 1; i < 9; i++){for(j = i; j < 10; j++){if(buff[i] < buff[j]){temp = buff[i];buff[i] = buff[j];buff[j] = temp;}}}temp = 0;for(i = 1; i < 9; i++){temp += buff[i];}touch.y = temp / 8; /* 求平均数 */return touch;
}
TOUCH_XY_TYPEDEF Get_Touch_Lcd(void)
{TOUCH_XY_TYPEDEF touch;touch=Touch_Get_XY( ); //获取触摸屏AD转换值touch.x = touch_adj.kx * touch.x + touch_adj.offset_x;touch.y = (touch_adj.ky * touch.y + touch_adj.offset_y);return touch;
}/*******************************************************************
* 函数名: Touch_Scanf()
* 功能描述 : 触摸屏坐标扫描函数
*******************************************************************/
TOUCH_XY_TYPEDEF Touch_Scanf(void)
{static u8 touch_sta = 1;TOUCH_XY_TYPEDEF touch_key[2];TOUCH_XY_TYPEDEF touchkey = {0xffff,0xffff};if( (touch_sta==1)&&(!GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)) ) //允许是被并且触摸屏有按下{Delay_ms(5); //延时去抖if( !GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) ){touch_key[0] = Get_Touch_Lcd();touch_key[1] = Get_Touch_Lcd();/* 求绝对值 */if( (abs(touch_key[0].x -touch_key[1].x)<5) &&(abs(touch_key[0].y -touch_key[1].y)<5) ) //识别到坐标有效{touchkey.x=(touch_key[0].x +touch_key[1].x)/2;touchkey.y=(touch_key[0].y +touch_key[1].y)/2; touch_sta=0; //不允许识别}else{touch_key[0].x=0xffff;touch_key[0].y=0xffff;}}}else if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)){touch_sta = 1; //允许识别}return touchkey;
}
void Touch_Adj_Init(void)
{float f1,f2;TOUCH_XY_TYPEDEF touch[4];RE_ADJUST://第一个点LCD_Draw_SZ(20, 20, 0xf800); //画一个十字while( GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) ) {/* 等待触摸屏被按下 */}Delay_ms(10); //延时去抖touch[0]=Touch_Get_XY( ); //读取触摸屏的XY轴值while(!GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)) {/* 等待释放触摸屏 */} LCD_Draw_SZ(20 ,20,0x07e0); //清除第一个十字//第二个点LCD_Draw_SZ((320 - 20),20, 0xf800); //画一个十字while( GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) ) {/* 等待触摸屏被按下 */}Delay_ms(10); //延时去抖touch[1]=Touch_Get_XY( ); //读取触摸屏的XY轴值while(!GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)) {/* 等待释放触摸屏 */} LCD_Draw_SZ((320 - 20), 20, 0x07e0); //清除第二个十字//第三个点LCD_Draw_SZ(20, (480 - 20), 0xf800); //画一个十字while( GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) ) {/* 等待触摸屏被按下 */}Delay_ms(10); //延时去抖touch[2]=Touch_Get_XY( ); //读取触摸屏的XY轴值while(!GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)) {/* 等待释放触摸屏 */} LCD_Draw_SZ(20,(480 - 20), 0x07e0); //清除第三个十字//第四个点LCD_Draw_SZ((320- 20), (480 - 20), 0xf800); //画一个十字while( GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) ) {/* 等待触摸屏被按下 */}Delay_ms(10); //延时去抖touch[3]=Touch_Get_XY( ); //读取触摸屏的XY轴值while(!GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)) {/* 等待释放触摸屏 */} LCD_Draw_SZ((320- 20), (480 - 20), 0x07e0); //清除第四个十字//第 1 2点间的距离的平方f1=(touch[1].x-touch[0].x)*(touch[1].x-touch[0].x) +(touch[1].y-touch[0].y)*(touch[1].y-touch[0].y);//第3 4点间的距离的平方f2=(touch[3].x-touch[2].x)*(touch[3].x-touch[2].x) +(touch[3].y-touch[2].y)*(touch[3].y-touch[2].y);if(f1 / f2 > 1.1 || f1 / f2 < 0.9){goto RE_ADJUST;}//第 1 3点间的距离的平方f1=(touch[2].x-touch[0].x)*(touch[2].x-touch[0].x) +(touch[2].y-touch[0].y)*(touch[2].y-touch[0].y);//第2 4点间的距离的平方f2=(touch[3].x-touch[1].x)*(touch[3].x-touch[1].x) +(touch[3].y-touch[1].y)*(touch[3].y-touch[1].y);if(f1 / f2 > 1.1 || f1 / f2 < 0.9){goto RE_ADJUST;}//第 1 4点间的距离的平方f1 = (touch[3].x-touch[0].x)*(touch[3].x-touch[0].x) +(touch[3].y-touch[0].y)*(touch[3].y-touch[0].y);//第2 3点间的距离的平方f2 = (touch[2].x-touch[1].x)*(touch[2].x-touch[1].x) +(touch[2].y-touch[1].y)*(touch[2].y-touch[1].y);if(f1 / f2 > 1.1 || f1 / f2 < 0.9){goto RE_ADJUST;}//求x方向的比例系数和偏移量touch_adj.kx =(float)((320 - 20) - 20) / (touch[3].x - touch[0].x);touch_adj.offset_x = 20 - touch_adj.kx * touch[0].x;//求y方向的比例系数和偏移量touch_adj.ky = (float)((480 - 20) - 20) / (touch[3].y - touch[0].y);touch_adj.offset_y = 20 - touch_adj.ky * touch[0].y;
}int main(void)
{TOUCH_XY_TYPEDEF touch_lcd;usart_Init();LCD_Init();Touch_Init();Touch_Adj_Init();while(1){if(!GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)){touch_lcd = Touch_Scanf();if(touch_lcd.x != 0xffff) //正常识别到触摸屏{printf("x=%d\r\n",touch_lcd.x);printf("y=%d\r\n\r\n",touch_lcd.y);}touch_lcd.x = 0xffff;} }}
stm32(十九)触摸屏XPT2046相关推荐
- 【正点原子STM32连载】 第二十九章 低功耗实验 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1
1)实验平台:正点原子MiniPro H750开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=677017430560 3)全套实验源码+手册+视频 ...
- 【正点原子STM32连载】第三十九章 DS18B20数字温度传感器实验 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1
1)实验平台:正点原子MiniPro H750开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=677017430560 3)全套实验源码+手册+视频 ...
- 【正点原子STM32连载】第五十九章 USB U盘(Host)实验 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1
1)实验平台:正点原子MiniPro H750开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=677017430560 3)全套实验源码+手册+视频 ...
- 【正点原子FPGA连载】 第二十九章TFT LCD画板实验 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南
1)实验平台:正点原子MPSoC开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=692450874670 3)全套实验源码+手册+视频下载地址: h ...
- 【正点原子MP157连载】第三十九章 LCD驱动实验-摘自【正点原子】STM32MP1嵌入式Linux驱动开发指南V1.7
1)实验平台:正点原子STM32MP157开发板 2)购买链接:https://item.taobao.com/item.htm?&id=629270721801 3)全套实验源码+手册+视频 ...
- stm32l0的停止模式怎么唤醒_「正点原子STM32Mini板资料连载」第十九章 待机唤醒实验...
1)实验平台:正点原子STM32mini开发板 2)摘自<正点原子STM32 不完全手册(HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 第十九章 待机唤醒实验 本章我们将向 ...
- c语言头文件格式图片_阿波罗 STM32F767 开发板资料连载第四十九章 图片显示实验...
1)实验平台:alientek 阿波罗 STM32F767 开发板2)摘自<STM32F7 开发指南(HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 第四十九章 图片显示实验 ...
- 37种传感器(十九)之红外避障模块+Stduino NanoUNO
37种传感器(十九)之红外避障模块+Stduino Nano&UNO 本文转载自:http://www.stduino.com/forum.php?mod=viewthread&tid ...
- 2021年大数据Hadoop(二十九):关于YARN常用参数设置
全网最详细的Hadoop文章系列,强烈建议收藏加关注! 后面更新文章都会列出历史文章目录,帮助大家回顾知识重点. 目录 本系列历史文章 前言 关于yarn常用参数设置 设置container分配最小内 ...
- python第二十九课——文件读写(复制文件)
自定义函数:实现文件复制操作有形参(2个) 没有返回值相似版(不用) def copyFile(src,dest):#1.打开两个文件:1个关联读操作,1个关联写操作fr=open(src,'rb') ...
最新文章
- shell 脚本简单入门
- 玩cf出现outofmemory_CF从女主播秀腿到假赛被罚,还能站在电竞上吗?
- python文字教程-Python
- Mysql-linux下密码修改,忘记密码修改,超级管理用户修改
- CTFshow sql注入 上篇(web171-220)
- Yet Another Problem About Pi
- 读书笔记 effective c++ Item 16 成对使用new和delete时要用相同的形式
- 简单使用TFS管理源代码
- python代码覆盖率怎么统计的_Python代码覆盖率统计工具coverage.py用法详解
- 公交车上应不应该给老人让座?
- php declaration of,PHP 7.2中的新功能(参数类型声明)
- exchange2003升级exchange2010思路----(3)卸载
- Linux内核分析-分析Linux内核创建一个新进程的过程
- mysql initialsize,单机数据库优化
- Python工具箱系列(十一)
- 【数学建模】CUMCM-2014B 创意平板折叠桌 解题思路整理
- SSM框架:MyBatis
- 金徽酒前三季净赚2.43亿 预计年底前走进华东市场
- 双光耦开关电源电路图_开关电源中的光耦经典电路设计分析
- 关于友情的励志故事------火炉的故事
热门文章
- 手机APP分析平台项目(一)
- 等保2.0.2021版等级测评报告模板修订总结
- hpuoj1691 CZY追女孩
- HTML5期末大作业:水果网站设计——水果介绍-橙子之家(6页) HTML+CSS+JavaScript 学生dreamweaver网页设计作业成品
- java printf输出40.0%_printf, TRACE, OutputDebugString有什么区别?
- iOS状态栏操作之获取WiFi信号强度,WiFi名字和IP,网络类型,运营商,电池电量,系统时间等...
- OPENCL异构计算——四大模型
- Camera初始化流程
- Redis - 适配全国产操作系统的那些坑
- 《构建之法》阅读以及工具调研