經典的 51 單片機入門實驗:控制 P2 口 8 顆 LED 交替閃爍。本文提供完整代碼、延時原理分析、硬體連接說明與常見問題排查。
完整代碼
//----------8個LED燈閃爍------------//
//----------------------------------//
//-----------杭哥工作室------------//
//-----------設計者:呂杭劍--------//
//-----------QQ:984966845----------//
//---------------------------------//
#include <reg51.h>
void delay(unsigned int d_time);
void main(void)
{
while(1)
{
P2 = 0x00; // 全亮(共陰極)或全滅(共陽極)
delay(20000);
P2 = 0xFF; // 全滅(共陰極)或全亮(共陽極)
delay(20000);
}
}
void delay(unsigned int d_time)
{
for(; d_time > 0; d_time--);
}
代碼逐行解析
| 代碼 | 說明 |
#include <reg51.h> | 51 系列單片機寄存器定義頭文件 |
P2 = 0x00 | P2 口輸出低電平(8 位全 0) |
P2 = 0xFF | P2 口輸出高電平(8 位全 1) |
delay(20000) | 軟體延時,約 20ms@12MHz |
while(1) | 無限循環,嵌入式主迴圈標準寫法 |
延時函數原理分析
void delay(unsigned int d_time)
{
for(; d_time > 0; d_time--);
}
- 空循環,每次迴減 1 直到 0
- 12MHz 晶振下,機器週期 1μs,指令週期 1~2 機器週期
d_time=20000 理論約 20~40ms(視編譯器優化)
- 缺點:受編譯器優化影響大,時序不精確
改進版:精確延時
// 12MHz 下約 1ms
void delay_ms(unsigned int ms) {
unsigned int i, j;
for(i = 0; i < ms; i++)
for(j = 0; j < 123; j++); // 經校準常數
}
// 或使用定時器 T0 中斷(推薦)
void timer0_init() {
TMOD = 0x01; // 模式 1:16 位定時器
TH0 = 0xFC; // 1ms@12MHz: 65536-1000=64536=0xFC18
TL0 = 0x18;
ET0 = 1; EA = 1;
TR0 = 1;
}
硬體連接說明
共陰極接法(常見)
- LED 陽極接 P2.0~P2.7,串聯限流電阻 (220Ω~1kΩ)
- LED 陰極接地
P2=0x00 → 低電平 → LED 亮
P2=0xFF → 高電平 → LED 滅
共陽極接法
- LED 陰極接 P2 口,陽極接 VCC
- 邏輯相反:
0x00 滅、0xFF 亮
進階擴展:流水燈、呼吸燈
// 流水燈(左移)
void flow_left() {
P2 = 0xFE; // 1111 1110
delay(50000);
for(int i=0; i<7; i++) {
P2 = (P2 << 1) | 0x01;
delay(50000);
}
}
// 呼吸燈(PWM 模擬)
void breathe() {
for(int duty=0; duty<255; duty++) {
for(int k=0; k<10; k++) {
P2 = 0xFF; delay_us(duty);
P2 = 0x00; delay_us(255-duty);
}
}
// 漸滅同理反向
}
常見問題排查