第018课 ADC和触摸屏

来自百问网嵌入式Linux wiki
Baiwen root讨论 | 贡献2018年1月19日 (五) 16:03的版本

第001节_ADC硬件原理

模数转换器即A/D转换器,或简称ADC,通常是指一个将模拟信号转变为数字信号的电子元件。
通常的模数转换器是把经过与标准量比较处理后的模拟量转换成以二进制数值表示的离散信号的转换器。
故任何一个模数转换器都需要一个参考模拟量作为转换的标准,比较常见的参考标准为最大的可转换信号大小。
而输出的数字量则表示输入信号相对于参考信号的大小。如图,是把可变电阻上的电压值变换的模拟信号通过ADC转换,输出数字信号。
Chapter18 lesson1 001.jpg

对于数字信号我们需要得到它的几个属性

  • 用多少位来存储这个数据(假设10bit)。
  • 最大值0b111111111 它对应的电压是多少伏(模拟信号输入的最大值是多少)我们就可以根据模拟信号(电压)的最大值,来计算出对应的数值。
  • 采样/转换速度。

对于程序员,我们不关心ADC的内部机制,我们只关心:

  • 怎么启动ADC
  • 启动之后怎么得到数据,

总之:我们都是通过寄存器操作的。
Chapter18 lesson1 002.png

从图1-1-1可以看出ADC有8个多路选择器,显然,以后我们写程序的时候,我们可以8个多路选择之一, 下面是编写程序要做的步骤:

  1. 确定是哪一路信号:设置8:1MUX,选择要测量哪一个引脚,(看原理图选择要测量的引脚)
  2. 设置工作时钟(从工作室中,可以算出转换一次,需要多长时间)
  3. 启动
  4. 读状态,判断ADC转换是否成功。
  5. 读数据

ADC寄存器介绍

1,ADC 控制寄存器(ADCCON) ADCCON控制寄存器,用于标志转换是否完成,控制是否使能预分频器,输入通道选择,工作模式,ADC是否启动。它的各位含义如下图所示。
Chapter18 lesson1 003.png

2,ADC 启动延时寄存器(ADCDLY) ADCDLY 启动延时寄存器用于启动或初始化延时寄存器。它的各位含义如下图所示

Chapter18 lesson1 004.png

3,ADC 转换数据寄存器(ADCDAT0) ADCDAT0转换数据寄存器,本节中只用到该寄存器的前10位(用于保存转换后的结果)。

Chapter18 lesson1 005.png

第002节_ADC编程

编程步骤:

  1. 初始化ADC
  2. 读数据,
  3. 在串口上显示出来。

Chapter18 lesson2 001.png

一,初始化ADC 下面的函数实现对ADC的初始化。

03	void adc_init(void)
04	{
05	/* [15] : ECFLG,  1 = End of A/D conversion
06	 	* [14] : PRSCEN, 1 = A/D converter prescaler enable
07	 	* [13:6]: PRSCVL, adc clk = PCLK / (PRSCVL + 1)
08	 	* [5:3] : SEL_MUX, 000 = AIN 0
09		 * [2]   : STDBM
10	 	* [0]   : 1 = A/D conversion starts and this bit is cleared after the startup.
11	 	*/
12		ADCCON = (1<<14) | (49<<6) | (0<<3);
13
14		ADCDLY = 0xff;	
15	}
  • 第12行:配置ADCCON寄存器,使能A/D 转换器预分频器,设置A/D 转换器预分频值,上拉使能。
  • 第14行:设置ADC 转换启动延时值。

二,读数据 在这个读函数中启动ADC,并且等待ADC转换成功。然后返回数据,

17	int adc_read_ain0(void)
18	{
19			/* 启动ADC */
20		ADCCON |= (1<<0);
21
22		while (!(ADCCON & (1<<15)));  /* 等待ADC结束 */
23
24		return ADCDAT0 & 0x3ff;
25	}
  • 第20行:启动ADC。
  • 第22行:等待A/D转换结束(ADCCON第15位置1),
  • 第24行:返回转换的值。(ADCDAT0寄存器的前10位,是保存转换后的值)。

三,ADC测试 函数代码如下: 函数功能:在串口/LCD上打印ADC转换后的结果。

04	void adc_test(void)
05	{
06		int val;
07		double vol;
08		int m; /* 整数部分 */
09		int n; /* 小数部分 */
10	
11		adc_init();
12
13		while (1)
14		{
15			val = adc_read_ain0();
16			vol = (double)val/1023*3.3;   /* 1023----3.3v */
17			m = (int)vol;   /* 3.01, m = 3 */
18			vol = vol - m;  /* 小数部分: 0.01 */
19			n = vol * 1000;  /* 10 */
20
21			/* 在串口上打印 */
22			printf("vol: %d.%03dv", m, n);  /* 3.010v */
23
24			/* 在LCD上打印 */
25			//fb_print_string();
26			}
27	}
  • 第11行:初始化ADC.
  • 第15行:把ADC转换得到的值赋值给变量val.
  • 第16行:把变量val的值转化为电压值。
  • 第17行:取vol整数部分赋值给变量m。
  • 第18行:取vol的小数部分赋值给vol。

测试 把生成的二进制文件烧录到开发板上,接上SPI模块,旋转可变电阻就可以在串口上看到电压值发生变化。原理图如图1-1-2

第003节_电阻触摸屏硬件原

这节课我们来讲电阻触摸屏的硬件原理

假设有一个比较长的电阻 电阻是R 上面接3.3V电压,下面接地 ![](https://i.imgur.com/reKZhLZ.png) 假设整个电阻的阻值是R 某一个触电它的阻值是R1 根据欧姆定律

3.3v/R = V/R1
V=3.3 *(R1/R)

假设R1是x坐标 R的长度是l 这个电阻非常的均匀,那么这个电压就等于 3.3V * (x / l) 这个电压和这个触电的x坐标有一个线性关系 我使用ADC把这个电压算出来,就可以间接得到这个触电的x坐标 电阻触摸屏就是使用欧姆定律使用电阻原理作出来的

可以上百度图片搜索触摸屏,就知道了触摸屏的样子 它是一个透明的薄膜 注意 LCD是LCD 触摸屏是触摸屏它是两个设备 我们只不过是把触摸屏做的和LCD大小一样,粘在LCD上面 实际上触摸屏是由两层膜组成,他们靠的非常近

上面这层右边引出来,代表xp ,p代表正极 上面这层左边引出来,代表xm, m代表负极 ![](https://i.imgur.com/Iz6ktFu.png) 下面这层膜 前面这条边引出来为yp,后面这层边为ym

假设我们手指要点击触摸屏,那么上下就会粘贴在一起,我怎么算出这个 x y点的坐标呢? 测量触电x坐标: 1 xp接3.3v,xm接GND ![](https://i.imgur.com/PKpCniB.png) yp,ym不接电源

2 测yp电压 上下膜连接在一起,我就可以通过yp测量这个触电的电压 这个yp就像探测一样,从前面的原理我们可以知道,当这个触电越靠近左边这个电压越小,越靠近右边电压越大 这个yp的电压就可以认为是这个触电的坐标(x坐标)


类似的我们怎么测量触电y坐标 类似的xp xm不接电源,同样yp接3.3v, ym接GND,这时候电流就从 yp这里流向ym,让后我们就可以测量xp电压 当按下屏幕时,上下两层膜链接在一起,这个xp就像探针一样,这个触电越靠近yp电压值越大,越靠近ym电压值越小 ![](https://i.imgur.com/4EWzkTX.png) 1 yp接3.3V ym接GND,xp xm不接电源 2 测量xp电压,就是y坐标

注意 x y坐标都是电压值,不是屏幕上480 * 272 这些值,我们需要把电压值转换为坐标值,这需要经过一些转换

我们测量xp yp可以得到触点的两个方向的电压值,这些电压值和坐标是线性关系 我们现在总结下使用触摸屏的流程 1 按下触摸屏 按下触摸屏时,对于一个高效的系统,产生中断,这是触摸屏中断 2 在触摸中断程序中 启动ADC,(获得数据,xy坐标) 启动ADC就开始模数转换,不可能瞬间完成, 3 ADC完成, 产生中断 4 ADC中断中读取x y坐标,


我们来想想,在这个流程里,启动触摸屏的源头是按下触摸屏,那如果长按触摸屏,我按下之后一直不松开 滑动手指呢 那么谁来触发后续的多次ADC转换呢 不可能只启动一次吧 为了支持 长按 滑动操作,我们需要启用定时器

5 启动定时器 6 定时器中断发生,判断触摸屏是否仍被按下,如果按下就循环上述过程( 2 在触摸中断程序中 启动ADC,(获得数据,xy坐标) 启动ADC就开始模数转换,不可能瞬间完成, 3 ADC完成, 产生中断 4 ADC中断中读取x y坐标,) 7 松开结束一个流程 这就是整个触摸屏的使用流程

在14章里讲解了触摸屏,他抽象了几张图

平时的时候上下两层膜并不连接,我们按下触摸屏的时候就会产生中断,那么你怎么知道产生中断,肯定是由某个引脚的电平发生变化 平时 Y_ADC/xp是高电平 按下之后Y_ADC就接地了,就是被拉低了,就产生了低电平 ![](https://i.imgur.com/gNdGzNy.png)

产生低电平后就知道触摸屏被按下了,这个时候就需要测量电压值 读取x坐标 XP XM通电我就测量YP的电压,这不就是 x 点的坐标 ![](https://i.imgur.com/LDsh0Ob.png)

读取Y坐标 YP YM 通电,按下后XP通电,这不就是y点的坐标么 ![](https://i.imgur.com/URJw5tR.png)