导航:首页 > 操作系统 > 基于51单片机的频率计程序

基于51单片机的频率计程序

发布时间:2022-05-14 23:05:22

1. 51单片机的数字频率计

本应用系统设计的目的是通过在“单片机原理及应用”课堂上学习的知识,以及查阅资料,培养一种自学的能力。并且引导一种创新的思维,把学到的知识应用到日常生活当中。在设计的过程中,不断的学习,思考和同学间的相互讨论,运用科学的分析问题的方法解决遇到的困难,掌握单片机系统一般的开发流程,学会对常见问题的处理方法,积累设计系统的经验,充分发挥教学与实践的结合。全能提高个人系统开发的综合能力,开拓了思维,为今后能在相应工作岗位上的工作打下了坚实的基础。

1.1数字频率计概述
数字频率计是计算机、通讯设备、音频视频等科研生产领域不可缺少的测量仪器。它是一种用十进制数字显示被测信号频率的数字测量仪器。它的基本功能是测量正弦信号,方波信号及其他各种单位时间内变化的物理量。在进行模拟、数字电路的设计、安装、调试过程中,由于其使用十进制数显示,测量迅速,精确度高,显示直观,经常要用到频率计。
本数字频率计将采用定时、计数的方法测量频率,采用一个1602A LCD显示器动态显示6位数。测量范围从1Hz—10kHz的正弦波、方波、三角波,时基宽度为1us,10us,100us,1ms。用单片机实现自动测量功能。
基本设计原理是直接用十进制数字显示被测信号频率的一种测量装置。它以测量周期的方法对正弦波、方波、三角波的频率进行自动的测量。
点击重新加载
1.2频率测量仪的设计思路与频率的计算

图1 频率测量原理图

频率测量仪的设计思路主要是:对信号分频,测量一个或几个被测量信号周期中已知标准频率信号的周期个数,进而测量出该信号频率的大小,其原理如右图1所示。

若被测量信号的周期为,分频数m1,分频后信号的周期为T,则:T=m1Tx 。由图可知: T=NTo
(注:To为标准信号的周期,所以T为分频后信号的周期,则可以算出被测量信号的频率f。)
由于单片机系统的标准频率比较稳定,而是系统标准信号频率的误差,通常情况下很小;而系统的量化误差小于1,所以由式T=NTo可知,频率测量的误差主要取决于N值的大小,N值越大,误差越小,测量的精度越高。

1.3 基本设计原理

基本设计原理是直接用十进制数字显示被测信号频率的一种测量装置。它以测量周期的方法对正弦波、方波、三角波的频率进行自动的测量。
所谓“频率”,就是周期性信号在单位时间(1s)内

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

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

#include<reg52.h>
#defineucharunsignedchar
#defineuintunsignedint
ucharan[10]={0xc0,0Xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //所需的段的位码
//ucharwei[4]={0XEf,0XDf,0XBf,0X7f};//位的控制端 (开发板)
ucharwei[4]={0X80,0X40,0X20,0X10};//位的控制端 (仿真)
uintz,x,c,v,date; //定义数据类型
uintdispcount=0;
uintlck=0;
uintdisp=0;
/******************************************************************

延时函数

******************************************************************/
voiddelay(uchart)
{
uchari,j;
for(i=0;i<t;i++)
{
for(j=13;j>0;j--);
{;
}
}
}

/**********************************************************************
数码管动态扫描
*********************************************************************/
voidxianshi()
{
/*****************数据转换*****************************/
z=date/1000; //求千位
x=date%1000/100; //求百位
c=date%100/10; //求十位
v=date%10; //求个位

P2=wei[0];
P0=an[z];
delay(50);
P2=wei[1];
P0=an[x];
delay(50);
P2=wei[2];
P0=an[c];
delay(50);
P2=wei[3];
P0=an[v];
delay(50);


}

/*************************************************************************
定时器初值1ms
**************************************************************************/
voidinitTimer(void)
{
TMOD=0x0;
TH0=0xe3;
TL0=0xc;
}

/*************************************************************************
定时器函数
**************************************************************************/
voidtimer0(void)interrupt1
{
TH0=0xe3;
TL0=0xc;
lck++;
if(lck==1000)
{
disp=dispcount;
lck=0;
dispcount=0;
}

}

/*************************************************************************
中断函数
**************************************************************************/
voidint0(void)interrupt0
{

dispcount++;//每一次中断,计数加一

}

/*************************************************************************
主函数
**************************************************************************/
voidmain(void)
{

IT0=1;//INT0下降沿中断
EX0=1;//允许INT1中断
initTimer();//装入初值
TR0=1;
ET0=1;
EA=1;
while(1)

{
date=disp;
xianshi();
}
}

3. 做用51单片机做一个频率计,测量范围为0.1Hz~10kHz

在不改变定时时间的前提下,也就是0.5秒定时,是不能实现0.1~2Hz频率的测量的。
你所谓2Hz~10KHz易实现也是基于这个道理。但这个也是理论情况。
当你0.5s内刚好检测到一个脉冲,你认为这个时候是2Hz而不是2.5hz或者3.9hz?
这中间存在一个测量精度的问题。实际上你所测到的信号是在2hz到4hz之间。

实际上我们在测量信号的时候,低频一般会采用测周期,高频用测频才能提高测量的准确性。
至于高低频的临界点,跟你的计数频率有关,感兴趣的话可以去看《电子测量原理》。

下面我来讲下测周实现的方法,可以使用边沿触发的D触发器输出作为单片机的外部定时控制,测量信号作为触发时钟,计数值作为该信号的周期。

4. 单片机 程序

下面这个是51单片机的频率计程序,因51单片机内没有CCP输入捕捉模块,软件用主程序去不停地查询输入引用状态,电平一发生改变就用定时器计时,这样就计算出了周期、频率,P0口接8位数码管的共阴极,如用三个数码显示就接高三位,
利用PIC单片机CCP模块设计频率计请参照网页:
http://danpj.com/PICdanpianji/2009/0403/179.html
http://www.700q.com/article/show.asp?id=57467

#include <AT89X51.H>
//********数码管位代码表(P0口)**********//
unsigned char code dispbit[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
//********数码管段代码表(P2口,共阴且高位接a,低位接h笔段)**********//
unsigned char code dispcode[]={0xFC,0x60,0xDA,0xF2,0x66,0xB6,0xBE,0xE0,
0xFE,0xF6,0xEE,0x3E,0x9C,0x7A,0x9E,0x8E,0x00};
//********8位数据缓冲器**********//
unsigned char dispbuf[8];
unsigned char temp[8];
unsigned char dispcount;
unsigned char T0count;
unsigned char timecount;
bit flag;
unsigned long x;

//*********初始化模块**********//
void initial(void){
TMOD=0x15;
TH0=0;
TL0=0;
TH1=(65536-4000)/256;
TL1=(65536-4000)%256;
TR1=0;
TR0=0;
ET0=1;
ET1=1;
EA=1;
}
//******************************************************//

//*********显示模块**********//
void dataDisplay(){
unsigned char i;
for(i=0;i<8;i++){
temp[i]=0;
}
i=0;
while(x/10){
temp[i]=x%10;
x=x/10;
i++;
}
temp[i]=x;
for(i=0;i<8;i++){
dispbuf[i]=temp[i];
}
P2=dispcode[dispbuf[dispcount]];
P0=dispbit[dispcount];
dispcount++;
if(dispcount==8){
dispcount=0;
}
}
//******************************************************//

//*********信号频率测量模块**********//
float frequency(float freq){
initial();
TR0=1;TR1=1;
if(timecount==250){
TR0=0;
freq=T0count*65536+TH0*256+TL0;
return(freq);
}
}
//******************************************************//

//*********信号周期测量模块**********//
float cycle(float count){
initial();
if(P3_4==1){
TR0=1;TR1=1;
if(P3_4==0){
TR0=0;
count=1000000/(timecount*4000+TH1*256+TL1-61536);
}
}
return(count);
}
//******************************************************//

//*********定时中断服务程序1**********//
void t1(void) interrupt 3 using 0{
//initial();
//TR0=1;
//TR1=1;
TH1=(65536-4000)/256;
TL1=(65536-4000)%256;
timecount++;
}
//******************************************************//

//*********定时中断服务程序2**********//
void t0(void) interrupt 1 using 0{
//initial();
//TR0=1;
//TR1=1;
T0count++;
}
//******************************************************//

//*********主函数**********//
void main(void){
while(1){
x=frequency(x);
if(x<100){
x=cycle(x);
}
dataDisplay();
}
}
//******************************************************//

5. 51单片机频率计的中断程序怎么设计

定时器11MS中断一次,5次是5ms,乘200就是1秒种,其初值由晶振频率决定,有计算软件
当然,也可以中断10次或20次,频率判断更准确,但响应速度慢了
1600或800方波接入定时器/计数器0的外部输入引脚上,好像是P3.4
程序如下:
void
init()//初始化设置
{
TMOD=0x15;//定时器0作为计数器,定时器1作为定时器用
TH0=.0;//计数器清0
TL0=0;
EA=1;//开总中断
ET1=1;//允许定时器1中断
TH1=......;
TL1=.......;
TR0=1;//启动计数器
TR1=1;//启动定时器
aa=0;
}
void
main()//主程序很简单
{
init();//初始化
while(1)//循环程序
{
dd=bb*256+cc;//
5ms的计数值
ee=200*dd;//换算为1秒钟的计数值
if((ee>750)&&(ee<850))
{
P3.5=0;
}
if((ee>1550)&&(ee<1650))
{
P3.5=1;
}
}
}
void
timer1()interrupt
3//注意:定时器1的中断序号为3
{
aa++;
TH1=....;.
TL1=....;.
if(aa==5)//中断5次,共5ms
{
TR0=0;//暂停计数
aa=0;
bb=TH0;//读出计数器数据
cc=TL0;
TL0=0;//计数器清0
TH0=0;
TR0=1;//重新启动计数器
}
}

6. 基于51单片机的数字频率计设计资料。要C语言的,谢谢。

#include <reg51.h>
#include <intrins.h>

#define uchar unsigned char
#define uint unsigned int
#define NOP() _nop_()

sbit key1=P1^0;//key1 按此按键输出1000Hz
sbit key2=P1^1;//key2 按此按键输出100Hz
sbit key3=P1^2;//key3 按此按键输出1Hz 1Hz是采用纯粹软件延时

sbit square=P2^7;//方波输出引脚
sbit fenpin=P2^6;//分频后信号输出引脚

uchar TMRH,TMRL;//定时器T1初值寄存器
uchar square_delay;//延时产生方波标志

struct
{
uchar value;//当前键值
uchar backvalue;//上次键值
uchar done;//按键是否响应 1为已经响应
} key;

uchar KeyScan(void); //按键扫描 获取键值
void KeyProc(void);//按键处理
void KeyAction(void);//按键散转 转向需要执行的程序
void delay500ms(void);//500ms延时程序 用于产生1Hz方波

void timer0() interrupt 1 using 1 //12M晶振 20ms中断 用于按键扫描 T0中断
{
TH0=0xB1;
TL0=0xE0;
KeyProc(); //避免按键在纯粹软件延时的时候不响应
}

void timer1() interrupt 3 using 1 //T1中断
{
TH1=TMRH;
TL1=TMRL;
square=~square;
if(square==1)
EX1=1;
}

void EXT_INT1() interrupt 2 using 1 //外部INT1中断 低电平触发
{
EX1=0;
fenpin=~fenpin;
}

void main()
{
TMRH=0xFE;
TMRL=0x0C;
TCON=0x00;
EX1=1; //允许INT1中断
TMOD=0x11; //定时器T0,T1工作在方式1
TH0=0xB1;
TL0=0xE0;
TH1=TMRH;
TL1=TMRL;
ET0=1; //允许T0溢出中断
ET1=1; //允许T1溢出中断
TR0=1; //启动计数器T0
TR1=1; //启动计数器T1
EA = 1; //开中断
while(1)
{
if(square_delay)
{
delay500ms();
square=~square;
if(square==1)
EX1=1;
}
}
}

void KeyProc(void)
{
key.value=KeyScan();
if(key.value==key.backvalue)
{
if(!key.done)
{
KeyAction();
key.done=1;
}
}
else
{
key.backvalue=key.value;
key.done=0;
}

}

void KeyAction(void)
{
switch(key.value)
{
case 1:
{
ET1=0;
TR1=0;
TMRH=0xFE; //0.5ms初值
TMRL=0x0C;
TR1=1;
ET1=1;
square_delay=0;
}break;

case 2:
{
ET1=0;
TR1=0;
TMRH=0xEC;//5ms初值
TMRL=0x78;
TR1=1;
ET1=1;
square_delay=0;
}break;

case 3:
{
ET1=0;
TR1=0;
square_delay=1;
}break;
}

}

//获取键值
uchar KeyScan(void)
{
uchar keyval=0;
if (key1==0) keyval=1;
else if(key2==0) keyval=2;
else if(key3==0) keyval=3;
else keyval=0;
return keyval;
}

//500ms延时 晶振12M
void delay500ms(void)
{
unsigned char i,j,k;
for(i=15;i>0;i--)
for(j=202;j>0;j--)
for(k=81;k>0;k--);
}

7. 各位老铁,小弟在论文进行答辩的时候碰到了点问题,论文题目是基于51单片机的数字频率计设计

1。单片机测量的是方波信号,如果是其它波形或幅度不合适,就进行放大和整形
2。.该信号进入单片机的哪个引脚,如果用定时器0作为计数器,输入引脚是P3.4
如果用定时器1作为计数器,输入引脚是P3.5 如果测单个脉冲宽度(或周期),可以输入任意引脚,但最好用中断引脚P3.2或P3.3
3。.信号进入引脚之后怎么计算它的程序
用另外一个定时器定时50ms,测50ms内有多少个脉冲输入,然后乘以20(即1S)即是频率

8. 基于51单片机的数字频率计设计(proteus仿真)

#include"reg51.h"
#define uchar unsigned char
uchar tt;
void init();
void main(uchar t) //根据需要修改相应的值;
{
t=tt;
init();
while(1)
{
if(tt==t) //如果t==10,那么周期是1秒,即平率==1Hz;
{
tt=0;
P0^0=~P0^0; //设信号从P0_0口输出;
}
}
}
void init()
{
TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256; //这里周期是100ms,你可以根据你的需要修改
EA=1;
ET0=1;
TR0=1;
}
void timer() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
tt++;
}

9. 基于51单片机的数字频率计(0—10MHZ)

再加两个数码管,用T1引脚检测频率,打开T1中断,每中断一次加1计数,

满1秒中后停止T1计数,读出T1计数器的TH1 TL1,

频率= 65536x中断次数+TH1 HL1。

前提是选择高速单片机,即只要T1引脚能够响应10M的频率就没有问题

因为要计数65536次才T1才会中断一次。

10. 求51单片机程序

这是51单片机频率计程序,弄明白了写你的程序就 很简单了
#include <math.h>
#define uint unsigned int
#define uchar unsigned char
//定义以I/O口的功能
sbit beiguang=P3^2;//液晶屏背光
sbit rs=P1^3;//液晶屏写选择,0命令 1数据
sbit rw=P1^4;//液晶屏读写选择
sbit lcden=P1^5;//液晶屏使能
#define db P2 //定义P2为数据输出口,写数据时用db代替P2,增加液晶屏程序的通用性

//更改硬件接线时,只更改此处,而不必去更改液晶屏读写子程序
uchar aa,bb,cc;
uint dd,ee;
void Delay1ms(unsigned int i) //1ms延时程序
{
unsigned int j;
for(;i>0;i--)
{
for(j=0;j<125;j++)
{;}
}
}
void init()//初始化设置
{
TMOD=0x15;//定时器0作为计数器,定时器1作为定时器用
TH0=0;//计数器清0
TL0=0;
EA=1;//开总中断
ET1=1;//允许定时器1中断
TH1=0x4c;
TL1=0x5c;
TR0=1;//启动计数器
TR1=1;//启动定时器
aa=0;
}
void write_com(uchar com)//向液晶屏写命令
{
db=com;
rs=0;
rw = 0;
lcden=0;
Delay1ms(10*12);
lcden=1;
Delay1ms(10*12);
lcden=0;
}
void write_date(uchar date)//向液晶屏写数据
{
db=date;
rs=1;
rw = 0;
lcden=0;
Delay1ms(10*12);
lcden=1;
Delay1ms(10*12);
lcden=0;
}
void init2()//液晶屏初始化
{
beiguang=0;
rw=0;
write_com(0x38);//显示模式16字*2行,5*7点阵,数据口8位
Delay1ms(10*12);
write_com(0x0f);//开显示,显示光标,光标闪烁
Delay1ms(10*12);
write_com(0x06);//写完数据后数据指针和光标位置自动加1
Delay1ms(10*12);
write_com(0x01);//屏幕清除
Delay1ms(10*12);
}
void display4(unsigned int number) //单行多位显示程序
{
uchar A1,A2,A3,A4,A5;
init2();//液晶屏初始化
A1=number/10000%10;//分离出十万,万,千,百,十,个
A2=number/1000%10;
A3=number/100%10;
A4=number/10%10;
A5=number%10;

write_com(0x80);//第1个数据的位置设定,第1行第1列
Delay1ms(10);
write_date(0x30+A1);//写数据
Delay1ms(10);
write_date(0x30+A2);
Delay1ms(10);
write_date(0x30+A3);
Delay1ms(10);
write_date(0x30+A4);
Delay1ms(10);
write_date(0x30+A5);
Delay1ms(10);

write_com(0x87);//第6个数据'H'的位置,中间空85和86 二格
write_date('H');
Delay1ms(10);
write_date('z');
Delay1ms(10);
}
void main()//主程序很简单
{
init();//初始化
while(1)//循环程序
{
dd=bb*256+cc;//0.5S的计数值
ee=2*dd;//换算为1秒钟的计数值
if(aa==1)
{
if(TH0>12)//预判断,50ms内TH0>12,1s内计数值将超过可计数的最大值65535
fm=1;//报警
}
display4(ee);//显示
fm=0;//报警停止
}
}
void timer1()interrupt 3//注意:定时器1的中断序号为3
{
aa++;
TH1=0x4c;//11.0592Mhz
//TL1=0;//11.0592Mhz
TL1=0x5c;//实际电路振荡频率11.03705Mhz,对TL1修正
if(aa==10)//中断10次,共0.5S
{
TR0=0;//暂停计数
aa=0;
bb=TH0;//读出计数器数据
cc=TL0;
TL0=0;//计数器清0
TH0=0;
TR0=1;//重新启动计数器
}
}

阅读全文

与基于51单片机的频率计程序相关的资料

热点内容
时政新闻app哪个好 浏览:904
手机已加密怎么办 浏览:199
安卓手机截屏怎么传到苹果 浏览:525
京管家app哪里下载 浏览:33
文件夹横向排列的竖向排列 浏览:451
51单片机驱动摄像头模块 浏览:689
政府文件加密没法转换 浏览:373
android判断栈顶 浏览:331
凭证软件源码 浏览:860
androidwebview滚动事件 浏览:11
如何将电脑上的图片压缩成文件包 浏览:899
程序员转金融IT 浏览:837
黑马程序员培训效果如何 浏览:913
本地集成编译 浏览:528
韩国电影哪个app可以看 浏览:703
玖月授权什么app什么梗 浏览:785
怎么使用服务器上的ip地址是什么情况 浏览:752
手机密码加密后怎么解密 浏览:343
华为云的服务器的ip地址怎么访问不 浏览:367
webstormvue在线实时编译生效 浏览:184