》》点此进入 http://bbs.armavr.com/ ARM-AVR嵌入式开发论坛
ARM-AVR嵌入式开发论坛,专为AVR单片机初学者而建,以资源共享、经验交流为主旨,以共同进步和提高为目标。期待志同道合的朋友加入!
【相关实验】
【ATMEGA16L】实验一:流水灯实验(八种LED点亮模式)
【ATMEGA16L】实验三:按键扫描(用KEY选择对应LED点亮)
【ATMEGA16L】实验四:键盘扫描+8种LED亮灭模式控制
【ATMEGA16L】实验二四:四线制LCD1602B驱动实验
【ATMEGA16L】实验二五:八线制LCD1602B驱动实验
*********************************************************************
09年3月25日发表的日志:【ATMEGA16L】实验三十:ADC实验 “对ATMEGA16L的2.56V片内基准电压源存在疑问:为什么实际测得值是2.633V,误差似乎太大了,并且以此做为基准时,ADC转换结果不稳定,有较大波动。”
的表述是不正确的,今天发现程序有问题:function.c中void UartRecvData(void)中断函数对ADC通道进行重复配置,以致于main.c中void AdcInit(void)对ADC通道的配置失效。改正后验证通过,证明了2.56V片内基准电压源可以作为ADC的基准来使用。误导了大家,请见谅!
修改后的完整程序如下:
**********************************************************************
一、硬件电路:
二、程序结构:
三、程序源代码
1、main.c
/*******************************************************************************
Platform: AVR mega16学习板(www.iccavr.com)
Project : 实验三十:ADC实验
Clock F : 3.6864MHz
Software: ICCAVR7.14C
Author : 林夕依然
Version : 09.03.24
Updata : 09.04.01 确认2.56V片内基准可用
comments:
1、串口发送命令开启一次ADC,并将结果通过串口发送到PC,任意字符开始;
2、USART使用中断方式接收数据,当接收到数据后,开启一次ADC转换;
3、当ADC转换完成后产生中断,并置一个自定义的标志;
4、对ADC转换完成后的中断标志进行检测,为1时则将ADC转换数据发送给PC;
5、采用单通道AVCC外部参考源和2.56V 的片内基准电压源两种方式;
6、不用去管ADC转换结果的进制,这是由编译器完成的。转换得到的结果也不用管,是由单
片自己完成的。
7、参考:D:\mcu\ICCAVR学习板\旧版例程\7-ADC
problem :
1、2.56V 的片内基准电压源实测值为2.634V,误差0.07V.
*******************************************************************************/
#include <iom16v.h>
#include <macros.h>
#define uchar unsigned char
#define uint unsigned int
uchar AdcData; //ADC转换的结果
uchar AdcConCom = 0; //ADC转换完成标志
/*-----------------------------------------------------------------
函数名称: void AdcInit(void)
函数功能: ADC初始化
参 数:
返 回 值: 无
-----------------------------------------------------------------*/
void AdcInit(void)
{
ADCSR = 0x00; //ADC关闭
//ADMUX = 0x67; //外部参考源AVCC,左对齐,选择ADC7通道
//ADMUX = 0xE7; //2.56V 的片内基准电压源,左对齐,选择ADC7通道
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); //向PC发送转换结果
}
}
}
/************************模拟比较器控制和状态寄存器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,即十进制199,经计算:Vin=5.02/256*199=3.902265625V
据此可验证串口助手接收到的数据是准确的。
2)将RW2分得电压为4.71V接在ADC7上,用万用表测得AVCC=5.02V
用串口助手接收AdcData的值为F0,即十进制240,经计算:Vin=5.02/256*240=4.70625V
据此可验证串口助手接收到的数据是准确的。
2、ADMUX = 0xE7; //2.56V 的片内基准电压源,左对齐,选择ADC7通道
AdcData= ADCH; //读ADC转换结果,只读高8位,即8位精度,此种情况Vin=(AREF/256)*AdcData
1)将RW2分得电压为1.018V接在ADC1上,用万用表测得AREF=2.634V,并非手册上的2.56V,有0.07V偏差
用串口助手接收AdcData的值为62,即十进制98,经计算:Vin=2.634/256*98=1.008V
据此可验证串口助手接收到数据是准确的。
2)将通道换为ADC0,结果同上。
*****************************************************************************/
2、function.c
#include <iom16v.h>
#include <macros.h>
#define uchar unsigned char
#define uint unsigned int
#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;
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 *str)
函数功能: 发送字符串(方法一)
参 数: str 发送字符串的首地址
返 回 值:
说 明:已通过验证,str必须定义为指针,调用时只需指针名即可
例 如:定义指针 uchar *buffer0="2009年03月26日23:40";
调用函数 USART_Transmits02(buffer0); 即可
-----------------------------------------------------------------*/
void USART_Transmits02(unsigned char *ptr)//字符串
{
while (*ptr)
{
USART_Transmit(*ptr);
*ptr++;
}
newline();
}
/*-----------------------------------------------------------------
函数名称: void USART_Transmits03(uchar *str, uint len)
函数功能: 发送字符串(方法二)
参 数: str 发送字符串的首地址
len 发送字符串的长度
返 回 值:
说 明:已通过验证,str必须定义为指针,调用时只需指针名即可
例 如:定义指针 uchar *buffer0="2009年03月26日23:40";
调用函数 USART_Transmits03(buffer0,19); 即可
-----------------------------------------------------------------*/
void USART_Transmits03(uchar *str,uint len)
{
uint i;
for( i = 0; i < len; i++)
{
while ( !( UCSRA & (1<<UDRE)) ); //等待发送缓冲器为空
UDR = str;
}
}
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 位
*************************************************/
文章评论(0条评论)
登录后参与讨论