历史上的今天
今天是:2024年12月19日(星期四)
2020年12月19日 | 神舟IV学习笔记-触摸控制XPT2046(十五)
2020-12-19 来源:eefocus
IAR5.4编译环境 ,看了很多XPT2046的驱动,都是软件模拟SPI接口来驱动,偶用硬件SPI接口驱动成功。
触摸控制器芯片介绍:
XPT2046内部有 2.5V的参考电压源,可以作为辅助输入、电池电压测量和片内温度测量的参考电压。当不使用时,参考电压源可以处于省电模式。内部参考电压源在电源电压低至2.7V时仍可正常工作。当不使用时,参考电压还可以处于省电模式。内部参考电压在电源电压低于2.7V时仍可正常工作,并且监测着在 0V~6V范围内的电源电压。XPT2046在 125KHz转换速率和 2.7V电压下的功耗仅为750 µW。XPT2046以其低功耗和高速率等特性,被广泛应用在采用电池供电的小型手持设备上,比如 PDA、手机等。
XPT2046 是一种典型的逐次逼近型模数转换器(SAR ADC),包含了采样/保持、模数转换、串口数据输出等功能。同时芯片集成有一个 2.5V的内部参考电压源、温度检测电路,工作时使用外部时钟。XPT2046 可以单电源供电,电源电压范围为 2.7V~5.5V。参考电压值直接决定ADC的输入范围,参考电压可以使内部参考电压,也可以从外部直接输入1V~VCC范围内的参考电压(要求外部参考电压源输出阻抗低)。X、Y、Z、VBAT、Temp和AUX模拟信号经过片内的控制寄存器选择后进入ADC,ADC可以配置为单端或差分模式。选择VBAT、Temp和AUX时可以配置为单端模式;作为触摸屏应用时,可以配置为差分模式,这可有效消除由于驱动开关的寄生电阻及外部的干扰带来的测量误差,提高转换准确度。
XPT2046_SPI.H
#ifndef __XPT2046_SPI_H
#define __XPT2046_SPI_H
#include "stm32f10x_conf.h"
//XPT2046 与STM32107VCT6的连线方式
//MISO PC11/SPI3_MISO REMAP
//MOSI PC12/SPI3_MISO
//SCK PC10/SPI3_SCK
//TP_CS PC9
//INT PC5
// A/D 通道选择命令字和工作寄存器
#define CMD_RDX 0x90
#define CMD_RDY 0xD0
#define READ_TIMES 15 //读取次数
#define LOST_VAL 5 //丢弃值
#define ERR_RANGE 50 //误差范围
#define TPCS_L GPIO_ResetBits(GPIOC, GPIO_Pin_9)
#define TPCS_H GPIO_SetBits(GPIOC, GPIO_Pin_9)
//extern u16 X_Addata,Y_Addata;
//extern void delay_ms(u16 Nms);好像不延时也可以用哦
void XPT2046_Configuration(void);//配置GPIO/SPI3/EXTI中断
u16 ADS_Read_AD(u8 CMD);
//void XPT2046_Rd_Addata(void);//读位置,村到全局变量X_Addata,Y_Addata
//读取一个坐标值
//连续读取READ_TIMES次数据,对这些数据升序排列,
//然后去掉最低和最高LOST_VAL个数,取平均值
u16 ADS_Read_XY(u8 xy);//
u8 Read_ADS(u16 *x,u16 *y);////最小值不能少于100.
u8 Read_ADS2(u16 *x,u16 *y);//2次读取ADS7846,连续读取2次有效的AD值,且这两次的偏差不能超过ERR_RANGE
#endif
XPT2046_SPI.C
#include "xpt2046_spi.h"
u16 X_Addata=0,Y_Addata=0;
static void XPT2046_INT_EXIT_Init(void)//中断设置下降沿
{
EXTI_InitTypeDef EXTI_InitStructure;
/* Connect Button EXTI Line to Button GPIO Pin */
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource5);
/* Configure Button EXTI line */
EXTI_InitStructure.EXTI_Line = EXTI_Line5;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
}
/*******************************************************************************
* Function Name : InterruptConfig
* Description : Configures the used IRQ Channels and sets their priority.NVIC_Configuration
* Input : None
* Output : None
* Return : None
*******************************************************************************/
static void XPT2046_InterruptConfig(void)//NVIC
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Set the Vector Table base address at 0x08000000 */
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0000);
/* Configure the Priority Group to 2 bits */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/* Enable the EXTI5 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void XPT2046_Configuration(void)
{
SPI_InitTypeDef SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable SPI3and GPIO clocks */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC| RCC_APB2Periph_AFIO, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SPI3,ENABLE);//SPI3 REMAP
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
TPCS_H;
//GPIO_SetBits(GPIOC, GPIO_Pin_9); /* Disable TP CS PC9 */
// Set as Output AF push-pull - SCK and MOSI PC10 PC12//SPI3_MISO PC11
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
//中断端口GPIO设置 PC5
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;//设置输入
//GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉
GPIO_Init(GPIOC, &GPIO_InitStructure);
//SPI3 设置
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;//由于说明书最高速率2M //72/256=
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI3, &SPI_InitStructure);
/* Enable SPI3 */
SPI_Cmd(SPI3, ENABLE);
//中断设置
XPT2046_INT_EXIT_Init();
XPT2046_InterruptConfig();
//GPIO_SetBits(GPIOC, GPIO_Pin_12);//mosi=1
//clk=0
}
u8 XPT2046_SendByte(u8 byte)
{
/* Loop while DR register in not emplty */
while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_TXE) == RESET);
/* Send Half Word through the SPI3 peripheral */
SPI_I2S_SendData(SPI3, byte);
/* Wait to receive a Half Word */
while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_RXNE) == RESET);
/* Return the Half Word read from the SPI bus */
return SPI_I2S_ReceiveData(SPI3);
}
u8 XPT2046_ReadByte(void)
{
return (XPT2046_SendByte(0x00));
}
/*
void XPT2046_Rd_Addata(void)
{
u16 temp;
TPCS_L;
//GPIO_ResetBits(GPIOC, GPIO_Pin_9);//CS=0
//delay_ms(1);
XPT2046_SendByte( CHX ) ;
//delay_ms(1);
temp=0;//相当于简短的延时啦
temp= XPT2046_ReadByte() ;
Y_Addata =temp<<8;
temp= XPT2046_ReadByte() ;
Y_Addata |=temp;
Y_Addata >>=3;
Y_Addata &=0XFFF;
//GPIO_SetBits(GPIOC, GPIO_Pin_9);
//GPIO_ResetBits(GPIOC, GPIO_Pin_9);
//delay_ms(1);
XPT2046_SendByte( CHY) ;
temp=0;
//delay_ms(1);
temp= XPT2046_ReadByte();
X_Addata=temp<<8;
temp= XPT2046_ReadByte();
X_Addata |=temp;
X_Addata >>=3;
X_Addata &=0XFFF;
TPCS_H;
//GPIO_SetBits(GPIOC, GPIO_Pin_9);
}*/
u16 ADS_Read_AD(u8 CMD)
{
u16 temp,Addata;
TPCS_L;//使能
XPT2046_SendByte(CMD) ;
temp=0;//相当于简短的延时啦
temp= XPT2046_ReadByte() ;
Addata =temp<<8;
temp= XPT2046_ReadByte() ;
Addata |=temp;
Addata >>=3;//SPI读数由于第8位为0
Addata &=0XFFF;
return Addata;
}
//读取一个坐标值
//连续读取READ_TIMES次数据,对这些数据升序排列,
//然后去掉最低和最高LOST_VAL个数,取平均值
u16 ADS_Read_XY(u8 xy)
{
u16 i, j;
u16 buf[READ_TIMES];
u16 sum=0;
u16 temp;
for(i=0;i
buf[i]=ADS_Read_AD(xy);
}
for(i=0;i
for(j=i+1;j
if(buf[i]>buf[j])//升序排列
{
temp=buf[i];
buf[i]=buf[j];
buf[j]=temp;
}
}
}
sum=0;
for(i=LOST_VAL;i
return temp;
}
//带滤波的坐标读取
//最小值不能少于100.
u8 Read_ADS(u16 *x,u16 *y)
{
u16 xtemp,ytemp;
xtemp=ADS_Read_XY(CMD_RDX);
ytemp=ADS_Read_XY(CMD_RDY);
if(xtemp<100||ytemp<100)return 0;//读数失败
*x=xtemp;
*y=ytemp;
return 1;//读数成功
}
//2次读取ADS7846,连续读取2次有效的AD值,且这两次的偏差不能超过
//50,满足条件,则认为读数正确,否则读数错误.
//该函数能大大提高准确度
u8 Read_ADS2(u16 *x,u16 *y)
{
u16 x1,y1;
u16 x2,y2;
u8 flag;
flag=Read_ADS(&x1,&y1);
if(flag==0)return(0);
flag=Read_ADS(&x2,&y2);
if(flag==0)return(0);
if(((x2<=x1&&x1
*x=(x1+x2)/2;
*y=(y1+y2)/2;
return 1;
}else return 0;
}
史海拾趣
|
有归属、没宗派,有尊重、没辈分,有针对、没争竞,有奉献、没名利 相互尊重、友好交流、扩大共识,倡导不同文化间增进了解、相互借鉴 电子工程师,结构工程师,软件工程师,硬件工程师,FPGA研发。另有数码产品,影音视听产品,手机,微型硬盘播放机,R ...… 查看全部问答> |
|
阿牛哥冒着七月的艳阳酷暑,晚上听完国际广播电台的新闻,西瓜荔枝,要看世界杯球赛了。晚上的这场要看,凌晨的那场要听。电视电脑收音机都需要,就是不能影响白天的工作。先说说世界杯比赛,不能在家里看,太影响家人.去哥们马六家看;啤酒不喝 ...… 查看全部问答> |
|
PC104设备在纯DOS下跑程序的问题,虚拟软驱引导的纯DOS和实际安装的DOS有区别不? 如题。 现在程序跑在虚拟软驱引导的纯DOS里面,2000里面用bc31写的程序在2000下跑很流畅,但是到DOS下却非常卡。 想在DOS里面再编译,链接模式选small能通过,但是程序一跑就死,选large能通过,一跑连画面都没有,选其他linker都不成功。何解? ...… 查看全部问答> |
|
wince 是否支持\"微软雅黑\"字体? 看到linux下显示的字体比较漂亮,font文件下看到msyh.ttf,也就是雅黑字体了,EVC下显示的字效果比较一般,要是wince支持msyh.ttf的话,应该怎样添加呢? … 查看全部问答> |
|
紧急求救!!用c开发手机或PDA需要看什么方面的书籍资料!!谢谢各位拉 本人用vc写过应用程序,用c写过mp3的程式,但是c++不太好,在vc里面基本用的都是c,现在想转做手机或pda方面,请教需要看哪些书啊?我看些资料,一般都是在用WinCE或在Linux下开发,哪个发展更好些?不知道这方面薪水待遇怎么样?敢请各位不啬赐教 ...… 查看全部问答> |
|
MSP430FG461X系列的20位地址指针在C语言中如何实现? 我把一个20位的地址0x10000,赋值给一个指针变量时,总是提示超出了0~0xFFFF的范围。 在汇编中这是可以做到的,因为MSP430X提供了MOVA等带A的指令,且工作寄存器都是20位的,可以用于20位的地址传输。就是不知道C语言中怎么实现。 不知是不是有 ...… 查看全部问答> |
|
问题1:一般在主函数中装定时器初值,有必要吗?我好像试了,不装也能正常运行。 问题2:如果在定时器1中关闭了定时器0,用TR0=1再次打开定时器0时,需要重新装定时器0的初值吗?还是TR0=1直接就进入定时器0的中断函数从头开始执行。我试过两次不 ...… 查看全部问答> |
|
使用C2000的SPI驱动ADS8332,过去曾成功过,是不同的PCB。然而再次搞它时,却问题多多。 现象:采样转换的通道,采样(转换)时,输入端悬空或稍大的旁路电阻(>10K,再小没试),就有有1V左右的电压。而未采样的通道,采样通道未采样时,没有这个 ...… 查看全部问答> |




