1. 程式人生 > 其它 >第5章 定時器與數碼管基礎

第5章 定時器與數碼管基礎

時鐘週期:時鐘週期 T 是時序中最小的時間單位。晶振是 11.0592M,則時鐘週期=1/11059200 秒。

機器週期:微控制器完成一個操作的最短時間。51微控制器系列,在其標準架構下一個機器週期是 12 個時鐘週期,也就是 12/11059200 秒。對於增強型微控制器,一個機器週期可能只需要4個時鐘週期。

定時器:作用用來定時。定時器內部有一個暫存器,我們讓它開始計數後,這個暫存器的值每經過一個機器週期(標準51微控制器也就是12/11059200 秒)就會自動加 1。當計數達到某一值,產生溢位,具體溢位值根據定時器模式不同而不同。

標準的 51 微控制器內部有 T0 和 T1 這兩個定時器。對應特殊功能暫存器如下:

是定時器控制暫存器 TCON 位分配暫存器各位功能描述:

TMOD暫存器介紹:

模式 1,是 THn 和 TLn 組成了一個 16 位的定時器,計數範圍是 0~65535,溢位後,只要不對 THn 和 TLn 重新賦值,則從 0 開始計數。

模式 2,是 8 位自動重灌載模式,只有 TLn做加 1 計數,計數範圍 0~255,THn 的值並不發生變化,而是保持原值,TLn 溢位後,TFn就直接置 1 了,並且 THn 原先的值直接賦給 TLn,然後 TLn 從新賦值的這個數字開始計數。 

使用定時器步驟:

第一步:設定特殊功能暫存器 TMOD,配置好工作模式。
第二步:設定計數暫存器 TH0 和 TL0 的初值。
第三步:設定 TCON,通過 TR0 置 1 來讓定時器開始計數。
第四步:判斷 TCON 暫存器的 TF0 位,監測定時器溢位情況。 

 

使用定時器計算時間,假如需要定時0.2s,首先需要確定定時器需要多長時間才會使計數器加1,一般是1/11059200s,那麼需要計數多少才能達到0.2s?

應該是0.2/(1/11059200);再計算需要給計數器賦初始值多少,才能確保計數0.2/(1/11059200)之後達到溢位狀態?對於模式1的16位定時器,其最大計數到65535,那麼可以得到需要給定時器賦初值為65536-0.2/(1/11059200)。

 

使用定時器完成小燈一秒鐘的閃爍,程式碼如下:

#include <reg52.h>

sbit LED = P0^0;
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;

void main()
{
    unsigned char cnt = 0;  

    ENLED = 0;   
    ADDR3 = 1;
    ADDR2 = 1;
    ADDR1 = 1;
    ADDR0 = 0;
    TMOD = 0x01;  //設定T0為模式1
    TH0  = 0xB8;  //定時0.2s賦初值,計算得出
    TL0  = 0x00;
    TR0  = 1;     //啟動T0
    
    while (1)
    {
        if (TF0 == 1)        //判斷T0是否溢位
        {
            TF0 = 0;         //清零中斷標誌並重新賦初值
            TH0 = 0xB8;     
            TL0 = 0x00;
            cnt++;           
            if (cnt >= 50)   //溢位達到50次,累計計時正好1秒鐘
            {
                cnt = 0;     
                LED = ~LED;  
            }
        }
    }
}

數碼管

數碼管原理圖:

數碼管共有 a、b、c、d、e、f、g、dp 共8 個段,每段可以當作是一個led小燈。

數碼管有共陰極和共陽極兩種,其結構示意圖如下:

數碼管真值表如下 :

數碼管原理圖:

對應譯碼器電路圖:

數碼管靜態顯示,讓數碼管DS1顯示數字1,程式碼如下:

#include <reg52.h>
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
void main()
{
 ENLED = 0; //使能 U3,選擇數碼管 DS1
 ADDR3 = 1;
 ADDR2 = 0;
 ADDR1 = 0;
 ADDR0 = 0;
 P0 = 0xF9; //點亮數碼管段 b 和 c
 while (1);
}

實現數碼管從0到F依次顯示,間隔時間為1秒,程式碼如下:

#include <reg52.h>
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
unsigned char code LedChar[] = {
 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
};

void main()
{
	 unsigned char cnt = 0; //記錄 T0 中斷次數
 unsigned char sec = 0; //記錄經過的秒數
 ENLED = 0; //使能 U3,選擇數碼管 DS1
 ADDR3 = 1;
 ADDR2 = 0;
 ADDR1 = 0;
 ADDR0 = 0;
 TMOD = 0x01; //設定 T0 為模式 1
 TH0 = 0xB8; //為 T0 賦初值 0xB800
 TL0 = 0x00;
 TR0 = 1; //啟動 T0
 
 while (1)
 {
 	if (TF0 == 1) //判斷 T0 是否溢位
 	{
		 TF0 = 0; //T0 溢位後,清零中斷標誌
		 TH0 = 0xB8; //並重新賦初值
		 TL0 = 0x00;
		cnt++; //計數值自加 1
		 if (cnt >= 50) //判斷 T0 溢位是否達到 50 次
		 {
		 cnt = 0; //達到 50 次後計數值清零
		 P0 = LedChar[sec]; //當前秒數對應的真值表中的值送到 P0 口
		 sec++; //秒數記錄自加 1
		 if (sec >= 16) //當秒數超過 0x0F(15)後,重新從 0 開始
			 {
				 sec = 0;
			 }
		 }
	 }
}

}