① 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;//重新啟動
}
}
② 基於51單片機的數字頻率計(0—10MHZ)
再加兩個數碼管,用T1引腳檢測頻率,打開T1中斷,每中斷一次加1計數,
滿1秒中後停止T1計數,讀出T1計數器的TH1 TL1,
頻率= 65536x中斷次數+TH1 HL1。
前提是選擇高速單片機,即只要T1引腳能夠響應10M的頻率就沒有問題
因為要計數65536次才T1才會中斷一次。
③ 單片機頻率計
1.實驗任務
利用51單片機的T0、T1的定時計數器功能,來完成對輸入的信號進行頻率計數,計數的頻率結果通過8位動態數碼管顯示出來。要求能夠對0-250KHZ的信號頻率進行准確計數,計數誤差不超過±1HZ。
2.電路原理圖
見插圖
3.程序設計內容
(1).定時/計數器T0和T1的工作方式設置,由圖可知,T0是工作在計數狀態下,對輸入的頻率信號進行計數,但對工作在計數狀態下的T0,最大計數值為fOSC/24,由於fOSC=12MHz,因此:T0的最大計數頻率為250KHz。對於頻率的概念就是在一秒只數脈沖的個數,即為頻率值。所以T1工作在定時狀態下,每定時1秒中到,就停止T0的計數,而從T0的計數單元中讀取計數的數值,然後進行數據處理。送到數碼管顯示出來。
(2).T1工作在定時狀態下,最大定時時間為65ms,達不到1秒的定時,所以採用定時50ms,共定時20次,即可完成1秒的定時功能。
4.C語言源程序
/******************************************************************************
*定時器+計數器測頻
*
*file:frequency.c
*name:zhzhchang
*time:2010.3.17
*V1.0
*blog:http://blog.csdn.net/zhzht19861011
*Nots:本程序定義6個數碼管,經過實測,在200HZ~50KHZ時結果較准確,誤差小於0.4%,
*50KHZ以上頻率未進行測量.據資料表明,可以測量到120KHZ,本程序未證明.
*********************************************************************************/
#include<reg52.h>
bitint_flag;//定時器01S到標志位
unsignedcharvolatileint_count;//定時器0中斷次數
unsignedcharvolatileT1count;//定時器1中斷次數
unsignedcharcodedofly[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//顯示段碼值0123456789
unsignedlongsum;//1S內脈沖總個數
unsignedcharled[6];//LED顯示緩存
///////////////軟體延時/////////////
voiddelay(unsignedintcnt)
{
while(--cnt);
}
///定時器0初始化
voidinit_t0(void)
{
TMOD=(TMOD&0xF0)||0x01;//定時器0工作於方式1
TH0=(65536-50000)/256;//定時50ms
TL0=(65535-50000)%256;
}
//定時器1初始化
voidinit_t1(void)
{
TMOD=(TMOD&0x0F)|0x50;//timer1forcount
TH1=0x00;
TL1=0x00;
}
//顯示
voiddisp(void)
{
unsignedchari;
for(i=0;i<6;i++)
{
P0=dofly[(led[i])];//取顯示數據
P2=5-i;//取段碼
delay(100);//掃描間隙延時,根據單片機調整,延時1ms即可
}
}
///////////////////////////////////////////////////////
voidmain(void)
{
EA=1;//開總中斷
init_t0();//初始化定時器
init_t1();
TR0=1;//定時器開始工作
TR1=1;
ET0=1;//開T0中斷
while(1)
{
if(int_flag==1)
{
int_flag=0;
sum=TL1+TH1*256+T1count*65536;//計算1秒內的脈沖個數
//以下將數據格式化,轉成LED可顯示的BCD碼
led[0]=sum%10;//最低位
sum=sum/10;
led[1]=sum%10;//第二位
sum=sum/10;
led[2]=sum%10;
sum=sum/10;
led[3]=sum%10;
sum=sum/10;
led[4]=sum%10;
led[5]=sum/10;
int_count=0x00;
T1count=0;
TH1=0x00;
TL1=0x00;
TR1=1;
}
disp();
}
}
//定時器0中斷服務程序
voidint_t0(void)interrupt1
{
TH0=(65535-50000)/256;
TL0=(65535-50000)%256;
int_count++;
if(int_count==20)
{
TR1=0;
int_flag=1;
int_count=0x00;
}
}
//定時器1中斷服務程序
voidint_t1(void)interrupt3
{
T1count++;
}
別說你的設計要求用匯編啊!!!
不過既然是課程設計,我這個只是給你參考,你自己一定要弄懂,變成自己的。我實測過,程序沒問題,但用到你的硬體上可能需要改一下,因為你的硬體數碼管不一定和我的硬體接法一樣,但整體思路我都給你了。
④ 51單片機製作頻率計,測周法如何測量(用T0和T1兩個就可以了嗎),求大蝦幫忙啊,最好詳細點
#include<REG51.H>
#defineU8unsignedchar
U8codetab[]={0xa0,0xbb,0x62,0x2a,0x39,0x2c,0x24,0xba,0x20,0x28};
U8codescn[]={0x7f,0xbf,0xdf,0xef};//先點亮左邊一個數碼管
U8buf[4]={0,0,0,0};//顯示緩沖區
U8cnt=0;//掃描計數
unsignedintfreq=0;
unsignedintF;
voidmain(void)
{EA=1;//允許中斷
TMOD=0x01;//設定時器0為模式1(16位)
ET0=1;//定時器0中斷允許
TH0=(65536-5000)/256;//晶振12MHz,中斷周期5mS
TL0=(65536-5000)%256;;
TR0=1;//開始計數
PX0=1;//外部中斷優先順序高
EX0=1;//允許外部中斷
IT0=1;//外部中斷下降沿觸發
while(1);
}
voidexint0(void)interrupt0//外部中斷0服務程序
{freq++;
}
voidtimeint(void)interrupt1//定時器0中斷服務程序
{chari;
TH0=(65536-5000)/256;//晶振12MHz,中斷周期5mS
TL0=(65536-5000)%256;;
i=cnt&0x03;//求應點亮的LED號(從左到右依次為0,1,2,3)
P0=tab[buf[i]];//筆劃代碼送P0口
P2=scn[i];//控制掃描碼送P2口
cnt++;
if(cnt==200)
{cnt=0;//到1秒鍾,顯示的數字加一
F=freq;freq=0;
buf[0]=F/1000;
buf[1]=(F/100)%10;
buf[2]=(F/10)%10;
buf[3]=F%10;
}
}
⑤ 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;//重新啟動計數器
}
}
⑥ 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();
}
}