导航:首页 > 操作系统 > 单片机频率计汇编

单片机频率计汇编

发布时间:2024-12-17 13:45:51

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

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

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

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

B. 单片机频率计原理程序代码

#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();
}
}
//******************************************************//

C. 51单片机用定时器计数器测量频率

定时器1对外部脉冲计数时TMOD高4位设置应该是5
因此TMOD=0x51;
以下我的频率计程序:
#include <reg52.h>//因没用到STC12C5410专有特殊功能寄存器,此处用52或51的头文件均可
#define unit 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;//液晶屏使能
sbit fm=P1^7;//蜂鸣器

#define db P2 //定义P2为数据输出口,写数据时用db代替P2,增加液晶屏程序的通用性

//更改硬件接线时,只更改此处,而不必去更改液晶屏读写子程序
uchar aa,bb,cc;//变量声明
unit 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);
Delay1ms(10*12);
write_com(0x0f);
Delay1ms(10*12);
write_com(0x06);
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;//分离出万,千,百,十,个,对于int型数据,最大不超过65535
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=0;//报警
}
display4(ee);//显示
fm=1;//报警停止
}
}
void timer1()interrupt 3//注意:定时器1的中断序号为3
{
aa++;
TH1=0x4c;//11.0592Mhz
TL1=0x5c;
if(aa==10)//中断10次,共0.5S
{
TR0=0;//暂停计数
aa=0;
bb=TH0;//读出计数器数据
cc=TL0;
TL0=0;//计数器清0
TH0=0;
TR0=1;//重新启动
}
}

D. 基于51单片机上的频率计怎么设计频率量程转换 例如通过按键切换Hz~kHz,程序怎么编写

通过不同的端口控制外接的分频器。或接外接与门和二进制计数器。

E. 求51单片机设计数字频率计,附带Proteus仿真和程序

刚刚下了一楼传的附件,测试后发现精度和测量范围都比较差。如果单从测频的角度来说,51的频率计是很简单的。恰好几年前我写过类似的程序,是用来测频率和占空比的。

理论上单用C52这单片机测频率最高为:12M/12/2=500KHZ。我写的这个程序可以同时测频率和脉宽,仿真下大概可以测到350KHZ;测脉宽好像10KHZ左右,再高的话脉宽的精度就会下降。测频精度在100KHZ以内,基本是2HZ;200K是5HZ;350KHZ以内是10HZ;最低测量频率1HZ。

仿真比较慢,数据要3秒后才会稳定,有兴趣的话自测吧。

50KHZ测量

F. 设计一个以单片机为核心的频率测量装置。求大神给写一下程序。

单片机频率计仿真。

#include<reg52.h>

#define uchar unsigned char

#define uint unsigned int

sbit p0=P1^0;

bit tb0,tb1;

uchar tt0,tt1,tt2,tt3;

uchar code led[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

void main()

{

TMOD=0x11;

TH0=(65535-50000)/256;

TL0=(65535-50000)%256;

EA=1;

ET0=1; //开定时器0中断

ET1=1; //开定时器1中断

TR0=1; //启动定时器0

TR1=1; //启动定时器1

while(1)

{

if(TR1==0)

{

// tt3=65536*tt2+266*TH1+TL1

TH1=0x00;TL1=0x00;

tt1=0x00;tt2=0x00;

tb1=1;

led[0]=tt3/1000000;

led[1]=tt3/100000%10;

led[2]=tt3/100000%10;

led[3]=tt3/10000%10;

led[4]=tt3/1000%10;

led[5]=tt3/100%10;

led[6]=tt3/10%10;

led[7]=tt3%10;

}

if(tt0==1 && tb0=1)

{

tb0=1;P0==0xff;

P2=led[0];P0=0xfe

}

if(tt0==2 && tb0=1)

{

tb0=1;P0==0xff;

P2=led[1];P0=0xfd

}

if(tt0==3 && tb0=1)

{

tb0=1;P0==0xff;

P2=led[2];P0=0xfb

}

if(tt0==4 && tb0=1)

{

tb0=1;P0==0xff;

P2=led[3];P0=0xf7

}

if(tt0==5 && tb0=1)

{

tb0=1;P0==0xff;

P2=led[4];P0=0xef

}

if(tt0==6 && tb0=1)

{

tb0=1;P0==0xff;

P2=led[5];P0=0xdf

}

if(tt0==7 && tb0=1)

{

tb0=1;P0==0xff;

P2=led[6];P0=0xbf

}

if(tt0==8 && tb0=1)

{

tb0=1;P0==0xff;

P2=led[7];P0=0x7f

tt0=0;

}

}

}

void timer0() interrupt 1

{

TH0=(65535-2000)/256;

TL0=(65535-2000)%256;

tt1++;

if(tt1==500)

{

TR1=0; //启动定时器1

tb1=0

}

tt0++;tb0=1;

if(tb1==1 && TR1==0)TR1=1;

}

void timer1() interrupt 3

{

tt2++;

}

阅读全文

与单片机频率计汇编相关的资料

热点内容
数据加密升级 浏览:164
移动设备网页源码 浏览:702
做程序员几年了感觉都是在做业务 浏览:68
移动魔白盒服务器地址 浏览:348
linuxapache状态 浏览:298
华为服务器准系统是什么 浏览:236
word压缩所有图片大小 浏览:389
php求平均值 浏览:118
焊锡单片机 浏览:917
自由程序员如何赚钱 浏览:682
手机pdf阅读器哪个好 浏览:25
命令行插件 浏览:111
安卓手机没有呼吸灯怎么看消息 浏览:751
噪声检测app哪个好 浏览:812
androidapp生命周期 浏览:344
小众搭配app哪个好用 浏览:825
奥特佳电动空调压缩机 浏览:596
用什么编译器看nginx源码 浏览:333
java中局部变量 浏览:821
云服务器命令行复制文件 浏览:401