Auto_LCR_Meter_XJW01/1602.c

650 lines
23 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//==========================================================================
// LCR表驱动程序 V1.0
// xjw01 于莆田 2011.10
//==========================================================================
//==========================================================================
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#include <reg52.h>
#include <math.h>
//==========================================================================
// 项目LCD1602 四线驱动程序
// 设计要点:
// LCD1602 的运行速度慢,而单片机运行的速度快,因此容易因为速度不
// 匹配造成调试失败。因此调试之前应准确测试lcd_delay() 延时函数
// 准确的延时量,如果不能满足注释中的要求,则应调整循次数。每步操
// 作所需的延时量,按照数据手册指标指行,同时留下足够的时间余量。
// 硬件连接:
// 至少需要9条线电源线2条7条信号线。信号线详见程序中的接口定义。
// 清注意对LCD1602比对的调节否则无显示。
// 设计:许剑伟,于莆田,2010.12
//==========================================================================
sbit lcd_RS = P0^6; //数据命令控制位,0命令1数据
sbit lcd_RW = P0^5; //读写位,0写1读
sbit lcd_EN = P0^4; //使能位,下降沿触发
sbit lcd_D4 = P0^3; //数据端口D4
sbit lcd_D5 = P0^2; //数据端口D5
sbit lcd_D6 = P0^1; //数据端口D6
sbit lcd_D7 = P0^0; //数据端口D7
//==========================================================================
void lcd_delay(int n){ //LCD专用延时函数
//32MHz钟频下约循环3000次延迟1毫秒
int i,j;
if(n<0) { for(i=0;i< 30;i++); return; } //10us
if(n== 0) { for(i=0;i<150;i++); return; } //50us
for(;n;n--){ for (j=0;j<3000;j++); } //n毫秒
}
//==========================================================================
void lcd_B(char f, uchar c, char t){ //控制四线式接口LCD的7个脚
//f=0写命令字, f=1写RAM数据, f=2读RAM数据, f=3读RAM数据
lcd_EN = 0;
lcd_RS = f%2;
lcd_RW = f/2%2;
//移入高四位
lcd_D4 = c & 16;
lcd_D5 = c & 32;
lcd_D6 = c & 64;
lcd_D7 = c & 128;
lcd_EN = 1; lcd_delay(-1); lcd_EN = 0; //使能脉冲
if(f==4) { lcd_delay(t); return; }
//移入低四位
lcd_D4 = c & 1;
lcd_D5 = c & 2;
lcd_D6 = c & 4;
lcd_D7 = c & 8;
lcd_EN = 1; lcd_delay(-1); lcd_EN = 0; //使能脉冲
lcd_delay(t); //不同的命令,响应时间不同,清零命令需要2ms
}
//==========================================================================
void lcd_init(){ //LCD1602 初始化
//启动四线模式须势行9个步骤初始化所须耗时较长约65ms时限不可减
lcd_delay(20); //启动lcd之前须延时大于15ms直到VDD大于4.5V
lcd_B(4, 0x30, 9); //置8线模式,须延时大于4.1ms
lcd_B(4, 0x30, 5); //置8线模式,须延时大于100us
lcd_B(4, 0x30, 5); //置8线模式,手册中未指定延时
lcd_B(4, 0x20, 5); //进入四线模式
lcd_B(0, 0x28, 5); //四线模式双行显示
lcd_B(0, 0x0C, 5); //打开显示器
lcd_B(0, 0x80, 5); //RAM指针定位
lcd_B(0, 0x01, 5); //启动清屏命初始化LCD
}
//==========================================================================
//=========================几个功能常用函数=================================
void lcd_cls() { lcd_B(0, 0x01+0, 2); } //清屏
void lcd_cur0() { lcd_B(0, 0x0C+0, 0); } //隐藏光标
void lcd_goto1(uchar x){ lcd_B(0, 0x80+x, 0); } //设置DDRAM地址,第1行x位
void lcd_goto2(uchar x){ lcd_B(0, 0xC0+x, 0); } //设置DDRAM地址,第2行x位
void lcd_putc(uchar d) { lcd_B(1, 0x00+d, 0); } //字符输出
void lcd_puts(uchar *s){ for(; *s; s++) lcd_B(1,*s,0); } //字串输出
//==========================================================================
//===============================延时函数===================================
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 getAD2(){
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;
}
*/
uint getAD10() reentrant { //10次采样
char i;
uint c = 0;
for(i=0;i<10;i++) c += getAD2();
return c;
}
//==========================================================================
//==================================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
应注意,擦除命令会将整个扇区擦除
*********************/
void saEEP(){ //EEP保护
IAP_cmd = 0; //关闭令,保护
IAP_contr = 0; //关EEPROM保护
IAP_trig = 0;
IAP_addrL = 255; //设置读取地址的低字节,地址改变才需要设置
IAP_addrH = 255; //设置读取地址的高字节,地址改变才需要设置
}
uchar readEEP(uint k){ //读取
IAP_addrL = k; //设置读取地址的低字节,地址改变才需要设置
IAP_addrH = k>>8; //设置读取地址的高字节,地址改变才需要设置
IAP_contr = 0x81; //设置等待时间1MHz以下取72M以下取63M取56M取412M取320M取224M取130M取0前导1表示许档IAP
IAP_cmd = 1; //读取值1写取2擦除取3擦除时按所在字节整个扇区撺除
IAP_trig = 0x5A; //先送5A
IAP_trig = 0xA5; //先送5A再送A5立即触发
saEEP(); //保护
return IAP_data;
}
void writeEEP(uint k, uchar da){ //写入
IAP_data = da; //传入数据
IAP_addrL = k; //设置读取地址的低字节,地址改变才需要设置
IAP_addrH = k>>8; //设置读取地址的高字节,地址改变才需要设置
IAP_contr = 0x81; //设置等待时间1MHz以下取72M以下取63M取56M取412M取320M取224M取130M取0前导1表示许档IAP
IAP_cmd = 2; //读取值1写取2擦除取3擦除时按所在字节整个扇区撺除
IAP_trig = 0x5A; //先送5A
IAP_trig = 0xA5; //先送5A再送A5立即触发
saEEP(); //保护
}
void eraseEEP(uint k){ //擦除
IAP_addrL = k; //设置读取地址的低字节,地址改变才需要设置
IAP_addrH = k>>8; //设置读取地址的高字节,地址改变才需要设置
IAP_contr = 0x81; //设置等待时间1MHz以下取72M以下取63M取56M取412M取320M取224M取130M取0前导1表示许档IAP
IAP_cmd = 3; //读取值1写取2擦除取3擦除时按所在字节整个扇区撺除
IAP_trig = 0x5A; //先送5A
IAP_trig = 0xA5; //先送5A再送A5立即触发
saEEP(); //保护
}
xdata struct Ida{
char zo[3];//三个频率下的零点改正值
char j1; //相位补偿(3倍档)
char j2; //相位补偿(10倍档)
char J[4]; //相位补偿(V/I变换器)
char R[4]; //下臂电阻修正(20,1k,10k,100k)
char g1; //增益修正(3倍档)
char g2; //增益修正(10倍档)
} cs;
void cs_RW(char rw){
uchar i,*p = &cs;
if(rw){
eraseEEP(0);
for(i=0;i<sizeof(cs);i++) writeEEP(i,p[i]);
}else{
for(i=0;i<sizeof(cs);i++) p[i]=readEEP(i);
}
}
//==========================================================================
//==================================LCR主程序===============================
//==========================================================================
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 spk=P2^3; //蜂鸣器
sbit Kb=P2^1; //量程开关B
sbit Ka=P2^2; //量程开关A
sbit DDS2=P1^2;//移相方波输出口
sbit K3=P1^7;
sbit K4=P1^6;
sbit K5=P1^5; //7.8kHz滤波开关
sbit K6=P1^4;
sbit K8=P2^0; //100Hz滤波开关
xdata uchar menu=1,menu2=0; //菜单变量
//==============字符显示函数====================
#define digW 4 //数字显示位数宏
void lcd_putp(float a,float b,char bo,char n, float qmin){ //带单位显示复数,n是单位下限,qmin是最小位权值(用于限定有效数字)
code uchar dwB[] = {'p','n','u','m','o','k','M','G'}; //单位表
char i,j, c=0, h=digW-1, fh[2]={' ','+'};
long d,q,Q=1; //D最高位权
float f,g=1;
if(a<0) fh[0] = '-', a = -a;
if(b<0) fh[1] = '-', b = -b;
if(a>b) f = a; else f = b;
if(qmin) {
a += qmin/2, a -= fmod(a,qmin)-qmin/1000;
b += qmin/2; b -= fmod(b,qmin)-qmin/1000;
}
for(i=1;i<digW;i++) Q *= 10;
for(i=0;i<3;i++){ if(f*g >= 1000) g/=1000, c++; } //以3位为单位移动小数点,右移
for(i=0;i<n;i++){ if(f*g < 1) g*=1000, c--; } //以3位为单位移动小数点,左移
for(i=1;i<digW && f*g<Q;i++) g*=10,h--; //继续移动小数点,使之满字
for(i=0;i<2;i++){
if(i) d = b*g; //取出实部
else d = a*g; //取出虚部
q = Q;
lcd_putc(fh[i]); //显示符号
for(j=0; j<digW; j++){ //数字输出
lcd_putc(d/q+48); //数字
if(j==h) lcd_putc('.');//小数点
d %= q, q /= 10;
}
if(!bo) break; //不显示虚部
}
lcd_putc(dwB[c+4]); //单位
}
void lcd_putf(float a, char n, float qmin) //带单位显示浮点数,n是单位下限
{ lcd_putp(a,0,0,n,qmin); }
void lcd_int(uint a,char w){ //定宽显示正整数
char i=0, s[5] = {' ',' ',' ',' ',' '};
for(;a;i++){ s[i] = a%10+48, a /= 10; }
for(;w;w--) lcd_putc(s[w-1]);
}
//==============低频信号DDS====================
//PCA相关寄存器
sfr CMOD = 0xD9; //钟源选择控制等
sfr CH = 0xF9; //PCA的计数器
sfr CL = 0xE9; //PCA的计数器
sfr CCON = 0xD8; //PCA控制寄存器
sfr CCPAM0 = 0xDA; //PCA模块0工作模式寄存器
sfr CCPAM1 = 0xDB; //PCA模块1工作模式寄存器
sfr CCAP0L = 0xEA; //模块0捕获寄存器低位
sfr CCAP0H = 0xFA; //模块0捕获寄存器高位
sbit PPCA = IP^7; //PCA的中断优先级设置
sbit CCF0 = CCON^0; //PCA的模块0中断标志
sbit CCF1 = CCON^1; //PCA的模块1中断标志
sbit CR = CCON^6; //PCA计数器使能
void PWM_init(){ //把PCA置为PWM
CMOD = 2; //0000 0010 计数源选择,钟源取fosc/2
CL = CH = 0;
CCAP0L = CCAP0H = 192; //占空比为25%
//CCPAM0=0x42;//0100 0010,PCA的模块0设置为PWM模式,无中断
CCPAM0=0x53;//0101 0011,PCA的模块0设置为PWM模式,有中断,下降沿中断
PPCA = 1; //优先中断
//CR = 1; //开始计数
EA = 1; //开总中断
}
uint ph=0, phM=256, feq=1000; //相位,phM相位步进值
xdata float feqX=1000; //实际输出频率
uchar code sinB[256]={
//查询表中不可装载零值,否则会造成无中断产生
255,255,255,255,255,255,254,254,253,252,252,251,250,249,248,247,246,245,243,242,240,239,237,236,234,232,230,229,227,225,222,220,
218,216,214,211,209,206,204,201,199,196,194,191,188,185,183,180,177,174,171,168,165,162,159,156,153,150,147,144,140,137,134,131,
128,125,122,119,116,112,109,106,103,100, 97, 94, 91, 88, 85, 82, 79, 76, 73, 71, 68, 65, 62, 60, 57, 55, 52, 50, 47, 45, 42, 40,
38, 36, 34, 31, 29, 27, 26, 24, 22, 20, 19, 17, 16, 14, 13, 11, 10, 9, 8, 7, 6, 5, 4, 4, 3, 2, 2, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 16, 17, 19, 20, 22, 24, 26, 27, 29, 31, 34, 36,
38, 40, 42, 45, 47, 50, 52, 55, 57, 60, 62, 65, 68, 71, 73, 76, 79, 82, 85, 88, 91, 94, 97,100,103,106,109,112,116,119,122,125,
128,131,134,137,140,144,147,150,153,156,159,162,165,168,171,174,177,180,183,185,188,191,194,196,199,201,204,206,209,211,214,216,
218,220,222,225,227,229,230,232,234,236,237,239,240,242,243,245,246,247,248,249,250,251,252,252,253,254,254,255,255,255,255,255
};
uchar code fbB[256]={ //方波DDS查询表
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
};
uchar chuX=0; //方波DDS初相
void PCAinter(void) interrupt 7 {//PCA中断
uchar x,y;
CCF0=0; //清除中断请求,以免反复中断
x = ph >> 8; //截断正弦相位累加器,取高8位
y = x + chuX; //方波相位
CCAP0H = sinB[x];//正弦DDS输出
DDS2 = fbB[y]; //方波DDS输出
ph += phM; //相位累加
}
void setDDS(uint f){ //参考时钟是c=(fosc/2)/256=32000000/2/256=62500,频率f=c*phM/2^16
feq = f;
phM=f*65536.0/62500; //phM=f*2^16/62500
feqX = 62500.0*phM/65536; //实际输出频率
ph = 0; //高频时,使波形对称
if(!f) CR=0; else CR=1;
}
//相位控制函数
xdata char xw=0; //相位
void set90(char k){ //设置方波的相位差
k %= 4;
if(k<0) k += 4;
if(k==0) chuX=0; //移相0度
if(k==1) chuX=64; //移相90度
if(k==2) chuX=128; //移相180度
if(k==3) chuX=192; //移相270度
xw = k;
}
void set902() { set90(xw+1); } //相位步进
//==============量程控制函数====================
xdata char rng=1; //量程
void setRng(char k){//切换量程
if(k==0) Ka=0,Kb=0; //100欧
if(k==1) Ka=0,Kb=1; //1k欧
if(k==2) Ka=1,Kb=0; //10k欧
if(k==3) Ka=1,Kb=1; //100k欧
rng = k;
}
void setRng2(){ setRng( (rng+1)%4); } //量程步进
//==============增益控制函数====================
char curGain=1; //当前增益索引号
void setGain(char k){ //设置电路增益
if(k>3) k=3;
if(k<0) k=0;
if(k==0) K4=0,K6=0; //1倍
if(k==1) K4=0,K6=1; //3倍
if(k==2) K4=1,K6=0; //10倍
if(k==3) K4=1,K6=1; //30倍
curGain = k;
}
void setGain2(){ setGain((curGain+1)%4); }
//==============LCR测量====================
xdata int Vxy[4]={0,0,0,0}; //Vxy[Vx1,Vy1,Vx2,Vy2]
xdata char Sxw[4]={0,1,0,1}; //保存正确相位
xdata char Vga[4]={1,1,1,1}; //上下臂增益记录表
xdata uchar tim=0,tims=0;
xdata char pau=0; //暂停坐标自动旋转
#define Vfull 9600
#define gad (9600/30)
uchar mT = 6; //测量速度,mT取值为6或12或24时可以消除数字噪声尾数不动但不利于于取平均
//==============设置频率====================
xdata char feqK=1; //频率索引号
void setF(char k){
if(k==-1){ //步进
k = 0;
if(feq==100) k=1;
if(feq==1000) k=2;
if(feq==7813) k=0;
}
feqK = k;
if(k==0) { setDDS(100); K5=0; K8=1; mT=12; } //置为100Hz
if(k==1) { setDDS(1000); K5=0; K8=0; mT=6; } //置为1kHz
if(k==2) { setDDS(7813); K5=1; K8=0; mT=6; } //置为7.8125kHz
TH1 = 47, TL1 = 171; //置为20ms
tims = 0;
tim = 0;
ph = 0;
}
int absMax(int a,int b){ //取两个数绝对值最大者
if(a<0) a = -a;
if(b<0) b = -b;
if(b>a) a = b;
return a;
}
#define avn 4 //求平无个数
xdata float vq[3][avn]; //数据缓存,用于求平均
void LCRcalc(int *v,char *g){ //LCR计算
code float ga[4] = { 1, 3, 9, 27 }; //增益表
code float dwR[4] = { 20, 1e3, 1e4, 1e5 }; //各档电阻表
xdata int g12 = (int)cs.g1+cs.g2; //增益最大补偿
xdata int j12 = (int)cs.j1+cs.j2; //相位最大补偿
xdata float JD = 0,cJD, G = 0; //补偿变量
xdata float a,b,c,e;
char i;
a = +( 1.0*v[2]*v[2] + 1.0*v[3]*v[3] );
b = -( 1.0*v[0]*v[2] + 1.0*v[1]*v[3] );
c = -( 1.0*v[2]*v[1] - 1.0*v[0]*v[3] );
a *= ga[g[0]] / ga[g[2]];
a /= dwR[rng]*(1+cs.R[rng]/10000.0); //除以下臂电阻阻值
//可控增益单元的增益修正、相位补偿量
if(g[0] == 1) JD += cs.j1, G += cs.g1;
if(g[0] == 2) JD += cs.j2, G += cs.g2;
if(g[0] == 3) JD += j12, G += g12;
if(g[2] == 1) JD -= cs.j1, G -= cs.g1;
if(g[2] == 2) JD -= cs.j2, G -= cs.g2;
if(g[2] == 3) JD -= j12, G -= g12;
JD -= cs.J[rng];
JD *= feqX/7813/1000;
cJD = 1 - JD*JD/2;
a *= 1+G/10000; //增益补偿
e = b*cJD - c*JD; //相位补偿
c = b*JD + c*cJD; //相位补偿
b = e;
//入队
for(i=1;i<avn;i++){
vq[0][i] = vq[0][i-1];
vq[1][i] = vq[1][i-1];
vq[2][i] = vq[2][i-1];
}
vq[0][0]=a, vq[1][0]=b, vq[2][0]=c;
}
void timerInter1(void) interrupt 3 {//T1中断,LCR数据采集
char g; int c=0;
tims++;
if(tims>=mT) tims = 0, tim++, c = 1;
if(tim>=4) tim=0;
if(pau) return;
if(c){ //tim进位触发
c = getAD10(); //读取电压值
c -= cs.zo[feqK];
Vxy[tim] = xw<2 ? c : -c; //保存当前电压
Vga[tim] = curGain; //保存当前增益
Sxw[tim] += c<0 ? 2 : 0; //相位翻转(预测下次的相位采用值)
Sxw[tim] %= 4;
if(tim==1||tim==3){ //上下臂切换
//电压模值才能反应运放的输出幅度,所以增益切换判断得用模值
if(tim==1) K3=1, c = absMax(Vxy[2],Vxy[3]), g=Vga[2]; //切换到下臂
if(tim==3) K3=0, c = absMax(Vxy[0],Vxy[1]), g=Vga[0]; //切换到上臂
if(c>Vfull) g--;
else if(c<gad*1 ) g += 3; //增加27倍
else if(c<gad*3 ) g += 2; //增加9倍
else if(c<gad*9) g++; //增加3倍
setGain(g);
}
set90( Sxw[ (tim+1)%4 ] ); //相位旋转
LCRcalc(Vxy,Vga);
}
}
void showR(char binLian){ //显示LCR
char i;
xdata float a=0,b=0,c=0,e,w;
for(i=0;i<avn;i++)
a += vq[0][i]/avn,
b += vq[1][i]/avn,
c += vq[2][i]/avn;
//电学量显示 if(!a) { lcd_cls(); lcd_puts("DIV 0"); return; }
w = 2*3.1415926*feqX;
lcd_goto2(0); //显示频率
if(feq==100) lcd_putc('A');
if(feq==1000) lcd_putc('B');
if(feq==7813) lcd_putc('C');
lcd_putc(rng+49); //显示量程
if(binLian){ //并联
e = (b*b+c*c)/a;
lcd_goto1(0);
lcd_puts("Zp");
lcd_putf(e/b, 1, 1e-4); //显示并联复阻抗,显示到毫欧
lcd_putf(e/c, 1, 1e-4); //显示并联复阻抗,显示到毫欧
lcd_goto2(2);
if(c<0) { lcd_putf(-c/e/w, 4, 1e-14); lcd_putc('F'); } //显示并联C值,显示到pF
else { lcd_putf(+e/c/w, 2, 1e-8 ); lcd_putc('H'); } //显示并联L值,显示到uH
}else{ //串联
e = a;
lcd_goto1(0);
lcd_puts("Zs");
lcd_putp(b/e, c/e, 1, 1, 1e-4); lcd_putc(244); //显示串联复阻抗,显示到毫欧
lcd_goto2(2);
if(c<0) { lcd_putf(-e/c/w, 4, 1e-14); lcd_putc('F'); } //显示C值,显示到pF
else { lcd_putf(+c/e/w, 2, 1e-8 ); lcd_putc('H'); } //显示L值,显示到uH
}
if(b){ c = fabs(c/b); if(c>999) c=999; } //计算Q
else c = 999;
lcd_putf(c,0,0); //显示Q
}
//void timerInter(void) interrupt 1 {}//T0中断
main(){
uchar i=0,kn=0,key=0;
uchar dispN=0; //显示扫描索引
uchar spkN=0; //蜂鸣器发声时长
uint nn=0;
uchar binLian=0;
lcd_init(); //初始化LCD
lcd_cur0(); //隐藏光标
lcd_puts("LCR 2.0");
lcd_goto2(0);
lcd_puts("XJW Putian,2011");
delay2(80); //启动延时
cs_RW(0); //读EEPROM
TCON=0, TMOD=0x12; //将T0置为自动重装定时器T1置为定时器
TH1 = 0, TL1 = 0;
TR1=1; //T1开始计数
TR0=0; //T0暂停计数
ET1=1; //T1开中断
ET0=1; //T1开中断
EA=1; //开总中断
PT0=1; //设置优先级
set_channel(0); //设置AD转换通道
P2M0 = 0xFF; //P2.01234567置为推勉输出
P1M0 = 0xFC; //P1.234567置为推换口
P1M1 = 0x03; //P1.0置为高阻抗
P2 = 0x0F;
PWM_init();//DDS初始化
set90(2); //初始设置相位
setRng(1); //初始设置量程
setGain(1); //初始设置增益
setF(1); //DDS初始设置为1kHz
while(1){
//显示disp
nn++;
//扫描键盘
key = ~P3;
if(key&&kn<255) kn++; else kn=0;
for(i=0;key;i++) key/=2; key=i;
if(kn==4) spkN=10; else key=0; //当按下一定时间后key才有效。spkN发声时长设置
if(spkN) spkN--, spk=0; else spk=1; //键盘发声
//菜单系统
if(key==8){//菜单键
lcd_cls(); lcd_puts("Menu: 1 LCR");
lcd_goto2(0); lcd_puts("3 Test,7 Set");
menu=0; key=0;
}
if(menu>=1 && menu<=4){
if(key==7) setRng2(); //量程步进
if(key==6) setF(-1); //设置频率
}
if(menu==0){ //显示量程和菜单
if(key) lcd_cls();
if(key>=1 && key<=7) menu = key, menu2 = 0;
key = 0;
}
if(menu==1){ //LCR测量(串联)
pau = 0;
if(key==1) binLian = (binLian+1)%2; //串并联切换
showR(binLian);
}
if(menu==2){
lcd_goto1(0);
lcd_puts("up:"); lcd_putc(Vga[0]+48);
lcd_puts(" dw:"); lcd_putc(Vga[2]+48);
}
if(menu==3){ //手动调试
pau = 1;
if(key==1) setGain2();//增益控制
if(key==2) { };
if(key==3) K3=~K3; //切换上下臂
if(key==4) set902(); //相位旋转
lcd_goto1(0);
lcd_puts(" xw="); lcd_putc(xw+48); //相位索引号
lcd_puts(" K3="); lcd_putc(K3?49:48); //K3状态
lcd_puts(" Ga="); lcd_putc(curGain+48); //增益索引号
lcd_goto2(0);
if(nn%32==0) lcd_int(getAD10(),5);
}
if(menu==7){ //设置零点偏移数
code char *csR[15] = {
"Z0 : 20", "Z1 : 20","Z2 : 20",
"R1X: 20", "R2X: 1k", "R3X:10k", "R4X:.1M", "G1X:3k3", "G2X:10k",
"R1 : 20", "R2 : 1k", "R3 :10k", "R4 :.1M", "G1 :3k3", "G2 :10k"};
char *p,bc=1, feqD=1,rngD=1;
static char kc=0, mo=0;
if(menu2==0) p = cs.zo+0, feqD=0, rngD=2; //100Hz零点校准,接入10欧电阻
if(menu2==1) p = cs.zo+1, feqD=1, rngD=2; //1kHz零点校准,接入10欧电阻
if(menu2==2) p = cs.zo+2, feqD=2, rngD=2; //7.8kHz零点校准,接入10欧电阻
if(menu2==3) p = cs.J+0, feqD=2, rngD=0; //VI变换器相位校准,接入20电阻
if(menu2==4) p = cs.J+1, feqD=2, rngD=1; //VI变换器相位校准,接入1k电阻
if(menu2==5) p = cs.J+2, feqD=2, rngD=2; //VI变换器相位校准,接入10k电阻
if(menu2==6) p = cs.J+3, feqD=2, rngD=3; //VI变换器相位校准,接入100k电阻
if(menu2==7) p = &cs.j1, feqD=2, rngD=1; //运放3倍档相位校准,接入3.3k欧电阻
if(menu2==8) p = &cs.j2, feqD=2, rngD=1; //运放10倍档相位校准,接入10k欧电阻
if(menu2==9) p = cs.R+0, bc=2, feqD=1, rngD=0; //VI变换器模值校准,接入20欧
if(menu2==10) p = cs.R+1, bc=2, feqD=1, rngD=1; //VI变换器模值校准,接入1k欧
if(menu2==11) p = cs.R+2, bc=2, feqD=1, rngD=2; //VI变换器模值校准,接入10k欧
if(menu2==12) p = cs.R+3, bc=2, feqD=1, rngD=3; //VI变换器模值校准,接入100k欧
if(menu2==13) p = &cs.g1, bc=2, feqD=1, rngD=1; //运放3倍增益校准,接入2k欧电阻
if(menu2==14) p = &cs.g2, bc=2, feqD=1, rngD=1; //运放10倍增益校准,接入10k欧电阻
if(key==1) *p += bc; //X键增
if(key==2) *p -= bc; //R键减
if(key==3) { cs_RW(1); setF(feqK); } //L键保存
if(key==4) *p = 0; //C键清除
if(key==5) { if(menu2==0) menu2=14; else menu2--; mo=0; }
if(key==6) { if(menu2==14)menu2=0; else menu2++; mo=0; }
if(key==7) mo = (mo+1)%2;
if(key==4){ //恢复到默认值
if(++kc==5){
kc = 0;
cs.j1 = 16, cs.j2 = 18;
cs.g1 = 0, cs.g2 = 0;
cs.zo[0] = 20;
cs.zo[1] = 19;
cs.zo[2] = 14;
cs.J[0] = cs.J[1] = cs.J[2] = 0, cs.J[3] = 20;
cs.R[0] = cs.R[1] = cs.R[2] = cs.R[3] = 0;
}
}
else { if(key) kc=0; }
//显示
if(mo){
if(feqD!=feqK) setF(feqD);
if(rngD!=rng) setRng(rngD);
showR(1);
}else{
lcd_cls();
lcd_goto1(0);
lcd_puts(csR[menu2]); //输出参数名称
lcd_goto2(0);
lcd_putf(*p,0,0);
lcd_puts("X:+ R:-");
}
}
delay(20000);
}//while end
}
//==========================================================================