概述
转
6.2 模数转换的ADC实验 在本实例中,我们将编写程序实现将模数转换后获得的电压值通过单片机的串口发送到计算机,然后通过计算机上的串口助手显示测量的电压值。
6.2.2、器件和原理
1、ATmega16单片机的模数转换器ADC介绍
2、ATmwga16单片机的模数转换器ADC相关的I/O寄存器
- 位7,6—REFS[1:0]:ADC参考电源选择
REFS1、REFS2用于选择ADC的参考电压源,见表6.2.1。如果这些位在ADC转换过程中被改变,新的选择将在该次ADC转换完成后(ADCSRA中的ADIF被置位)才生效。一旦选择内部参考源(AVcc、2.56V)为ADC的参考电压后,AREF引脚上不得施加外部的参考电源,只能与GND之间并接抗干扰电容。
REFS1 | REFS0 | ADC参考电源 |
0 | 0 | 外部引脚AREF,断开内部参考源连接 |
0 | 1 | AVcc,AREF外部并接电容 |
1 | 0 | 保留 |
1 | 1 | 内部2.56V,AREF外部并接电容 |
- 位5—ADLAR:ADC结果左对齐选择
ADLAR位决定转换结果在ADC数据寄存器中的存放形式。写“1”到ADLAR位,将使转换结果左对齐(LEFT ADJUST);否则,转换结果为右对齐(RIGHT ADJUST)。无论ADC是否正在进行转换,改变ADLAR位都将会立即影响ADC数据寄存器。
- 位4..0—MUX4:0:模拟通道和增益选择
这5个位用于对连接到ADC的输入通道和差分通道的增益进行选择设置,详见表6.2.2。注意,只有转换结束后(ADCSRA的ADIF是“1”),改变这些位才会有效。
MUX[4:0] | 单端输入 | 差分正极输入 | 差分负极输入 | 增益 |
00000 | ADC0 | N/A | ||
00001 | ADC1 | |||
00010 | ADC2 | |||
00011 | ADC3 | |||
00100 | ADC4 | |||
00101 | ADC5 | |||
00110 | ADC6 | |||
00111 | ADC7 | |||
01000 | N/A | ADC0 | ADC0 | 10× |
01001 | ADC1 | ADC0 | 10× | |
01010 | ADC0 | ADC0 | 200× | |
01011 | ADC1 | ADC0 | 200× | |
01100 | ADC2 | ADC2 | 10× | |
01101 | ADC3 | ADC2 | 10× | |
01110 | ADC2 | ADC2 | 200× | |
01111 | ADC3 | ADC2 | 200× | |
10000 | ADC0 | ADC1 | 1× | |
10001 | ADC1 | ADC1 | 1× | |
10010 | ADC2 | ADC1 | 1× | |
10011 | ADC3 | ADC1 | 1× | |
10100 | ADC4 | ADC1 | 1× | |
10101 | ADC5 | ADC1 | 1× | |
10110 | ADC6 | ADC1 | 1× | |
10111 | ADC7 | ADC1 | 1× | |
11000 | ADC0 | ADC2 | 1× | |
11001 | ADC1 | ADC2 | 1× | |
11010 | ADC2 | ADC2 | 1× | |
11011 | ADC3 | ADC2 | 1× | |
11100 | ADC4 | ADC2 | 1× | |
11101 | ADC5 | ADC2 | 1× | |
11110 | 1.22V(VBG) | N/A | ||
11111 | 0V(GND) |
本实例中我们需要设置ADC的参考电压源为AVcc,即REFS0设置为1,ADC默认转换结果为右对齐,我们不需要改变,模拟通道选择ADC0通道单端输入,即MUX4:0。
- 位7—ADEN:ADC使能
该位写入“1”时使能ADC,写入“0”关闭ADC。如在ADC转换过程中将ADC关闭,该次转换随即停止。
- 位6—ADSC:ADC转换开始
在单次转换模式下,置该位为“1”,将启动一次转换。在自由连续转换模式下,该位写入“1”将启动第一次转换。先置位ADEN位使能ADC,再置位ADSC;或置位ADSC的同时使能ADC,都会使能ADC开始进行第一次转换。第一次ADC转换将需要25个ADC时钟周期,而不是常规转换的13个ADC时钟周期,这是因为第一次转换需要完成对ADC的初始化。
- 位5—ADATE:ADC自动转换触发允许
当该位被置为“1”时,允许ADC工作在自动转换触发工作模式下。在该模式下,在触发信号的上升沿时ADC将自动开始一次ADC转换过程。ADC的自动转换触发信号源由SFIOR寄存器中的ADTS位选择确定。
- 位4—ADIF:ADC中断标志位
当ADC转换完成并且ADC数据寄存器被更新后该位被置位。如果ADIE位(ADC转换结束中断允许)和SREG寄存器中的I位被置“1”,ADC中断服务程序将被执行。ADIF在执行相应的中断处理向量时被硬件自动清零。此外,ADIF位可以通过写入逻辑“1”来清零。
- 位3—ADIE:ADC中断允许
当该位和SREG寄存器中的I位同时被置位时,允许ADC转换完成中断。
- 位2,0—ADPS[2:0]:ADC预分频选择
这些位决定了XTAL时钟与输入到ADC的ADC时钟之间分频数,见表6.2.3。
表6.2.3 ADC时钟分频 | |
ADPS[2:0] | 分 频 系 数 |
000 | 2 |
001 | 2 |
010 | 4 |
011 | 8 |
100 | 16 |
101 | 32 |
110 | 64 |
111 | 128 |
本实例中我们需要使能ADC,即ADEN设置为1,我们不用自动转换,也不需要中断,所以,ADTE、ADIE位不需要设置。在通常情况下,ADC的逐次比较转换电路要达到最大精度时,需要50kHz~200kHz之间的采样时钟。本例中使用的时钟是12M的,所以要将时钟64分频,分频后ADC频率为188KHz,即时钟分频选择ADPS[2:0]=6。
3.ADC数据寄存器—ADCL和ADCH
- ADLAR = 0,ADC转换结果右对齐时,ADC结果的保存方式
- ADLAR = 1,ADC转换结果左对齐时,ADC结果的保存方式
- 位7..5—ADTS[2:0]:ADC自动转换触发源选择
当ADCSRA寄存器中的ADATE为“1”,允许ADC工作在自动转换触发工作模式时,这3位的设置用于选择ADC的自动转换触发源。如果禁止了ADC的自动转换触发(ADATE为“0”),这3个位的设置值将不起任何作用。
表10-6 ADC自动转换触发源的选择 | |
ADTS[2:0] | 触 发 源 |
000 | 连续自由转换 |
001 | 模拟比较器 |
010 | 外部中断0 |
011 | T/C0比较匹配 |
100 | T/C0溢出 |
101 | T/C1比较匹配B |
110 | T/C1溢出 |
111 | T/C1输入捕捉 |
本例中我们不使用自动转换功能,所以该寄存器可以不必设置。
6.2.3、电路
1、电路原理
2、电路连接
是交叉串口线,而不是串口延长线。
2、 单片机与计算机串行通信结果的观察
3、函数说明
注意是晶振,不是外部振荡器,一定不要选择错了,否则会导致单片机不能再烧写程序)。
#include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> //中断函数头文件
//常量声明 #define BAUD 9600 //波特率设置值
//全局变量声明 unsigned int ADData; //AD转换获得的数据
//函数声明 void Port_Init(void); //端口初始化配置 void Usart_Init(void); //USART寄存器设置 void AD_Init(void); //AD初始化 void Usart_PutChar(unsigned char cTXData); //字节发送函数 void Usart_PutString(unsigned char *pcString); // 字符串发送数据 unsigned int AD_GetData(void); //AD转换函数
int main(void) { unsigned char Delay3s;
Port_Init(); Usart_Init(); AD_Init(); Usart_PutString("AD转换测试程序"); Usart_PutString("测得ADC0通道的电压值为:"); sei(); //使能全局中断 while(1) { ADData = (int)((long)AD_GetData() * 5010 / 1024); //将获得的AD值转换为电压值 //单位为mv。 Usart_PutChar(ADData / 1000 + 0x30); //得到电压值的千位并发送 Usart_PutChar('.'); //发送小数点 Usart_PutChar(ADData % 1000 / 100 + 0x30); //得到电压值的百位并发送 Usart_PutChar(ADData % 100 / 10 + 0x30); //得到电压值的十位并发送 Usart_PutChar(ADData % 10 + 0x30); //得到电压值的个位并发送 Usart_PutChar('V'); //发送电压符号“V” Usart_PutChar(0x0d); // Usart_PutChar(0x0a); // AD值发送结束,回车换行 for(Delay3s = 0;Delay3s < 30;Delay3s++) //延时3S { _delay_ms(90); } } }
//端口状态初始化设置函数 void Port_Init() { PORTA = 0X00; DDRA = 0x00; //ADC通道设置为输入口,高阻态 }
//USART寄存器配置函数 void Usart_Init() { UCSRA = 0X00; UCSRC |= (1<<URSEL) | (1 << UCSZ1) | (1 << UCSZ0); //异步,数据格式8,N,1 //UCSRC寄存器与UBRRH寄存器共用相同的I/O地址,写 UCSRC 时, URSEL 应设置为 1。 UBRRL = (F_CPU / BAUD / 16 - 1) % 256; //波特率设置 UBRRH = (F_CPU / BAUD / 16 - 1) / 256; UCSRB |= (1 << RXCIE) | (1 << RXEN) | (1 << TXEN); //发送使能 }
//字节发送函数 void Usart_PutChar(unsigned char cTXData) { while( !(UCSRA & (1 << UDRE)) ); //只有数据寄存器为空时才能发送数据 UDR = cTXData; //发送数据送USART I/O数据寄存器-UDR }
//接收中断函数 ISR(USART_RXC_vect ) { unsigned char Rev; Rev = UDR; //从USART I/O数据寄存器-UDR中读出数据 Usart_PutChar(Rev); //将接收到的数据发送 }
void Usart_PutString(unsigned char *pcString) { while (*pcString) { Usart_PutChar(*pcString++); } Usart_PutChar(0x0D); Usart_PutChar(0x0A); //结尾发送回车换行 }
//AD转换初始化函数 void AD_Init() { ADMUX |= (1 << REFS0); //ADC参考电压为AVcc,ADC结果右对齐,选择通道ADC0 ADCSRA |= (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1); //使能AD转换,ADC时钟64分频 }
//AD转换函数 unsigned int AD_GetData() { ADCSRA |= (1 << ADSC); //开始AD转换 while(!(ADCSRA & (1 << ADIF))); //等待转换完成 ADCSRA |= (1 << ADIF); //清零ADC中断标志位 return ADC; //返回ADC值 }
附录:ADC应用设计要点
1.预分频与转换时间
转 换 形 式 | 采样保持时间 | 完 成 转 换 总 时 间 |
启动ADC后的第一次转换 | 13.5个ADC时钟 | 25个ADC时钟 |
正常转换,单端输入 | 1.5个ADC时钟 | 13个ADC时钟 |
自动触发方式 | 2个ADC时钟 | 13.5个ADC时钟 |
正常转换,差分输入 | 1.5/2.5个ADC时钟 | 13/14个ADC时钟 |
当ADCSRA寄存器中的ADSC位置位,启动ADC转换时,A/D转换将在随后ADC时钟的上升沿开始。一次正常的A/D转换开始时,需要1.5个ADC时钟周期的采样保持时间(ADC首次启动后需要13.5个ADC时钟周期的采样保持时间)。当一次A/D转换完成后,转换结果写入ADC数据寄存器,ADIF(ADC中断标志位)将被置位。在单次转换模式下,ADSC也同时被清零。用户程序可以再次置位ADSC位,新的一次转换将在下一个ADC时钟的上升沿开始。
2.ADC输入通道和参考电源的选择
- 当要改变ADC输入通道时,应该遵守以下方式,以保证能够选择到正确的通道:
在单次转换模式下,总是在开始转换前改变通道设置。尽管输入通道改变发生在ADSC位被写入“1”后的1个ADC时钟周期内,然而,最简单的方法是等到转换完成后,再改变通道选择。
- ADC电压参考源
ADC的参考电压(VREF)决定了A/D转换的范围。如果单端通道的输入电压超过VREF,将导致转换结果接近于0x3FF。ADC的参考电压VREF可以选择为AVCC或芯片内部的2.56V参考源,或者为外接在AREF引脚上的参考电压源。
附录2、ADC应用设计的深入讨论
最后
以上就是粗暴蜗牛为你收集整理的AVR单片机模数转换的ADC实验 ATmega16的全部内容,希望文章能够帮你解决AVR单片机模数转换的ADC实验 ATmega16所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复