#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 |
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%)。
for (h=1000; h>0; h--); 處設中斷點volatile 或使用內嵌組合語言 NOP
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、支援多任務,是工程實務首選。