51单片机制作简易数字频率计程序

51单片机制作简易数字频率计程序,第1张

这里有一个四位数码管的频率计,供参考

#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


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/11112977.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-13
下一篇 2023-05-13

发表评论

登录后才能评论

评论列表(0条)

保存