原创 【ATMEGA16L】实验三十:ADC实验

2009-8-14 09:39 4674 12 14 分类: MCU/ 嵌入式

》》点此进入      http://bbs.armavr.com/   ARM-AVR嵌入式开发论坛 


       今天对ADC模块进行了深入学习和实践验证,对ATMEGA16L的2.56V片内基准电压源存在疑问:为什么实际测得值是2.633V,误差似乎太大了,并且以此做为基准时,ADC转换结果不稳定,有较大波动。因此,我推断ATMEGA16L的2.56V片内基准电压源有较大跳变,并因此导致ADC转换结果有较大波动一、硬件电路:


a93f73bf-cb2a-48a4-be32-55998f47ec16.jpg


二、程序结构:


0ee61338-b592-4de0-bdeb-de219fd5b1c5.jpg


三、程序源代码


1、main.c


/*******************************************************************************
Platform: AVR mega16学习板(www.iccavr.com
Project : 实验三十:ADC实验
Clock F : 3.6864MHz
Software: ICCAVR7.14C
Author  : 林夕依然
Version : 09.03.24
Updata  :
comments:
1、串口发送命令开启一次ADC,并将结果通过串口发送到PC,任意字符开始;
2、USART使用中断方式接收数据,当接收到数据后,开启一次ADC转换;
3、当ADC转换完成后产生中断,并置一个自定义的标志;
4、对ADC转换完成后的中断标志进行检测,为1时则将ADC转换数据发送给PC;
5、采用单通道AVCC外部参考源和2.56V 的片内基准电压源两种方式;
5、参考:D:\mcu\ICCAVR学习板\旧版例程\7-ADC
problem :
1、2.56V 的片内基准电压源实测值在ADC0/ADC1通道时均为2.633V,误差较大,
   可能是造成ADC转换电压不稳定的主要原因。
*******************************************************************************/
#include <iom16v.h>
#include <macros.h>
#define uchar unsigned char


uchar AdcData;                       //ADC转换的结果
uchar AdcConCom = 0;     //ADC转换完成标志
/*-----------------------------------------------------------------
函数名称: void AdcInit(void)
函数功能: ADC初始化
参    数:
返 回 值: 无
-----------------------------------------------------------------*/
void AdcInit(void)
{
 ADCSR = 0x00;  //ADC关闭
 ADMUX = 0x67;  //外部参考源AVCC,左对齐,选择ADC7通道
 //ADMUX = 0xE0;  //2.56V 的片内基准电压源,左对齐,选择ADC0通道
 //ADMUX = 0xE1;  //2.56V 的片内基准电压源,左对齐,选择ADC1通道
 ACSR =  0x80;  //模拟比较器控制和状态寄存器ACSR的ACD置1,使模拟比较器禁用
 ADCSR = 0x8B;  //开启ADC,8分频,ADC中断使能
}
/*-----------------------ADC转换中断程序--------------------------------------*/
#pragma interrupt_handler adc_isr:15
void adc_isr(void)
{
 AdcData= ADCH; //读ADC转换结果,只读高8位,即8位精度,此种情况Vin=(AVCC/256)*ADC 
 AdcConCom = 1; //置ADC转换完成标志
}
/*-----------------------------------------------------------------
函数名称: void InitDevices(void)
函数功能: 初始化各种信息
参    数:
返 回 值: 无
-----------------------------------------------------------------*/
void InitDevices(void)
{
  CLI();           //关全部中断
  Usart_init03();                     //中断方式初始化
 AdcInit();


  MCUCR = 0x00;
  SEI();              //开全中断
}


void main(void)
{
 InitDevices();
  while(1)
 {
   if(AdcConCom)
  {
    AdcConCom = 0;    //清ADC转换完成标志
   USART_Transmit(AdcData);   //发送转换结果
  }
 }
}


/************************模拟比较器控制和状态寄存器ACSR************************
ACD    模拟比较起禁用
ACBG   模拟比较器的能隙基准源
ACO    模拟比较起输出
ACI    模拟比较器中断标志
ACIE   模拟比较器中断使能
ACIC   模拟比较器输入捕捉使能
ACIS1  模拟比较器中断模式选择
ACIS0
*******************************************************************************/


/*************************ADC控制和状态寄存器A-ADCSRA**************************
             ADEN   ADSC  ADATE   ADIF   ADIE  ADPS2  ADPS1  ADPS0
 ADEN      ADC使能模数转换
 ADSC      ADC开始转换
 ADATE     ADC自动触发使能
 ADIF      ADC 中断标志
 ADIE      ADC中断使能
 ADPS2     ADC 预分频器选择位
 ADPS1
 ADPS0
 *****************************************************************************/
/***********************************测试*************************************
1、ADMUX = 0x67;  //外部参考源AVCC,左对齐,选择ADC7通道
   AdcData= ADCH; //读ADC转换结果,只读高8位,即8位精度,此种情况Vin=(AVCC/256)*AdcData
   1)将RW2分得电压为3.92V接在ADC7上,用万用表测得AVCC=5.02V
      用串口助手接收AdcData的值为C7(图1),即十进制199,经计算:Vin=5.02/256*199=3.902265625V
      据此可验证串口助手接收到的数据是准确的。
   2)将RW2分得电压为4.71V接在ADC7上,用万用表测得AVCC=5.02V
      用串口助手接收AdcData的值为F0(图2),即十进制240,经计算:Vin=5.02/256*240=4.70625V
      据此可验证串口助手接收到的数据是准确的。
  
2、ADMUX = 0xE1;  //2.56V 的片内基准电压源,左对齐,选择ADC1通道
   AdcData= ADCH; //读ADC转换结果,只读高8位,即8位精度,此种情况Vin=(AREF/256)*AdcData
   1)将RW2分得电压为1.008V接在ADC1上,用万用表测得AREF=2.633V,并非手册上的2.56V,有较大偏差
      用串口助手接收AdcData的值不确定(图3),而由:1.008=2.633/256*AdcData计算得AdcData=98,即二进制62才对
   2)将通道换为ADC0,现象同上。
      据上可推知,有可能ATMEGA16L内部基准电压误差太大。
*****************************************************************************/


2、function.c


#include <iom16v.h>
#include <macros.h>
#define uchar unsigned char


#define F_CPU 3686400


/*-----------------------------------------------------------------
函数名称: void Usart_init01(void)
函数功能: 串口初始化方式01(波特率设置用查表)
    波特率 9600 0.2% ,8bit,异步,倍速,无奇偶校验,1个停止位
参    数:
返 回 值: 无
-----------------------------------------------------------------*/
void Usart_init01(void)       //初始化串口方式1
{
  UCSRA="0X02";                 //倍速选择
  UCSRB=(1<<RXEN)|(1<<TXEN);  //使能接收,发送
  UCSRC=(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);//8bit,异步,无奇偶校验,1个停止位
  UBRR="47"; //9600波特率,见M16_cn中文P155:Table68-72通用振荡器频率下设置 UBRR                    
}
/*-----------------------------------------------------------------
函数名称: void Usart_init02(void)
函数功能: 串口初始化方式02(波特率设置用公式)
    波特率 9600 0.2% 8bit,异步,常速,无奇偶校验,2个停止位
参    数:
返 回 值: 无
-----------------------------------------------------------------*/
void Usart_init02( unsigned int baud )//初始化串口方式2,并设置波特率
{
unsigned int tmp;
tmp= F_CPU/baud/16-1;        //设置波特率,见M16_cn中文P135:Table60波特率计算公式
UBRRH = (unsigned char)(tmp>>8);
UBRRL = (unsigned char)tmp;
UCSRB = (1<<RXEN)|(1<<TXEN); //接收器与发送器使能
UCSRC = (1<<URSEL)|(1<<USBS)|(1<<UCSZ0)|(1<<UCSZ1);//异步,8bit,2停止位,无奇偶校验
}
/*-----------------------------------------------------------------
函数名称: void Usart_init03(void)
函数功能: 串口初始化方式03(中断方式接收)
    波特率 9600 0.2%,8bit,异步,倍速,无奇偶校验,1个停止位
参    数:
返 回 值: 无
-----------------------------------------------------------------*/
void Usart_init03(void)
{
  UCSRB = 0x00;             //关串口
  UCSRA = 0x02;            //倍速模式   M16中文P151
  UCSRC = BIT(URSEL) | 0x06;         //写UCSRC寄存器,设定8个bit,1停止位,异步
  UBRR  = 47;                      //设定串口波特率为9600
  UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);//使能接收结束中断,使能收发
}


#pragma interrupt_handler UartRecvData:12
void UartRecvData(void)
{
  uchar temp;
 temp = UDR;
 ADMUX |= (1<<MUX2)|(1<<MUX1)|(1<<MUX0); //选择ADC7通道
 ADCSRA|= (1<<ADSC);              //开启一次ADC转换
}


/*-----------------------------------------------------------------
函数名称: void USART_Transmit( unsigned char data )
函数功能: 数据发送【发送5 到8 位数据位的帧】
参    数:
返 回 值: 无
说    明:直接从数据手册上拷贝过来的
-----------------------------------------------------------------*/
void USART_Transmit( unsigned char data )
{
while ( !( UCSRA & (1<<UDRE)) ) ;  //等待发送缓冲器为空
UDR = data;                        // 将数据放入缓冲器,发送数据
}
/*-----------------------------------------------------------------
函数名称: unsigned char USART_Receive( void )
函数功能: 数据接收【以5 到8 个数据位的方式接收数 据帧】
参    数:
返 回 值: UDR
说    明:直接从数据手册上拷贝过来的
-----------------------------------------------------------------*/
unsigned char USART_Receive( void )
{
while ( !(UCSRA & (1<<RXC)) );  // 等待接收数据
return UDR;                     // 从缓冲器中获取并返回数据
}
/*-----------------------------------------------------------------
函数名称: void USART_Transmits01( void )
函数功能: 连续发送字符"Hello"
参    数:
返 回 值:
-----------------------------------------------------------------*/
void USART_Transmits01( void )
{
while ( !( UCSRA & (1<<UDRE)) );
UDR = 'H';
while ( !( UCSRA & (1<<UDRE)) );
UDR = 'e';
while ( !( UCSRA & (1<<UDRE)) );
UDR = 'l';
while ( !( UCSRA & (1<<UDRE)) );
UDR = 'l';
while ( !( UCSRA & (1<<UDRE)) );
UDR = 'o';
}


/*-----------------------------------------------------------------
函数名称: void USART_Transmits02(unsigned char *ptr)
函数功能: 字符串的操作
参    数:
返 回 值:
说    明:未能过验证
-----------------------------------------------------------------*/
void USART_Transmits02(unsigned char *ptr)//字符串
{
   while (*ptr)
   {
       USART_Transmit(*ptr);
       *ptr++;
   }
   newline();
}


void newline()   //换行
{
   USART_Transmit(0x0d);  //发送一个回车
   USART_Transmit(0x0a);  //发送一个换行
}


void blank()    //空格
{
   USART_Transmit(0x20); 
}



/************************************************
  UMSEL  模式选择
    0    异步操作
    1    同步操作


  USBS 停止位位数
    0     1
    1     2


  UCSZ2 UCSZ1 UCSZ0 字符长度
    0     0     0     5 位
    0     0     1     6 位
    0     1     0     7 位
    0     1     1     8 位
    1     0     0     保留
    1     0     1     保留
    1     1     0     保留
    1     1     1     9 位
*************************************************/


四、附图


图1:


48fd909b-a951-4d68-aa6d-cab53a911e6f.jpg


图2:


7a353771-5712-4949-a3b0-34ab26316366.jpg


图3:


a943d7fd-27a2-4388-8207-5864b31c27ce.jpg


点此进入:AVR单片机小组


        AVR单片机小组,以ICCAVR为编译平台,以资源共享、经验交流为主旨,以共同进步和提高为目标。期待志同道合的朋友加入!


【相关实验】


实验一:流水灯实验(八种LED点亮模式)


实验二:有源蜂鸣器驱动实验


实验三:按键扫描(用KEY选择对应LED点亮)


实验四:键盘扫描+8种LED亮灭模式控制


实验二四:四线制LCD1602B驱动实验        


实验二五:八线制LCD1602B驱动实验


实验二八:USART综合实验


实验二九:模拟比较器实验

文章评论2条评论)

登录后参与讨论

xucun915_925777961 2009-3-26 12:42

好,不错,学习学习……

用户174125 2009-3-26 10:35

111
相关推荐阅读
用户1400544 2012-09-24 08:55
【分享】ATmega16学习笔记PDF完整版下载(WinAVR)
  笔记均为原创,欢迎转载,转载请注明出处!   笔记1:8种LED点亮模式_GCC.pdf 笔记2:有源蜂鸣器驱动实验_GCC.pdf 笔记3:按键扫描(用KEY选择对应LED...
用户1400544 2011-01-19 23:26
博主邀请您:加入千脑,拥有“我的在线电脑”
点击加入千脑,拥有“我的在线电脑”在线电脑随时随地可用,安全可靠您可能遇到以下情况: 用户场景一:        我是一个集团公司的企业白领,经常负责写些策划书,制作各类表格等,有时候上班时间做不完就...
用户1400544 2010-04-07 00:43
ATmega16_Basic_V1.1范例2:8种LED点亮模式(ICC)
一、程序结构二、程序源码1、main.c /******************************************************************************...
用户1400544 2010-04-07 00:22
ATmega16_Basic_V1.1范例1:LED流水灯(ICC)
一、程序结构二、程序源码1、main.c /******************************************************************************...
用户1400544 2010-03-30 14:39
Altium Designer 6原理图元件库大全(7个种类)
》》点此进入      http://bbs.armavr.com/   ARM-AVR嵌入式开发论坛       ARM-AVR嵌入式开发论坛推出【Altium Designer 6 原理图元件库大...
用户1400544 2010-03-30 14:39
protel99原理图元件库大全(8个种类)
》》点此进入      http://bbs.armavr.com/   ARM-AVR嵌入式开发论坛       ARM-AVR嵌入式开发论坛推出【protel99原理图元件库大全(8个种类)】,共...
我要评论
2
12
关闭 站长推荐上一条 /2 下一条