M8查询方式ADC测试程序(来自AVR单片机GCC程序设计)
/*******************************************功能: ATmega8查询方式A/D转换测试程序
文件名:ad_0.c
时钟:11.0592MHz
I/O:ADC用内部参考电压源2.56,PC0/ADC0
编译 WinAVR-20070525rc2,优化选项:00
********************************************/
#include <avr/io.h>
#include <avr/delay.h>
#include <stdio.h>
#define uchar unsigned char
#define uintunsigned int
static uint g_aAdValue;//A/D转换缓冲区
//向UART写入一字节
int usart_putchar(char c)
{
if(c == '\n')
usart_putchar('\r');
loop_until_bit_is_set(UCSRA,UDRE);
UDR = c;
return 0;
}
//从标准设备中输入一个字节
int usart_getchar(void)
{
loop_until_bit_is_set(UCSRA,RXC);
return UDR;
}
void IoInit(void)
{
//I/O流UART连接
UCSRB = _BV(TXEN)|_BV(RXEN);
UBRRL = 71; //设置波特率为9600
fdevopen(usart_putchar,usart_getchar);
}
uint AdcConvert(void)
{
uchar i;
uintret;
uchar max_id,min_id,max_value,min_value;
ADMUX = 0xC0;//内部2.56V参考电压,0通道
ADCSRA = _BV(ADEN);//使能ADC,单次转换模式
//连续转换8次
for (i=0;i<8;i++)
{
ADCSRA |= _BV(ADSC);
_delay_ms(5);
while(ADCSRA&_BV(ADSC))
_delay_ms(5);
ret = ADCL;
ret |= (uint)(ADCH<<8);
g_aAdValue=ret;
}
ret =0;
//下列代码抛弃第一次转换结果
for (i=1;i<8;i++)
ret += g_aAdValue;
//找到最大值和最小索引
ret /=7;
max_id=min_id=1;
max_value=min_value=0;
for(i=1;i<8;i++)
{
if(g_aAdValue>ret)
{
if(g_aAdValue-ret>max_value)
{
max_value=g_aAdValue-ret;
max_id = i;
}
}
else
{
if(ret-g_aAdValue>min_value)
{
min_value = ret-g_aAdValue;
min_id = i;
}
}
}
//去掉第一个,最大值和最小值后的平均值;
ret = 0;
for (i=1;i<8;i++)
{
if((i!=min_id)&&(i!=max_id))
ret+=g_aAdValue;
}
if(min_id!=max_id)
ret/=5;
else
ret/=6;
ADCSRA = 0;//关闭ADC
return ret;
}
int main(void)
{
uchar i;
IoInit();
while(1)
{
scanf("%c",&i);
if(i=='c')
printf("ADC转换结果:%d\n\r",AdcConvert());
}
} 编译结果:
Build started 13.3.2008 at 11:04:17
avr-gcc.exe-mmcu=atmega8 -Wall -gdwarf-2 -std=gnu99 -DF_CPU=11059200UL -O0 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT ad_0.o -MF dep/ad_0.o.d-c../ad_0.c
In file included from ../ad_0.c:10:
c:/winavr/bin/../avr/include/avr/delay.h:36:2: warning: #warning "This file has been moved to <util/delay.h>."
In file included from c:/winavr/bin/../avr/include/avr/delay.h:37,
from ../ad_0.c:10:
c:/winavr/bin/../avr/include/util/delay.h:89:3: warning: #warning "Compiler optimizations disabled; functions from <util/delay.h> won't work as designed"
../ad_0.c: In function 'IoInit':
../ad_0.c:41: warning: passing argument 1 of 'fdevopen' from incompatible pointer type
../ad_0.c:41: warning: passing argument 2 of 'fdevopen' from incompatible pointer type
avr-gcc.exe -mmcu=atmega8 -Wl,-Map=ad_0.map ad_0.o -o ad_0.elf
avr-objcopy -O ihex -R .eepromad_0.elf ad_0.hex
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O ihex ad_0.elf ad_0.eep || exit 0
c:\WinAVR\bin\avr-objcopy.exe: there are no sections to be copied!
avr-objdump -h -S ad_0.elf > ad_0.lss
AVR Memory Usage
----------------
Device: atmega8
Program: 8192 bytes (100.0% Full)
(.text + .data + .bootloader)
Data: 62 bytes (6.1% Full)
(.data + .bss + .noinit)
Build succeeded with 4 Warnings... 从编译结果看:Program: 8192 bytes (100.0% Full)
刚刚好用满FLASH空间../emotion/em006.gif
使用优化01级,降到4564;
使用优化02级,降到4568;
使用优化03级,降到5764;
使用优化0s级,降到4512;
_delay_ms(5)函数改为与书上的_delay_loop_1(60)后,占用空间可降到4964(00优化选项)
优化选项 字节数
01 4550
02 4554
03 5726
0S 4508
从空间角度来看,0S优化最省空间.
测试结果表明,AD转换结果的数据很稳定,优化对结果无不良影响,与万用表测出的结果基本一致. 为什么我用芯艺的程序,读出的数据波动很大. mark 这个ADC读取程序还是写的不错的,加了滤波! 读取ADC的值,使用的是 delay函数 等待,这样程序效率会比较低 学习学习,谢谢 来学习下! 学习记号备用 M 不错收藏
页:
[1]