搜索
bottom↓
回复: 7

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

[复制链接]

出0入0汤圆

发表于 2010-1-28 08:48:15 | 显示全部楼层 |阅读模式
新手想学单片机,刚买了块学习板,照着范例程序做,遇到个问题请各位高手指点:
下面的范例程序是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;
}

出0入0汤圆

发表于 2010-1-28 10:38:50 | 显示全部楼层
左对齐,那么高8位在ADCH中,低2位就在ADCL中
不过10位的话使用右对齐方便,直接读取ADC就可以了

出0入0汤圆

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

出0入0汤圆

发表于 2010-1-28 16:43:35 | 显示全部楼层
直接用一个int型变量去读,应该会成功。

出0入0汤圆

发表于 2010-1-28 17:30:45 | 显示全部楼层
8位和10位,CUP都给出了10位,你只用了8位,另两位在ADCL里,1楼的方法简单,好用,要不你也可以用一个int型变量
int adcbuf[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);
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;
}

出0入0汤圆

 楼主| 发表于 2010-1-30 01:31:43 | 显示全部楼层
非常感谢各位的指点!我是新手,买了块学习板看着范例摸索,非常快乐!

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

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

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

出0入0汤圆

 楼主| 发表于 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; //这样也不行???????????????????

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

出0入0汤圆

 楼主| 发表于 2010-1-30 11:23:35 | 显示全部楼层
非常感谢楼上各位兄弟的帮助!
问题总算解决了:
adcbuf 要设置为int,原来只读八位的范例设定的是char
是不是adcbuf原来定义的char变量类型只能容纳8位的数据?

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

谢谢大家,谢谢ouravr,谢谢阿莫!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-3 10:40

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表