在異構系統間進行序列埠通訊時,因 CPU 速度差異導致「錯幀」,發送端速度快於接收端導致「過衝」。為解決此問題,本文採用簡單握手協定:每次僅發送半個位元組(低 4 位)作為資料,高 4 位作為控制資訊:
0x0:新資料半位元組0x1:重發上次錯誤資料0x2:檔名結束0x3:檔案結束發送端發出一個位元組後等待接收端回送同一位元組作為確認;若一致則發送新資料,否則重發。資料新舊由高 4 位區分。
程式包含發送檔案、接收檔案、序列埠初始化、讀寫埠、狀態檢查等模組,主流程如下:
main() ├─ InitPort(PORT, 231) // 初始化 COM1,231 = 9600,N,8,1 ├─ argv[1] == 'S' ? SendFile(argv[2]) : ReceiveFile() └─ 錯誤參數處理
SendFile() / Send()ch % 16)與高 4 位(ch / 16)兩次呼叫 Send()。Send() 發送後等待握手信號 ReadPort(),比對不同時在高 4 位置 1(s += 16)重發,直到收到相同回送。0x2E(46)代表 0x3 結束標記。ReceiveFile() / Receive()GetFileName() 解析檔名(高 4 位為 0x2 時結束)。Receive() 取得高、低半位元組,組合為完整位元組 ch = (G1 % 16) + G2 * 16 寫入檔案。Receive() 內部處理重發邏輯:若收到高 4 位為 0x1,持續回送並重讀直到非重發標記。InitPort / SendPort / ReadPort / CheckStateint 0x14 操作 UART(8250/16450/16550 相容)。union REGS 配合 int86() 設定 AH/AL/DX 傳遞參數:ReadPort() 輪詢 CheckState() 的 bit 8(資料就緒),支援鍵盤中斷退出。// 發送單一位元組並等待確認
void Send(int s) {
int G;
SendPort(PORT, s);
G = ReadPort(PORT);
if (s != G) s += 16; // 標記重發
do {
SendPort(PORT, s);
G = ReadPort(PORT);
} while (s != G);
}
// 接收並處理重發
int Receive(int port, int *G) {
int GM;
SendPort(port, *G); // 回送確認
GM = ReadPort(port);
if (GM / 16 == 0) return GM; // 正常新資料
if (GM / 16 == 1) { // 重發請求
do {
*G = GM;
SendPort(port, GM);
GM = ReadPort(port);
} while (GM / 16 == 1);
}
return GM;
}
CreateFile, SetCommState, ReadFile/WriteFile) 或 Linux termios 實現跨平台。此程式展示了以 C 語言直接操作硬體實作可靠傳輸協定的經典思路,適合嵌入式開發者參考學習。