#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
//==============LCD1602接口連接方法=====================
/*-----------------------------------------------------
|DB0-----P0.0 | DB4-----P0.4 | RW-------P2.3 |
|DB1-----P0.1 | DB5-----P0.5 | RS-------P2.4 |
|DB2-----P0.2 | DB6-----P0.6 | E--------P2.2 |
|DB3-----P0.3 | DB7-----P0.7 |
---------------------------------------------------*/
//================================================*/
#define LCM_Data P0 //LCD1602數據接口
#define Busy 0x80 //用于檢測LCM狀態字中的Busy標識
sbit LCM_RW = P2^3; //讀寫控制輸入端,LCD1602的第五腳
sbit LCM_RS = P2^4; //寄存器選擇輸入端,LCD1602的第四腳
sbit LCM_E = P2^2; //使能信號輸入端,LCD1602的第6腳
sbit int0_int= P3^2;
sbit l_button = P2^0;//電感測量控制開關;
sbit c_button=P2^1;//電容測量控制開關;
sbit f_button=P2^6;//頻率測試控制開關;
sbit min_elect_c_button=P2^7;//小電容測試控制開關
sbit max_elect_c_button=P3^6;//小電容測試控制開關
sbit fangdian_button=P2^5;//電解電容測量時放電控制腳
//**************函數聲明***************************************
void WriteDataLCM (uchar WDLCM);//LCD模塊寫數據
void WriteCommandLCM (uchar WCLCM,BuysC); //LCD模塊寫指令
uchar ReadStatusLCM(void);//讀LCD模塊的忙標
void DisplayOneChar(uchar X,uchar Y,uchar ASCII);//在第X+1行的第Y+1位置顯示一個字符
void LCMInit(void);//LCD初始
void delayms(uint ms);//1MS基準延時程序
void DisplayListChar(uchar X,uchar Y,uchar delayms, uchar code *DData);
void judge_xianshi(void);//顯示處理程序
void lx_display();
void cx_display();
void fx_display();
void init_t0();
void strive_f1();//求取F1
void strive_f2();//求取電感的大小
void strive_cx();//求取小電容(無極性電容)的大小
void strive_fx();//測試外邊頻率
void strive_min_c();//小電容測試
void strive_max_c();//大電容測試
uchar t0_crycle=0;
uchar f_crycle;
uchar flag1;//
uchar display_flag;
uint f1,temp,f2;
long ryz;
//***********************主程序******************************
main()
{
fangdian_button=1;
LCMInit();
init_t0();
strive_f1();//求取F1
DisplayListChar(0,0,0, "F/L/C Tester");
while(1)
{
strive_f2();//求取F1
strive_cx();
strive_fx();
strive_min_c();
strive_max_c();
judge_xianshi();
}
}
void judge_xianshi()
{
lx_display();
cx_display();
fx_display();
}
void strive_max_c()//大電解電容測試
{
max_elect_c_button=1;//置為1,準備判斷小電容測量開關的狀態,上電時這個開關比較彈起
if(max_elect_c_button==0)
{
f_crycle=0;
fangdian_button=0;
delayms(250);
fangdian_button=1;
TMOD=0x10;//設定T0以工作方式1定時
TH1=0;
TL1=0;
EA=1;
ET1=1;//允許定時器0中斷
TR1=1;
int0_int=1;
while(int0_int==1);
TR1=0;
ryz=0;
ryz= f_crycle*50000;
ryz+=TH1*256+TL1;
DisplayListChar(1,0,0, "Cx=");
DisplayOneChar(1,3, ryz/1000000%10+0x30);
DisplayOneChar(1,4, ryz/100000%10+0x30);
DisplayOneChar(1,5, ryz/10000%10+0x30);
DisplayOneChar(1,6, ryz/1000%10+0x30);
DisplayOneChar(1,7, ryz/100%10+0x30);
DisplayOneChar(1,8,'.');
DisplayOneChar(1,9, ryz/10%10+0x30);
DisplayOneChar(1,10,ryz%10+0x30);
DisplayListChar(1,11,0, "UF ");
}
}
void strive_min_c()//小電容測試
{
min_elect_c_button=1;//置為1,準備判斷小電容測量開關的狀態,上電時這個開關比較彈起
if(min_elect_c_button==0)
{
f_crycle=0;
fangdian_button=0;
delayms(250);
fangdian_button=1;
TMOD=0x10;//設定T0以工作方式1定時
TH1=0;
TL1=0;
EA=1;
ET1=1;//允許定時器0中斷
TR1=1;
display_flag=4;//顯示標志,為4為測試小電解電容
int0_int=1;
while(int0_int==1);
TR1=0;
ryz=0;
ryz+=50000*f_crycle;
ryz+=TH1*256+TL1;
ryz/=20;
DisplayListChar(1,0,0, "Cx=");
DisplayOneChar(1,3, ryz/1000000%10+0x30);
DisplayOneChar(1,4, ryz/100000%10+0x30);
DisplayOneChar(1,5, ryz/10000%10+0x30);
DisplayOneChar(1,6, ryz/1000%10+0x30);
DisplayOneChar(1,7, ryz/100%10+0x30);
DisplayOneChar(1,8,'.');
DisplayOneChar(1,9, ryz/10%10+0x30);
DisplayOneChar(1,10,ryz%10+0x30);
DisplayListChar(1,11,0, "UF ");
display_flag=4;//顯示標志,為4為測試小電解電容
}
}
void timer1() interrupt 3
{
TH1=(65536-50000)/256;//定時50毫秒
TL1=(65536-50000)%256;
f_crycle++;
}
//求取小電容(無極性電容)的大小
void strive_fx()
{
uchar i;
f_button=1;//置為1,準備判斷小電容測量開關的狀態,上電時這個開關比較彈起
if(f_button==0)
{
if(display_flag!=3)init_t0();
display_flag=3;//顯示標志,為3為測試頻率
TR0=1;
TR1=1;
ryz=0;
for(i=0;i<20;i++)
{
f_crycle=0;
while(f_crycle<1);
f_crycle=0;
ryz+=temp;
}
TR0=0;
TR1=0;
}
}
void timer0() interrupt 1
{
TH0=(65536-50000)/256;//定時50毫秒
TL0=(65536-50000)%256;
f_crycle++;
t0_crycle=0;
TR0=0;//關閉定時0
temp=TH1*256+TL1;//
TH1=0;
TL1=0;
TR0=1;
}
void fx_display()
{
if(display_flag==3)
{
DisplayListChar(1,0,0, "Fx=");
DisplayOneChar(1,3, ryz/1000000%10+0x30);
DisplayOneChar(1,4, ryz/100000%10+0x30);
DisplayOneChar(1,5, ryz/10000%10+0x30);
DisplayOneChar(1,6, ryz/1000%10+0x30);
DisplayOneChar(1,7, ryz/100%10+0x30);
DisplayOneChar(1,8, ryz/10%10+0x30);
DisplayOneChar(1,9,ryz%10+0x30);
DisplayListChar(1,10,0, "HZ ");
}
}
void cx_display()
{
if(display_flag==2)
{
DisplayListChar(1,0,0, "Cx=");
DisplayOneChar(1,3, ryz/1000000%10+0x30);
DisplayOneChar(1,4, ryz/100000%10+0x30);
DisplayOneChar(1,5, ryz/10000%10+0x30);
DisplayOneChar(1,6, ryz/1000%10+0x30);
DisplayOneChar(1,7, ryz/100%10+0x30);
DisplayOneChar(1,8, ryz/10%10+0x30);
DisplayOneChar(1,9, ryz%10+0x30);
DisplayListChar(1,10,0, "pF ");
}
}
void lx_display()
{
if(display_flag==1)
{
DisplayListChar(1,0,0, "Lx=");
DisplayOneChar(1,3, ryz/10000000%10+0x30);
DisplayOneChar(1,4, ryz/1000000%10+0x30);
DisplayOneChar(1,5, ryz/100000%10+0x30);
DisplayOneChar(1,6, ryz/10000%10+0x30);
DisplayOneChar(1,7, ryz/1000%10+0x30);
DisplayOneChar(1,8, ryz/100%10+0x30);
DisplayOneChar(1,9, ryz/10%10+0x30);
DisplayOneChar(1,10,'.');
DisplayOneChar(1,11,ryz%10+0x30);
DisplayListChar(1,12,0, "uH ");
}
}
//********************************************************************************************
void init_t0()
{
TMOD=0x51;//設定T0以工作方式1定時50毫秒,T1為計數器,工作方式1
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1;//開總中斷
ET0=1;//允許定時器0中斷
t0_crycle=0;//定時器中斷次數計數單元
TH1=0;
TL1=0;
}
//求取小電容(無極性電容)的大小
void strive_cx()
{
c_button=1;//置為1,準備判斷小電容測量開關的狀態,上電時這個開關比較彈起
if(c_button==0)
{
if(display_flag!=2)init_t0();
display_flag=2;//顯示標志,為1為測試小電容
TR0=1;
TR1=1;
f_crycle=0;
while(f_crycle<=10);
f_crycle=0;
TR0=0;
TR1=0;
f2=temp;//
if(f2>f1)f2=f1;
if(f2<65)f2=65;
if(f2!=0)
{
ryz=((unsigned long) f1)*((unsigned long )f1);
ryz/=f2;
ryz*=2000;//換算為PF
ryz/=f2;
ryz-=2000;
}
}
}
//測電感
void strive_f2()
{
l_button=1;//置為1,準備判斷電感測量開關的狀態,上電時這個開關比較彈起
if(l_button==0)
{
if(display_flag!=1)init_t0();
display_flag=1;//顯示標志,為1為測試電感
TR0=1;
TR1=1;
f_crycle=0;
while(f_crycle<=15);
f_crycle=0;
TR0=0;
TR1=0;
f2=temp;//
if(f2>f1)f2=f1;
if(f2<65)f2=65;
if(f2!=0)
{
ryz=((unsigned long) f1)*((unsigned long )f1);
ryz/=f2;
ryz*=1000;//換算為UH
ryz/=f2;
ryz-=1000;
}
}
}
//******************************************************
//上電的時候求取F1
void strive_f1()
{
uchar i;
for(i=0;i<5;i++)
{
l_button=1;//置為1,準備判斷電感測量開關的狀態,上電時這個開關比較彈起
while(l_button==0);
TR0=1;
TR1=1;
while(f_crycle<=10);
f_crycle=0;
TR0=0;
TR1=0;
f1=temp;
}
}
/*====================================================================
按指定位置顯示一串字符:第 X 行,第 y列
注意:字符串不能長于16個字符
======================================================================*/
void DisplayListChar(uchar X,uchar Y,uchar ms, uchar code *DData)
{
unsigned char ListLength;
ListLength = 0;
X &= 0x1;
Y &= 0xF; //限制X不能大于15,Y不能大于1
while (DData[ListLength]!='\0') //若到達字串尾則退出
{
if (Y <= 0xF) //X坐標應小于0xF
{
DisplayOneChar(X, Y, DData[ListLength]); //顯示單個字符
ListLength++;
Y++;
delayms(ms);//延時顯示字符串
}
else
break;//跳出循環體
}
}
/*======================================================================
LCM初始化
======================================================================*/
void LCMInit(void)
{
LCM_Data = 0;
WriteCommandLCM(0x38,0); //三次顯示模式設置,不檢測忙信號
delayms(5);
WriteCommandLCM(0x38,0);
delayms(5);
WriteCommandLCM(0x38,0);
delayms(5);
WriteCommandLCM(0x38,1); //顯示模式設置,開始要求每次檢測忙信號
WriteCommandLCM(0x08,1); //關閉顯示
WriteCommandLCM(0x01,1); //顯示清屏
WriteCommandLCM(0x06,1); // 顯示光標移動設置
WriteCommandLCM(0x0C,1); // 顯示開及光標設置
delayms(100);
}
//==============================LCD1602顯示子程序================================================
// 寫數據函數: E =高脈沖 RS=1 RW=0
//======================================================================*/
void WriteDataLCM(uchar WDLCM)
{
ReadStatusLCM(); //檢測忙
LCM_Data = WDLCM;
LCM_RS = 1;
LCM_RW = 0;
LCM_E = 0; //若晶振速度太高可以在這后加小的延時
LCM_E = 0; //延時
LCM_E = 1;
}
/*====================================================================
寫指令函數: E=高脈沖 RS=0 RW=0
======================================================================*/
void WriteCommandLCM(uchar WCLCM,BuysC) //BuysC為0時忽略忙檢測
{
if (BuysC) ReadStatusLCM(); //根據需要檢測忙
LCM_Data = WCLCM;
LCM_RS = 0;
LCM_RW = 0;
LCM_E = 0;
LCM_E = 0;
LCM_E = 1;
}
/*====================================================================
正常讀寫操作之前必須檢測LCD控制器狀態:E=1 RS=0 RW=1;
DB7: 0 LCD控制器空閑,1 LCD控制器忙。
讀狀態
======================================================================*/
uchar ReadStatusLCM(void)
{
LCM_Data = 0xFF;
LCM_RS = 0;
LCM_RW = 1;
LCM_E = 0;
LCM_E = 0;
LCM_E = 1;
while (LCM_Data & Busy); //檢測忙信號
return(LCM_Data);
}
/*======================================================================
功 能: 在1602 指定位置顯示一個字符:第一行位置0~15,第二行16~31
說 明: 第 X 行,第 y 列 注意:字符串不能長于16個字符
======================================================================*/
void DisplayOneChar( uchar X, uchar Y, uchar ASCII)
{
X &= 0x1;
Y &= 0xF; //限制Y不能大于15,X不能大于1
if (X) Y |= 0x40; //當要顯示第二行時地址碼+0x40;
Y |= 0x80; // 算出指令碼
WriteCommandLCM(Y, 0); //這里不檢測忙信號,發送地址碼
WriteDataLCM(ASCII);
}
/*====================================================================
設定延時時間:x*1ms
====================================================================*/
void delayms(uint Ms)
{
uint i,TempCyc;
_nop_();
for(i=0;i<Ms;i++)
{
TempCyc =70;
while(TempCyc--);
}
}
|