首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

8051 單晶片 1 秒精確延時程式原理與實現

     編輯:關於C語言

程式碼實現


#include <reg52.h>

sbit P1_0 = P1^0;        // 定義 P1.0 腳位
void Delay(void);        // 函式宣告

void main(void) {
    while (1) {          // 無限迴圈
        P1_0 = 0;        // 輸出低電位(LED 亮)
        Delay();         // 延時 1 秒
        P1_0 = 1;        // 輸出高電位(LED 滅)
        Delay();         // 延時 1 秒
    }
}

// 12MHz 晶振下約 1 秒延時
void Delay(void) {
    unsigned char h, i, j, k;
    for (h = 5; h > 0; h--)
        for (i = 4; i > 0; i--)
            for (j = 116; j > 0; j--)
                for (k = 214; k > 0; k--); // 空指令消耗週期
}

延時原理深度解析

時脈週期定義

名稱定義12MHz 下數值
時鐘週期晶振震盪週期1/12,000,000 ≈ 83.3 ns
狀態週期2 個時鐘週期≈ 166.7 ns
機器週期6 個狀態週期 = 12 個時鐘週期1 μs
指令週期執行一條指令所需機器週期數(1~4)單週期指令 = 1 μs

for 迴圈指令週期分析

Keil 仿真測量:for (h=1000; h>0; h--); 1000 次耗時 232.5 μs,單次約 0.2325 μs。

1 秒 = 1,000,000 μs,需迴圈次數 ≈ 1,000,000 / 0.2325 ≈ 4,300,000 次。

但 unsigned char 最大 255,單層迴圈不足,故採用四層巢狀:


5 * 4 * 116 * 214 = 496,480 次

接近理論值,誤差在可接受範圍內(約 0.1%)。

Keil 仿真驗證步驟

  1. 在 for (h=1000; h>0; h--); 處設中斷點
  2. 執行至中斷點,觀察模擬器時間
  3. 計算單次迴圈耗時,反推參數

常見問題與優化

  • 晶振頻率變更:須重新計算參數(如 11.0592MHz 機器週期 1.085 μs)
  • 編譯器優化:開啟優化可能移除空迴圈,建議加 volatile 或使用內嵌組合語言 NOP
  • 精確定時:推薦使用 Timer 0/1/2 硬體定時器,避免指令週期波動影響精度

硬體定時器替代方案(Timer 0 模式 1,16 位)


void Timer0_Init_1s(void) {
    TMOD &= 0xF0; TMOD |= 0x01; // 模式 1
    TH0 = 0x3C; TL0 = 0xB0;     // 12MHz 下 50,000 次 = 50ms
    ET0 = 1; EA = 1; TR0 = 1;   // 啟用中斷
    // 中斷服務程式計數 20 次 = 1 秒
}

硬體定時器精度高、不佔用 CPU、支援多任務,是工程實務首選。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved