第018课 ADC和触摸屏

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

第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. 在串口上显示出来。

图1


一,初始化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