51单片机频率计设计LCD显示1.docx
《51单片机频率计设计LCD显示1.docx》由会员分享,可在线阅读,更多相关《51单片机频率计设计LCD显示1.docx(16页珍藏版)》请在冰豆网上搜索。
![51单片机频率计设计LCD显示1.docx](https://file1.bdocx.com/fileroot1/2023-6/4/343e68ce-70d5-4f30-a075-6302ea576587/343e68ce-70d5-4f30-a075-6302ea5765871.gif)
51单片机频率计设计LCD显示1
//单片机89C51的数字频率计C程序:
#include
#include
#include
#include
floatf;//频率
floatp;//周期
floatsj;
floatmk;//脉宽
charidatabuff[20];
charxs=0;//设置闸门时间结束后是否显示结果的标志位
unsignedcharm=0,n=0,yichu=0,fenpin;//m定时中断次数n计数中断次数yichu判断是定时器还是
sbitB153=P2^4;
sbitA153=P2^3;
sbitP35=P3^5;
unsignedcharLCD_Wait(void);
voidLCD_Write(bitstyle,unsignedcharinput);
voidLCD_SetDisplay(unsignedcharDisplayMode);
voidLCD_SetInput(unsignedcharInputMode);
voidLCD_Initial();
voidGotoXY(unsignedcharx,unsignedchary);
voidPrint(unsignedchar*str);
voidC51_Initial();
voidDelay(unsignedintt);
voiddisplay(floatf);
voidcepin();
voidpanduan();
voidMkdisplay(floatmk);
voidccpin();
/****************************************
*模块名称:
LCD1602显示程序*
****************************************/
/***********************端口定义***********************************/
sbitLcdRs=P2^0;
sbitLcdRw=P2^1;
sbitLcdEn=P2^2;
sfrDBPort=0x80;//P0=0x80,P1=0x90,P2=0xA0,P3=0xB0.数据端口
/************************内部等待函数********************************/
unsignedcharLCD_Wait(void)
{
LcdRs=0;//寄存器选择输入端1:
数据0:
指令
LcdRw=1;_nop_();//RW:
为0:
写状态;为1:
读状态;
LcdEn=1;_nop_();//使能输入端,读状态,高电平有效;写状态,下降沿有效
LcdEn=0;
returnDBPort;
}
/***********************向LCD写入命令或数据*********************************/
#defineLCD_COMMAND0//Command
#defineLCD_DATA1//Data
#defineLCD_CLEAR_SCREEN0x01//清屏
#defineLCD_HOMING0x02//光标返回原点
voidLCD_Write(bitstyle,unsignedcharinput)
{
LcdEn=0;
LcdRs=style;
LcdRw=0;_nop_();
DBPort=input;_nop_();//注意顺序
LcdEn=1;_nop_();//注意顺序
LcdEn=0;_nop_();
LCD_Wait();
}
/********************设置显示模式****************************************/
#defineLCD_SHOW0x04//显示开
#defineLCD_HIDE0x00//显示关
#defineLCD_CURSOR0x02//显示光标
#defineLCD_NO_CURSOR0x00//无光标
#defineLCD_FLASH0x01//光标闪动
#defineLCD_NO_FLASH0x00//光标不闪动
voidLCD_SetDisplay(unsignedcharDisplayMode)
{
LCD_Write(LCD_COMMAND,0x08|DisplayMode);
}
/*********************设置输入模式***************************************/
#defineLCD_AC_UP0x02
#defineLCD_AC_DOWN0x00//default
#defineLCD_MOVE0x01//画面可平移
#defineLCD_NO_MOVE0x00//default
voidLCD_SetInput(unsignedcharInputMode)
{
LCD_Write(LCD_COMMAND,0x04|InputMode);
}
/******************初始化LCD******************************************/
voidLCD_Initial()
{
LcdEn=0;
LCD_Write(LCD_COMMAND,0x38);//8位数据端口,2行显示,5*7点阵
LCD_Write(LCD_COMMAND,0x38);
LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR);//开启显示,无光标
LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN);//清屏
LCD_SetInput(LCD_AC_UP|LCD_NO_MOVE);//AC递增,画面不动
}
/*****************************LCD**************************************/
voidGotoXY(unsignedcharx,unsignedchary)
{
if(y==0)
LCD_Write(LCD_COMMAND,0x80|x);
if(y==1)
LCD_Write(LCD_COMMAND,0x80|(x-0x40));
}
voidPrint(unsignedchar*str)
{
while(*str!
='\0')
{
LCD_Write(LCD_DATA,*str);
str++;
}
}
/***************************89c51初始化************************************/
voidC51_Initial()
{
sj=1000000.00;
TMOD=0x51;//01010001T1为计数器,T0为定时器
EA=1;
ET0=1;
ET1=1;
EX0=1;
PX0=1;//外部中断0设置为高优先级
IT0=0;//电平触发方式
}
/**************************ms延时子程序***************************/
voidDelay(unsignedintt)//t随着数值越大,误差趋于平衡.
{
unsignedchari;
while(t--)
{
for(i=0;i<123;i++){;}
}
}
/*************************计数中断**************************/
voidt1(void)interrupt3//计数器1溢出,yichu=1
{n++;
yichu=1;
TH1=0;
TL1=0;
}
/*************************定时中断******************************/
voidt0(void)interrupt1
{m++;
yichu=2;//定时器0溢出,yichu=2
TH0=0x3c;//定时50ms
TL0=0xb0;
}
/*************************显示频率******************************/
voidFdisplay(floatf)
{
if(f>999400.00)
{
if(f<4000400.00)
{sprintf(buff,"Freque%2.4fmHz",(f/1000000.00));}
}
else
{
if(f>1040.00)
{sprintf(buff,"Freque%4.2fkHz",(f/1000.00));}
else
{
if(f>0.06)
{sprintf(buff,"Freque%3.2fHz",f);}
}
}
GotoXY(0,1);
Print(buff);
}
/*************************显示周期************************/
voidPdisplay(floatp)
{
if(p>999400.00)
{
if(p<.00)
{sprintf(buff,"Perio%2.3fs",(p/1000000.00));}
else
{sprintf(buff,"error(TimeorF)",p);}
}
else
{
if(p>9950.00)
{sprintf(buff,"Perio%4.1fms",(p/1000.00));}
else
{
if(p>0.248)
{sprintf(buff,"Perio%3.2fus",p);}
else
{sprintf(buff,"error(TimeorF)",p);}
}
}
GotoXY(0,1);
Print(buff);
}
/*************************显示脉宽*****************************/
voidMkdisplay(floatmk)
{
if(mk>499700.00)
{
if(p<5000200.00)
{sprintf(buff,"Maikua%2.3fs",(mk/1000000.00));}
else
{sprintf(buff,"error(TimeorF)",mk);}
}
else
{
if(p>4975.00)
{sprintf(buff,"Maikua%4.1fms",(mk/1000.00));}
else
{
if(p>0.124)
{sprintf(buff,"Maikua%3.2fus",mk);}
else
{sprintf(buff,"error(TimeorF)",mk);}
}
}
GotoXY(0,0);
Print(buff);
}
/*************************测试频率*****************************/
voidcepin()
{
unsignedchara;
unsignedlongjs;
m=0;
n=0;
TMOD=0x51;
TH0=0x3c;//定时50ms
TL0=0xb0;
TH1=0;
TL1=0;
a=sj/50000.00;
TCON=0x50;//启动定时器和计数器
while(m!
=a);
TCON=0;
js=TH1*256+n*65536+TL1;
f=(js/(sj/1000000.00))*fenpin;
p=sj/(js*fenpin);
mk=p/2;
Pdisplay(p);
Mkdisplay(mk);
}
voidccpin()
{
unsignedchara;
unsignedlongjs;
m=0;
n=0;
TMOD=0x51;
TH0=0x3c;//定时50ms
TL0=0xb0;
TH1=0;
TL1=0;
a=sj/50000.00;
TCON=0x50;//启动定时器和计数器
while(m!
=a);
TCON=0;
js=TH1*256+n*65536+TL1;
f=(js/(sj/1000000.00))*fenpin;
p=sj/(js*fenpin);
mk=p/2;
Fdisplay(f);
}
/************************判断频率**************************/
voidpanduan()
{
xs=0;//设置结束后第二次循环显示结果
B153=1;//选择16分频
A153=0;
yichu=0;
TMOD=0x51;
TH0=0xff;//定时器0200us
TL0=0x38;
TH1=0xff;//计数器1100脉冲
TL1=0x9c;
TR0=1;//启动定时器0和计数器1
TR1=1;
while(yichu==0);//如果没有溢出一直循环
TR0=0;//已经溢出关闭定时器0和计数器1
TR1=0;
if(yichu==1)//计数器先溢出:
在200ms内测得的脉冲过多,说明频率较高
{fenpin=16;//转为测16分频后的频率16
cepin();}
else//定时器先溢出:
100个脉冲的时间比较短,即频率较低,可以减少分频数
{
yichu=0;
B153=0;
A153=1;
TH0=0xfc;//定时器01ms
TL0=0x18;
TH1=0xff;//计数器1100个脉冲
TL1=0x9c;
TR0=1;//启动定时器0和计数器1
TR1=1;
while(yichu==0);//如果没溢出一直循环
TR0=0;//已经溢出关闭定时器0和计数器1
TR1=0;
if(yichu==1)//计数器先溢出:
在1ms内测得的脉冲过多,说明频率较高(1khz{fenpin=4;//转为测4分频后的频率4
cepin();}
else//定时器先溢出:
100个脉冲的时间比较短,即频率较低
{fenpin=1;
B153=0;
A153=0;
cepin();}
}
}
voidpd()
{
xs=0;//设置结束后第二次循环显示结果
B153=1;//选择16分频
A153=0;
yichu=0;
TMOD=0x51;
TH0=0xff;//定时器0200us
TL0=0x38;
TH1=0xff;//计数器1100脉冲
TL1=0x9c;
TR0=1;//启动定时器0和计数器1
TR1=1;
while(yichu==0);//如果没有溢出一直循环
TR0=0;//已经溢出关闭定时器0和计数器1
TR1=0;
if(yichu==1)//计数器先溢出:
在200ms内测得的脉冲过多,说明频率较高
{fenpin=16;//转为测16分频后的频率16
ccpin();}
else//定时器先溢出:
100个脉冲的时间比较短,即频率较低,可以减少分频数
{
yichu=0;
B153=0;
A153=1;
TH0=0xfc;//定时器01ms
TL0=0x18;
TH1=0xff;//计数器1100个脉冲
TL1=0x9c;
TR0=1;//启动定时器0和计数器1
TR1=1;
while(yichu==0);//如果没溢出一直循环
TR0=0;//已经溢出关闭定时器0和计数器1
TR1=0;
if(yichu==1)//计数器先溢出:
在1ms内测得的脉冲过多,说明频率较高(1khz{fenpin=4;//转为测4分频后的频率4
ccpin();}
else//定时器先溢出:
100个脉冲的时间比较短,即频率较低
{fenpin=1;
B153=0;
A153=0;
ccpin();}
}
}
voidmain()
{
LCD_Initial();//LCD初始化
GotoXY(0,0);
Print("***B09010407***");
Delay(1000);
GotoXY(0,0);
Print("Testing...");
C51_Initial();//89c51初始化
while
(1)
{
pd();
Delay(2000);
panduan();
Delay(3000);
}
}
仅供个人用于学习、研究;不得用于商业用途。
Forpersonaluseonlyinstudyandresearch;notforcommercialuse.
NurfürdenpersönlichenfürStudien,Forschung,zukommerziellenZweckenverwendetwerden.
Pourl'étudeetlarechercheuniquementàdesfinspersonnelles;pasàdesfinscommerciales.
толькодлялюдей,которыеиспользуютсядляобучения,исследованийинедолжныиспользоватьсявкоммерческихцелях.
以下无正文