『壹』 怎樣用單片機實現頻率的測量
這個太簡單了,
//搞個外中斷,中斷來了就計數
#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();
}
}