在 Keil C51 開發環境中,<intrins.h> 頭文件提供了一組映射到 8051 核心指令集的內部函數。這些函數讓 C 語言能直接調用汽編指令,實現高效的位操作、空操作延時、位測試等底層控制,是編寫高性能、精確定時嵌入式代碼的利器。本文詳細解析各函數原型、功能、指令對應關係及實戰示例。
| 函數名 | 功能 | 對應指令 | 適用類型 |
|---|---|---|---|
_crol_ | 字符循環左移 | RL A | unsigned char |
_cror_ | 字符循環右移 | RR A | unsigned char |
_irol_ | 整數循環左移 | RL A (16位) | unsigned int |
_iror_ | 整數循環右移 | RR A (16位) | unsigned int |
_lrol_ | 長整數循環左移 | RL A (32位) | unsigned long |
_lror_ | 長整數循環右移 | RR A (32位) | unsigned long |
_nop_ | 空操作(1機器週期) | NOP | void |
_testbit_ | 測試並清零位 | JBC bit, rel | bit |
unsigned char _crol_(unsigned char val, unsigned char n);
unsigned char _cror_(unsigned char val, unsigned char n);
unsigned int _irol_(unsigned int val, unsigned char n);
unsigned int _iror_(unsigned int val, unsigned char n);
unsigned long _lrol_(unsigned long val, unsigned char n);
unsigned long _lror_(unsigned long val, unsigned char n);
將 val 以位為單位循環左移/右移 n 位。高位移出後補入低位(左移)或低位移出補入高位(右移),無數據丟失。編譯器直接生成 RL A/RR A 指令序列,無函數調用開銷。
#include <intrins.h>
void main() {
unsigned int y = 0x00FF;
y = _irol_(y, 4); // y = 0x0FF0 (高4位 0000 移至低位)
unsigned char c = 0x55; // 01010101b
c = _crol_(c, 1); // c = 0xAA (10101010b)
}
void _nop_(void);
插入一條 NOP 指令(1 個機器週期,12T 模式下 1μs@12MHz)。編譯器內聯展開,不產生 CALL/RET 開銷。常用於:
P1_0 = 1;
_nop_(); _nop_(); // 2μs 延時,確保電平穩定
P1_0 = 0;
bit _testbit_(bit x);
生成 JBC bit, rel 指令:若位 x 為 1,返回 1 並將該位硬件自動清零;若為 0,返回 0。整個操作不可中斷,屬原子操作。
sbit、bit 類型、SFR 位)。sbit FLAG = P3^2; // 假設 P3.2 為外部中斷標誌位
if (_testbit_(FLAG)) {
// FLAG 原為 1,已被硬件自動清零,進入處理流程
handle_interrupt();
}
unsigned char crc8_update(unsigned char crc, unsigned char data) {
crc ^= data;
for (int i = 0; i < 8; ++i) {
if (crc & 0x80) crc = _crol_(crc, 1) ^ 0x07;
else crc = _crol_(crc, 1);
}
return crc;
}
void delay_us(unsigned int us) {
while (us--) {
_nop_(); _nop_(); _nop_(); _nop_(); // 12MHz 下約 1μs,需根據晶振調整
_nop_(); _nop_(); _nop_(); _nop_();
}
}
主循環與中斷服務程序共享標誌位時,_testbit_ 保證「讀-清」原子性,避免競態條件。
#include <intrins.h>,否則編譯器報錯「未定義標識符」。_crol_ 接收 unsigned char,傳入 int 會隱式截斷高位,導致邏輯錯誤。n 超過類型位寬(如 char 移位 ≥8)行為未定義,需自行取模或判斷。intrins.h 專屬 Keil C51,遷移到 SDCC、IAR、ARM 等平台需改寫為內聯匯編或平台庫函數。_nop_(),需加 volatile 或降低優化等級。intrins.h 將 8051 強大的位操作指令集封裝為 C 函數,讓開發者在保持代碼可讀性的同時,榨乾單片機性能。熟練掌握循環移位、_nop_ 延時、_testbit_ 原子操作,是 C51 進階開發的必修課。但在現代 32 位 MCU(STM32 等)開發中,CMSIS、HAL 庫已提供更豐富、可移植的位操作 API,新項目建議優先使用標準庫。