历史上的今天
今天是:2025年01月22日(星期三)
2020年01月22日 | 怎样用AVR微控制器集成的ADC从周围环境中获取模拟读数
2020-01-22 来源:eefocus
原理图

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完成转换操作后,结果存储在一对中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项目!
史海拾趣
|
承接嵌入式系统项目开发 相信大家都知道,要想产品具有竞争力,一般都要使用操作系统来提高附加值。然而使用别人的操作系统就要支付高额的授权费。这直接导致了开发成本的增加,降低了产品的竞争力。 我们团队独立研发了具有自主知识产权的操作系 ...… 查看全部问答> |
|
Crosstar嵌入式学院“利用/proc实现内核与用户空间通信” Linux内核空间与用户空间的通信可通过\"/proc\"目录的文件读写来实现,如果只是控制内核中的参数而不是传输较多数据的话,用“/proc”是很合适的。另外几种内核与用户空间通信方式方式是:1)对内核设备的读写或IOCTL;2)通过/sys内存文件系统来 ...… 查看全部问答> |
|
发现个很郁闷的问题。用TCP发送数据。数据中如果有 0x0D 0x0A的话,模块会给你做些处理,收到以后就变成了 0x0D,0x0D,0x0A.或者0x0D,0x0A,0x0A. 发短信,用文本方式时也有这样的问题 大家有没有出现同样问题的?… 查看全部问答> |
|
大家好.... 我在弄LM3S9997 可是下载不了程序。。 (原文件名:222.jpg) 引用图片下面的资料。可能发现看不问题。。觉得哪里可能有问题就说说吧。。我改的 希望过来人教教我。。还有就是读到了芯片的ID以及ROM的ID ,是不是就说 ...… 查看全部问答> |
|
1、关于TI教室中课程,除了第一个有进度其他的看了,没进度,不知道什么原因,希望能给个解释。 [ 本帖最后由 Sur 于 2013-12-3 21:20 编辑 ]… 查看全部问答> |




