MM32通过ADC控制4线电阻触摸屏

judy的头像
judy 发布于:周五, 10/20/2017 - 13:27 ,关键词:

前段时间有一个客户需要用到4线电阻触摸屏,为了节省一片触摸屏控制芯片,客户决定使用MCU直接控制4线电阻触摸屏,主要使用到了MM32的ADC外设资源,通过ADC采集触摸屏的X+\Y+的电压,算出相对应的坐标轴,并且显示在显示屏上。所以今天将结合该例程和大家一起熟悉、了解MM32的ADC配置流程。

一、触摸屏操作原理

电阻触摸屏利用压力感应进行控制。电阻触摸屏的主要部分是一块与显示器表面非常配合的电阻薄膜屏,这是一种多层的复合薄膜,它以一层玻璃或硬塑料平板作为基层,表面涂有一层透明氧化金属(透明的导电电阻)导电层,上面再盖有一层外表面硬化处理、光滑防擦的塑料层,它的内表面也涂有一层涂层,在他们之间有许多细小的(小于1/1000英寸)的透明隔离点把两层导电层隔开绝缘。当手指触摸屏幕时,两层导电层在触摸点位置就有了接触,电阻发生变化,在X和Y两个方向上产生信号,然后送触摸屏控制器。控制器侦测到这一接触并计算出(X,Y)的位置,再根据模拟鼠标的方式运作。这就是电阻技术触摸屏的最基本的原理。

二、MM32驱动电阻触摸屏的实现

MM32系列MCU的I/O口可以编程配置成带上拉电阻的模式,这个特点可以用来检测有无触摸。MM32的GPIO管脚连接触摸屏的Y+和X- ,连接Y+的管脚配置成内部电阻上拉模式,连接X-的管脚配置成推挽输出低电平。如果Y+为高电平,那么就是没有触摸。如果Y+为低电平,触摸屏被压下。从高到低电平的跳变可以检测触摸,可以用外部中断,在本例程中将使用ADC的单次扫描模式采集X+\Y+电压。

图1. 4线电阻触摸屏坐标读取

 MM32通过ADC控制4线电阻触摸屏

三、MM32 ADC介绍

12 位 ADC 是逐次逼近式的模拟-数字转换器(SAR A/D 转换器),且ADC转换数据分辨率可设置8-12位有效。

高达1Msps转换速率,有很多用户在计算采样频率设置时会觉得很难理解,在这里将为大家讲一下采样频率计算方法,ADC 的时钟 ADCLK 由 PCLK2 分频得到ADC 的输入时钟(不得超过 15MHz,它是由 PCLK2 经分频产生)。分频系数可通过设置 ADCFG 寄存器的 ADCPRE 位来确定,即 PCLK2/(N+1)/2 分频后作为 ADC 时钟。设置 ADC 分辨率为 n 位(n=8,9,10,11,12),每个通道采样时间为 m, Fsample = FADCLK/(m + n + 1.5)。假设分辨率配置为 12bit,每个通道采样时间为 1.5T, 则 Fsample =FADCLK/15。

例如:设置 ADC 分辨率为 n =12,每个通道采样时间m =1.5个周期,FADCLK=15MHz
Fsample = FADCLK/(m + n + 1.5)=15/(12+1.5+1.5)=1Msps

根据此配置可以得到1Msps转换速率,也就是转换时间为1us,用户可以根据项目的需求配置相对应的转换速率。

A/D 转换器支持多种工作模式:单次转换、单周期扫描模式和连续转换模式。
- 单次转换模式: A/D 转换在指定通道完成一次转换。
- 单周期扫描模式: A/D 转换在所有指定通道完成一个周期(从低序号通道到高序号通道)转换。

- 连续扫描模式: A/D 转换连续执行单周期扫描模式直到软件停止 A/D 转换。

支持DMA传输,单周期扫描和连续扫描时通道转换的值存储在各自通道的数据寄存(ADDRn)中,最近一次转换的结果也会保存在 ADDATA 寄存器中。DMA 传输时可以选择传输某个特定通道的数据,或者传输所有扫描通道的结果。

A/D 转换的启动方式有软件设定(即在配置相关寄存器时,直接开启采样)、外部引脚触发(例如定时器捕获,EXTI线)以及各个定时器启动(Timer1/2/3/4 匹配或者 TRGO 信号,在配置电机应用时需要使用定时器触发ADC采样)。

窗口比较器(模拟看门狗)允许应用程序检测输入电压是否超出了用户设定的高/低阀值值,转换结果可和指定的值相比较,当转换值和设定值相匹配时,用户可设定是否产生中断请求。

四、用MM32L373读触摸屏参数
在硬件中使用了MM32L373的ADC单周期扫描功能,使用到的GPIO分别是:PA1\PA3\PA4\PA5,分两步读取X,Y坐标值。

//测量X+电压的GPIO配置
void XP_GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
//将X+配置模拟输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
//GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//将X-配置浮空模式
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//将Y+、Y-配置为通用推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_ResetBits(GPIOA,GPIO_Pin_4);//Y-输出低电平
GPIO_SetBits(GPIOA,GPIO_Pin_5); //Y+输出高电平
}
//测量Y+电压的GPIO配置
void YP_GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
//将Y+ 配置模拟输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
//GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//将Y- 配置浮空模式
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//将X+、X-配置为通用推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_ResetBits(GPIOA,GPIO_Pin_3);//X-输出低电平
GPIO_SetBits(GPIOA,GPIO_Pin_1); //X+输出高电平
}
第一步,驱动Y+为高电平,Y-为低电平,接X+管脚配置成AD输入模式,检测X+的电压,此电压与驱动电压的比例即Y坐标和整个屏的高度比率。
/***************************************************************************
** 函数信息:void XP_ADC1_SingleChannel(uint8_t ADC_Channel_x)
**功能描述:测量X+电压,配置ADC单次扫描通道
**输入函数:ADC_Channel_x , x为0~8
**输出函数:无
***************************************************************************/
void XP_ADC1_SingleChannel(uint8_t ADC_Channel_x)
{
ADC_InitTypeDef ADC_InitStructure;
XP_GPIO_Configuration();
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);//开启ADC1时钟
/* Initialize the ADC_PRESCARE values */
ADC_InitStructure.ADC_PRESCARE = ADC_PCLK2_PRESCARE_16;//16分频
/* Initialize the ADC_Mode member */
ADC_InitStructure.ADC_Mode = ADC_Mode_Single;//配置单通道扫描模式
/* Initialize the ADC_ContinuousConvMode member */
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//关闭连续转换模式
/* Initialize the ADC_DataAlign member */
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//数据右对齐
/* Initialize the ADC_ExternalTrigConv member */
ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_T1_CC1;//外部触发通道选择
ADC_Init(ADC1, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC1, ADC_Channel_x, 0, ADC_SampleTime_1_5Cycles); //设置换换顺序和采样时间
ADC_Cmd(ADC1, ENABLE); //使能ADC1
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能ADC1软件转换启动
if(ADC_Channel_x==ADC_Channel_8)
{
ADC1->ADCFG|=0x04;
}
}

第二步,驱动X+为高电平,X-为低电平,接Y+的管脚配置成AD输入模式,检测Y+的电压,此电压与驱动电压的比例即X坐标和整个屏的宽度比率。
/***************************************************************************
** 函数信息:void YP_ADC1_SingleChannel(uint8_t ADC_Channel_x)
**功能描述:测量Y+电压,配置ADC单次扫描通道
**输入函数:ADC_Channel_x , x为0~8
**输出函数:无
***************************************************************************/
void YP_ADC1_SingleChannel(uint8_t ADC_Channel_x)
{
ADC_InitTypeDef ADC_InitStructure;
YP_GPIO_Configuration();
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //开启ADC1时钟
/* Initialize the ADC_PRESCARE values */
ADC_InitStructure.ADC_PRESCARE = ADC_PCLK2_PRESCARE_16; //16分频
/* Initialize the ADC_Mode member */
ADC_InitStructure.ADC_Mode = ADC_Mode_Single; //配置单通道扫描模式
/* Initialize the ADC_ContinuousConvMode member */
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //关闭连续转换模式
/* Initialize the ADC_DataAlign member */
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //数据右对齐
/* Initialize the ADC_ExternalTrigConv member */
ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_T1_CC1;//外部触发通道选择
ADC_Init(ADC1, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC1,ADC_Channel_x,0,ADC_SampleTime_1_5Cycles); //设置换换顺序和采样时间
ADC_Cmd(ADC1, ENABLE); //使能ADC1
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能ADC1软件转换启动
if(ADC_Channel_x==ADC_Channel_8)
{
ADC1->ADCFG|=0x04;
}
}

第三步:根据ADC采集到的数据做校验算法,得到触摸点坐标,并且显示在显示屏对应的区域。

图2 实验效果

 MM32通过ADC控制4线电阻触摸屏

转自: 灵动微电子

围观 632