我是靠谱客的博主 苹果可乐,最近开发中收集的这篇文章主要介绍ATmega16开发板教程(8)——ADC,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

​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所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(51)

评论列表共有 0 条评论

立即
投稿
返回
顶部