‘壹’ 怎样用单片机实现频率的测量
这个太简单了,
//搞个外中断,中断来了就计数
#include<包头reg51.h>
void t0(void) interrupt 0
{
T0count++; //这是全局变量
}
//T1工作在定时状态下,每定时1秒钟到,刷新T0的计数,
void t1(void) interrupt 1
{
TR0=1;//搞个计数器中断
TH0=0x3c;//重新初始化
TL0=0xb0;//这是12M晶振的
timecount++; //中断一次,记个数
if(timecount==20) //一个计数器,一次记不到一秒的,只有记很多次,才能算一秒,这就一秒了
{ frequency=T0count; //看看中断多少次,frequency就是你要的频率。
T0count=0;//把这个清了,记下一秒的次数。
}
}
main()
{
TMOD = 0x01; //选择计数器0的模式
EA=1; // 打开总中断
EX0=1; IT0=1;//开0外中断
ET0=1;TR0=1;//开0计时器
这里你加点代码,把frequency显示出来。
}
万一你想要周期
知道频率了,已经很简单了。
T=1/f;单位是多少?是秒!
T=1000000000/f;单位是多少?是纳秒!
主程序加个
long T=0;
T=1000000000/f;//T就是周期,单位是NS。
万一你测的频率很低
把
if(timecount==20) //一个计数器,一次记不到一秒的,只有记很多次,才能算一秒,这就一秒了
改为
if(timecount==200)//这就成十秒记一次了,不够就2000, 不过记得要frequency/10,否者频率就大了10倍。
测频率的就在这了
你要显示,看你用什么了 是数码管 还是1602,这就靠你自己了。
加油练吧
‘贰’ 单片机课程设计数字频率计
数码管台古老了,你用这个吧,看着还稍微有点可以,代码和电路都给你了,没有做不出来的理由,有问题加我QQ11422376745
#include "d:c51 eg51.h"
#include "d:c51intrins.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=0;i<k;i++)
{
for(j=0;j<60;j++)
{;}
}
}
/**********写指令到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);
}
‘叁’ 单片机测量频率C程序。
将需要测量的信号接入单片机的一个IO,然后中断扫描这个IO后,记录时间,不过一般51单片机测量信号的平率不高,几k还是可以的,如果很高的话建议用32位单片机,比如说stm32系类的,有捕获模式硬件触发,信号几百k也没有问题,采集到信号后放入ram,内部ram够大的话就不需要外扩了,然后将数据在电脑上显示出来,或者直接在单片机的液晶上显示出来也行。。
希望能解决您的问题。
‘肆’ 用51单片机测频率,T0定时,T1计数,具体程序应该怎么写呀,跪求完整点的
数码管还是液晶屏显示?晶振频率多少?
用定时器时,先设置工作方式再装入初值开启中断再开启定时器/计数器
void init()//初始化设置
{
TMOD=0x51;//定时器1作为计数器,定时器0作为定时器用
TH1=0;//计数器清0
TL1=0;
EA=1;//开总中断
ET0=1;//允许定时器0中断
TH0=(65535-50000)/256;// 晶振12M时 定时50ms需装入的初值
TL0==(65535-50000)%256;
TR0=1;//启动计数器
TR1=1;//启动定时器
}
定时器中断程序
void timer0()interrupt 1//注意:定时器0的中断序号为1
{
TH0=(65535-50000)/256;
TL0==(65535-50000)%256;
TR1=0;//暂停计数
bb=TH1;//读出计数器数据
cc=TL1;
TL1=0;//计数器清0
TH1=0;
TR1=1;//重新启动
}
频率f=(bb*256+cc)*20
然后分离出个十百千万,送液晶屏或数码管去显示
主程序先初始化,然后就是不停地显示
‘伍’ 51单片机测频率的程序
测频率时,频率高的时候,采用“定时计数法”。
楼上给出的“开启一个定时器,计算一定时间t内的count值”,就是这种方法。
但是,频率低的时候,这种方法是不适用的。
因为想要计几个数,就要花费很长的时间。
故此,频率低的时候,应该使用“测量周期法”,再换算成频率。
‘陆’ 单片机方式3怎么编频率计程序
你应该是T0做,T1另外有用吧?我花了一个小时,调了一个,只计算了频率,频率低是1秒计算一次,你可以改,部分地方应该可以优化。你试试,如果可以可以把keil的项目打包发给你。
程序如下:
/*
testT0T1.c
芯片:AT89C51
晶振:12MHz
*/
#include <reg51.h>
bit g_bitNewF; //计算了新频率
unsigned int g_Count;
unsigned int g_Timer200;
unsigned long frequency;
void Init(void)
{
EA = 0;
//T0使用模式3,TL0计数,
TMOD = 0x07;
TL0 = 0x00;
//TH0计时200us
TH0 = 0x38;
//启动
TF0 = 0;
TF1 = 0; //可以不清这两个
TR0 = 1;
TR1 = 1;
EA = 1;
ET0 = 1;
ET1 = 1;
}
void main (void)
{
g_bitNewF = 0;
g_Timer200 = 0;
Init();
while(1)
{
if (g_bitNewF)
{
g_bitNewF = 0;
//display or do something else.
}
}
}
//计数满中断
void T0_Int(void) interrupt 1
{
TL0 = 0x00;
g_Count += 255;
if (g_Count > 65535-255) //频率大提前计算
{
g_bitNewF = 1;
if (g_Timer200<10){;return;}//误差太大,请自己增加出错处理
frequency = ((long)g_Count*5000)/g_Timer200;
}
}
//定时到中断
void T1_Int(void) interrupt 3
{
TH0 = 0x46;
g_Timer200++;
if (g_Timer200 == 5000)
{
g_Timer200 = 0;
g_bitNewF = 1;
frequency = g_Count + TL0;
TL0 = 0;
g_Count = 0;
}
}
//end
‘柒’ 跪求单片机at89c52频率计c语言程序
方波叫函数发生器。频率计程序如下:
#include "reg51.h"
#define uchar unsigned char
uchar disp[8]={0,0,0,0,0,0,0,0};
uchar T0count,T1count;
void delay(void)
{
uchar i;
for(i=250;i>0;i--);
}
void display()
{
//uchar i,j,k=0x80;
uchar dispcode[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uchar i,k;
k=0x80;
for(i=0;i<8;i++)
{
P2=0;
P0=dispcode[disp[i]];
P0=~P0;
P2=k;
k=k>>1;
delay();
}
P2=0;
}
void calc()
{
uchar i;
long frequency;
frequency=(T0count*256+TH0)*256+TL0;
for(i=7;i>0;i--)
{
disp[i]=frequency%10;
frequency=frequency/10;
}
disp[0]=frequency;
}
void init()
{
T0count=0;
T1count=0;
TH0=0;
TL0=0;
}
void main()
{
init();
TMOD=0x15;
TH1=(65536-5*110592/12)/256;
TL1=(65536-5*110592/12)/256%10;
ET1=1;
ET0=1;
EA=1;
TR1=1;
TR0=1;
//以下四句的作用是在P1.0引脚上形成1000Hz的脉冲,用导线连接到P3.4作为测试用,如果是AT89S51,则四句不用。将其中
//高8位和低8位的初始值更改后可输出不同频率的脉冲。
/*
T2MOD=0x2;
RCAP2H=245;
RCAP2L=74;
TR2=1;
*/
while(1)
{
display();
}
}
void time0() interrupt 1
{
T0count++;
}
void time1() interrupt 3
{
TH1=(65536-5*110592/12)/256;
TL1=(65536-5*110592/12)/256%10;
if(T1count==19)
{
calc();
init();
}
else T1count++;
}
‘捌’ 单片机频率计原理程序代码
#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();
}
}
//******************************************************//
‘玖’ 如何实现单片机输出信号中的频率变化
输出信号的频率变化应该是指输出方波的频率。
1. 如果你是用定时器来实现的,改变定时器的定时周期可以改变输出频率。
2. 如果用延时来实现,改变延时时间可以改变输出频率。
3. 如果需要用按键来选择频率,只需要在按键处理程序(查询或中断)中改变相应的(上述两例)中相应的参数即可。
4. 改变晶振频率可以改变输出频率变化。
如果还有其它的方法,请补充。
‘拾’ 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();
}
}