关于单片机AD采集到的电压跟实际测试到的电压相差较大的问题分析

当遇到MCU采集到的AD值相差特别大的时候,应该怎么分析。
1.首先再次确认采样点的实际电压。
2.确认采样的参考电压是否正确,是内部参电压VCC、1.2V或者是外部的Vref.
3.以上两步都确认没有问题后,核查代码的初始化有无问题。
4.以上都确认无误的话,观察AD的IO口的对外电阻值,是否在芯片推荐使用的对外电阻值得范围之内。如果超出芯片推荐的范围值得话就要小心了,有可能是因为外部阻抗过大所导致的AD采样不准。
如果是这种情况的话,可以先将AD的采样保持时间设置的尽量长,将AD的的分频调至最大,以保证采样时间的充足。如果依旧无法解决的话,建议将对外阻抗调整到芯片推荐范围之内。

案例:
我遇到过的一个现象就是如此:
AD采样的电压跟实际值相差太大,软件和采样时间都检查过了没有问题,最后去看AD口的阻抗,我们使用220M :22M的分压比来采样的(因为产品的低功耗需求,必须在每一个节点来把控功耗的限制,因为AD采样其实是蛮增加功耗的,所以就尽量放大阻抗限流,以此来控制功耗。)。查看芯片数据手册,推荐使用的是1M以内的推荐对外阻抗,所以将阻抗调整到推荐范围就顺利解决了该问题。

说到这里不得不提及一个问题,为什么外部阻抗过大会导致AD采样失准呢?
因为芯片内部的AD采样的原理是靠一个RC电路来实现的,采样保持时间其实就是等C充电完成来测量C的电压就是实际测得的电压值,由于外部阻抗过大的时候,限流严重导致AD口灌入的电流减小很多,导致RC即使在最大的采样保持时间也没法将C充电至外部实际电压值,所以导致AD采样失准,这是阻抗过大之后AD采样失准的核心原因。

  • 13
    点赞
  • 69
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
好的,这里提供一个简单的基于51单片机AD采集电压并显示在数码管上的代码示例,供参考: ``` #include <reg52.h> #include <intrins.h> #define uint unsigned int #define uchar unsigned char sbit DSPORT=P2^2; //数码管数据口 sbit DS1=P0^0; //数码管第一位 sbit DS2=P0^1; //数码管第二位 sbit DS3=P0^2; //数码管第三位 sbit DS4=P0^3; //数码管第四位 sbit CS=P2^1; //ADC芯片片选信号 sbit CLK=P2^0; //ADC芯片时钟信号 sbit DIN=P2^3; //ADC芯片数据输入信号 void delay(uint xms) //延时函数 { uint i,j; for(i=xms;i>0;i--) for(j=110;j>0;j--); } uchar code table[] = { //数码管显示表 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71 }; void Dsplay(uchar num) //数码管显示函数 { switch(num) { case 1: DSPORT=0; DS1=0; DS2=0; DS3=0; DS4=1; break; case 2: DSPORT=0; DS1=0; DS2=0; DS3=1; DS4=0; break; case 3: DSPORT=0; DS1=0; DS2=0; DS3=1; DS4=1; break; case 4: DSPORT=0; DS1=0; DS2=1; DS3=0; DS4=0; break; case 5: DSPORT=0; DS1=0; DS2=1; DS3=0; DS4=1; break; case 6: DSPORT=0; DS1=0; DS2=1; DS3=1; DS4=0; break; case 7: DSPORT=0; DS1=0; DS2=1; DS3=1; DS4=1; break; case 8: DSPORT=0; DS1=1; DS2=0; DS3=0; DS4=0; break; case 9: DSPORT=0; DS1=1; DS2=0; DS3=0; DS4=1; break; case 10: DSPORT=0; DS1=1; DS2=0; DS3=1; DS4=0; break; case 11: DSPORT=0; DS1=1; DS2=0; DS3=1; DS4=1; break; case 12: DSPORT=0; DS1=1; DS2=1; DS3=0; DS4=0; break; case 13: DSPORT=0; DS1=1; DS2=1; DS3=0; DS4=1; break; case 14: DSPORT=0; DS1=1; DS2=1; DS3=1; DS4=0; break; case 15: DSPORT=0; DS1=1; DS2=1; DS3=1; DS4=1; break; case 16: DSPORT=1; DS1=0; DS2=0; DS3=0; DS4=0; break; default: break; } } uchar ADConvert() //ADC采集函数 { uchar i,dat=0; CS=0; CLK=0; DIN=1; for(i=0;i<8;i++) { CLK=0; _nop_(); dat<<=1; if(DOUT) dat++; CLK=1; _nop_(); } CS=1; return dat; } void main() { uchar num=0; uint vol=0; while(1) { vol=ADConvert(); //采集电压值 vol=vol*5000/256; //转换为实际电压值,假设ADC参考电压为5V num=vol/1000; //将电压值拆分成四位数 Dsplay(num+1); //显示千位数 delay(5); num=(vol%1000)/100; Dsplay(num+1); //显示百位数 delay(5); num=(vol%100)/10; Dsplay(num+1); //显示十位数 delay(5); num=vol%10; Dsplay(num+1); //显示个位数 delay(5); } } ``` 需要注意的是,这段代码仅供参考,具体实现时需要根据自己的硬件实际情况进行修改。同时,需要注意电压转换的精度和参考电压的设置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值