| 單片機腳位 | USB-TTL 模塊腳位 | 說明 |
|---|---|---|
| TXD (發送) | RXD (接收) | 單片機發 → 電腦收 |
| RXD (接收) | TXD (發送) | 電腦發 → 單片機收 |
| GND | GND | 共地,必須連接 |
| VCC (可選) | 3.3V/5V | 若單片機需供電,注意電平匹配 |
class CSerialPort {
public:
BOOL OpenPort(int portNum, int baudRate = 9600,
BYTE byteSize = 8, BYTE stopBits = ONESTOPBIT, BYTE parity = NOPARITY);
BOOL WriteData(const void* data, DWORD length);
BOOL ReadData(void* buffer, DWORD maxLen, DWORD& bytesRead);
void ClosePort();
// 事件驅動:設置接收回調
void SetReceiveCallback(std::function callback);
private:
HANDLE hComm;
OVERLAPPED osReader, osWriter;
// 異步讀寫線程...
};
// 打開串口
CreateFile(L"\\\\.\\COM3", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
// 設置參數
DCB dcb = {0};
dcb.DCBlength = sizeof(DCB);
GetCommState(hComm, &dcb);
dcb.BaudRate = CBR_9600;
dcb.ByteSize = 8;
dcb.StopBits = ONESTOPBIT;
dcb.Parity = NOPARITY;
SetCommState(hComm, &dcb);
// 設置超時
COMMTIMEOUTS timeouts = {0};
timeouts.ReadIntervalTimeout = 50;
timeouts.ReadTotalTimeoutConstant = 50;
timeouts.ReadTotalTimeoutMultiplier = 10;
SetCommTimeouts(hComm, &timeouts);
// 幀格式:[帧頭] [長度] [命令] [數據] [校驗] [帧尾]
// 例:0xAA 0x05 0x01 0x12 0x34 0x56 0x78 0xXX 0x55
struct Frame {
BYTE header = 0xAA;
BYTE length; // 數據長度
BYTE cmd; // 命令碼
BYTE data[256]; // 數據載荷
BYTE checksum; // 累加和或 CRC8
BYTE tail = 0x55;
};
// 發送按鈕點擊
void CSerialPortDlg::OnBnClickedBtnSend() {
CString str;
m_editSend.GetWindowText(str);
// 組幀發送
Frame frame = BuildFrame(str);
serialPort.WriteData(&frame, sizeof(frame));
}
// 接收回調(需 PostMessage 到 UI 線程)
void OnDataReceived(const BYTE* data, DWORD len) {
Frame* frame = (Frame*)data;
if (VerifyFrame(frame)) {
::PostMessage(m_hWnd, WM_USER_RECEIVE, (WPARAM)frame->cmd, (LPARAM)frame->data);
}
}
// UI 線程處理
LRESULT CSerialPortDlg::OnReceive(WPARAM wParam, LPARAM lParam) {
BYTE cmd = (BYTE)wParam;
BYTE* data = (BYTE*)lParam;
// 解析顯示到列表控件
m_listRecv.AddString(FormatData(cmd, data));
return 0;
}
// 串口中斷接收
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
if (huart->Instance == USART1) {
RingBuffer_Put(&rxRing, rxByte);
HAL_UART_Receive_IT(&huart1, &rxByte, 1); // 重新開啟中斷
}
}
// 主循環解析
void ProcessUartData() {
while (RingBuffer_Get(&rxRing, &byte)) {
if (ParseFrame(byte, &frame)) {
HandleCommand(frame.cmd, frame.data, frame.length);
}
}
}
// 發送分數數據
void SendScore(uint16_t home, uint16_t guest) {
Frame frame;
frame.cmd = 0x01; // 記分板命令
frame.data[0] = home >> 8;
frame.data[1] = home & 0xFF;
frame.data[2] = guest >> 8;
frame.data[3] = guest & 0xFF;
frame.length = 4;
frame.checksum = CalcChecksum(&frame);
HAL_UART_Transmit(&huart1, (uint8_t*)&frame, sizeof(frame), 100);
}
硬件:USB-TTL + 交叉接線 + 共地。
軟件:MFC 異步串口類 + 定義協議幀 + UI 線程分離。
單片機:環形緩衝區 + 中斷接收 + 幀解析 + 命令分發。