新人第一次发帖 ,大家不要见笑 程序是在51hei电子论坛下的 再次感谢这位楼主!费时三天。第一次调试1602没有显示!检查半天查看电路没有错,按照楼主说的加上拉电阻也没有字符!原来是调电位器终于显示了,幸福激动!哪个测大电容的电位器是校准的。没有合适的电感 电感档误差大 随后在做调整。借用别人的程序(本帖附件中可下载)
原理图:
实物制作图:
测试电容105的
没有按键开关只有用这了
电感
5v 电源供电
这是外壳
网购的1602屏
背部飞线严重就不拍了
51单片机源程序:
- //*****************************************************************
- // 大道必成 原创作品 //
- //*****************************************************************
- #include "reg52.h"
- #include "intrins.h"
- //-------宏定义---------
- #define u8 unsigned char
- #define u16 unsigned int
- #define u32 unsigned long
- #define Cref 2200 //基准电容值(单位pF)
- #define LCD_DATA P0 //LCD数据口(8位)
- //-------I/O定义--------
- sbit LCD_BUSY = P0^7; //LCD忙信号
- sbit LCD_RS = P1^0; //数据/命令选择(数据=1,命令=0)
- sbit LCD_RW = P1^1; //读/写选择(写=0,读=1)
- sbit LCD_EN = P1^2; //使能信号
- sbit K1_F_LC = P1^3; //F/LC测量选择按钮(自锁),([抬起]=0测LC,[按下]=1测F)
- sbit K2_L_C = P1^4; //L/C测量选择按钮(自锁)([抬起]=0测C,[按下]=1测L)
- sbit K3_Eb_Es = P1^6; //电解量程选择按钮(自锁),([抬起]=0低量程,[按下]=1高量程)
- sbit K4_FLC_EC = P3^6; //FLC或EC(电解电容)测量选择按钮(无锁)(每按一次,翻转一次)
- sbit K5_Calib = P3^7; //手工校正(清零)按钮(无锁)(消除寄生电容值)
- sbit Dischg = P1^5; //测量电解电容时的充放电控制端口(=0放电,=1充电)
- //-------全局变量定义--------
- bit FLC_EC_Flag; //测量标志(=0测FLC,=1测电解电容)
- u8 Measure_Flag; //测量标志(=1测电容,=2测电感,=3测频率,=4测小电解,=5测大电解)
- u8 Lref; //基准电感值(单位uH)(原作没有)
- u16 T0_times; //T0中断计数预设值(每50ms一次),测F=20次(1s),测LC=10次(0.5s)
- u16 Timer0_Num; //T0计数
- u16 Timer1_Num; //T1计数
- u32 Frequency0; //频率0(未接被测元件时的频率)
- u32 Frequency1; //频率1(接入被测元件时的频率)
- u32 Cx; //被测电容
- u32 Lx; //被测电感
- u32 ECx_H; //被测电解电容(大)
- u32 ECx_L; //被测电解电容(小)
- //------x的n次方------------
- u32 power(u8 x,u8 n)
- {
- u8 i;
- u32 j = 1;
- if(n == 0)
- {
- return 1;
- }
- else
- {
- for(i=0; i<n; i++)
- {
- j *= x;
- }
- return j;
- }
- }
- //----延时n毫秒(12M晶振,12T模式,一个指令周期=1us)---
- //----1ms=(跳转等3个指令周期+两个空指令)*200----
- void Delay_ms(u8 n)
- {
- u8 i,j;
- for(i=0; i<n; i++)
- {
- for(j=0; j<200; j++)
- {
- _nop_();
- _nop_();
- }
- }
- }
- //------LCD1602读忙标志位------
- void Check_busy(void)
- {
- do
- {
- LCD_EN=0;
- LCD_RS=0;
- LCD_RW=1;
- LCD_DATA=0xFF;
- LCD_EN=1;
- }
- while(LCD_BUSY==1);
- LCD_EN=0;
- }
- //------LCD1602写指令------
- void Write_Command(u8 cmd)
- {
- Check_busy();
- LCD_RS=0;
- LCD_RW=0;
- LCD_DATA=cmd;
- LCD_EN=0;
- LCD_EN=1;
- LCD_EN=0;
- }
- //------LCD1602写数据------
- void Write_Data(u8 dat)
- {
- Check_busy();
- LCD_RS=1;
- LCD_RW=0;
- LCD_DATA=dat;
- LCD_EN=0; //机器周期小于1us时,须加延时
- LCD_EN=1;
- LCD_EN=0;
- }
- //-----LCD1602写字符串------
- //---x=列(0~15); y=行(0,1)
- //---从指定的位置开始写,直到超出屏幕显示
- void LCD_Write_String(u8 y,u8 x,u8 *Data)
- {
- if(y==0) //第一行
- {
- if(x<16)
- {
- Write_Command(0x80+x); //0x80 + 第一行起始地址
- for(; x<16&&*Data!='\0'; x++) //'\0'字符串结束标志
- {
- Write_Data(*(Data++));
- }
- }
- }
- if(y==1) //第二行
- {
- if(x<16)
- {
- Write_Command(0xc0+x); //0xc0 + 第二行起始地址
- for(; x<16&&*Data!='\0'; x++) //'\0'字符串结束标志
- {
- Write_Data(*(Data++));
- }
- }
- }
- }
- //------LCD1602写长整型数据------
- //x=列(0~15); y=行(0,1);截取长整型后length个数字显示在指定位置(全显示length=10)
- //注意此函数不支持换行,起始列+length>15时后面的显示不出来,仅能单行显示
- void LCD_Write_Long(u8 y,u8 x,u8 length,u32 Data)
- {
- u8 i,k;
- if(length>10)
- {
- length = 10;
- }
- if(length<10)
- {
- Data = Data%power(10,length);
- }
- if(y==0) //第一行
- {
- Write_Command(0x80+x); //0x80 + 第一行起始地址
- for(i=0; i<length; i++)
- {
- k = (u8)(Data/power(10,length-1-i));
- Data = Data%power(10,length-1-i);
- Write_Data(k+0x30);
- }
- }
- if(y==1) //第二行
- {
- Write_Command(0xc0+x); //0xc0 + 第二行起始地址
- for(i=0; i<length; i++)
- {
- k = (u8)(Data/power(10,length-1-i));
- Data = Data%power(10,length-1-i);
- Write_Data(k+0x30);
- }
- }
- }
- //------LCD1602写长整型数据,可以指定小数点后位数-------
- //x=列(0~15); y=行(0,1);截取长整型后length个数字显示在指定位置(全显示length=10)
- //注意此函数不支持换行,起始列+length>15时后面的显示不出来,仅能单行显示
- //pot:小数点后显示几个数字 例:1234567 pot=2时显示为12345.67
- void LCD_Write_LongPoint(u8 y,u8 x,u8 length,u8 pot,u32 Data)
- {
- u8 i,j,k;
- if(length>10)
- {
- length = 10;
- }
- if(length<10)
- {
- Data = Data%power(10,length);
- }
- if(y==0) //第一行
- {
- j=0;
- Write_Command(0x80+x); //0x80 + 第一行起始地址
- for(i=0; i<=length; i++)
- {
- if(i==(length-pot))
- {
- Write_Data(0x2e); //小数点
- Write_Command(0x80+x+i+1);
- }
- else
- {
- k = (u8)(Data/power(10,length-1-j));
- Data = Data%power(10,length-1-j);
- Write_Data(k+0x30);
- j++;
- }
- }
- }
- if(y==1) //第二行
- {
- j=0;
- Write_Command(0xc0+x); //0xc0 + 第二行起始地址
- for(i=0; i<=length; i++)
- {
- if(i==(length-pot))
- {
- Write_Data(0x2e); //小数点
- Write_Command(0xc0+x+i+1);
- }
- else
- {
- k = (u8)(Data/power(10,length-1-j));
- Data = Data%power(10,length-1-j);
- Write_Data(k+0x30);
- j++;
- }
- }
- }
- }
- //------LCD1602清屏---------
- void LCD_Clear(void)
- {
- Write_Command(0x01);
- }
- //------LCD1602初始化-----
- void LCD1602_Init(void)
- {
- Delay_ms(15);
- Write_Command(0x38); //16x2显示,8位数据
- Write_Command(0x0c); //开显示
- Write_Command(0x06); //AC自动加1,字符依次向后写
- LCD_Clear();
- }
- //------判断测量类型-------
- void Get_Measure_Flag(void)
- {
- if(FLC_EC_Flag==0) //测FLC按键选择标志位
- {
- if(K1_F_LC==1)
- {
- Measure_Flag = 3; //测频率
- T0_times = 20; //T0定时1s
- }
- else
- {
- if(K2_L_C==0)
- {
- Measure_Flag = 1; //测电容
- }
- else
- {
- Measure_Flag = 2;
- }
- T0_times = 10; //T0定时0.5s
- }
- }
- else
- {
- TR0 = 0; //关闭测频率(含LC)功能
- ET0 = 0;
- if(K3_Eb_Es==0)
- {
- Measure_Flag = 4; //测小电解
- }
- else
- {
- Measure_Flag = 5; //测大电解
- }
- }
- }
- //------测试(F/L/C)初始化(T0,T1初始化)------
- void MeasureFLC_init(void)
- {
- Timer0_Num = 0;
- Timer1_Num = 0;
- TMOD = 0x51; //T0作定时器,T1作计数器
- TH0 = 0x3c; //T0初值高8位(定时50ms)
- TL0 = 0xb0; //T0初值低8位
- TH1 = 0x3c; //T1初值高8位(计数50000次)
- TL1 = 0xb0; //T1初值低8位
- TR0 = 1; //T0开
- TR1 = 1; //T1开
- ET0 = 1; //T0中断开
- ET1 = 1; //T1中断开
- EA = 1; //总中断开
- }
- //--------计算L/C值--------
- void LC_Calculate(void)
- {
- float mes;
- mes = (float)Frequency0/(float)Frequency1; //频率比
- mes *= mes; //平方值
- if(mes < 1) //取绝对值
- {
- mes = 1 - mes;
- }
- else
- {
- mes -= 1;
- }
- Cx = 100 * mes * Cref; //计算被测电容值(精确到0.1pF)
- if((Cx%10) >= 5) //四舍五入
- {
- Cx = Cx/10 + 1;
- }
- else
- {
- Cx = Cx/10;
- }
- Lx = mes * Lref * 1000; //计算被测电感值(精确到0.01uH)
- if((Lx%10) >= 5) //四舍五入
- {
- Lx = Lx/10 + 1;
- }
- else
- {
- Lx = Lx/10;
- }
- if(Frequency1<50) //防止不接入电感时显示溢出值
- {
- Lx = 0;
- }
- }
- //----自动校正(清除寄生电容值)-------
- void Auto_Calib(void)
- {
- u8 i;
- if((K1_F_LC != 0) || (K2_L_C != 0)) //判断K1,K2的初始位置
- {
- LCD_Clear();
- LCD_Write_String(0,0,"Auto Calib fail!");
- if((K1_F_LC == 1) && (K2_L_C == 1))
- {
- LCD_Write_String(1,0,"Need up K1 & K2 ");
- }
- else
- {
- if(K1_F_LC == 1)
- {
- LCD_Write_String(1,0," Need up K1 ");
- }
- else
- {
- LCD_Write_String(1,0," Need up K2 ");
- }
- }
- while((K1_F_LC == 1) || (K2_L_C == 1)); //等待K1,K2的准确初始位置
- for(i=0; i<20; i++)
- {
- Delay_ms(75); //延时1.5秒,消抖.
- }
- }
- LC_Calculate();
- Delay_ms(150);
- Lref = (Cx/Cref + 1) * 100; //计算基准电感值(单位uH)
- Frequency0 = Frequency1;
- }
- //-------按键读取--------
- void Get_Key(void)
- {
- if(K4_FLC_EC == 0) //如果=0(按钮按下)
- {
- Delay_ms(50);
- if(K4_FLC_EC == 0)
- {
- FLC_EC_Flag = ~FLC_EC_Flag; //测量标志取反
- if(FLC_EC_Flag == 0) //如果=0,是测FLC
- {
- EX0 = 0; //关闭测电解电容的功能(外部中断0关)
- MeasureFLC_init(); //测试(F/L/C)初始化(T0,T1初始化)
- }
- else //否则,是测量电解电容.
- {
- TR0 = 0; //T0关
- ET0 = 0; //T0中断关
- }
- }
- }
- if(K5_Calib == 0) //如果=0(按钮按下)(手工校正)
- {
- Delay_ms(50); //延时50sm,消抖
- if(K5_Calib == 0)
- {
- if((K1_F_LC == 0) && (K2_L_C == 0)) //如果K1,K2处于测量电容位置
- {
- Frequency0 = Frequency1;
- }
- }
- }
- }
- //-------测试电解电容初始化(T0,T1及外部中断初始化)-------
- void MeasureElec_init(void)
- {
- u8 i;
- ECx_H = 0;
- ECx_L = 0;
- TR1 = 0;
- ET1 = 0;
- EX0 = 0; //关外部中断
- Dischg = 0; //放电
- Delay_ms(180);
- Delay_ms(200);
- Dischg = 1; //充电
- Timer1_Num = 0;
- TMOD = 0x11; //T0,T1都作定时器
- TH1 = 0x3c; //T1初值高8位(定时50ms)
- TL1 = 0xb0; //T1初值低8位
- TR1 = 1; //T1开
- ET1 = 1; //T1中断开
- IT0 = 1; //下降沿触发
- EX0 = 1; //外部中断开
- EA = 1; //总中断开
- for(i=0; i<65; i++) //延时1.3s,等待测量
- {
- Delay_ms(20);
- if(K4_FLC_EC == 0) //如果测量期间K4键按下
- {
- Delay_ms(20);
- if(K4_FLC_EC == 0)
- {
- break; //中止
- }
- }
- }
- EX0 = 0; //外部中断关
- Dischg = 0; //放电
- }
- //--------定时器0中断处理---------
- void Timer0_interrupt(void) interrupt 1
- {
- TH0 = 0x3c; //重装载T0初值高8位(定时50ms)
- TL0 = 0xb0; //重装载T0初值低8位
- Timer0_Num++; //T0计次累加
- if(Timer0_Num >= T0_times) //如果T0计次数=T0预设值(测F=20(1s),测LC=10(0.5s))
- {
- TR0 = 0; //T0关
- TF0 = 0; //T0溢出标志清零
- TR1 = 0; //T1关
- TF1 = 0; //T1溢出标志清零
- Frequency1 = 50000*Timer1_Num + ((u16)((TH1<<8)+TL1)-0x3cb0);
- //计算频率值(Frequency1)
- Timer0_Num = 0; //T0计次清零
- Timer1_Num = 0; //T1计次清零
- TH0 = 0x3c; //重装载T0初值高8位(定时50ms)
- TL0 = 0xb0; //重装载T0初值低8位
- TH1 = 0x3c; //重装载T1初值高8位(计数50000次)
- TL1 = 0xb0; //重装载T1初值低8位
- TR0 = 1; //T0开
- TR1 = 1; //T1开
- }
- }
- //------定时器1中断处理-------
- void Timer1_interrupt(void) interrupt 3
- {
- TH1 = 0x3c; //重装载T1初值高8位(定时50ms,或计数50000次)
- TL1 = 0xb0; //重装载T1初值低8位
- Timer1_Num++; //T1计次累加
- }
- //-------外部INT0中断处理--------
- void INT0_Interrupt(void) interrupt 0
- {
- if(Measure_Flag==4)
- {
- ECx_L = (50000*Timer1_Num + ((u16)((TH1<<8)+TL1)-0x3cb0))*100/2000;
- //计算低容量电解电容值(精确到0.01uF)
- if((ECx_L-2)>=0)
- {
- ECx_L -= 2; //修正误差
- }
- }
- if(Measure_Flag==5)
- {
- ECx_H = (50000*Timer1_Num + ((u16)((TH1<<8)+TL1)-0x3cb0))*10/100;
- //计算高容量电解电容值(精确到0.1uF)
- if((ECx_H-4)>=0)
- {
- ECx_H -= 4; //修正误差
- }
- }
- }
- //-----------
- void Main(void)
- {
- u8 i;
- u8 clear; //清屏标志位,如果功能转换则需要清屏
- Measure_Flag = 0;
- FLC_EC_Flag = 0; //开机默认测FLC
- T0_times = 10;
- Timer0_Num = 0;
- Timer1_Num = 0;
- Frequency0 = 169500;
- //基准频率的一半(基准频率是:当L=100uH,C=2200pF时的频率,=339000Hz)
- Frequency1 = 0;
- LCD1602_Init();
- MeasureFLC_init();
- LCD_Write_String(0,0," L.C.F Meter ");
- LCD_Write_String(1,0," 2015-08-01 ");
- for(i=0; i<20; i++)
- {
- Delay_ms(150); //开机画面显示3秒
- }
- Auto_Calib();
- while(1)
- {
- Get_Key(); //按键扫描
- Delay_ms(70); //该延时使按键切换稳定
- clear = Measure_Flag; //读测量类型标志及清屏
- Get_Measure_Flag(); //获取测量类型标志
- if(clear != Measure_Flag)
- {
- LCD_Clear();
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
51黑论坛_自动校正.zip
(32.65 KB, 下载次数: 488)
|