概述
9、ADC
在将ADC之前,先聊聊其前因后果——由于计算机在自动控制、检测以及其他领域广泛应用数字电子技术,而大自然的信号全是模拟信号,如果通过计算机保存自然信号呢?那么就需要ADC(模数转换器Analog-Digital Converter)来讲模拟信号转换为数字信号,这样才能存储到计算机中。
那么ADC是如何转换的呢?
l首先对选定一个瞬间对模拟信号进行采样;
l然后将值转换为数字量;
l最后按照一定编码格式转换。
—>
一个模拟信号肯定是不能采样一个点的,而是许多点集合而成。当长方形又窄又长时几乎接近竖线时,就可以很好的还原之前的波形了。
用官方的话说:抽样定理——若原图的最大频率是fmax,那么采样频率要比原图的最大频率2倍还要大,这样才能准备无误的还原原来的波形。
如图,0-1V是连续的电压量,而0-0.125V被当做0△,那么就会存在最小误差△;接着通过一定的编码方式转换,如二进制、八进制、十六进制等。
至于ADC的转换过程如何,可以通过网上的介绍来深入了解。现在我们来看看AVR的ADC特点以及如何操作。
ATmega16单片机内部自带ADC,不需要外部ADC芯片来转换。其主要特点是:
l10位精度的逐次逼近型ADC,±2LSB的绝对精度
l65-260us的转换时间
l最高分辨率时采样率高达15kSPS
l8路复用的单端输入通道
l0-AVcc的ADC输入电压范围,包括内部2.56V参考电压
l支持连续转换或单词转换模式
l可触发ADC中断
再来看看ADC时序图——连续转换
可以发现前面13个时钟周期是没有采集的,主要是为了初始化模拟电路。ADC的转换结果为——ADC=Vin*1024/Vref,Vin是ADC通道的输入电压,Vref是参考电压。
下面开始介绍ADC的主要寄存器:
ADMUX(多工选择寄存器):
6-7位:用来设置参考电压是内部、外部还是都要,具体如下图
第5位:ADC转换结果左对齐,主要影响ADC值在寄存器中存放形式;
0-4位:用来选择ADC通道
本案例使用的是外部AVcc参考电压,以及通道0,右对齐,所以ADMUX = 0x00。
ADCSRA(控制和状态寄存器):
7位:ADC使能位;
6位:ADC开始转换位;
5位:ADC自动触发使能,启动自动触发,触发信号的上升沿驱动转换;
4位:ADC中断标志,在ADC转换结束后,ADIF置位,需要软件清零;
0-2位:ADC预分频器选择。
最后还有一个老朋友——SFIOR寄存器(设置过IO是否上拉)
5-7位:这3位的设置是当ADCSRA中的ADATE位置1才有效,被选中的中断在上升沿时触发ADC转换(本案例例程不做该功能,了解一下)。
现开始代码讲解:
初始化ADC,选择通道,分频128,并使能即可。
采集ADC值,开启转换,等待转换完毕,清零标志位,得到ADC值。
最后将采集的值通过公式转换为电压即可。
仿真视频
/**
******************************************************************************
* @file main.c
* @author Alex——小白
* @version V1.0
* @date 2021.1.20
* @brief 头文件调用,类型重定义
* @store Proteus仿真店子——公众号
* @Link https://shop484534014.taobao.com/
* @Email 844545015@qq.com
******************************************************************************
* @attention All Rights Reserved
**/
#include <main.h>
/*
Touch Pad的步进值为0.5V,即10档
这里将电压放大100倍,便于数据处理
*/
void main(void)
{
uint16_t adcValue = 0;
uint16_t vol = 0;
uint8_t cnt = 0;
DDRB_DDB3 = 1;
AD.ADC_Init(0); //ADC通道0
LCD.LCD1602_Init();
LCD.LCD1602_WriteStr(0,2,"ADC:");
LCD.LCD1602_WriteStr(1,2,"Vol:");
Delay.Delay_ms(1000);
while(1)
{
adcValue = AD.ADC_GetValue(); //ADC数据采集
vol = (uint16_t)(adcValue * 5.0 * 100 / 1024); //放大100倍
LCD.LCD1602_WriteChar(0,8,adcValue/1000 + '0');
LCD.LCD1602_WriteChar(0,9,adcValue%1000/100 + '0');
LCD.LCD1602_WriteChar(0,10,adcValue%1000%100/10 + '0');
LCD.LCD1602_WriteChar(0,11,adcValue%1000%100%10 + '0');
LCD.LCD1602_WriteChar(1,8,vol/100 + '0');
LCD.LCD1602_WriteChar(1,9,'.');
LCD.LCD1602_WriteChar(1,10,vol%100/10 + '0');
LCD.LCD1602_WriteChar(1,11,vol%100%10 + '0');
if(vol > 250) //实际电压值>2.5V时,蜂鸣器报警
{
for(cnt = 0;cnt < 80;cnt++)
{
PORTB_PORTB3 = 0;
Delay.Delay_us(2);
PORTB_PORTB3 = 1;
Delay.Delay_us(2);
}
}
}
}
/********************************************************
End Of File
********************************************************/
如需Proteus和IAR安装包以及AVR编程参考手册,请关注公众号:
Proteus仿真店子
可通过查看历史记录,查看源码和仿真工程
(若需Proteus和IAR安装包以及AVR编程参考手册,后台回复:AVR;若需其它设计,后台回复:AVR设计)
最后
以上就是苹果可乐为你收集整理的ATmega16开发板教程(8)——ADC的全部内容,希望文章能够帮你解决ATmega16开发板教程(8)——ADC所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复