kkkkkk 发表于 2010-1-28 08:48:15

大家好,新手请教ad基础问题,请老师指点,谢谢!

新手想学单片机,刚买了块学习板,照着范例程序做,遇到个问题请各位高手指点:
下面的范例程序是ATmega88的ad转换,测试成功,
它只读了8位,我想把它改成读10位的,精度高点,应该怎么改呢?


void AD_init(void)
{
        ADMUX=0X60; //参考电压=AVCC 转换结果向左看齐,AD通道0
        ADCSRA=0X85;        //AD使能,转换时钟选择位=FOSC/32,单次转换               
}
//---------------------------------------
//名称: AD转换函数
//-----------------------------------------
unsigned char adc_read(void)
{
        unsigned char i;
        unsigned int ret;
        for(i=0;i<8;i++)
        {
                ADCSRA|=0X40;//启动转换
                while(ADCSRA&0x40);
                adcbuf=ADCH;       
        }
        ret=0;
        for(i=0;i<8;i++)
        {
                ret+=adcbuf;
        }
        ret=ret/8;       
        return ret;
}

liaowei 发表于 2010-1-28 10:38:50

左对齐,那么高8位在ADCH中,低2位就在ADCL中
不过10位的话使用右对齐方便,直接读取ADC就可以了

admvip 发表于 2010-1-28 11:11:17

我也是初学者,我觉得将AD初始化里面的ADMUX=0X60 改为0x40就行了,就是不打开左对齐选择位。
读取ADC值的时候需要注意变量应为无符号整形变量,读取的顺序是先读ADCL,再读ADCH,注意数据的位移处理。如果用的是ICCAVR编译器可以这样读取:
i=ADC;
编译器自己处理读取顺序,你试试吧,讲得不对也请指教!

ilearnit 发表于 2010-1-28 16:43:35

直接用一个int型变量去读,应该会成功。

YUZH282 发表于 2010-1-28 17:30:45

8位和10位,CUP都给出了10位,你只用了8位,另两位在ADCL里,1楼的方法简单,好用,要不你也可以用一个int型变量
int adcbuf

void AD_init(void)
{
ADMUX=0X60; //参考电压=AVCC 转换结果向左看齐,AD通道0
ADCSRA=0X85; //AD使能,转换时钟选择位=FOSC/32,单次转换
}
//---------------------------------------
//名称: AD转换函数
//-----------------------------------------
unsigned char adc_read(void)
{
unsigned char i;
unsigned int ret;
for(i=0;i<8;i++)
{
ADCSRA|=0X40;//启动转换
while(ADCSRA&0x40);
ret=ADCH;
ret<<=2;
ret+=(ADCL>>6);
adcbuf=ret;
}
ret=0;
for(i=0;i<8;i++)
{
ret+=adcbuf;
}
ret=ret/8;
return ret;
}


上面太笨了
//从AD口读入一个值
unsigned int GetADC(void)
{

unsigned int        adc_value;

        ADC = 0;
        ADCSRA|=(1 << ADSC);        //启动AD转换

        del(10);
        while(!(ADCSRA&(BIT(ADIF))));////ADIF=4, 表示若ADCSR的第5位置为1,则中断AD转换
        //loop_until_bit_is_set(ADCSRA, ADIF);//等待AD转换结束

        ADCSRA |= (1 << ADIF);                //写1清除标志位

        adc_value = ADC;                //读转换结果

        return adc_value;
}

kkkkkk 发表于 2010-1-30 01:31:43

非常感谢各位的指点!我是新手,买了块学习板看着范例摸索,非常快乐!

设定为0x40后,我按照书上的范例如下读入,可是数据总是不对,郁闷得很
      temp1=ADCL;
      temp2=ADCH;
      adcbuf=(temp2<<8)+temp1;

楼上还有老大直接读adc的,我看书上是高低位分开读的(winavr)

这两天比较忙没折腾,等等我把问题整理一下再发上来。
谢谢大家!

kkkkkk 发表于 2010-1-30 10:55:14

各位老师好,今天又在试,还是不成功,请帮小弟看看:

ADMUX=0X40; //参考电压=AVCC 转换结果向右看齐,AD通道0
ADCSRA=0X85; //AD使能,转换时钟选择位=FOSC/32,单次转换

//---------------------------------------
//名称: AD转换函数里的语句
//-----------------------------------------
        unsigned int temp1;
        unsigned int temp2;
ADCSRA|=0X40;//启动转换
while(ADCSRA&0x40);
      temp1=ADCL; //这个单独输出得到的数值是0-255,即八位
      temp2=ADCH; //这个单独输出得到的数值是0-3,即2两位
      adcbuf=(temp2<<8)+temp1; //但是合成的数据总是不对??????????????
      adcbuf=temp2*256 + temp1; //这样也不行???????????????????

郁闷,请各位老大帮忙解决下,问题肯定不复杂,只是我是初次接触单片机……

kkkkkk 发表于 2010-1-30 11:23:35

非常感谢楼上各位兄弟的帮助!
问题总算解决了:
adcbuf 要设置为int,原来只读八位的范例设定的是char
是不是adcbuf原来定义的char变量类型只能容纳8位的数据?

由于程序没有贴完整,使各位老大费心了,非常抱歉
其实上面早有兄弟指出一定要用int来读取,我这儿读取是int但是保存到数组中去就变成char了
解决了接触单片机后遇到的第一个问题!

谢谢大家,谢谢ouravr,谢谢阿莫!
页: [1]
查看完整版本: 大家好,新手请教ad基础问题,请老师指点,谢谢!