|

楼主 |
发表于 2017-10-22 18:29:21
|
显示全部楼层
更新了程序,200HZ以下使用周期测量法,精确到0.1HZ。以下是c程序:
#include "at89x52.h"
#define LCM_Data P2
#define Busy 0x80 //用于检测LCM状态字中的Busy标识
//22.1184M
sbit LCM_RS = 0x0ed;//p45
sbit LCM_E = 0x0ec; //p44
sbit LCM_RW = 0x0ee;//p46
void WriteDataLCM(unsigned char WDLCM);
void WriteCommandLCM(unsigned char WCLCM,BuysC);
unsigned char ReadDataLCM(void);
unsigned char ReadStatusLCM(void);
void LCMInit(void);
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData);
void Displayunlong(unsigned long long1);
void Delay5Ms(void);
void Delay400Ms(void);
void t2Init(void); //t2初始化
unsigned char code uctech[] = {"0123456789"};
unsigned char code uctech1[] = {"HZ"};
unsigned char code uctechK[] = {"K"};
unsigned char code uctechM[] = {"M"};
//void cheshi(unsigned long ci);
void InitTimer0(void);
unsigned long kk,jishu ,jishi;
// unsigned int jishi ;
// double hh;
unsigned char weee, pph,zhouqipd;
// bit pd;
//22.1184M 1秒闸门
void main(void)
{
// P1_4=1;
// P1_5=1;
// P1_6=1;
// P1_7=1;
P1_3=0; // P1_2=1; 74hc393 输入允许-------- P1_2=0; 74hc393 输入关
P1_3=1; //P1_1=0; P1_1=1; 模拟计数脉冲
P1_3=0;//P1_3=0; P1_3=1; P1_3=0;74hc393 clear 复位
P1_2=0;
// P3_7=0;
// pd=1;//1秒闸门
//pd=0;//0.1秒闸门
//we=0;
// pp=0x30; //0.1秒闸门
LCMInit(); //LCM初始化
WriteCommandLCM(0x01,1); //显示清屏
// Displayunlong (1234567898);
InitTimer0();
while(1)
{
}
}
/*
void cheshi(unsigned long ci)
{
unsigned long i;
for(i=0;i<ci;i++)
{
P1_1=1;
P1_1=0;
}
}
*/
void InitTimer0(void)//Timer0定时器10毫秒
{
P1_2=0;//停止计数
weee=100;
while(weee)
{
weee--;
}
kk=TH2;//long*int=long,int*int=int会溢出
//jishi=TL2;
kk=kk*0x1000+TL2*0x10+P1/0x10+ 0x100000*jishu-1;//1秒闸门
// kk=kk*10;
//0x100000-
//----------------------------------
zhouqipd=0;
if( P1_1==1)
{
// if ((kk<301)& (kk>0)) //小于1000HZ使用测量周期法
if (kk<200) //小于1000HZ使用测量周期法
{
zhouqipd=1;
if (kk==0)
{
Displayunlong(0);
}
EA=0;
jishi=0;
P1_2=1;//开始计数
while(P1_4==1)//保证p1_4=0
{
} //保证p1_4=0
while(P1_4==0)// p1_4由0跳变到1
{
} // p1_4由0跳变到1
while(P1_4==1) //开始计时
{
jishi++;
}
while(P1_4==0)
{
jishi++;
} //这里jishi是一个周期的计数
P1_2=0;//停止计数
kk= 520400000/jishi;
}
//----------------------------------
}
Displayunlong (kk);
t2Init();
// InitTimer0();
//-------------------------------------
//char ppdd=0;
pph=0;
TR0 = 0;//停止定时器0
jishi=0;
TMOD = 0x01;
//TH0 = 0x70; //22.1184M 6T 10ms
TH0 =0; //25.000M 6T 10ms
// TL0 = 0x00;
// TL0 = 0x10;
TL0 = 0;
EA = 1;
ET0 = 1;
//--------------------------检测低到高跳变
// P1_2=1;
// while (ppdd==0)
// {
// if( P1_2==0)
// {
// while (P1_2==0)
// {
// }
// ppdd=1;
// }
// }
// P1_2=0;
//-----------------------------
P1_3=1;
P1_3=0;//P1_3=0; P1_3=1; P1_3=0;74hc393 clear 复位
TR2=1; //启动定时器2
TR0 = 1;//启动计数器0
P1_2=1;//开始计数
}
void t2Init(void) //t2初始化
{
TR2=0; //停止定时器2
RCAP2H=0x0;
RCAP2L=0x0; // 自动重装
TH2=RCAP2H;
TL2=RCAP2L; //定时器2赋初值
T2CON=0x2; //计数器
T2MOD=0x0;
EA=1; //开总中断
ET2=1; // 开外定时器2中断
// TR2=1; //启动定时器2
jishu=0;
}
void Timer0Interrupt(void) interrupt 1
{
//-----------------------------------------------
if( P3_7==0) // 0.1秒闸门
{
if (jishi==5)
{
if (pph==0)
{
TH0 = 0xa4;
TL0 = 0xf8; //25000000
// TH0 = 0xa4;
// TL0 = 0xf8; //25000000
pph=1;
}
else
{
InitTimer0();
}
}
else
{
jishi++;//timer0计时次数
}
}
else
{ //1秒闸门
if (jishi==62)
{
if (pph==0)
{
TH0 = 0x6e;
TL0 = 0xa4; //11.059200显示11.059208
// TH0 = 0x6c;
// TL0 = 0x88; //25000006
// TH0 = 0x6c;
// TL0 = 0x89; //24999994
pph=1;
}
else
{
InitTimer0();
}
}
else
{
jishi++;//timer0计时次数
}
}
//----------------------------------------------
}
void timer2() interrupt 5
{
TF2=0; //!!!注意!!! 定时器2必须由软件对溢出标志位清零,硬件不能清零,这里与定时器0和定时器1不同!!!
jishu++;//timer2计数次数
}
void Displayunlong(unsigned long long1)
{
char pp1,i ;
P1_1=1;
if( P1_1==0) //高频
{
long1=long1*128;
DisplayOneChar(15, 0, 'G');
}
else
{
DisplayOneChar(15, 0, 'D');
}
// P3_7=1;
if( P3_7==0) //1秒 0.1秒闸门
{ long1=long1*10;
// pd=0;
// we=131;
DisplayOneChar(15, 1, 'k');
}
else
{
// pd=1;
// we=136;
DisplayOneChar(15, 1, 'm');
}
jishu=long1;
// WriteCommandLCM(0x01,1); //显示清屏
for (i=11;i>=0;i--)
{
pp1=long1 % 10;
if(i==8)
{
if ( zhouqipd==0)
{
DisplayListChar(8, 0, uctechK); //显示K
}
else
{
DisplayOneChar(8, 0, '.');
}
}
else
{
if(i==4)
{
DisplayListChar(4, 0, uctechM);//显示M
}
else
{
DisplayOneChar(i ,0,uctech[pp1]);//显示数字
long1=long1/10;
}
}
}
DisplayListChar(12, 0, uctech1);
long1=1000000000/jishu ; //显示周期
if ( zhouqipd==1)
{
long1=long1*1000;
}
if (jishu==0)
long1=0;
for (i=11;i>=0;i--)
{
pp1=long1 % 10;
if(i==8)
{
DisplayOneChar(8, 1, 'u'); //显示u
}
else
{
if(i==4)
{
DisplayOneChar(4, 1, 'm');//显示m
}
else
{
DisplayOneChar(i ,1,uctech[pp1]);//显示数字
long1=long1/10;
}
}
DisplayOneChar(12, 1, 'n'); //显示u
DisplayOneChar(13, 1, 's'); //显示u
}
}
//写数据
void WriteDataLCM(unsigned char WDLCM)
{
ReadStatusLCM(); //检测忙
LCM_Data = WDLCM;
LCM_Data = WDLCM;
LCM_RS = 1;
LCM_RS = 1;
LCM_RW = 0;
LCM_RW = 0;
LCM_E = 0;
LCM_E = 0; //若晶振速度太高可以在这后加小的延时
//Delay5Ms();
LCM_E = 1;
LCM_E = 1;
LCM_E = 1;
LCM_E = 1;
//Delay5Ms();
LCM_E = 0;
}
//写指令
void WriteCommandLCM(unsigned char WCLCM,BuysC) //BuysC为0时忽略忙检测
{
if (BuysC) ReadStatusLCM(); //根据需要检测忙
LCM_Data = WCLCM;
LCM_Data = WCLCM;
LCM_RS = 0;
LCM_RS = 0;
LCM_RW = 0;
LCM_RW = 0;
LCM_E = 0;
LCM_E = 0;
// Delay5Ms();
LCM_E = 1;
LCM_E = 1;
LCM_E = 1;
LCM_E = 1;
// Delay5Ms();
LCM_E = 0;
}
//读数据
unsigned char ReadDataLCM(void)
{
LCM_RS = 1;
LCM_RW = 1;
LCM_E = 0;
LCM_E = 0;
LCM_E = 1;
return(LCM_Data);
}
//读状态
unsigned char 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);
}
void LCMInit(void) //LCM初始化
{
Delay400Ms(); //启动等待,等LCM讲入工作状态
Delay400Ms(); //启动等待,等LCM讲入工作状态
LCM_Data = 0;
WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号
Delay5Ms();
WriteCommandLCM(0x38,0);
Delay5Ms();
WriteCommandLCM(0x38,0);
Delay5Ms();
WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号
WriteCommandLCM(0x08,1); //关闭显示
WriteCommandLCM(0x01,1); //显示清屏
WriteCommandLCM(0x06,1); // 显示光标移动设置
WriteCommandLCM(0x0C,1); // 显示开及光标设置
}
//按指定位置显示一个字符
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
{
Y &= 0x1;
X &= 0xF; //限制X不能大于15,Y不能大于1
if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;
X |= 0x80; // 算出指令码
WriteCommandLCM(X, 1); //这里不检测忙信号,发送地址码
WriteDataLCM(DData);
}
//按指定位置显示一串字符
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)
{
unsigned char ListLength;
ListLength = 0;
Y &= 0x1;
X &= 0xF; //限制X不能大于15,Y不能大于1
while (DData[ListLength]>0x19) //若到达字串尾则退出
{
if (X <= 0xF) //X坐标应小于0xF
{
DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符
ListLength++;
X++;
}
}
}
//5ms延时
void Delay5Ms(void)
{
unsigned int TempCyc = 5552;
while(TempCyc--);
}
//400ms延时
void Delay400Ms(void)
{
unsigned char TempCycA = 5;
unsigned int TempCycB;
while(TempCycA--)
{
TempCycB=7269;
while(TempCycB--);
};
}
|
|