Keil C51 編譯器為 8051 系列單晶片提供了豐富的關鍵字擴展,直接對應硬體架構。理解這些擴展是編寫高效、可靠嵌入式程式的關鍵。本文系統整理 8 大類擴展:儲存類型、儲存模式、變數宣告、資料類型、位操作、SFR、指標與函數屬性。
_at_ _idata_ sfr16 alien interrupt small
bdata large _task_ _Code bit pdata
using reentrant xdata compact sbit data
sfr
code:最多 64 KB 程式碼空間 (0000H~FFFFH)| 關鍵字 | 位址範圍 | 定址方式 | 說明 |
|---|---|---|---|
data | 00H~7FH | 直接定址 | 存取最快,適合常用變數 |
idata | 00H~FFH | 間接定址 | 涵蓋完整內部 RAM |
bdata | 20H~2FH | 位可定址 | 可進行位元操作 |
| 關鍵字 | 範圍 | 用途 |
|---|---|---|
xdata | 0000H~FFFFH (64 KB) | 大型陣列、緩衝區 |
pdata | 單頁 256 Bytes | Compact 模式預設區域,由 P2 埠決定頁碼 |
| 關鍵字 | 定址寬度 | 範例 |
|---|---|---|
sfr | 位元組 | sfr P0 = 0x80; |
sfr16 | 字 (16-bit) | sfr16 T2 = 0xCC; // T2L=0xCC, T2H=0xCD |
sbit | 位元 | sbit EA = 0xAF; // 中斷允許位 |
替代定義方式:
sbit OV = PSW^2; // 以 SFR 位元定義
sbit OV = 0xD0^2; // 以位址定義
bit OV = 0xD2; // 直接指定位址
| 模式 | 預設變數位置 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|---|
| Small | 內部 RAM (data) | 速度最快 | 空間極限 128/256 Bytes | 小型程式 |
| Compact | 外部 RAM 一頁 (pdata) | 空間較大,速度中等 | 需管理頁切換 | 中型程式 |
| Large | 外部 RAM 完整 64 KB (xdata) | 空間最大 | 速度最慢 | 大型程式 |
設定位置:專案選項 → C51 標籤 → Memory Model。
不依賴模式預設,直接指定變數位置:
data unsigned char uart_buf[32];
code const char msg[] = "Hello!";
xdata unsigned long big_array[10][4][4];
pdata int compact_buf[128];
idata char indirect_var;
| 類型 | 大小 | 範圍/用途 |
|---|---|---|
bit | 1 bit | 0/1,儲於 20H~2FH |
sbit | 1 bit | 從 SFR/位址定義的位元 |
sfr | 8 bit | SFR 位址 0~255 |
sfr16 | 16 bit | SFR 字位址 0~65535 |
其餘 char, enum, short, int, long, float 與 ANSI C 相同。
bit *ptr 錯誤)bit arr[5] 錯誤)#pragma disable 或 using 的函數不可傳回 bit
int bdata i;
char bdata arr[3];
sbit bit0 = i^0; // i 的第 0 位
sbit bit15 = i^15; // i 的第 15 位
sbit a07 = arr[0]^7; // arr[0] 的第 7 位
sbit a17 = arr[1]^7;
long *ptr1; // 指向 long,指標本身依模式儲存
char xdata *ptr2; // 指向 char,指標本身放 xdata
結構:[記憶體類型(1B)][高位址(1B)][低位址(1B)]
char data *str; // 指向 data 區 char
int xdata *pow; // 指向 xdata 區 int
僅儲存位移量,效率更高。
void serial_ISR() interrupt 4 using 1 { /* ISR 程式碼 */ }
// 定義未使用的中斷入口,產生 RETI
void extern0_ISR() interrupt 0 {}
void timer0_ISR() interrupt 1 {}
void extern1_ISR() interrupt 2 {}
void timer1_ISR() interrupt 3 {}
void serial_ISR() interrupt 4 {}
using 1 指定使用第 1 組暫存器銀行 (R0~R7),中斷與主程式使用不同銀行可避免衝突。
void fast_func(void) small {} // 區域變數置內部 RAM,加速執行
函數執行期間禁止中斷,適用於關鍵區段。
void func(int param) reentrant;
// 建議搭配
#pragma noaregs
編譯器會建立重入堆疊模擬參數傳遞,解決主程式與中斷共用函數的資料破壞問題。
alien 關鍵字指定 PL/M-51 呼叫慣例。
熟練運用 Keil C51 的記憶體關鍵字、儲存模式、位元操作與函數屬性,能充分發揮 8051 硬體效能,編寫出程式碼緊湊、執行高效的嵌入式應用。