4.10 使用計數器測量NE555脈沖頻率
4.10.1 原理圖介紹

圖4-10-1

圖4-10-2
4.10.2 單片機的計數器模式介紹
STC90C51RC/RD+系列單片機內部設定的兩個16位定時器/計數器T0和T1都具有計數方式和定時方式兩種作業方式,對每個定時器/計數器(T0和T1),在特殊功能暫存器TMOD中都有一控制-C/T來選擇T0或者T1為定時器還是計數器,定時器/計數器的核心部件是一個加法計數器,其本質是對脈沖進行計數,只是計數脈沖來源不同:如果計數脈沖來自系統時鐘,則為定時方式,此時定時器/計數器每12個時鐘或者每6個時鐘得到一個計數脈沖,計數值加1;如果計數脈沖來自單片機外部引腳(T0為P3.3,T1為P3.3),則為計數方式,每來一個脈沖加1,

圖4-10-3
4.10.3 NE555定時器介紹
555定時器是一種集成電路芯片,常被用于定時器、脈沖產生器和振蕩電路,555可被作為電路中的延時器件、觸發器或起振元件,
555定時器可作業在三種作業模式下:
單穩態模式:在此模式下,555功能為單次觸發,應用范圍包括定時器,脈沖丟失檢測,反彈跳開關,輕觸開關,分頻器,電容測量,脈沖寬度調制(PWM)等,
無穩態模式:在此模式下,555以振蕩器的方式作業,這一作業模式下的555芯片常被用于頻閃燈、脈沖發生器、邏輯電路時鐘、音調發生器、脈沖位置調制(PPM)等電路中,如果使用熱敏電阻作為定時電阻,555可構成溫度傳感器,其輸出信號的頻率由溫度決定,
雙穩態模式(或稱施密特觸發器模式):在DIS引腳空置且不外接電容的情況下,555的作業方式類似于一個RS觸發器,可用于構成鎖存開關,
4.10.4 示例代碼
下面代碼里,配置定時器1為16位計數器模式并開啟計數中斷;NE555脈沖發生器接在單片機的P3.3引腳輸入脈沖,通過定時器1進行計數,再配置定時器0為16位定時器模式,50毫秒超時一次,在中斷服務函式里記錄超時的次數,當超時20次表示1秒鐘時間到達,1秒鐘時間到達之后,在定時器0的中斷服務函式里關閉定時器0和計數器1,在主函式里判斷計數器是否停止,如何計數器停止就表示1秒鐘時間到達,之后就讀取1秒鐘之內計數器1記錄的脈沖數量,通過數碼管進行顯示,
用總脈沖量/總時間,就可以得出脈沖的周期,
示例代碼:
#include <reg51.h>
u32 time1_cnt=0; //記錄計數器1收到的外部脈沖數量
u32 time0_cnt=0; //記錄定時器0的超時時間次數
u32 Freq=0;
int main()
{
Timer0_16bit_Init(50000); //初始化定時器0,定時50ms一次
Timer1_16bit_CntMode_Init(); //初始化計數器1
while(1)
{
if(TR0==0) //當定時器0停止時,表示1秒鐘時間到達
{
Freq=time1_cnt+(TH1<<8|TL1); //得到1秒鐘內計算的脈沖數
time1_cnt=0;//清除脈沖計數
TH1=0; //將計數器的值清零
TL1=0;
TR0=1; //開啟定時器0
TR1=1; //開啟計數器1
}
LED_DisplayNumber(Freq); //顯示脈沖個數
}
}
//共陰極數碼管編碼(要顯示的段就輸出1)
//數字0~9
code u8 LED2_Coding[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
//定義38譯碼器的引腳
sbit HC138_A0=P2^2; //A
sbit HC138_A1=P2^3; //B
sbit HC138_A2=P2^4; //C
#define LED P0 //定義LED引腳
//設定數碼管顯示指定的數字
void LED_DisplayNumber(unsigned long number)
{
u16 i,j;
u8 display_data[8];//存放當前數碼管顯示的資料
//以下代碼將number按十進制位從低到高依次提取并轉為數碼管顯示字符
display_data[0] = LED2_Coding[number/10000000%10];
display_data[1] = LED2_Coding[number/1000000%10];
display_data[2] = LED2_Coding[number/100000%10];
display_data[3] = LED2_Coding[number/10000%10];
display_data[4] = LED2_Coding[number/1000%10];
display_data[5] = LED2_Coding[number/100%10];
display_data[6] = LED2_Coding[number/10%10];
display_data[7] = LED2_Coding[number/1%10];
for(i=0;i<8;i++)
{
switch(i) //位選,選擇點亮的數碼管,
{
case 0:
HC138_A0=0;HC138_A1=0;HC138_A2=0; break;//顯示第0位
case 1:
HC138_A0=1;HC138_A1=0;HC138_A2=0; break;//顯示第1位
case 2:
HC138_A0=0;HC138_A1=1;HC138_A2=0; break;//顯示第2位
case 3:
HC138_A0=1;HC138_A1=1;HC138_A2=0; break;//顯示第3位
case 4:
HC138_A0=0;HC138_A1=0;HC138_A2=1; break;//顯示第4位
case 5:
HC138_A0=1;HC138_A1=0;HC138_A2=1; break;//顯示第5位
case 6:
HC138_A0=0;HC138_A1=1;HC138_A2=1; break;//顯示第6位
case 7:
HC138_A0=1;HC138_A1=1;HC138_A2=1; break;//顯示第7位
}
LED=display_data[i]; //控制數碼管的顯示資料值
j = 100; //掃描間隔時間設定
while(j--){}
LED=0x00; //消隱,所有數碼管都不顯示
}
}
u16 T0_Update_data;//定時器0的初始值
void Timer0_16bit_Init(u16 us)
{
//當前實驗板上的晶振實際頻率為: 12MHZ
u16 val=us/(12/12); //得到計數的時間,只要整數部分
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的重裝值更新函式
void Timer0_Update(void)
{
TH0=T0_Update_data>>8; //定時器0高位重裝值
TL0=T0_Update_data; //定時器0低位重裝值
}
/*
配置定時器1初始化為16位計數器模式
*/
void Timer1_16bit_CntMode_Init(void)
{
//當前實驗板上的晶振實際頻率為: 12MHZ
TMOD&=0x0F; //清除配置
TMOD|=0x50; //配置定時器1作業在16位計數器模式
EA=1; //開啟總中斷
ET1=1; //開啟定時器1溢位中斷
TR1=1; //啟動定時器1
}
/*定時器0的中斷服務函式*/
void TIM0_IRQHandler(void) interrupt 1
{
time0_cnt++;
//定時器0配置50ms超時一次,超時次數到達20次表示1秒鐘時間到達
if(time0_cnt==20)
{
time0_cnt=0;
TR0=0; //關閉定時器0
TR1=0; //關閉計數器1
}
Timer0_Update(); //定時器0的重裝載
}
/*定時器1的中斷服務函式*/
void TIM1_IRQHandler(void) interrupt 3 //定時器1
{
//當前計數器配置為16位模式,進入一次中斷就表示計數了65536次
time1_cnt+=65536;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/394063.html
標籤:其他
