|
![](static/image/common/ico_lz.png)
楼主 |
发表于 2010-1-3 17:07:11
|
显示全部楼层
2009.12.31
开始我是没有AD芯片的, 玩的单片机也是没AD的s52. 但是我无意间看到电源网的azhu原创的(应该是原作者)《用普通单片机实现低成本高精度A/D转换》, 但是原文已经没有了. 只有一些转载. 基本原理如下. 利用电压比较和RC电路判断输入电压的值.
![](http://docs.google.com/File?id=dcbsxfpf_728gh687wdc_b)
原理是这个样子的,PWM经过滤波后得到一个稳定的电压值: U1=VDD*D1/(D1+D2). 只要逐步的增加占空比,就能让U1‘线性’增加, 等到RA1第一次出现翻转(1->0),就可以根据占空比得知模拟量的值. 如果PWM是16bit的, 那么理论上精度是也是16bit(应该只是理论上,没有测试过). 误差来源:
1)电源电压, 如果VDD 0.5%, 最后能得到1%精度
2)软件产生的PWM占空比不准确
3)RC电路波纹影响
变下方向还可以DA.(RC大波纹小,但是速度可以想像,不咋的的)
![](http://docs.google.com/File?id=dcbsxfpf_729gp5t2jgh_b)
是的,一开始我就用这个电路. 做了详细的测试. 无奈s52连pwm也没有, 速度低, 12M,1us的指令周期,用timer产生15khz的pwm有困难,还要兼顾扫描显示, 是在力不从心.
不断的调试和调整参数,优化程序(没有用汇编,只是c),也没有取得能用的精度..和测量结果. 虽然也能探测0.05的变化这个显然不能探测-dV, 差了不少呢. 所以也只能显压充电. 最大的问题是ADC的时候必须关闭pwm,否则更为不准确,如此以来-dV更是无从谈起阿.电流的测量更是不准确. 速度也成问题.
下面是调试的一些log和最终结果:
------------------------------------------------------------------------
r67 | heyongli | 2009-10-18 23:30:10 +0800 (日, 2009-10-18) | 3 行
发现不同loop值在不同范围内有最好的精度
ad转化后在180一下, loop=25即可.
>188. loop12 可以修正测量值,使0.05V的adc值为8
------------------------------------------------------------------------
r65 | heyongli | 2009-10-18 19:36:31 +0800 (日, 2009-10-18) | 195 行
经过两天的调试,终于得到一个看起来不错的版本.
犯过的错误:
1) 最大的一个: ADC_PWM pull-up使用100k电阻, 结果RC的R不是
10k, 而是110k, 导致5v VCC下,RC最高只能达到 1.6V的电压
2) 多少次loop,频率不能猜, 用multisim模拟RC,大约5ms RC电压
基本达到稳定,得到loop理论值应该是: 5000/511 = 10
实际测量15比较好
经历的挫折:
1) 程序中udelay不能接受0值
2) 在pwm loop中使用 取余,整除: /,%, 非常慢,不要用
3) 测试了使用udelay,不用udelay(while(--cyc)),测试了多种RC值
甚至使用推挽对RC充电(这个版本吧推挽去掉了推挽电路,改天加上看
看是否好些)
4) PWM对测量产生的干扰, RC滤波
这个版本的程序可以测量0.5 到 大约3.9V的电压 <0.5V 无法测量.
0.5 到 2.3V 线性比较好,分辨率约0.1V
2.3 V以上 误差%5左右.
-----------------------------------------------
100 loop 511 cycle
+1k pull-up RC:10k,1uf
0.50 0..1
0.55 8
0.60 17..20
0.65 24
0.70 32
0.75 40
0.80 48
0.85 56
0.90 64
0.95 72
1.00 80
1.10 96
1.2 112
1.3 128
1.4 144..145 +1
1.5 159..161 +-1
1.6 172 -4
1.7 188 -4
1.8 205..207 -3..-1
1.9 220 -4
2.0 236 -4 (259)
2.1 248..252 -5 20 loop: 250..252 15loop:256 -1, good
2.2 264 -9
2.3 280 -9
2.4 296 -9
2.5 305..312 -9
2.6 323..324 -13 loop=15, 330 -6
2.7 340..341 -12 loop=15, 347 -6
2.8 359..365 -4
2.9 398..407 +22
3.0 420..424 +22
3.1 440..447 +29
3.2 460 +29
3.3 476 +29
3.4 500 +37
------------ RESULT -----------------
20 loop same as above: about ~1 flick
20 loop is better than 100
15 seem better than 20 loop
100 loop 511 cycle
+1k pull-up RC:10k,1uf
better adc method:
d=adc(0,2); fast serch
adc(d-5,15); multiple adjust adc
if(timeafter(jiffers,lasttime+1000) ){
pwm_safeoff();
//fast search
if(onduty>10)
onduty = adc(onduty-5,15);
else
onduty = adc(0, 2);
pwm_safeon();
printhex(onduty);
vledmod('H');
lasttime = jiffers;
}
unsigned short adc(unsigned short adc_duty,unsigned short loop)
{
unsigned short adcloop;
ADC_PWMPIN = 0;
ADC_SIGNAL = 1;
//mdelay(1000); //uncharge
// free+6us
for(; adc_duty<= (ADC_CYCLE); adc_duty+=ADC_STEP){
xadc_free = ADC_CYCLE-adc_duty;
adcloop =loop;
while(adcloop){
ADC_PWMPIN = 1;
udelay(adc_duty);
ADC_PWMPIN = 0;
udelay(xadc_free);
adcloop--;
}
if(0 == ADC_SIGNAL) {
// printhex(adc_duty);
return adc_duty;
}
}
return adc_duty;//adc_duty;
}
------------------------------------------------------------------------
r64 | heyongli | 2009-10-17 15:20:28 +0800 (六, 2009-10-17) | 140 行
加了不少东西. check in主要为了ADC
这个版本的ADC使用 udelay, 8us的增量才准确, 总周期1khz.
下面是一些adc的测试,精度 1000/8 128step, 5v的话是0.05v
=======================================================
cycle:100
step: 1
loop: 100
0.25 4
0.30 4
0.35 4
0.40 4
0.45 5
0.50 8
0.55 8
0.60 13
0.65 16
0.70 16
0.75 16
0.80 22
0.85 24
0.90 24
0.95 29
1.00 32
1.05 32
1.10 32
1.15 37
cycle:256
step: 1
loop: 100
0.25 8
0.30 8
0.35 16 0.1v 8
0.40 24
0.45 32 0.1 6
0.50 32
0.55 40 0.1 8
0.60 48
0.65 49 0.1 9
0.70 56
0.75 64 0.1 15
0.80 65
0.85 72 0.1 8
0.90 73
0.95 80 0.1 8
1.00 88
1.05 88 0.1 8
1.10 96
1.15 97 0.1 8
1.20 104
1.25 105 0.1 8
1.30 112
1.35 113 0.1 8
1.40 120
1.45 121 0.1 8
1.55 129 8
cycle:1024 (/8= 128step)
1.55 273
1.50 269
1.48 265
1.44 257
1.40 250
1.35 241
1.30 233
1.24 225
1.20 217
1.05 194
//1uf
1.054 176
1.000 168
0.95 160
0.90 152
0.85 144
0.80 136
15
0.75 121
0.70 113
0.65 104
0.60 96
0.55 88
14
0.50 74
0.45 65
0.40 56
0.35 48
15
0.30 33
0.25 25
0.20 16
0.15 8 ..4
0.10 0
优化udelay
cycle:1024 (/8= 128step)
step :2
0.152 4
0.200 12
0.25 24
0.30 32
0.35 44
0.40 54
0.45 64
0.50 76
0.55 86
0.60 96
0.65 104
0.70 114
0.75 124
0.80 132
0.85 142
0.90 150
0.95 160
1.00 168
1.05 176
1.10 184
1.15 192
1.20 200..
1.25 210
1.30 218 |
|