这里有一个四位数码管的频率计,供参考
#include <reg52.h>#define uchar unsigned char
#define uint unsigned int
uchar duan[10]={0xc0,0Xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90} //所需的段的位码
//uchar wei[4]={0XEf,0XDf,0XBf,0X7f} //位的控制端 (开发板)
uchar wei[4]={0X80,0X40,0X20,0X10} //位的控制端 (仿真)
uint z,x,c,v, date //定义数据类型
uint dispcount=0
uint lck=0
uint disp=0
/******************************************************************
延时函数
******************************************************************/
void delay(uchar t)
{
uchar i,j
for(i=0i<ti++)
{
for(j=13j>0j--)
{
}
}
}
/**********************************************************************
数码管动态扫描
*********************************************************************/
void xianshi()
{
/*****************数据转换*****************************/
z=date/1000 //求千位
x=date%1000/100 //求百位
c=date%100/10 //求十位
v=date%10 //求个位
P2=wei[0]
P0=duan[z]
delay(50)
P2=wei[1]
P0=duan[x]
delay(50)
P2=wei[2]
P0=duan[c]
delay(50)
P2=wei[3]
P0=duan[v]
delay(50)
}
/*************************************************************************
定时器初值1ms
**************************************************************************/
void initTimer(void)
{
TMOD=0x0
TH0=0xe3
TL0=0xc
}
/*************************************************************************
定时器函数
**************************************************************************/
void timer0(void) interrupt 1
{
TH0=0xe3
TL0=0xc
lck++
if(lck==1000)
{
disp=dispcount
lck=0
dispcount=0
}
}
/*************************************************************************
中断函数
**************************************************************************/
void int0(void) interrupt 0
{
dispcount++ //每一次中断,计数加一
}
/*************************************************************************
主函数
**************************************************************************/
void main(void)
{
IT0=1 //INT0下降沿中断
EX0=1 //允许INT1中断
initTimer() //装入初值
TR0=1
ET0=1
EA=1
while(1)
{
date=disp
xianshi()
}
}
数码管台古老了,你用这个吧,看着还稍微有点可以,代码和电路都给你了,没有做不出来的理由,有问题加我QQ11422376745
#include "d:\c51\reg51.h"
#include "d:\c51\intrins.h"
sbit LCM_RS=P3^0
sbit LCM_RW=P3^1
sbit LCM_EN=P3^7
#define BUSY 0x80 //常量定义
#define DATAPORT P1
#define uchar unsigned char
#define uint unsigned int
#define L 50
uchar str0[16],str1[16],count
uint speed
unsigned long time
void ddelay(uint)
void lcd_wait(void)
void display()
void initLCM()
void WriteCommandLCM(uchar WCLCM,uchar BusyC)
void STR()
void account()
/*********延时K*1ms,12.000mhz**********/
void int0_isr(void) interrupt 0 /*遥控使用外部中断0,接P3.2口*/
{
unsigned int temp
time=count
TR0=0
temp=TH0
temp=((temp <<8) | TL0)
TH0=0x3c
TL0=0xaf
count=0
TR0=1
time=time*50000+temp
}
void time0_isr(void) interrupt 1 /*遥控使用定时计数器1 */
{
TH0 =0x3c
TL0 =0xaf
count++
}
void main(void)
{
TMOD=0x01 /*TMOD T0选用方式1(16位定时) */
IP|=0x01 /*INT0 中断优先*/
TCON|=0x11 /*TCON EX0下降沿触发,启动T0*/
IE|=0x83
TH0=0x3c
TL0=0xaf
initLCM()
WriteCommandLCM(0x01,1) //清显示屏
for()
{
account()
display()
}
}
void account()
{
unsigned long a
if (time!=0)
{
a=L*360000000/time
}
speed=a
}
void STR()
{
str0[0]='S'
str0[1]='p'
str0[2]='e'
str0[3]='e'
str0[4]='d'
str0[5]=' '
str0[6]=(speed%100000)/10000+0x30
str0[7]=(speed%10000)/1000+0x30
str0[8]=(speed%1000)/100+0x30
str0[9]='.'
str0[10]=(speed%100)/10+0x30
str0[11]=speed%10+0x30
str0[12]='k'
str0[13]='m'
str0[14]='/'
str0[15]='h'
}
void ddelay(uint k)
{
uint i,j
for(i=0i<ki++)
{
for(j=0j<60j++)
{}
}
}
/**********写指令到LCD子函数************/
void WriteCommandLCM(uchar WCLCM,uchar BusyC)
{
if(BusyC)lcd_wait()
DATAPORT=WCLCM
LCM_RS=0 /* 选中指令寄存器*/
LCM_RW=0 // 写模式
LCM_EN=1
_nop_()
_nop_()
_nop_()
LCM_EN=0
}
/**********写数据到LCD子函数************/
void WriteDataLCM(uchar WDLCM)
{
lcd_wait( ) //检测忙信号
DATAPORT=WDLCM
LCM_RS=1 /* 选中数据寄存器 */
LCM_RW=0 // 写模式
LCM_EN=1
_nop_()
_nop_()
_nop_()
LCM_EN=0
}
/***********lcd内部等待函数*************/
void lcd_wait(void)
{
DATAPORT=0xff //读LCD前若单片机输出低电平,而读出LCD为高电平,则冲突,Proteus仿真会有显示逻辑黄色
LCM_EN=1
LCM_RS=0
LCM_RW=1
_nop_()
_nop_()
_nop_()
while(DATAPORT&BUSY)
{ LCM_EN=0
_nop_()
_nop_()
LCM_EN=1
_nop_()
_nop_()
}
LCM_EN=0
}
/**********LCD初始化子函数***********/
void initLCM( )
{
DATAPORT=0
ddelay(15)
WriteCommandLCM(0x38,0) //三次显示模式设置,不检测忙信号
ddelay(5)
WriteCommandLCM(0x38,0)
ddelay(5)
WriteCommandLCM(0x38,0)
ddelay(5)
WriteCommandLCM(0x38,1) //8bit数据传送,2行显示,5*7字型,检测忙信号
WriteCommandLCM(0x08,1) //关闭显示,检测忙信号
WriteCommandLCM(0x01,1) //清屏,检测忙信号
WriteCommandLCM(0x06,1) //显示光标右移设置,检测忙信号
WriteCommandLCM(0x0c,1) //显示屏打开,光标不显示,不闪烁,检测忙信号
}
/****显示指定坐标的一个字符子函数****/
void DisplayOneChar(uchar X,uchar Y,uchar DData)
{
Y&=1
X&=15
if(Y)X|=0x40 //若y为1(显示第二行),地址码+0X40
X|=0x80 //指令码为地址码+0X80
WriteCommandLCM(X,0)
WriteDataLCM(DData)
}
/*******显示指定坐标的一串字符子函数*****/
void DisplayListChar(uchar X,uchar Y,uchar *DData)
{
uchar ListLength=0
Y&=0x01
X&=0x0f
while(X<16)
{
DisplayOneChar(X,Y,DData[ListLength])
ListLength++
X++
}
}
void display()
{
STR()
DisplayListChar(0,0,str0)
DisplayListChar(0,1,str1)
}
频率测量的方法常用的有测频法和测周法两种。
测频法的基本思想是让计数器在闸门信号的控制下计数1秒时间,计数结果是1秒内被测信号的周期数,即被测信号的频率。若被测信号不是矩形脉冲,则应先变换成同频率的矩形脉冲。测频法的原理框图如图所示。
图中,秒脉冲作为闸门信号,当其为高电平时,计数器计数;低电平时,计数器停止计数。显然,在同样的闸门信号作用下,被测信号的频率越高,测量误差越小。当被测频率一定时,闸门信号高电平的时间越长,测量误差越小。但是闸门信号周期越长,测量的响应时间也越长。
2、当被测信号频率较低时,为保证测量精度,常采用测周法。即先测出被测信号的周期,再换算成频率。测周法的实质是把被测信号作为闸门信号。
在它的高电平的时间内,用一个标准频率的信号源作为计数器的时钟脉冲。若计数结果为N,标准信号频率为f1,则被测信号的周期为:T=T1·N。被测信号的频率为:f=1/T1·N=f1/N。
利用测周法所产生的最大绝对误差,显然也等于±1个标准信号周期。如果被测信号周期的真值为T真=T1·N,则T测=T1·(N±1)σmax=(f测-f真)/f真=T真/T测_1=±1/(N±1)由上式可知,对于一定的被测信号,标准信号的频率越高,则N的值越大,因而相对误差越小。
3、低频段的测量,鉴于上述困难,对于低频信号,为了达到规定的精度,要采取一些比较特殊的方法。例如,可考虑将被测信号倍频后再用测频法测量。
或将闸门信号展宽。由于倍频电路比较复杂,所以一般采用后一种方法,实际上闸门信号展宽与被测信号倍频在效果上是相同的。
闸门信号展宽比较容易做到,例如采用分频电路就可以实现。若闸门信号高电平时间从1秒展宽到10秒,则相对误差可以按比例下降,但响应时间也增大相同的比例。
4、显示方式:共用右边四个数码管,左三个显示数据,最右端一个显示单位,为0时单位为Hz,为1时单位为Khz
5、代码:
//#include<c8051F330.h>
#include<ZLG7289.h>
#include<init.h>
#defineuintunsignedint
uinta,b,c,d
unsignedlong x
unsignedlong count
unsignedcharflag=0
voidTimer0_Init()interrupt1
{
TH0=(65535-10000)/256
TL0=(65535-10000)%256
if(++count==40)
{
count=0
TR1=0
x=TH1*256+TL1
TH1=0
TL1=0
TR1=1
flag=1
}
}
voidshow(void)
{if(x>=10&&x<100)
{
a=0
b=x*10%100
c=x/10
d=x%10
ZLG7289_Download(1,7,0,a)
ZLG7289_Download(1,6,0,b)
ZLG7289_Download(1,5,1,d)
ZLG7289_Download(1,4,0,c)
}
elseif(x>=100&&x<1000)
{
a=0
b=x/100
c=x%100/10
d=x%10
ZLG7289_Download(1,7,0,a)
ZLG7289_Download(1,6,1,d)
ZLG7289_Download(1,5,0,c)
ZLG7289_Download(1,4,0,b)
}
elseif(x>=1000&&x<10000)
{
a=x/1000
b=x%1000/100
c=x%100/10
d=1
ZLG7289_Download(1,7,0,d)
ZLG7289_Download(1,6,0,c)
ZLG7289_Download(1,5,0,b)
ZLG7289_Download(1,4,1,a)
}
}
main(void)
{
system_init()
systemclk_init()
port_init()
ZLG7289_Init(40)
ZLG7289_Reset()
timer_init()
while(1)
{
if(flag==1)
{
show()
flag=0
}
}}
#include<C8051F330.h>
#include<port.h>
voidsystem_init()
{
PCA0MD&=~0x40
}
voidsystemclk_init()
{
OSCICL=OSCICL+42//设置内部振荡器为24MHZ
OSCICN|=0x01 //内部振荡器4分频
}
voidport_init()
{
P0SKIP=0x00 //跳过P0.0做INT0.P0.1做INT1(P0.6,P0.7模拟输出不跳)
P1SKIP=0x00 //跳过P1.2,P1.3,P1.4
XBR0=0x00 //交叉开关使能UART0
XBR1=0x60 //打开交叉开关
//IT01CF=0x10 //INT0配置在P0.0,INT1配置在P0.1
P0MDIN=0xFF //数字输入
P1MDIN=0xFF
P0MDOUT=0xFF//推挽
P1MDOUT=0xFF
}
voidtimer_init()
{
TMOD=0X51
TH0=(65535-2500)/256
TL0=(65535-2500)%256
EA=1
ET0=1
TR1=1
TR0=1
}
#ifndef__port_H_
#define__port_H_
voidsystem_init(void)
voidsystemclk_init(void)
voidport_init(void)
voidtimer_init(void)
#endif
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)