搜索
bottom↓
回复: 37

在线等,看看这个AD采集为何不正确

[复制链接]

出0入0汤圆

发表于 2013-7-9 22:05:44 | 显示全部楼层 |阅读模式
本帖最后由 孤独将一 于 2013-7-10 15:30 编辑
  1. //===================AD 转换==========]
  2. void ADC_Convect(unsigned char channel)
  3. {       
  4.         ADMUX = channel & 0x07;
  5.         AD_value =  ((int)( ADCL+ADCH*256)) * 500.0 / 1023.0;
  6.         put_char(AD_value/100 +0x30);        put_char('.');  put_char(AD_value/10%10+0x30);  put_char(AD_value%10+0x30);  put_char('V');
  7.         put_char('\n');
  8.         _delay_ms(500);
  9. }
  10. int main()
  11. {
  12.         DDRA = 0xf8;
  13.         usart_init();
  14.         ADCSRA = 0xe6;                                //启动转换,64分频
  15.         _delay_ms(200);
  16.         while(1)
  17.         {
  18.                 ADC_Convect(5);
  19.         }
  20.         return 0;
  21. }
复制代码
===============================================
1:代码简化,芯片AVR16的,直接用片上AD0。AREF接的外置5v。
2:我采集到串口的每次都是5v,虽然以前做过更复杂采集的,但这次不知道为何,哪错了。
3:输出接到0V或不接


=========================================================
解决,不是代码问题,是硬件AVCC接了5v,导致ADMUX=0时通道采集到的可定时5V

出0入0汤圆

发表于 2013-7-10 01:43:42 | 显示全部楼层
there are so many thing wrong that it probably makes sense for you to go back to more basic stuff.

some suggestions:

1) read the datasheet. make you you understand it;
2) change the structure of your code. I would break down your code into two pieces, one initialize the adc module and another performs the adc and returns its result.

出0入0汤圆

发表于 2013-7-10 09:04:12 | 显示全部楼层
((int)( ADCL+ADCH*256))
换成
((unsigned int) ADCL+(unsigned int)ADCH*256))
试试

出0入0汤圆

 楼主| 发表于 2013-7-10 09:09:55 | 显示全部楼层
millwood0 发表于 2013-7-10 01:43
there are so many thing wrong that it probably makes sense for you to go back to more basic stuff.

...

Thank you, I saw datasheet several times. But still don't know what's wrong.

出0入0汤圆

 楼主| 发表于 2013-7-10 09:12:31 | 显示全部楼层
本帖最后由 孤独将一 于 2013-7-10 09:13 编辑
lcw_swust 发表于 2013-7-10 09:04
((int)( ADCL+ADCH*256))
换成
((unsigned int) ADCL+(unsigned int)ADCH*256))


我就是换成这个也是
  1. AD_value =  ADC * 500.0 / 1023.0;
复制代码
问题也是5V

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2013-7-10 09:19:03 | 显示全部楼层
怎么没有看到启动转换的代码呢。                                                                                                                    

出0入0汤圆

 楼主| 发表于 2013-7-10 09:21:09 | 显示全部楼层
.titrwh 发表于 2013-7-10 09:19
怎么没有看到启动转换的代码呢。                                                                       ...

你指的是不是:
  1. put_char('.');  put_char(AD_value/10%10+0x30);  put_char(AD_value%10+0x30);  put_char('V');
复制代码
数据处理这



转换就是ADCSRA = 0xe6;ADMUX = channel & 0x07;

出0入0汤圆

发表于 2013-7-10 09:26:05 | 显示全部楼层
//===================AD 转换==========]

void ADC_Convect(unsigned char channel)

{        

        ADMUX = channel & 0x07;
        ADCSRA = 0xe6;
        AD_value =  ((int)( ADCL+ADCH*256)) * 500.0 / 1023.0;

        put_char(AD_value/100 +0x30);        put_char('.');  put_char(AD_value/10%10+0x30);  put_char(AD_value%10+0x30);  put_char('V');

        put_char('\n');

        _delay_ms(500);

}
感觉应该这样

出0入0汤圆

 楼主| 发表于 2013-7-10 09:37:22 | 显示全部楼层
.titrwh 发表于 2013-7-10 09:26
//===================AD 转换==========]

void ADC_Convect(unsigned char channel)

ADCSRA = 0xe6;加到转换里面,不顶用的

出0入0汤圆

发表于 2013-7-10 09:44:16 | 显示全部楼层
孤独将一 发表于 2013-7-10 09:37
ADCSRA = 0xe6;加到转换里面,不顶用的

那就不太清楚了,好多年没用AVR了,记得大概流程就是IO设置输入悬空,设置转换模式一般为单次转换,左对齐右对齐,然后选择通道,启动一次转换,等待转换结束,读取的时候好像是先低位还是先高位忘了。看看相关几个寄存器就行了,认真就好,如果还不行估计就是硬件问题了。

出0入0汤圆

 楼主| 发表于 2013-7-10 10:57:16 | 显示全部楼层
.titrwh 发表于 2013-7-10 09:44
那就不太清楚了,好多年没用AVR了,记得大概流程就是IO设置输入悬空,设置转换模式一般为单次转换,左对 ...

谢谢。硬件不会错的,换做以前的板子也是这问题,估计哪个点没注意

出0入0汤圆

发表于 2013-7-10 12:16:18 | 显示全部楼层
本帖最后由 machao 于 2013-7-10 12:53 编辑

先把这条语句的错误找到。
       AD_value =  ((int)( ADCL+ADCH*256)) * 500.0 / 1023.0;

先把数据类型搞清楚,模拟个ADC的值,比如4.5V的二进制值,看显示是否对,如果送显示不对,先把后面的调好。最后再去读真正ADC寄存器的值

我的书上有ADC的例子,你看我的书,应该真正的去看懂和理解?

出0入0汤圆

 楼主| 发表于 2013-7-10 12:53:08 | 显示全部楼层
machao 发表于 2013-7-10 12:16
先把这条语句的错误找到。
       AD_value =  ((int)( ADCL+ADCH*256)) * 500.0 / 1023.0;

哪错了,不清楚啊。
  1.         AD_value =  (unsigned long)ADC * 500.0 / 1023.0;
复制代码
=====================================================
  1. AD_value =  (( int)( ADCL+ADCH*256)) * 500.0 / 1023.0;
复制代码
==========================================================
  1. AD_value =  (int) ADCW* 500.0 / 1023.0;
复制代码

出0入0汤圆

发表于 2013-7-10 12:54:42 | 显示全部楼层
孤独将一 发表于 2013-7-10 12:53
哪错了,不清楚啊。================================================================================ ...

C语言如何学的?

出0入0汤圆

发表于 2013-7-10 12:56:22 | 显示全部楼层
ADCH*256 就出问题了
ADCH是8位的,乘上255是多少位?

出0入0汤圆

 楼主| 发表于 2013-7-10 13:06:45 | 显示全部楼层
本帖最后由 孤独将一 于 2013-7-10 13:09 编辑
machao 发表于 2013-7-10 12:56
ADCH*256 就出问题了
ADCH是8位的,乘上255是多少位?


我的C基础不好。
AD_value =  (int) ADC* 500.0 / 1023.0;这个没问题吧,但是不对
  1. //===================AD 转换==========]
  2. void ADC_Convect(unsigned char channel)
  3. {       
  4.         ADMUX = channel & 0x07;
  5.         _delay_ms(500);
  6.         AD_value =  (unsigned long)ADCW * 500.0 / 1023.0;
  7.         put_char(AD_value/100 +0x30);        put_char('.');  put_char(AD_value/10%10+0x30);  put_char(AD_value%10+0x30);  put_char('V');
  8.         put_char('\n');
  9. }
  10. int main()
  11. {
  12.         DDRA = 0x00;
  13.         usart_init();
  14.         ADCSRA = 0xe6;                                //启动转换,64分频
  15.          sei();
  16.         while(1)
  17.         {
  18.                 ADC_Convect(0);
  19.                 _delay_ms(100);
  20.                 ADC_Convect(1);
  21.                 _delay_ms(100);
  22.         }
  23.         return 0;
  24. }
复制代码

出0入0汤圆

发表于 2013-7-10 13:13:58 | 显示全部楼层
// ADC 转换完成中断服务
interrupt [ADC_INT] void adc_isr(void)
{   
    unsigned int adc_data,adc_v;
    adc_data=ADCW;                  //读取ADC置换结果                  
    adc_v=(unsigned long)adc_data*5000/1024;    //换算成电压值
    adc_to_disbuffer(adc_v);
}

这是我书上的例子,能明白吗?

出0入0汤圆

发表于 2013-7-10 13:16:36 | 显示全部楼层
put_char(AD_value/100 +0x30);put_char('.');  put_char(AD_value/10%10+0x30);  put_char(AD_value%10+0x30);  put_char('V');

这段也是问题多多。先把C弄好吧

出0入0汤圆

发表于 2013-7-10 13:19:47 | 显示全部楼层
你手上真的有我的书?还是把它烧掉吧。免得害了你。因为我是一个“坑人”的教授。

出0入0汤圆

发表于 2013-7-10 13:25:01 | 显示全部楼层
machao 发表于 2013-7-10 13:19
你手上真的有我的书?还是把它烧掉吧。免得害了你。因为我是一个“坑人”的教授。 ...

呃,马老师怒了。

莫生气、莫生气。

出0入0汤圆

 楼主| 发表于 2013-7-10 13:27:00 | 显示全部楼层
machao 发表于 2013-7-10 13:19
你手上真的有我的书?还是把它烧掉吧。免得害了你。因为我是一个“坑人”的教授。 ...

你牛。。。。。。。。。

出0入0汤圆

发表于 2013-7-10 13:38:29 | 显示全部楼层
这代码的写的不敢直视啊。

出0入0汤圆

发表于 2013-7-10 15:06:23 | 显示全部楼层
孤独将一 发表于 2013-7-10 12:53
哪错了,不清楚啊。================================================================================ ...

AD_value =  (unsigned long)ADC * 500.0 / 1023.0;
ADC long型*500.0 浮点型这个是干嘛?通过仿真自己找找,不然别人告诉你,你下次也不会记得。

出0入0汤圆

 楼主| 发表于 2013-7-10 15:29:13 | 显示全部楼层
machao 发表于 2013-7-10 13:19
你手上真的有我的书?还是把它烧掉吧。免得害了你。因为我是一个“坑人”的教授。 ...

。。。。。找见根本原因了,根本不是代码的问题。最近一直气头,加上你一激,我更气了。
之前对不起,网上深鞠一躬。

出0入0汤圆

 楼主| 发表于 2013-7-10 15:31:10 | 显示全部楼层
guew 发表于 2013-7-10 13:38
这代码的写的不敢直视啊。

你的代码可以直视?亮出来嗮下,我们学习下

出0入0汤圆

发表于 2013-7-10 15:31:39 | 显示全部楼层
孤独将一 发表于 2013-7-10 15:29
。。。。。找见根本原因了,根本不是代码的问题。最近一直气头,加上你一激,我更气了。
之前对不起,网 ...

解决了就把问题和解决方法写出来,这是基本规矩,不要有问题的时候就不停问,解决了就不管了,要写出来让其他人以后不要犯类似错误。

出0入0汤圆

发表于 2013-7-10 15:44:02 | 显示全部楼层
孤独将一 发表于 2013-7-10 15:31
你的代码可以直视?亮出来嗮下,我们学习下

就是比你写的好,就是不给你看。

出0入0汤圆

发表于 2013-7-10 15:57:01 | 显示全部楼层
楼上不地道,你直接把马老师的代码移植过去,然后自己理解再加上自己想要加的,马老师那个代码我用过很多次,你也可以试着用共用体速度上会快点

出0入0汤圆

发表于 2013-7-10 16:02:50 | 显示全部楼层
本帖最后由 guew 于 2013-7-10 16:04 编辑
hyghyg1234 发表于 2013-7-10 15:57
楼上不地道,你直接把马老师的代码移植过去,然后自己理解再加上自己想要加的,马老师那个代码我用过很多次 ...


有的时候做烂好人反而会纵容一些坏风气,长远来看,对人,对己,都不好。

出0入0汤圆

发表于 2013-7-10 16:09:39 | 显示全部楼层
AD_value =  (unsigned long)ADCW * 500.0 / 1023.0;

===============
改成下面:AD_value要定义成无符号INT型

//AD_value = ADCW;    //1     
AD_value = 900;          //2  假定ADCW寄存器的值为900, 900*500/1023 = 4.51v,相当4.51V
AD_value =  (unsigned long)AD_value * 500 / 1023;

如果显示不对,先查输出显示。
如显示为4.51,则问题出在ADC转换。把2注释掉,用1。另外注意,ADC的输入脚要定义成高阻输入,不能定义上拉有效,更不能定义成输出。
这些在我的教程中都有说明的,不过你还是烧了它吧。


出0入0汤圆

发表于 2013-7-10 16:26:34 | 显示全部楼层
本帖最后由 machao 于 2013-7-10 16:28 编辑

首先要看是什么问题,代码的问题要先解决,保证转换显示正确,然后再查ADC设置和使用是否对。混在一起不容易找到问题。

LZ位的代码中的:  AD_value =  ((int)( ADCL+ADCH*256)) * 500.0 / 1023.0;

有2个可能的问题:
1、ADCH*256 可能就出问题了,因为ADCH是8位的,乘上256,两个8位乘,超限是肯定的(当然ADCH为1或0是可以的)。
2、(int)( ADCL+ADCH*256)) 这里把结果转换成INT,但乘上500,也超限,尽管后面写的是500.0实数,这个看编译器如何处理了。所以我喜欢直接强制转换成长整型,作整数的运算,比浮点运算也快,也保险。

出0入0汤圆

发表于 2013-7-9 22:05:45 | 显示全部楼层
LZ说解决了:

解决,不是代码问题,是硬件AVCC接了5v,导致ADMUX=0时通道采集到的可定时5V
==========================================

这个解释让人怀疑。
AVR有2个电源脚,VCC和AVCC。AVCC是提供A口的工作电压的,总是要接5V的。只是用ADC的话,AVCC的5V最好稳定些。如果AVCC不接5V,A口工作根本就不正常(不管是否使用ADC)。是ADC寄存器的设置问题还是其它的?ADC的参考电压可以设置成AVCC或内部2.56V或引脚REF电压

出0入0汤圆

 楼主| 发表于 2013-7-10 17:42:32 | 显示全部楼层
hyghyg1234 发表于 2013-7-10 15:57
楼上不地道,你直接把马老师的代码移植过去,然后自己理解再加上自己想要加的,马老师那个代码我用过很多次 ...

我没移植他的代码,我看过他的中断处理。我这个不是中断处理。

出0入0汤圆

 楼主| 发表于 2013-7-10 17:45:51 | 显示全部楼层
machao 发表于 2013-7-10 16:26
首先要看是什么问题,代码的问题要先解决,保证转换显示正确,然后再查ADC设置和使用是否对。混在一起不容 ...

我用的avr studio。
AD_value = (int)((ADCL + ADCH <<8) *500.0 /1023.0).

page 127.彭伟的书,你们学校的。
这个ADCH << 8 和ADCH * 256有区别吗,我的C确实不太好

出0入0汤圆

 楼主| 发表于 2013-7-11 10:14:06 | 显示全部楼层
本帖最后由 孤独将一 于 2013-7-11 10:33 编辑
machao 发表于 2013-7-10 16:41
LZ说解决了:

解决,不是代码问题,


搞错,1楼没有编辑选项了。
是AREF没接参考电压。我的错误,抱歉

出0入0汤圆

发表于 2013-7-11 10:16:33 | 显示全部楼层
楼主太扣了,悬赏莫元太少

出0入0汤圆

发表于 2013-7-11 10:20:03 | 显示全部楼层
starli 发表于 2013-7-11 10:16
楼主太扣了,悬赏莫元太少

lz发的几乎都是悬赏贴,基本都是5莫元以下。

出0入0汤圆

 楼主| 发表于 2013-7-11 10:36:08 | 显示全部楼层
不抠门。感觉像个漏洞。莫元又不能变钱。攒那么多不如干实事,发帖吸引眼球。

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

本版积分规则

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

GMT+8, 2024-4-21 00:34

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

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