电子说
原理图
ADC的快速回顾
大多数人认为模拟领域已经落后于他们,但事实是模拟领域从未如此强大!随着物联网的兴起和传感器的生产,全球每秒都在进行数十亿的模拟读数。这只是微控制器生产商将ADC外设直接集成到其器件中的众多原因之一。
ADC将模拟信号转换为数字信号
通常测量ADC
由于ADC是数字的,模拟信号被量化为离散的步骤
这意味着ADC只能准确无误地实现它们的位宽(即10位ADC)测量特定电压电平
最大数字值等于ADC 正参考电压(通常为VCC)
最小数字值等于ADC 负参考(通常为GND)
ADC需要时间来转换信号
在ATmega168中,ADC具有以下特性:
10位分辨率(+ Vref和-Vref之间的1024个离散电压电平)
精度为2LSB(高8位精度保证)
高达15,000个样本/秒
6个多路复用输入源
1.1V 带隙参考
配置ADC
我们可以使用之前ADC,需要配置用于ADC测量的外设和I/O引脚。
左对齐还是右对齐?
当ADC完成转换操作后,结果存储在一对中8位寄存器(10位结果不适合单个8位寄存器)。由于ATmega是原生的8位器件,因此使用8位ADC不如10位结果更有意义,但这会降低结果的分辨率。但是,必须正确读取10位数的8位结果,否则结果将不正确。为此,我们需要读取前8位(位9-2),而不是后8位。使用ADLAR位很容易实现,当设置为1时,将使ADC结果保持正确。这意味着我们不需要读取结果寄存器(ADCH和ADCL)并进行一些操作,而是直接读取ADCH并忘记ADCL。
配置I/O端口
现在我们可以直接读取ADCH以获得8位结果,而不必担心位操作(在分辨率的成本),我们现在需要配置我们的模拟引脚。默认情况下,ATmega168上的I/O引脚配置为数字引脚,这意味着它们只能处理1和0。因此,要将输入配置为模拟引脚,我们使用DIDR0寄存器,它代表数字输入禁用寄存器。不幸的是,并非每个引脚都具有模拟输入的能力,因此请务必注意带有标签ADCx的引脚。例如,引脚23至28是ATmega168上的模拟输入引脚。
配置ADC模块
配置ADC的最后阶段包括打开ADC,设置预缩放器时间以及确定ADC的参考值。
通过将ADCSRA寄存器中的ADEN位置1来打开ADC模块。
在大多数情况下,预缩放器不是太重要了,为了简单起见,我们将预缩放器设置为其最大值(设置ADCSRA寄存器中的所有ADPSx位)。
ATmega168上的ADC可以介于0V和某个参考电压之间,通常设置为VCC。由于大多数电路都是这种情况,我们需要将Aref引脚连接到也接地的电容,我们还需要将REFSx位设置为使用AVCC作为参考。
使用ADC
使用ADC非常简单。选择将从中取出模拟读数的通道,然后,为了开始转换,ADSC位(在ADCSRA中找到)将打开。转换完成后,ADC硬件会自动清零ADSC位。
通过设置ADMUX寄存器中的相应多路复用器位MUX3-MUX0来选择要读取的模拟引脚。
软件示例
此示例从ADC0(PC0,引脚23)读取模拟值并进行比较他们到一个特定的价值。如果模拟读数超出指定值(定义为TRIGPOINT),LED(连接到PD0,引脚2)将打开。一旦ADC读数低于指定值,LED就会关闭!
/*
* AVR IO.c
*
* Created: 03/01/2018 11:25:21
* Author : RobinLaptop
*/
#define F_CPU 1000000UL
#define TRIGPOINT 128
#include
#include
int main(void)
{
// Configure PORT D bit 0 to an output
DDRD = 0b00000001;
// Configure PORT C bit 0 to an input
DDRC = 0b00000000;
// Configure ADC to be left justified, use AVCC as reference, and select ADC0 as ADC input
ADMUX = 0b01100000;
// Enable the ADC and set the prescaler to max value (128)
ADCSRA = 0b10000111;
// Main program loop
while (1)
{
// Start an ADC conversion by setting ADSC bit (bit 6)
ADCSRA = ADCSRA | (1 《《 ADSC);
// Wait until the ADSC bit has been cleared
while(ADCSRA & (1 《《 ADSC));
if(ADCH 》 TRIGPOINT)
{
// Turn LED on
PORTD = PORTD | (1 《《 PD0);
}
else
{
// Turn LED off
PORTD = PORTD & ~(1 《《 PD0);
}
}
}
结论
本文仅介绍ADC背后的基础知识,但我们已经开始从现实世界中进行模拟测量。当然,您可以阅读数据表并了解其他更高级的功能,包括触发和其他电压参考。但就目前而言,这应该为您提供足够的知识,开始制作需要读取模拟值的AVR项目!
全部0条评论
快来发表一下你的评论吧 !