|
发表于 2024-4-19 10:47:54
|
显示全部楼层
本帖最后由 digitking 于 2024-4-19 10:52 编辑
我给你改好了,你再试试吧。注释里写了修改1和修改2
- /*************************************
- Q表驱动程序 V3.1
- xjw01 于莆田 2010.10
- **************************************/
- //====================================
- #define uchar unsigned char
- #define uint unsigned int
- #define ulong unsigned long
- #include <reg52.h>
- void delay(uint loop) { uint i; for(i=0;i<loop;i++); } //延时函数
- void delay2(uint k){ for(;k>0;k--) delay(10000); } //长延时,k=100大约对应1秒
- //========================AD转换=============================
- sfr P1ASF = 0x9D; //将P1置为模拟口寄存器(使能),各位中为1的有效
- sfr ADC_CONTR = 0xBC; //A/D转换控制寄存器
- sfr ADC_res = 0xBD; //A/D转换结果寄存器
- sfr ADC_resl = 0xBE; //A/D转换结果寄存器
- void set_channel(char channel){
- P1ASF = 1<<channel;
- ADC_CONTR = channel+128; //最高位是电源开关,低3位通道选择
- delay(1); //首次打开电源应延迟,使输入稳定
- }
- uint get_AD2(){
- ADC_CONTR |= 0x08; //00001000,置ADC_START=1启动A/D 转换
- while ( !(ADC_CONTR & 0x10) ); //等待A/D转换结束(ADC_FLAG==0)
- ADC_CONTR &= 0xE7; //11100111,置ADC_FLAG=0清除结束标记, 置ADC_START=0关闭A/D 转换
- return ADC_res*4 + ADC_resl;
- }
- /*
- uchar get_AD(){
- ADC_CONTR |= 0x08; //00001000,置ADC_START=1启动A/D 转换
- while( !(ADC_CONTR & 0x10) ); //等待A/D转换结束(ADC_FLAG==0)
- ADC_CONTR &= 0xE7; //11100111,置ADC_FLAG=0清除结束标记, 置ADC_START=0关闭A/D 转换
- return ADC_res;
- }
- */
- //============================EEPROW偏程=========================
- sfr IAP_data = 0xC2;
- sfr IAP_addrH = 0xC3;
- sfr IAP_addrL = 0xC4;
- sfr IAP_cmd = 0xC5;
- sfr IAP_trig = 0xC6;
- sfr IAP_contr = 0xC7;
- /********************
- 写字节时,可以将原有数据中的1改为0,无法将0改为1,只能使用擦除命令将0改为1
- 应注意,擦除命令会将整个扇区擦除
- *********************/
- uchar readEEP(uint k){ //读取
- IAP_addrL = k; //设置读取地址的低字节,地址改变才需要设置
- IAP_addrH = k>>8; //设置读取地址的高字节,地址改变才需要设置
- IAP_contr = 0x81; //设置等待时间,1MHz以下取7,2M以下取6,3M取5,6M取4,12M取3,20M取2,24M取1,30M取0,前导1表示许档IAP
- IAP_cmd = 1; //读取值1,写取2,擦除取3,擦除时按所在字节整个扇区撺除
- IAP_trig = 0x5A; //先送5A
- IAP_trig = 0xA5; //先送5A再送A5立即触发
- return IAP_data;
- }
- void writeEEP(uint k, uchar da){ //写入
- IAP_data = da; //传入数据
- IAP_addrL = k; //设置读取地址的低字节,地址改变才需要设置
- IAP_addrH = k>>8; //设置读取地址的高字节,地址改变才需要设置
- IAP_contr = 0x81; //设置等待时间,1MHz以下取7,2M以下取6,3M取5,6M取4,12M取3,20M取2,24M取1,30M取0,前导1表示许档IAP
- IAP_cmd = 2; //读取值1,写取2,擦除取3,擦除时按所在字节整个扇区撺除
- IAP_trig = 0x5A; //先送5A
- IAP_trig = 0xA5; //先送5A再送A5立即触发
- }
- void eraseEEP(uint k){ //擦除
- IAP_addrL = k; //设置读取地址的低字节,地址改变才需要设置
- IAP_addrH = k>>8; //设置读取地址的高字节,地址改变才需要设置
- IAP_contr = 0x81; //设置等待时间,1MHz以下取7,2M以下取6,3M取5,6M取4,12M取3,20M取2,24M取1,30M取0,前导1表示许档IAP
- IAP_cmd = 3; //读取值1,写取2,擦除取3,擦除时按所在字节整个扇区撺除
- IAP_trig = 0x5A; //先送5A
- IAP_trig = 0xA5; //先送5A再送A5立即触发
- }
- #define Nda 23
- xdata struct Ida{
- int bas; //比值基数
- int z[Nda]; //激励电压表
- int C,C2; //主调电容的电大值与最小值,单位0.1pF
- int jz[14]; //125等分非线性改正表,jz[0]存放初始温度下的零点电压(初次非线性桥正时的零点电压)而不存0值
- } cs;
- void cs_RW(char rw){
- uchar i,*p = &cs;
- if(rw){
- eraseEEP(0);
- for(i=0;i<sizeof(cs);i++) writeEEP(i,p);
- }else{
- for(i=0;i<sizeof(cs);i++) p=readEEP(i);
- }
- }
- //=============================DDS部分========================
- #define fMax 12500000
- xdata ulong feq=600000;
- xdata uchar fstep=100;
- sbit FSYNC=P2^1; //DDS使能
- sbit SCLK=P2^2; //DDS串行时钟
- sbit SDATA=P2^3; //DDS串行数据
- void DDS_W16(uint d){ //写32比特数据到DDS
- uchar i;
- SCLK = SDATA = FSYNC=1; delay(3000);
- FSYNC=0; //使能(或同步)打开,数据开始传送
- delay(5);
- for(i=0;i<16;i++){
- SDATA = d>>15; delay(1);
- SCLK = 0; delay(1);
- SCLK = 1; delay(1);
- d<<=1;
- }
-
- FSYNC=1; delay(1);
- SCLK=0; delay(1);
- }
- void DDS_init(void){
- DDS_W16(0x2100); //B28=1(28位连续写频置位),选择频率0相位0,RESET=1
- //DDS_W16(0x2500); //B28=1(28位连续写频置位),选择频率0相位1,RESET=1
- //DDS_W16(0x2900); //B28=1(28位连续写频置位),选择频率1相位0,RESET=1
- //DDS_W16(0x2D00); //B28=1(28位连续写频置位),选择频率1相位1,RESET=1
- //当RESET置位后,开始初始化频率和相位
- DDS_W16(0x4000); //写频率0寄存器的低字节LSB
- DDS_W16(0x4000); //写频率0寄存器的高字节MSB
- DDS_W16(0x8000); //写频率1寄存器的低字节LSB
- DDS_W16(0x8000); //写频率1寄存器的高字节MSB
- DDS_W16(0xC000); //写相位0
- DDS_W16(0xF000); //写相位1
- DDS_W16(0x2000); //28位连续,选择频率0,相位0,RESET=0
- }
- void DDS_f(){ //设置频率
- ulong m;
- uint mL,mH;
- if( feq > fMax ) feq = fMax;
- m = feq*10 + feq*11/16 + feq*12/256 + feq*12/256/16 + feq*6/65536; // f* 268435456/ 25000000
- mL = m, mH = m>>14; //分离出低字节和高字节(各14bit有效)
- mL = (mL & 0x3FFF) + 0x4000; //补上前导01
- mH = (mH & 0x3FFF) + 0x4000; //补上前导01
- DDS_W16(0x2000); DDS_W16(mL); DDS_W16(mH); //连续28bit写频,RESET=0时所设频率被应用
- }
- /**********
- 字形编码图
- 32
- -
- 64| | 128
- - 16
- 1| | 8
- _. 4
- 2
- **********/
- uchar code zk[20]={235,136,179,186,216,122,123,168,251,250}; //字库
- uchar disp[6]={168,251,250}; char cx=-1; //显示缓存,cx光标位置
- sfr P1M1=0x91; //P1端口设置寄存器
- sfr P1M0=0x92; //P1端口设置寄存器
- sfr P0M1=0x93; //P0端口设置寄存器
- sfr P0M0=0x94; //P0端口设置寄存器
- sfr P2M1=0x95; //P2端口设置寄存器
- sfr P2M0=0x96; //P2端口设置寄存器
- sfr P3M1=0xB1; //P3端口设置寄存器
- sfr P3M0=0xB2; //P3端口设置寄存器
- sbit ds3=P2^4; //数码管扫描口
- sbit ds2=P2^5; //数码管扫描口
- sbit ds1=P2^6; //数码管扫描口
- sbit ds0=P2^7; //数码管扫描口
- sbit kx0=P3^4; //键盘扫描口
- sbit kx1=P3^5; //键盘扫描口
- sbit kx2=P3^6; //键盘扫描口
- sbit kx3=P3^7; //键盘扫描口
- sbit K0=P3^3; //调零开关端口(输出)
- sbit KP=P3^2; //电源管理
- sbit spk=P2^0; //蜂鸣器
- //功能程序开始
- xdata uchar menu=1,menuF=0,menu2=0;
- void cls(){ char i; for(i=0;i<6;i++) disp=0; } //清屏
- void showDig(long f){ //显示数字
- uchar i;
- cls();
- for(i=0;i<6;i++) { disp=zk[f%10], f/=10; if(!f) break; }
- }
- uchar tms=0,ts=0,tm=0,th=0; ////tms为5ms计数器
- uchar tmX=0; //无操作时间(自动关机使用)
- void timerInter1(void) interrupt 3 {//T1中断
- TH1=0xa8; TL1+=0x11;
- tms++;
- if(tms==100){
- tms = 0, ts++; //秒跳变
- if(ts==60){
- ts=0, tm++,tmX++; //分钟跳变
- if(tm==60) tm=0, th++;
- if(th==24) th=0;
- if(tmX==8) KP = 0; //自动关机
- }
- }
- }
- void timerInter(void) interrupt 1 {//T0中断
- }
- xdata int V0=0,V1=0,V10=0; //V0调零电压,V1检波电压
- int code lineV[14]={0,1,2,3,4,5,10,15,20,25,50,75,100,125}; //娇正输出表(线性表)
- int jiaozheng(long v){ //输入已调零的电压值
- char i,b;
- int a;
- if(v<=0) return 0;
- for(i=1;i<14;i++) if(v<cs.jz) break;
- if(i==14) i=13;
- //温漂改正
- b = (V0-cs.jz[0])*7/10; //零点漂移量的70%
- if(v<170) v += v*b/170;
- else v += b;
- //矫正
- if(i) a = cs.jz[i-1]; else a = 0;
- return lineV[i-1]*10 + (lineV-lineV[i-1])*10*(v-cs.jz[i-1])/(cs.jz-cs.jz[i-1]);
- }
- uint Qlc(int f, ulong v){ //Q值计算,f单位千赫,非线性v矫正后的电压
- xdata int a = cs.z[Nda-1];
- xdata char i;
- i = f/500, f%=500;
- if(i<Nda-1) a = cs.z + f*(cs.z[i+1]-cs.z)/500;
- return (v*cs.bas + a/2)/a;
- }
- void showQ(){ //显示Q
- if(V1>=1023) { disp[0]=disp[1]=disp[2]=disp[3]=128; return; }
- showDig( Qlc(feq/1000,jiaozheng(V1-V0)) );
- disp[1] += 4;
- }
- void showF(){ //显示频率
- if(ts%4==0){
- showDig(feq%10000);
- disp[3] = 115;
- if(!disp[1]) disp[1]=zk[0];
- if(!disp[2]) disp[2]=zk[0];
- }else{
- showDig(feq/1000);
- if(feq>=10000000) disp[3]+=4;
- }
- }
- void zeroOff(){ //读取调零值
- spk=1; //关闭蜂鸣器,防音频干扰
- K0=1; delay2(50); //调零开关置位
- V0=get_AD2(); //读取调零电压
- K0=0; delay2(50); //调零开关复位
- }
- xdata ulong fm=0; //中心谐振点
- int Q3db=0,C0=0; //3dB Q值,C0分布电容
- long Lx = 10000,Cz=5000; //Lx被电感的电感量(单位0.01uH),Cz主调电容值(单位0.1pF)
- int readV(ulong f){ feq=f; DDS_f(); delay(60000); return jiaozheng(get_AD2()-V0); } //置频率并读取谐振电压,返回矫正后的电压
- void autoF(int maxQ,char N){ //自动查找谐振点,N扫频点数(实扫频2N+1点),通常N=50足够,N<maxQ/2
- char i,k; //循环变量
- xdata long bc=feq/maxQ; //扫描步长,建议maxQ=5000设计
- char im=0,an=0; int vm=0,qm; //极点变量
- xdata int va,vb,v3db; //偏频计算的变量
- xdata long pf,pf1,pf2; //偏频计算的变量
- spk=1; //关闭蜂鸣器,防音频干扰
- delay2(100);//等待1秒
- //开始扫频,查找极点
- fm = feq;
- for(k=0;k<2;k++){ //分两次查找,第一次粗调,第二次细调
- an=0, vm=0; //an溢出计数器
- for(i=-N;i<=N;i++){
- feq=fm+i*bc; DDS_f(); //设置频率
- delay(4000); V1=get_AD2(); //读电压
- if(vm<V1) im=i,vm=V1; //记录最大值
- if(V1>=1023) an++;
- }
- im += an/2, fm+=im*bc; //极值位置
- N=10, bc/=N;
- }
- vm=jiaozheng(vm-V0), v3db = vm*17/24, qm=Qlc(fm/1000,vm);
- //已找到谐振点,下面进一频做3dB分析
- pf = fm*5/qm; //带通半宽度
- va = readV(fm+pf/2); if(va<v3db) qm*=5,pf/=5; //量程判断
- pf1 = pf, pf2 = -pf;
- va = readV(fm+pf); //右频偏1
- vb = readV(fm+pf*9/10); //右频偏2
- if(vb!=va) pf1 -= (pf/10)*(v3db-va)/(vb-va); //精确右偏频点
- va = readV(fm-pf); //左频偏1
- vb = readV(fm-pf*9/10); //左频偏2
- if(vb!=va) pf2 += (pf/10)*(v3db-va)/(vb-va); //精确左偏频点
- //谐振点及3dB
- fm = fm+(pf2+pf1)/2; //谐振频率
- if(pf1>pf2) Q3db = fm*10/(pf1-pf2); else Q3db=0; //计算3dB Q值
- if(!Lx) Lx = 2.53303e19/fm/fm/cs.C; //电感量计算,单位0.01uH
- Cz = 2.53303e19/fm/fm/Lx; //谐振总电容,单位0.1pF
- if(Q3db>qm) C0 = Cz*(Q3db-qm)/Q3db; else C0=0; //1l是1的长整型
- feq = fm; DDS_f();
- }
- //修改1:按键转码
- uchar key_T[16]={
- 1,2,3,10,
- 4,5,6,11,
- 7,8,9,12,
- 13,0,14,15
- };
- //修改1:按键转码结束
- main(){
- uchar i=0,j=0,kn=0,key=0,act=1;
- uchar dispN=0; //显示扫描索引
- uchar spkN=0; //蜂鸣器发声时长
- //定时器T0设置,用于信号发生器
- TCON=0, TMOD=0x12; //将T0置为自动重装定时器,T1置为定时器
- TH1=0xA8, TL1=0x11;
- TR1=1; //T1开始计数
- TR0=0; //T0暂停计数
- ET1=1; //T1开中断
- ET0=1; //T1开中断
- EA=1; //开总中断
- PT0=1; //设置优先级
- set_channel(0); //设置AD转换通道
- P2M0 = 0xF0; //P2.4567置为推勉输出
- P1M1 = 0x03; //P1.01置为高阻抗
- P3M0 = 0x0C; //P3.23置为推勉输出口
- delay2(50); //等待电路的电压平稳
- zeroOff(); //调零
- DDS_init(); DDS_f(); //DDS初始化
- cs_RW(0); //读取比值基数(调零时已做开机延时,确保电压上升到可读取EEPROW)
- while(1){
- V10-=(V10+5)/10; V10+=get_AD2(); V1=(V10+5)/10; //取检波电压(数字滤波)
- //显示disp
- dispN=(++dispN)%4; //扫描器移动
- ds0=ds1=ds2=ds3=0;
- if(dispN==0) ds0=1;
- if(dispN==1) ds1=1;
- if(dispN==2) ds2=1;
- if(dispN==3) ds3=1;
- if(dispN==cx && tms>100) P0=255; //光标闪烁
- else P0=~disp[dispN]; //显示
- //扫描键盘
- for(i=0,key=255;i<16;i++){
- kx0=kx1=kx2=kx3=1;
- switch(i%4){ //X线置0
- case 0: kx0=0; break;
- case 1: kx1=0; break;
- case 2: kx2=0; break;
- case 3: kx3=0;
- }
- //修改2:键盘转码
- if(!(P1 & 1<<i/4+4 )) { key=key_T[i]; if(kn<255) kn++; break; } //有键按下
- }
- if(i==16) kn=0; //无键按下
- //键盘响应
- if(kn==20) spkN=50,tmX=0; else key=255; //当按下一定时间后,key才有效,否则无效。spkN发声时长设置
- if(spkN) spkN--, spk=0; else spk=1; //键盘发声
- //菜单系统
- if(key==15) menu=0,menu2=0;
- if(key==12) { if(menuF) menu=menuF, menuF=0; else menuF=menu, menu=255; key=255; } //频率显示键
- if(menuF){ //编辑频率
- if(key<10 ) feq = feq*10+key; //设置频率,有数字键按下则进入编辑状态
- if(key==10) feq = 0; //清除
- if(key==11) feq *= 1000; //整千赫输入
- if(key<15) DDS_f();
- showF(); //显示
- }
- if(menu==0){ //显示菜单
- int Vbat;
- set_channel(1); //设置AD转换通道
- delay(20); Vbat = get_AD2(); //读取电池电压
- set_channel(0); //设置AD转换通道
- Vbat = Vbat*14/29;
- showDig(Vbat);
- disp[2]+=4;
- disp[3]=2;
- if(key<15) { menu=key; continue; }
- }
- if(menu==1){ //显示Q
- if(key<=4) menu2 = key;
- if(key==13) { feq += fstep; DDS_f(); } //频率微调
- if(key==14) { feq -= fstep; DDS_f(); } //频率微调
- if(key==5) { feq = 1000000; DDS_f(); } //设置频率为中波段频率的中心
- if(key==6) { feq = 3000000; DDS_f(); } //设置频率为3MHz频率
- if(key==7) { autoF(200,100); } //宽范围自动粗调谐
- if(key==8) { fstep=20; }
- if(key==9) { fstep=100; }
- if(key==11) { autoF(5000,50); } //窄范围自动细调谐
- if(key==10) { zeroOff(); } //调零
- if(menu2==0) { if(tms%10==0) showQ(); } //显示Q
- if(menu2==1) { showDig(Q3db); disp[1]+=4; } //显示3dB法Q值
- if(menu2==2) { showDig(Cz); disp[1]+=4; } //显示主调电容
- if(menu2==3) { showDig(C0); disp[1]+=4; } //显示分布电容
- if(menu2==4) { //显示电感量
- if(Lx<9999) { showDig(Lx); disp[2]+=4; }
- else if(Lx<99999) { showDig(Lx/10); disp[1]+=4; }
- else { showDig(Lx/100); }
- }
- }
- if(menu==14){ Lx=0; autoF(5000,50); menu=1; key=255; } //电感量测量
- if(menu==2){ //显压显示
- if(key>=0&&key<10) menu2=key;
- if(key==10) zeroOff(); //强制调零
- if(menu2==0) { if(tms%10==0) showDig(jiaozheng(V1-V0)); } //显示矫正后的电压
- if(menu2==1) { if(tms%10==0) showDig(V0); } //显示调零电压
- if(menu2==2) { if(tms%10==0) showDig(V1); } //显示检波电压
- }
- if(menu==3){ //编辑比值基数
- if(key==14) menu2=0;
- if(key==13) menu2=1;
- if(menu2==0){ //设置变压器的比值(例如比值为56,应输入560)
- if(key<10) cs.bas = cs.bas*10+key; //修改
- if(key==10) cs.bas = 0; //清零
- if(key==11) cs_RW(1); //保存
- showDig(cs.bas);
- }
- if(menu2==1){ //设置主调电容的最大容量
- if(key<10) cs.C = cs.C*10+key; //修改
- if(key==10) cs.C = 0; //清零
- if(key==11) cs_RW(1); //保存
- showDig(cs.C);
- }
- }
- if(menu==4){ //编辑激励电压
- //频点选择
- if(key==14&&menu2>0) menu2--;
- if(key==13&&menu2<Nda-1) menu2++;
- //手动修改
- if(key<10) cs.z[menu2] = cs.z[menu2]*10+key; //手动修改
- if(key==10) cs.z[menu2] = 0; //清零
- if(key==0 && cs.z[menu2]==0){ //已清零再输入0则全部清0
- for(i=0;i<Nda;i++) cs.z=0;
- }
- if(key==11){ //保存
- spk=1; //关闭蜂鸣器,防音频干扰
- for(i=0;i<Nda;i++){ //自动检查,如果数据为空则自动测量
- if(cs.z>0&&cs.z<255) continue;
- if(i==0) feq = 300; else feq = i*500;
- feq*=1000; DDS_f();
- delay2(5); V1=get_AD2(); //读电压
- cs.z = jiaozheng(V1-V0);
- }
- cs_RW(1);
- }
- showDig(cs.z[menu2]*10+(menu2/2)%10);
- disp[1]+=4; if(menu2%2) disp[0]+=4;
- }
- if(menu==5){ //非线性校正数据编辑
- //插值点选择
- if(key==14&&menu2>0) menu2--;
- if(key==13&&menu2<13) menu2++;
- if(key<10) cs.jz[menu2] = cs.jz[menu2]*10+key; //编辑
- if(key==10) cs.jz[menu2] = 0; //清零
- if(key==11) cs_RW(1); //保存
- if(ts%2) { showDig(lineV[menu2]); disp[3]=207; }//显示等分定标电压值
- else showDig(cs.jz[menu2]); //显示未桥正的电压值(已调零)
- }
- delay(4000);
- }//while end
- }
复制代码
|
打赏
-
查看全部打赏
|