ADC模块(模数转换器)是几乎每个嵌入式应用程序中使用的一个常见功能。这些 模数转换器 可以从温度传感器,倾斜传感器,电流传感器,柔性传感器等模拟传感器读取电压。在本教程中,我们将学习 什么是Atmega16中的ADC以及如何使用ADC。本教程包括将一个小电位计连接到Atmega16的ADC引脚,并且8个LED用于显示ADC输出值相对于ADC输入值变化的变化电压。
之前,我们在其他微控制器中介绍了ADC:
- 如何在ARM7 LPC2148中使用ADC-测量模拟电压
- 如何在STM32F103C8中使用ADC-测量模拟电压
- 如何在MSP430G2中使用ADC-测量模拟电压
- 如何在Arduino Uno中使用ADC?
- 将PIC微控制器的ADC模块与MPLAB和XC8一起使用
什么是ADC(模数转换)
ADC代表模数转换器。在电子产品中,ADC是一种将模拟信号(例如电流和电压)转换为数字代码(二进制形式)的设备。在现实世界中,大多数信号都是模拟信号,任何微控制器或微处理器都能理解二进制或数字语言(0或1)。因此,为了使微控制器理解模拟信号,我们必须将这些模拟信号转换为数字形式。 ADC正是为我们做到这一点。有许多类型的ADC可用于不同的应用。很少有流行的ADC是闪存,逐次逼近和sigma-delta。
最便宜的ADC类型是逐次逼近,在本教程中将使用逐次逼近ADC。在逐次逼近型ADC中,依次生成一系列数字代码,每个数字代码对应于固定的模拟电平。内部计数器用于与转换后的模拟信号进行比较。当模拟电平刚好大于模拟信号时,将停止生成。对应于模拟电平的数字代码是所需的模拟信号数字表示。这样就完成了我们对逐次逼近的解释。
如果您想深入探讨ADC,则可以参考我们之前关于ADC的教程。ADC以IC的形式提供,如今,微控制器也都内置了ADC。在本教程中,我们将使用内置的Atmega16 ADC。让我们讨论一下Atmega16的内置ADC。
AVR微控制器Atmega16中的ADC
Atmega16具有内置的10位和8通道ADC。10位对应于如果输入电压为0-5V,则它将分成10位值,即1024个离散模拟值水平(2 10 = 1024)。现在,8通道对应于Atmega16上的专用8个ADC引脚,其中每个引脚都可以读取模拟电压。完整的PortA(GPIO33-GPIO40)专用于ADC操作。默认情况下,PORTA引脚是通用IO引脚,这意味着端口引脚是多路复用的。为了将这些引脚用作ADC引脚,我们将必须配置某些专用于ADC控制的寄存器。这就是为什么寄存器被称为ADC控制寄存器的原因。让我们讨论如何设置这些寄存器以启动内置ADC的功能。
Atmega16中的ADC引脚
所需组件
- Atmega16单片机IC
- 16Mhz晶体振荡器
- 两个100nF电容器
- 两个22pF电容器
- 按钮
- 跳线
- 面包板
- USBASP v2.0
- LED(任何颜色)
电路原理图
在Atmega16中设置ADC控制寄存器
1. ADMUX寄存器(ADC多路复用器选择寄存器):
ADMUX寄存器用于选择ADC通道和选择参考电压。下图显示了ADMUX寄存器的概述。下面说明该描述。
- 位0-4:通道选择位。
MUX4 |
MUX3 |
MUX2 |
MUX1 |
MUX0 |
ADC通道已选择 |
0 |
0 |
0 |
0 |
0 |
ADC0 |
0 |
0 |
0 |
0 |
1个 |
ADC1 |
0 |
0 |
0 |
1个 |
0 |
ADC2 |
0 |
0 |
0 |
1个 |
1个 |
ADC3 |
0 |
0 |
1个 |
0 |
0 |
ADC4 |
0 |
0 |
1个 |
0 |
1个 |
ADC5 |
0 |
0 |
1个 |
1个 |
0 |
ADC6 |
0 |
0 |
1个 |
1个 |
1个 |
ADC7 |
- 位5: 用于将结果向右或向左调整。
阿德拉尔 |
描述 |
0 |
正确调整结果 |
1个 |
左调整结果 |
- 位6-7:它们用于选择ADC的参考电压。
REFS1 |
REFS0 |
参考电压选择 |
0 |
0 |
AREF,内部Vref已关闭 |
0 |
1个 |
在AREF引脚上带有外部电容器的AVcc |
1个 |
0 |
已预留 |
1个 |
1个 |
内部2.56基准电压源,AREF引脚处带有外部电容器 |
现在开始在程序中配置这些寄存器位,这样我们就可以读取内部ADC并将其输出到PORTC的所有引脚。
为ADC编程Atmega16
完整的程序如下。使用JTAG和Atmel studio在Atmega16中刻录程序,然后旋转电位计以改变ADC值。在此,逐行解释代码。
首先提供一个功能来读取ADC转换值。然后在 ADC_read 函数 中将 通道值作为 “ chnl” 传递 。
无符号整数ADC_read(unsigned char chnl )
通道值必须在0到7之间,因为我们只有8个ADC通道。
chnl = chnl &0b00000111;
通过向ADMUX寄存器写入“ 40”即“ 01000000”,我们选择PORTA0作为ADC0,在该ADC0上将连接模拟输入以进行数字转换。
ADMUX = 0x40;
现在,此步骤涉及ADC转换过程,通过向ADCSRA寄存器的ADSC位写入ONE,我们开始转换。之后,等待ADIF位在转换完成后返回值。我们通过在ADCSRA寄存器的ADIF位写入1来停止转换。转换完成后,返回ADC值。
ADCSRA-=(1 <
这里,通过将REFS0位置1选择内部ADC参考电压。之后,启用ADC并将预分频器选择为128。
ADMUX =(1 <
现在保存ADC值,并将其发送到PORTC。在PORTC中,连接了8个LED,它们将以8位格式显示数字输出。我们显示的示例使用一个1K电位器在0V至5V之间改变电压。
i = ADC_read(0); PORTC = i;
数字万用表用于显示ADC引脚中的模拟输入电压,并且8个LED用于显示ADC输出的相应8位值。只需旋转电位计,即可在万用表以及发光的LED上看到相应的结果。
完整的代码和工作视频如下。