
前不久也刚做了测频
我想说的是,你外部有木有将信号转换为高低电平的电路?
用外部中断,用定时器定一秒钟,在一秒内,检测下降沿个数,就是信号频率了。或者检测固定的下降沿个数,算出时间求个倒数,也是频率,但是,就可 *** 作性而言,前者明显好于后者。。。
然后在回过头来看这程序吧,你说一点P3^2就出现0云云,您是直接把信号接在外部中断的脚上?如果是的话,我想说的是,这样是不行的。51单片机内部木有AD,木有比较器,对于这样的正弦信号表示压力。。。
就这样了。。。
数码管台古老了,你用这个吧,看着还稍微有点可以,代码和电路都给你了,没有做不出来的理由,有问题加我QQ11422376745
#include "d:\c51\reg51h"
#include "d:\c51\intrinsh"
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();
/延时K1ms,12000mhz/
void int0_isr(void) interrupt 0 /遥控使用外部中断0,接P32口/
{
unsigned int temp;
time=count;
TR0=0;
temp=TH0;
temp=((temp << 8) | TL0);
TH0=0x3c;
TL0=0xaf;
count=0;
TR0=1;
time=time50000+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=L360000000/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行显示,57字型,检测忙信号
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);
}
使用模数转换,采集被测波形,根据你自己的需要做FFT,可得到能量最大的频率点。
1234=>取最低位=>除以10=>取最低位=>除以10=>取最低位=>除以10=>取最低位=>除以10,即得到4,3,2,1四个单独数据,程序如下:
int x=1234,i,w[4],xx;
for ( i=0,xx=x;i<4;i++ ) { w[i]=x%10; x/=10; }
for ( i=0;i<4;i++ ) printf("%d ",w[3-i]); printf("\n");
一般测量频率有2中方法:\
1,你用T1定时1S(只用T1是无法达到定时1s的目的的,因为时间太长,你还可以借助别的单元+1,+1的形式),然后用T0记数在这1s内通过的方波个数,这个方法不是很精确
2,用外部中断,选择下降沿触发,程序响应中断后马上开启定时器,在下个下降沿来临的时候关掉定时器就可以了(记得定时器先清零)
以上就是关于单纯的用51单片机测频率全部的内容,包括:单纯的用51单片机测频率、单片机课程设计数字频率计、谁能教我一下如何用单片机测量频率。还有比如1234这个千位数如何拆分成一个一个等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)