|

楼主 |
发表于 2022-5-30 22:30:39
|
显示全部楼层
本帖最后由 xjw01 于 2022-5-30 22:33 编辑
以下代码,与原先代码比对,看看当时改了那些地方。
模拟电路是比较难,当时没有做详细记录,许多细节现在重算有点困难,可以考虑从代码中解读。
程序中的每个参数,几乎都是根据实际元件参数,由理论计算出来的。
以下程序只给出ESR计算、测量部分的代码。不是全部代码,因为我当时做了加密处理,其它的代码发出来没有用。
//==============ESR测量====================
ulong nn = 0; //时序计数器
uchar nn2 = 0;
//=====可编程时钟发生器======
//每完成一趟计数,TL0、TL1重装,输出口置反,所以两趟计数才能输了完整方波,共计数2*(256-THx)字
//THx取128,输出方波需2*(256-128)=256计数,即256个时钟周期
uchar XW=0;
void feqInit(){
WAKE_CLKO |= 0x07; //允许T0 T1 BRT独立发生时钟,以启动运放电源
TMOD = 0x22; //T0和T1工作在8位自动重装
AUXR |= 0x80; //T0工作在1T
AUXR |= 0x40; //T1工作在1T
AUXR |= 0x04; //独立波特率发生器工作在1T
TH0 = 128; //置T0频率字
TH1 = 128; //置T1频率字
BRT = 206; //置BTR频率
TL0 = 0; //置初相为0
TL1 = 0; //置初相为0(TR1启动延时4周期,所以补偿4字)
AUXR |= 0x10; //启动BRT,P1.0口输出
TCON |= 0x50; //启动T0和T1,T0和T1分别在P3.4和P3.5输出,同时置1启动.如果用TR0=1,TR1=1,则1T时TL1应补偿4字.
}
void setXW(uchar xw,uchar bc){ //xw为移相参数(360度对应256字),bc补偿字数(72kHz补4字)
uint m = 256-TH0; //半周期的计数值
uint n = (m*xw+64)/128+bc; //变换为计数偏移量,因TR1比TR0晚启动引入4周期延时,所以事先补偿4字
XW = xw;
TR0 = 0, TR1 = 0; //暂停计数
pt0 = 0, pt1 = n/m%2; //同相或反相处理
TL0 = 0, TL1 = n % m; //置相位差
TCON |= 0x50; //TR0与TR1同时置1启动T0和T1.如果用TR0=1,TR1=1;则1T时bc应补偿4字
}
void setFeq(char k,uchar w){ //设置频率,w是相位
if(k==5){ //直流电阻测量使用
P3M1 |= 0x10, P3M0 &= ~0x10; //P3.4置为高阻口
P1M0 |= 0x40, P1M1 &= ~0x40; //P1.6置为推挽口
TR0 = TR1 = 0; //停止计数器
pt1 = 1; //P3.5开路
DCo = 1; //开启直流源
return;
}
//交流阻抗测量使用
P1M1 |= 0x40, P1M0 &= ~0x40; //P1.6置为高阻口
P3M0 |= 0x10, P3M1 &= ~0x10; //P3.4置为推挽口
if(k==0){ AUXR |= 0x80; AUXR |= 0x40; TH0=176, TH1=176; } //1T模式, 置为双69.12kHz
if(k==1){ AUXR &= ~0x80; AUXR &= ~0x40; TH0=192, TH1=192; } //12T模式,置为双7.2kHZ
if(k==2){ AUXR &= ~0x80; AUXR &= ~0x40; TH0=0, TH1=0; } //12T模式,置为双1.8kHZ
if(k==3){ AUXR |= 0x80; AUXR |= 0x40; TH0=176, TH1=96; } //1T模式, 信号源69.12kHz,检波端34.56kHz
if(k==4){ AUXR |= 0xC0; TH0=176; TR0=1; TR1=pt1=0; return;} //1T模式, 信号源69.12kHz,检波端0Hz
setXW(w,0);
}
uint getAD10() { //过采样
//每秒取样速度为2.48万/1.67
int i;
long c = 0;
for(i=0;i<500;i++) c += getAD2();
c = (c+25)/50;
return c;
}
void putCx(float C,char g){ //显示电容,占用LCD屏7字符
char xs = 0;
float d=C;
if(d<0) d=-d;
if(d<10000) xs = 0;
if(d<1000) xs = 1;
if(d<100) xs = 2;
if(d<10) xs = 3;
if(g==0 && d>50 ) {lcd_puts1(" OL "); return; }
if(g==1 && d>500 ) {lcd_puts1(" OL "); return; }
if(g==2 && d>6000) {lcd_puts1(" OL "); return; }
lcd_putf1(C,xs,4);
}
void putNx(char *Lb,int a,char n){ //输出整数
lcd_puts1(Lb);
lcd_int1(a,n);
}
int Vx,Vy,Vz,Vw,Vd; //Vd是零点直流漂移
float Vpp=52500,Vbat,Vbat2; //Vpp信号电压,Vbat电池电压
char Ha=0;
void ESRcalc(char jiao, char ha){
const Bn = 3; //时序步数
char n = nn%(Bn*8);
int v,vxc=0,vx,vy,vz,vw,vd;
float R=0,C1=0,C2=0,C3=0,e;
if(n%Bn) return;
n /= Bn;
v = getAD10();
if(n==0){ //测得电源电压
set_channel(2); delay(6);
Vpp = getAD10()*(8.05)*(1+0.001*cs.Vp); //读信号电压
Vbat2 = getAD2();
set_channel(7); delay(6);
Vbat = (3.3*151/51/1024)*getAD2(); //利用HT7533作为电压基准换算电池电压
Vbat2 = (1.2/3.3*1024)/(1024-Vbat2)*Vbat; //利用Vpp间接读取口作为电压基准换算电池电压
Vbat2 += (Vbat2-3.6)*0.065; //Vbat2精度只有正负0.25V
if(Vbat<3.6 && Vbat2<Vbat){
Vbat = Vbat2;
}
Vbat += 0.1; //加上8550的压降
set_channel(1);
}
if(ha==0){ //测阻容
if(n==0){ Vd = v; setFeq(0, 0); return; } //测得零点直流,然后置为69.12kHz,0度
if(n==1){ Vx = v; setFeq(0,192); return; } //测得x相电压,然后置69.12kHz,270度
if(n==2){ Vy = v; setFeq(1,192); return; } //测得y相电压,然后置中频,270度
if(n==3){ Vw = v; setFeq(2,192); return; } //测得y相电压,然后置低频,270度
if(n==4){ Vz = v; setFeq(3, 0); } //低频测得y相电压,然后置为非相关频率
vd = Vd - cs.d0;
vx = Vx - cs.x0 - vd;
vy = Vy - cs.y0 - vd;
vz = Vz - cs.z0 - vd;
vw = Vw - cs.w0 - vd;
//Vpp += checkBB(1)*10;
if(Vy<9700){
e = 1.0*vy/Vpp; e = e*(1+e*e*1.7);
C1 = (14.47/8/101/1.015)/e; //电容量公式 (T/8)/R*(A/vy)
vxc = vy*(1.333*e + 0.005*cs.J1*e - 0.001*cs.J0);//电阻修正参数,理论系数是1.333,实测采用1.38比较好
R = 1.030*(vx-vxc)/(Vpp-vx)*104; //电阻计算,Vpp被高估2%左右所以补偿值为1.02
}
if(Vw<9700){ //中频测容量
e = vw/Vpp; e = e*(1+e*e*1.7);
C2 = (14.47/8/104*9.6/1.015)/e;
}
if(Vz<9700){ //低频测容量
e = vz/Vpp; e = e*(1+e*e*1.7);
C3 = (14.47/8/104*38.4/1.015)/e;
}
{
//static char checkA=0,check2=0;
//if (checkA<10){ if(C2>2.1&&C2<2.3) checkA++; }
//else if(checkA<20){ if(R>14.4&&R<15.6) checkA++; }
//else if(checkA<30){ if(R>19.2&&R<20.8) checkA++; }
//else{ if(!check2){ check2=1; checkAA(2); cs_RW(1); } }
//R += checkAA(1)*2 - cs.fmm;
//C2 *= 1+checkAA(1)*2 - cs.fmm;
}
if(jiao==0){ //阻容显示
if(Vx>=9700||Vy>=9700){ //主参数溢出(高频溢出)
lcd_goto(0,0); lcd_puts2(" !!!!!"); lcd_puts1(" \x8");
lcd_goto(96,7); lcd_putf0(Vbat,2,-3); lcd_puts0("V"); //输出电阻和电池电压
lcd_goto(0,4); lcd_puts0("=====================");
lcd_goto(0,5); lcd_puts1(" C < 100nF ");
return;
}
lcd_goto(0,0); lcd_putf2(R,2,4); lcd_puts1(" \x8");
lcd_goto(96,7); lcd_putf0(Vbat,2,-3); lcd_puts0("V"); //输出电阻和电池电压
lcd_goto(0,4); lcd_puts0("=====================");
lcd_goto(0,5);
if(vy>500){ lcd_puts1("CH"); putCx(C1,1); putCx(C2,2); } //电容输出
else { lcd_puts1("CL"); putCx(C2,1); putCx(C3,2); } //电容输出
lcd_puts1("\xa"); lcd_puts1("F"); //输出电容单位
}
if(jiao==1) { //过程显示
lcd_goto(0,0); putNx("D=",cs.d0,4); putNx(" d=",vd,5); //零点直流
lcd_goto(0,2); putNx("X=",cs.x0,4); putNx(" x=",vx,5); //显示Vx
lcd_goto(0,4); putNx("Y=",cs.y0,4); putNx(" y=",vy,5); //显示Vy
lcd_goto(0,6); putNx("Z=",cs.z0,4); putNx(" z=",vz,5); //显示Vz
}
//校准显示输出
if(jiao>=5) { lcd_goto(0,0); lcd_puts1("R="); lcd_putf1(R,2,4); lcd_puts1("\x8"); } //输出电阻
if(jiao==5) { lcd_goto(0,2); putNx("Vp=",cs.Vp,5); } //Vp校准输出
if(jiao==6) { lcd_goto(0,2); putNx("J0=",cs.J0,5); } //J0校准输出
if(jiao==7) { lcd_goto(0,2); putNx("J1=",cs.J1,5); } //J1校准输出
}
if(ha==1){ //测电感
if(n==0){ Vd = v; setFeq(5, 0); return; } //测得零点直流,置为72kHz,90度
if(n==1){ Vx = v; setFeq(0,64); return; } //测直流电阻
if(n==2){ Vy = v; setFeq(1,64); return; } //测得y相电压,置为中频90度
if(n==3){ Vw = v; setFeq(2,64); return; } //低频测得y相电压,置为低频90度
if(n==4){ Vz = v; setFeq(4, 0); return; } //低频测得y相电压,置为非相关频率
vd = Vd - cs.Ld0;
vy = Vy - cs.La0 - vd;
vw = Vw - cs.Lb0 - vd;
vz = Vz - cs.Lc0 - vd;
vx = Vx + cs.Ldc0; if(vx<0) vx = 0; vx = vx*2/3; //得到直流电阻,单位是0.01欧,实际上测得130R与电感直流电阻的并联,因为电感内阻小,130R可忽加略,用vx代替电感内阻
vy -= cs.La1*(vx/2000.0); //cs.La1是20欧对应的电抗偏移,69.1kHz
vw -= cs.Lb1*(vx/2000.0); //cs.Lb1是20欧对应的电抗偏移,7.2kHz
vz -= cs.Lc1*(vx/2000.0); //cs.Lc1是20欧对应的电抗偏移,1.8kHz
e = (104*14.47/4*1.010)/Vpp; //104*(T/2)/2
if(jiao==0){ //显示电感量
lcd_goto(0,0); lcd_puts1("69.1k L="); if(Vy>9700) lcd_puts1("Over "); else { lcd_putf1(e*vy*(1+0.00020*vx) , 2,4); lcd_puts1("uH"); } //高频测电感
lcd_goto(0,2); lcd_puts1("07.2k L="); if(Vw>9700) lcd_puts1("Over "); else { lcd_putf1(e*vw*(1+0.00017*vx)*9.6 , 1,4); lcd_puts1("uH"); } //中频测电感
lcd_goto(0,4); lcd_puts1("01.8k L="); if(Vz>9700) lcd_puts1("Over "); else { lcd_putf1(e*vz*(1+0.00013*vx)*38.4, 0,4); lcd_puts1("uH"); } //低频测电感
}
if(jiao==1){ //过程显示
lcd_goto(0,0); putNx("I=",checkBB(2),4); putNx(" D=",vx,5);
lcd_goto(0,2); putNx("G=",cs.Ld0,4); putNx(" g=",vd,5); //零点直流
lcd_goto(0,4); putNx("A=",cs.La0,4); putNx(" a=",vy,5); //显示Va
lcd_goto(0,6); putNx("B=",cs.Lc0,4); putNx(" b=",vz,5); //显示Vb
}
}
}
char nCls = 127;
void shortCls(){ //短路清零
if(nCls<127) nCls++; //延时计数器步增,等待键盘放开
if(nCls==1){ lcd_cls(); lcd_puts1("Clear...."); delay2(100); }
if(nCls!=50) return;
if(Ha&&Vx>2500&&Vx<3000){ //电感测量的电阻残余清零,接入标准20R电阻后进行清零
uchar i;
cs.La1 = Vy-cs.La0;
cs.Lb1 = Vw-cs.Lb0;
cs.Lc1 = Vz-cs.Lc0;
lcd_cls(); lcd_puts1("Check AD zeor");
setFeq(5,0);
DCo=0, cs.Ldc0=0;
for(i=0;i<200;i++){ //每循环约1ms时间
DCo = ~DCo; delay(60); //生成占空比为1:10的方波
DCo = ~DCo; delay(540);
if(i>=190) cs.Ldc0 += getAD2(); //读电压,仅在最后5%时间读电压,电容上的电压还有一定的保持作用,因此getAD2()占用的时间虽然影响占空比,但对读值准确性影响很小
}
DCo=1, cs.Ldc0 = 275 - cs.Ldc0; //每1欧150字,20//220=18.3,1/10即为1.83欧对应275字
lcd_goto(0,2); putNx("c1=",cs.Ldc0,4);
cs_RW(1); //保存
lcd_goto(0,2); lcd_puts1("Ind cleared.");
delay2(200);
return;
}
if(Ha){ //电感零点参数
cs.Ld0 = Vd, //直流零点
cs.La0 = Vy, //90度高频残余
cs.Lb0 = Vw, //90度中频残余
cs.Lc0 = Vz; //90度低频残余
}
else{ //阻容测量
cs.d0 = Vd;
cs.y0 = Vy; //90度高频残余
cs.w0 = Vw; //90度中频残余
cs.z0 = Vz; //90度低频残余
cs.x0 = Vx; //0度高频残余
}
cs_RW(1); //保存
lcd_cls(); lcd_puts0("Zero... OK");
delay2(200);
//Ha = (Ha+1)%2;
} |
|