binglin 发表于 2008-3-13 11:09:05

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());
        }
}

binglin 发表于 2008-3-13 11:09:54

编译结果:
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...

binglin 发表于 2008-3-13 11:27:00

从编译结果看: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转换结果的数据很稳定,优化对结果无不良影响,与万用表测出的结果基本一致.

a105 发表于 2008-8-28 15:15:43

为什么我用芯艺的程序,读出的数据波动很大.

yzeng 发表于 2010-8-23 18:00:19

mark

liangws201 发表于 2012-5-24 12:38:23

这个ADC读取程序还是写的不错的,加了滤波!

zhilve 发表于 2012-9-1 10:11:30

读取ADC的值,使用的是 delay函数 等待,这样程序效率会比较低

jz701209李 发表于 2012-9-1 14:29:52

学习学习,谢谢

goingdown的生活 发表于 2012-11-7 14:40:13

来学习下!

kuanglf 发表于 2013-2-5 04:31:00

学习记号备用

lkwslk1 发表于 2013-2-22 12:46:51

M                           

hewayking 发表于 2013-5-16 11:59:54

不错收藏
页: [1]
查看完整版本: M8查询方式ADC测试程序(来自AVR单片机GCC程序设计)