ATmega16进行多通道AD转换

合集下载

AD转换

AD转换

一、设置ADMUX(AD转换多路选择寄存器)1 参考电源的选择REFS1 REFS0 AREF引脚0 0 接外部参考电源(默认)0 1 内部接通AVCC,外部要求与GND之间并接电容(100nF)1 0 保留1 1 内部接通2.56V,外部要求与GND之间并接电容(100nF)2 对齐方式的选择ADLAR = 0: 右对齐(默认)转换结果如下:ADCH bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0内容 - - - - - - ADC9 ADC8ADCL bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0内容 ADC7 ADC6 ADC5 ADC4 ADC3 ADC2 ADC1 ADC0ADLAR = 1: 左对齐(一般用于不需要大于8位精度时,只读ADCH就可以了)转换结果如下:ADCH bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0内容 ADC9 ADC8 ADC7 ADC6 ADC5 ADC4 ADC3 ADC2ADCL bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0内容 ADC1 ADC0 - - - - - -3 通道号的选择对于MEGA8:MUX3 MUX2 MUX1 MUX0 输入端0 0 0 0 ADC00 0 0 1 ADC10 0 1 0 ADC20 0 1 1 ADC30 1 0 0 ADC40 1 0 1 ADC50 1 1 0 ADC60 1 1 1 ADC71 1 1 0 内部1.22V1 1 1 1 内部0V对于MEGA16:关于差分输入可以通过选择MUX4...0设置放大倍数,因没有做过试验,此处略。

MUX4 MUX3 MUX2 MUX1 MUX0 输入端0 0 0 0 0 ADC00 0 0 0 1 ADC10 0 0 1 0 ADC20 0 0 1 1 ADC30 0 1 0 0 ADC40 0 1 0 1 ADC50 0 1 1 0 ADC60 0 1 1 1 ADC71 1 1 1 0 内部1.22V1 1 1 1 1 内部0V二设置ADCSRA1 转换模式选择对于MEGA8ADFR=1:首次启动转换后,将自动连续转换ADFR=0: 启动一次,转换一次对于MEGA16ADATE=1:首次启动转换后,在触发脉冲上升沿时开始一次转换 ADATE=0:启动一次,转换一次当ADATE=1后,启动转换前先要在SFIOR中设置触发源(当ADATE=0时,设置SFIOR是无效的):ADTS2 ADTS1 ADTS0 触发源0 0 0 自动连续转换0 0 1 模拟比较器0 1 0 外部中断00 1 1 定时器/计数器0比较匹配1 0 0 定时器/计数器0溢出1 0 1 定时器/计数器比较匹配B1 1 0 定时器/计数器1溢出1 1 1 定时器/计数器1捕获事件2 中断/查询方式选择ADIE=1: 转换完成后激活AD中断(当SREG的I位=1时)ADIE=0: 通过查询ADIF标志判断是否完成了一次转换ADIF=1,表示完成了一次转换。

ATmega16进行多通道AD转换

ATmega16进行多通道AD转换

AVR 进行多通道AD转换的设计例子模型AD中断采集完成后切换通道,这样AD触发用定时器触发或者连续采集模式都可以使用。

采样结果用一个数组存起来。

CODE://注意,得到的AD值并非实际的电压,而是0~1024(10位)或0~255(8位)。

#pragma interrupt_handler adc_isr:iv_ADCvoid adc_isr(void){//conversion complete, read value (int) using...#if AD_JINGDU ==10advalue=ADCL; //Read 8 low bits first (important)advalue|=(int)ADCH << 8; //read 2 high bits and shift into top byte#endif#if AD_JINGDU ==8advalue = ADCH;#endifif(SET_ADC==3) SET_ADC=0; //这是多路采集的一个思路SET_ADC++;AD_done=1; //转换完成标识位}[Copy to clipboard]CODE://ICC-AVR application builder : 2007-7-25 10:40:22// Target : M16// Crystal: 7.3728Mhz// 作者:古欣AVR与虚拟仪器[url][/url]// AD转换测试程序#include "config.h"volatile uint8 ADC_Value[]={0x00,0x00,0x00};void main(void){adc_init(SET_ADC); //启动AD,ADC0(PA0)输入DDRB = 0xff;while(1){if(AD_done==1) //AD转换完成标志位{AD_done=0;advalue=(advalue*5000)/1024;//AVCC的实际测得电压乘以1000代替5000,结果转化成了mv,后面的1024取决于#define AD_JINGDU 10,如果使用8位精度,则是256ADC_Value[SET_ADC]=advalue; //SET_ADC从0到2变化,采集三路电压值,存到ADC_Value[0],ADC_Value[1],ADC_Value[2],具体的存放,你自己完成吧//PORTB = advalue; //AD采样结果将在中断中存入advalue//show(ADget_vol();) //显示浮点的实际电压值}}}[Copy to clipboard]压缩包中附一个AD转换测试程序,在硬件上测试通过。

ATmega16之ADC

ATmega16之ADC

§2. A/D转换的基本概念
输入信号量程:指A/D转换器输入信号的最低和最高的电压。 输入信号如果超出范围,则会导致芯片的损坏。ATmega16的 输入信号量程是0-5V的直流电压信号。 基准电源: A/D转换器为量化输入的电压信号,在转换时必须 提供一个基准电压,及基准电源。基准电源的电压值决定可 以转换输入信号的最大值,所以一般等于输入信号的最大值。
ADTS2
初始值 0
ADTS1
0
ADTS0
0
0
位7~位5(ADTS2~ADTS0):ADC转换的触发源。具体的设置见下表:
ADTS2
0 0 0 0 1 1 1 1
ADTS1
0 0 1 1 0 0 1 1
ADTS0
0 1 0 1 0 1 0 1 自由转换模式 模拟比较器 外部中断源0
触发源
定时器/计数器0比较匹配 定时器/计数器0溢出 定时器/计数器比较匹配B 定时器/计数器1溢出 定时器/计数器1输入捕获
§4.2. A/D相关寄存器介绍
控制和状态寄存器-ADCSRA
位 N
0
ADSC
0
ADATE
0
ADIF
0
ADIE
0
ADPS2
0
ADPS1
0
ADPS0
0
位7(ADEN):ADEN = 1,即启动ADC,否则ADC功能关闭。在转换过程 中关闭 ADC将立即中止正在进行的转换。 位6(ADSC):ADC开始转换。 在单次转换模式下, ADSC 置位将启动一次 ADC 转换。 在连续转换模式下, ADSC 置位将启动首次转换。第一次转换 ( 在 ADC 启动之后置位 ADSC,或者在使能 ADC 的同时置位 ADSC) 需要 25 个 ADC 时钟周期,而不是正常情况下的 13 个。第一次转换执行 ADC初始化的工作。在转换进行过程中读取 ADSC 的返回值为 "1”, 直到转换结束。 ADSC 清零不产生任何动作。

实现ATmega16单片机AD键盘与PC机的串口通信并用LCD1602显示程序

实现ATmega16单片机AD键盘与PC机的串口通信并用LCD1602显示程序
平台ATmega16
编程软件CodeVisionAV
实现功能:单片机与PC机(电脑)之间的串口通信。具体就是单片机最小系统上的AD键盘按键按下后发送键值到串口助手上显示,串口助手发送一串字符到最小系统上的lcd1602显示。
(程序或有冗余)
#include <mega16.h>
#include <delay.h>
data=rx_buffer[rx_rd_index]; //读取缓冲队列中的数据
if (++rx_rd_index == RX_BUFFER_SIZE) rx_rd_index=0;
#asm("cli") //关中断
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input | (ADC_VREF_TYPE & 0xff);
delay_us(10);
ADCSRA|=0x40;
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
// USART Receiver buffer:接收器缓冲
#define RX_BUFFER_SIZE 8
char rx_buffer[RX_BUFFER_SIZE];
#if RX_BUFFER_SIZE<256
unsigned char rx_wr_index,rx_rd_index,rx_counter;
#else
unsigned int rx_wr_index,rx_rd_index,rx_counter;
#endif

Atmega16模拟转换

Atmega16模拟转换

例[7-2] 测量与显示PA0引脚上的电压。
输入电压由电位器取5V的分压。电压变化在 0~5V之间,电压大小可滑动电位器来改变。采 用8次平均滤波和一阶滞后滤波。最程变换为: Y=K*X。
程序清单 #include “mega16.h” #include “delay.h” #include “math.h” #include “C:\cvavr\p_dkj\spi_7219.c” float lb,bl; int dy; int zhuanhuan(char tongdaohao) { ADCSRA=0x86 ; •ADMUX=0x40+ tongdaohao ; ADCSRA.6=1 ; while(!ADCSRA.4) ; return ADCW; }
信号滤波 量程变换
信号滤波
在模拟量测量中,因为有噪声干扰和其它干扰, 转换的数据会出现跳变,使显示的数据不稳定。 为了消除干扰,在硬件通道中要加入滤波电路, 在软件中需要采用滤波技术消除干扰。滤波的 方法有很多,这里介绍两种常见的滤波方法。
平均滤波:对一个参数进行连续的多次采样, 然后取其平均值。因为是在很短的时间内进行 的多次采样,对消除高频干扰是较有效的。 一阶滞后滤波:设上个采样周期的测量结果为 Yn-1,本次转换值为xn,滤波系数为α, 0<=α<1,本次的测量结果为Yn,则Yn=α×Yn1+(1-α)×xn。α越大,滤波作用越强。
量程变换
转换的数字与输入的被测量不同,如果直接显示 转换值,将与被测量的信号对应不上,要进行量 程变换。 例如:用某一通道测量温度,当温度为0时,其电 压值为1V;温度为100时,电压值为5V。而通道 经校准,在5V时的转换值为1000,1V时的转换值 为200。为了准确的显示温度值,应按下式进行变 换 Y=100*(X-200)/(1000-200) 式中,X为A/D转换后的值,Y为显示值,上式按 线性比例推算而出。

ADC实验 ATmega16

ADC实验 ATmega16

6.2模数转换的ADC实验 6.2.1、实例功能AVR的模数转换器ADC具有下列特点:110位精度;20.5LSB积分非线形误差3±2LSB的绝对精度;413µs~260µs的转换时间;5在最大精度下可达到每秒15kSPS的采样速率;68路可选的单端输入通道;77路差分输入通道;82路差分输入通道带有可选的10×和200×增益;9ADC转换结果的读取可设置为左端对齐(LEFT ADJUSTMENT);10ADC的电压输入范围0~Vcc;11可选择的内部2.56V的ADC参考电压源;12自由连续转换模式和单次转换模式;13ADC自动转换触发模式选择;14ADC转换完成中断;15休眠模式下的噪声抑制器(NOISE CANCELER)。

在本实例中,我们将编写程序实现将模数转换后获得的电压值通过单片机的串口发送到计算机,然后通过计算机上的串口助手显示测量的电压值。

本实例共有3个功能模块,分别描述如下:●单片机系统:使用单片机的串口实现将模数转换后获得的电压值通过串口发送到计算机。

●外围电路:RS232电平转换电路,DB9串行接口插座,模拟电压输入采集电路。

●软件程序:进一步熟悉单片机的串行通信,并掌握单片机的模数转换的方法。

6.2.2、器件和原理关于串行接口的原理已接单片机与计算机的串口的连接在上一实例中进行了描述,在本实例中不再重复。

本实例只介绍ATmega16单片机如何通过内置的模数转换模块采集外界输入的模拟电压。

1、ATmega16单片机的模数转换器ADC介绍由于单片机只能处理数字信号,所以外部的模拟信号量需要转变成数字量才能进一步的由单片机进行处理。

ATmega16内部集成有一个10位逐次比较(successive approximation)ADC电路。

因此使用AVR可以非常方便的处理输入的模拟信号量。

ATmega16的ADC与一个8通道的模拟多路选择器连接,能够对以PORTA作为ADC输入引脚的8路单端模拟输入电压进行采样,单端电压输入以0V(GND)为参考。

基于ATmega16的AD7705多通道模拟量采集系统设计

基于ATmega16的AD7705多通道模拟量采集系统设计

D R - P 3 串行 数据 输 入端 D N P 5 串行 数 R Y B、 I— B 、
据 输 出端 D U - P 6和 串行 时钟 S L - P 7 O T B CK B。

其导 通 断 开 通 过 P P三 极 管 Q N 1驱 动 , 制 控
信号 为 T 0 二极 管 D D , 1起 续 流 作 用 , 护 电 路 正 保 常工作 同时具有 抑 制尖 峰 干 扰 作用 。通 道 1~3 1 的选择 电路 类 似 , 同理 设 计 模 拟 信 号 输 入 A l~ l
T C 1 = O 0 ; / 动 定 时 器 ,5 CR B x4 / 启 2 6分 频 T M K l BT T I 1 ; / 能 溢 出 中断 IS _ I(OE ) /使 }
定 时器 1溢 出中断 函数 :
v d tme l o f i ( o ) oi i r v s vi r d
w i !(PR & ( hl e( SS 1< <S I ) ) / 待 传 输 PF ) / 等
结 束
} 读 出 A 70 D 7 5数 据 函 数 , 回 值 为 读 出 的 2字 节 数 返
据:
u sg e n d 7 0 vi ) n in d itr_ 7 5( od
T N 1 = 0 3 ; / 时器 1 出 时 间 2 m C TL xB /定 溢 0 s
v i od wr 7 0 ( n i e h r aa 7 5 u s n d c a d t) g
_ _
完成 , 以读 取 ; 2种 是 查 询 通 信 寄 存 器 中 的 可 第 DD R Y位 , 果是 0表示 可 以读 取数 据 : 如
定时器 1 始化 函数 : 初

Atmega16单片机介绍

Atmega16单片机介绍

Atmega16单片机介绍ATmega16是基于增强的AVR RISC结构的低功耗8 位CMOS微控制器。

由于其先进的指令集以及单时钟周期指令执行时间,ATmega16 的数据吞吐率高达1 MIPS/MHz,从而可以缓减系统在功耗和处理速度之间的矛盾。

ATmega16 AVR 内核具有丰富的指令集和32 个通用工作寄存器。

所有的寄存器都直接与算逻单元(ALU) 相连接,使得一条指令可以在一个时钟周期内同时访问两个独立的寄存器。

这种结构大大提高了代码效率,并且具有比普通的CISC 微控制器最高至10 倍的数据吞吐率。

ATmega16 有如下特点:16K字节的系统内可编程Flash(具有同时读写的能力,即RWW),512 字节EEPROM,1K 字节SRAM,32 个通用I/O 口线,32 个通用工作寄存器,用于边界扫描的JTAG 接口,支持片内调试与编程,三个具有比较模式的灵活的定时器/ 计数器(T/ C),片内/外中断,可编程串行USART,有起始条件检测器的通用串行接口,8路10位具有可选差分输入级可编程增益(TQFP 封装) 的ADC ,具有片内振荡器的可编程看门狗定时器,一个SPI 串行端口,以及六个可以通过软件进行选择的省电模式。

工作于空闲模式时CPU 停止工作,而USART、两线接口、A/D 转换器、SRAM、T/C、SPI 端口以及中断系统继续工作;掉电模式时晶体振荡器停止振荡,所有功能除了中断和硬件复位之外都停止工作;在省电模式下,异步定时器继续运行,允许用户保持一个时间基准,而其余功能模块处于休眠状态;ADC 噪声抑制模式时终止CPU 和除了异步定时器与ADC 以外所有I/O 模块的工作,以降低ADC 转换时的开关噪声;Standby 模式下只有晶体或谐振振荡器运行,其余功能模块处于休眠状态,使得器件只消耗极少的电流,同时具有快速启动能力;扩展Standby 模式下则允许振荡器和异步定时器继续工作。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

AVR 进行多通道AD转换的设计例子模型
AD中断采集完成后切换通道,这样AD触发用定时器触发或者连续采集模式都可以使用。

采样结果用一个数组存起来。

CODE:
//注意,得到的AD值并非实际的电压,而是0~1024(10位)或0~255(8位)。

#pragma interrupt_handler adc_isr:iv_ADC
void adc_isr(void)
{
//conversion complete, read value (int) using...
#if AD_JINGDU ==10
advalue=ADCL; //Read 8 low bits first (important)
advalue|=(int)ADCH << 8; //read 2 high bits and shift into top byte
#endif
#if AD_JINGDU ==8
advalue = ADCH;
#endif
if(SET_ADC==3) SET_ADC=0; //这是多路采集的一个思路
SET_ADC++;
AD_done=1; //转换完成标识位
}
[Copy to clipboard]
CODE:
//ICC-AVR application builder : 2007-7-25 10:40:22
// Target : M16
// Crystal: 7.3728Mhz
// 作者:古欣AVR与虚拟仪器[url][/url]
// AD转换测试程序
#include "config.h"
volatile uint8 ADC_Value[]={0x00,0x00,0x00};
void main(void)
{
adc_init(SET_ADC); //启动AD,ADC0(PA0)输入
DDRB = 0xff;
while(1)
{
if(AD_done==1) //AD转换完成标志位
{
AD_done=0;
advalue=(advalue*5000)/1024;//AVCC的实际测得电压乘以1000代替5000,结果转化成了mv,后面的1024取决于#define AD_JINGDU 10,如果使用8位精度,则是256
ADC_Value[SET_ADC]=advalue; //SET_ADC从0到2变化,采集三路电压值,存到
ADC_Value[0],ADC_Value[1],ADC_Value[2],具体的存放,你自己完成吧
//PORTB = advalue; //AD采样结果将在中断中存入advalue
//show(ADget_vol();) //显示浮点的实际电压值
}
}
}
[Copy to clipboard]
压缩包中附一个AD转换测试程序,在硬件上测试通过。

CODE:
//ICC-AVR application builder : 2007-7-25 10:40:22
// Target : M16
// Crystal: 7.3728Mhz
#include <iom16v.h>
#include <macros.h>
#define AD_JINGDU 10
volatile unsigned int value=0;
void port_init(void)
{
PORTA = 0x00;
DDRA = 0x00;
PORTB = 0x00;
DDRB = 0xFF;
PORTC = 0x00; //m103 output only
DDRC = 0x00;
PORTD = 0x00;
DDRD = 0x00;
}
//ADC initialize
// Conversion time: 112uS
void adc_init(void)
{
ADCSR = 0x00; //disable adc
ADMUX = 0x00; //select adc input 0
ACSR = 0x80;
ADCSR = 0xCE;
}
void adc_single_init(unsigned char adc_input)
{
ADCSR = 0x00; //disable adc
#if AD_JINGDU ==10
ADMUX=0xC0|(1<<ADLAR)|adc_input; //2.56V 的片内基准电压源,AREF 引脚外加滤波电容,左对齐,8位精度,AD输入端ADC0
#endif
#if AD_JINGDU == 8
ADMUX=0xC0|adc_input;
#endif
//ADMUX=0x40|adc_input; //AVCC,AREF 引脚外加滤波电容
//ADMUX=adc_input; //AREF,内部Vref 关闭,AREF 引脚外加滤波电容ACSR |= 0x80; //禁用模拟比较器
ADCSR = (1<<ADEN)|(1<<ADSC)|(1<<ADATE)|(1<<ADIE)|0x06; //允许AD,启动转换,自动触发使能,中断使能,64分频
SFIOR &=~ 0xe0;//自动中断源选择,连续转换模式
}
#pragma interrupt_handler adc_isr:iv_ADC
void adc_isr(void)
{
//conversion complete, read value (int) using...
#if AD_JINGDU ==10
value=ADCL; //Read 8 low bits first (important)
value|=(int)ADCH << 8; //read 2 high bits and shift into top byte #endif
#if AD_JINGDU ==8
value = ADCH;
#endif
}
//call this routine to initialize all peripherals void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
port_init();
adc_single_init(0);
MCUCR = 0x00;
GICR = 0x00;
TIMSK = 0x00; //timer interrupt sources SEI(); //re-enable interrupts
//all peripherals are now initialized
}
void main(void)
{
init_devices();
while(1)
{
PORTB = value;
}
}。

相关文档
最新文档