一、前言
1.1 功能介紹
在許多工業(yè)應(yīng)用、機械控制以及實驗設(shè)備中,準(zhǔn)確測量和監(jiān)控信號的頻率或轉(zhuǎn)速是確保系統(tǒng)正常運行、提高生產(chǎn)效率以及實現(xiàn)精確控制的關(guān)鍵。頻率作為信號的基本參數(shù)之一,直接反映了信號的變化速率,而轉(zhuǎn)速則通常通過測量旋轉(zhuǎn)物體的頻率來間接獲得。
為了實現(xiàn)對頻率和轉(zhuǎn)速的精確測量,本項目采用了STC90C51微控制器,結(jié)合定時器和外部中斷技術(shù),檢測NE555脈沖發(fā)生器產(chǎn)生的脈沖信號頻率。NE555作為一種廣泛使用的模擬定時器芯片,能夠通過配置外部電阻和電容參數(shù)產(chǎn)生穩(wěn)定的脈沖信號,其頻率可根據(jù)需要進行調(diào)整。因此,利用NE555脈沖發(fā)生器可以模擬不同頻率的輸入信號,用于測試STC90C51的頻率測量功能。
在項目中,STC90C51微控制器通過定時器設(shè)置合適的計時周期,并利用外部中斷捕捉NE555脈沖信號的上升沿或下降沿。通過記錄定時器計數(shù)值和中斷觸發(fā)次數(shù),可以計算出輸入信號的頻率。此外,根據(jù)項目需求,還可以進一步將頻率信息轉(zhuǎn)換為轉(zhuǎn)速值,實現(xiàn)轉(zhuǎn)速的精確測量和監(jiān)控。
本項目的開發(fā)背景體現(xiàn)了對精確頻率測量和轉(zhuǎn)速監(jiān)控技術(shù)的迫切需求。通過結(jié)合STC90C51微控制器和NE555脈沖發(fā)生器的技術(shù)優(yōu)勢,本項目實現(xiàn)一種高效、精確的頻率和轉(zhuǎn)速測量系統(tǒng)。該系統(tǒng)不僅可以用于工業(yè)生產(chǎn)和機械控制等領(lǐng)域,還可以為科學(xué)實驗和教學(xué)提供有力的支持。同時,本項目的實施還將促進微控制器和定時器技術(shù)在信號處理和控制領(lǐng)域的應(yīng)用和發(fā)展。
1.2 NE555介紹
NE555是一款經(jīng)典的集成電路,屬于555系列定時器芯片的一種型號,在1971年由Signetics Corporation發(fā)布。作為一款多功能的定時器芯片,NE555在電子領(lǐng)域有著廣泛的應(yīng)用,包括脈沖信號發(fā)生、定時控制、波形產(chǎn)生等場景。
- 基本功能
- NE555可以作為一個脈沖發(fā)生器,通過外部電阻和電容的配置,產(chǎn)生穩(wěn)定的脈沖信號。
- 它還廣泛應(yīng)用于定時器、頻率計、脈寬調(diào)制(PWM)等電子電路中。
- 主要特點
- 工作原理
- 引腳功能
- NE555是8腳時基集成電路,各引腳功能包括地線、觸發(fā)點、輸出、重置、控制、重置鎖定、放電和正電源電壓端。這些引腳允許用戶通過外部電路配置來實現(xiàn)各種功能。
- 市場應(yīng)用由于其穩(wěn)定度高、精度高、溫度穩(wěn)定性好等優(yōu)點,NE555在市場上非常受歡迎。主流品牌如TI、ST等都有生產(chǎn),并且廣泛應(yīng)用于各種電子設(shè)備中。
NE555是一款功能強大、設(shè)計簡單、穩(wěn)定可靠的集成電路芯片,其作為脈沖發(fā)生器在電子領(lǐng)域有著廣泛的應(yīng)用,特別是在需要精確控制時間、頻率和脈沖寬度的場景中。
二、代碼實現(xiàn)
2.1 main.c
#include <reg51.h>
#include <INTRINS.H>
#include "delay.h"
#include "type.h"
#include "uart.h"
#include "ds1302.h"
#include "pcf8591.h"
//#include "key.h"
//#include "led.h"
#include "timer.h"
//#include "exti.h"
//#include "infrared.h"
//#include "ds18b20.h"
//#include "at24c02.h"
u32 time1_cnt=0; //記錄計數(shù)器1收到的外部脈沖數(shù)量
u32 time0_cnt=0; //記錄定時器0的超時時間次數(shù)
u32 Freq=0;
int main()
{
Timer0_16bit_Init(50000); //初始化定時器0,定時50ms一次
Timer1_16bit_CntMode_Init(); //初始化計數(shù)器1
while(1)
{
if(TR0==0) //當(dāng)定時器0停止時,表示1秒鐘時間到達
{
Freq=time1_cnt+(TH1<<8|TL1); //得到1秒鐘內(nèi)計算的脈沖數(shù)
time1_cnt=0;//清除脈沖計數(shù)
TH1=0; //將計數(shù)器的值清零
TL1=0;
TR0=1; //開啟定時器0
TR1=1; //開啟計數(shù)器1
}
LED_DisplayNumber(Freq);
}
}
2.2 timer.c
#include "timer.h"
/*
配置定時器0工作在16位定時器模式
51單片機標(biāo)準(zhǔn)架構(gòu)下一個機器周期是 12個時鐘周期,也就是12/11059200秒。(11.059200是晶振頻率)
定時器每過一個機器周期的時間,也就是12/11059200秒,計數(shù)器自動加1。
通過計算得知,定時器+1的時間: 12/11.059200=1.085069us
如果定時器工作在16位模式下,最大值可以存放:0~65535
那么最大的定時時間就可以得知:65535*1.085069=71,109.996915us=71.109996915ms
如果要定時1000us,那么公式:x*1.085069=1000 ->1000/1.085069=921 ,
通過公式,計算出定時器需要+921次剛好得到1000us。
但是單片機工作在16位模式情況下,需要加滿65535才能溢出,所以需要給定時器賦初值。
65535-921=64614,這樣定時器就可以從64614開始計數(shù),當(dāng)計數(shù)到65535時,定時器就會溢出,
TF0就會置1,這時剛好經(jīng)過1000us時間。
那么定時器就可以這樣賦值:
u16 t0_data=64614;
TH0=t0_data>>8;
TL0=t0_data;
*/
u16 T0_Update_data;//定時器0的初始值
void Timer0_16bit_Init(u16 us)
{
//當(dāng)前實驗板上的晶振實際頻率為: 12MHZ
u16 val=us/(12/12); //得到計數(shù)的時間,只要整數(shù)部分
T0_Update_data=65535-val; //得到重裝載值
TMOD&=0xF0; //清除配置
TMOD|=0x01; //配置定時器0工作在16位定時器模式
TH0=T0_Update_data>>8; //定時器0高位重裝值
TL0=T0_Update_data; //定時器0低位重裝值
EA=1; //開啟總中斷
ET0=1; //開啟定時器0溢出中斷
TR0=1; //開啟定時器0
}
//定時器0的重裝值更新函數(shù)
void Timer0_Update(void)
{
TH0=T0_Update_data>>8; //定時器0高位重裝值
TL0=T0_Update_data; //定時器0低位重裝值
}
u16 T1_Update_data;//定時器1的初始值
void Timer1_16bit_Init(u16 us)
{
//當(dāng)前實驗板上的晶振實際頻率為: 11.956MHZ
u16 val=us/(12/11.956); //得到計數(shù)的時間,只要整數(shù)部分
T1_Update_data=65535-val; //得到重裝載值
TMOD&=0x0F; //清除配置
TMOD|=0x10; //配置定時器1工作在16位定時器模式
TH1=T1_Update_data>>8; //定時器1高位重裝值
TL1=T1_Update_data; //定時器1低位重裝值
EA=1; //開啟總中斷
ET1=1; //開啟定時器1溢出中斷
TR1=1; //啟動定時器1
}
//定時器1的重裝值更新函數(shù)
void Timer1_Update(void)
{
TH1=T1_Update_data>>8; //定時器1高位重裝值
TL1=T1_Update_data; //定時器1低位重裝值
}
/*
配置定時器0工作在8位自動重裝載模式
注意,時間不能超過定時器最大時間
255*(12/11.059200)=276us
*/
void Timer0_8bit_Init(u16 us)
{
//當(dāng)前實驗板上的晶振實際頻率為: 11.956MHZ
u16 val=us/(12/11.956); //得到計數(shù)的時間,只要整數(shù)部分
TMOD&=0xF0; //清除配置
TMOD|=0x02; //配置定時器0工作在8位自動重載模式
TL0=TH0=255-val;//得到重裝載值;
EA=1; //開啟總中斷
ET0=1; //開啟定時器0溢出中斷
TR0=1; //啟動定時器0
}
/*
配置定時器1初始化為16位計數(shù)器模式
*/
void Timer1_16bit_CntMode_Init(void)
{
//當(dāng)前實驗板上的晶振實際頻率為: 12MHZ
TMOD&=0x0F; //清除配置
TMOD|=0x50; //配置定時器1工作在16位計數(shù)器模式
EA=1; //開啟總中斷
ET1=1; //開啟定時器1溢出中斷
TR1=1; //啟動定時器1
}
extern u32 time1_cnt; //記錄計數(shù)器1收到的外部脈沖數(shù)量
extern u32 time0_cnt; //記錄定時器0的超時時間次數(shù)
/*
定時器0的中斷服務(wù)函數(shù)
*/
void TIM0_IRQHandler(void) interrupt 1
{
time0_cnt++;
//定時器0配置50ms超時一次,超時次數(shù)到達20次表示1秒鐘時間到達
if(time0_cnt==20)
{
time0_cnt=0;
TR0=0; //關(guān)閉定時器0
TR1=0; //關(guān)閉計數(shù)器1
}
Timer0_Update(); //定時器0的重裝載
}
/*
定時器1的中斷服務(wù)函數(shù)
*/
void TIM1_IRQHandler(void) interrupt 3 //定時器1
{
//當(dāng)前計數(shù)器配置為16位模式,進入一次中斷就表示計數(shù)了65536次
time1_cnt+=65536;
}
2.3 timer.h
#ifndef TIMER_H
#define TIMER_H
#include <reg51.h>
#include "delay.h"
#include "key.h"
#include "type.h"
#include "led.h"
#include "uart.h"
void Timer0_16bit_Init(u16 us);
void Timer0_Update(void);
void Timer1_16bit_Init(u16 us);
void Timer1_Update(void);
void Timer0_8bit_Init(u16 us);
void Timer1_16bit_CntMode_Init(void);
#endif