首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

C++ MFC 串口助手與單片機通信:硬件連接與軟件實現全流程

     編輯:程式設計疑難解答

硬件連接方案

1. 所需模塊

  • USB 轉 TTL 模塊(CH340/CP2102/PL2303,淘寶幾元)
  • 單片機最小系統板(STM32/51/AVR 等)
  • 杜邦線若干

2. 接線原則:交叉連接

單片機腳位USB-TTL 模塊腳位說明
TXD (發送)RXD (接收)單片機發 → 電腦收
RXD (接收)TXD (發送)電腦發 → 單片機收
GNDGND共地,必須連接
VCC (可選)3.3V/5V若單片機需供電,注意電平匹配

3. 電平匹配注意

  • 單片機 3.3V 電平 → 選 3.3V 模塊或加電平轉換
  • 單片機 5V 電平 → 選 5V 模塊
  • 不確定時用萬用表測量模塊 TXD 空閒電平

軟件實現:MFC 串口助手

1. 核心類:CSerialPort 封裝

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;
    // 異步讀寫線程...
};

2. 關鍵 API 序列

// 打開串口
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);

3. 通信協議設計(建議)

// 幀格式:[帧頭] [長度] [命令] [數據] [校驗] [帧尾]
// 例: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;
};

4. MFC 界面收發

// 發送按鈕點擊
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;
}

單片機端配合代碼(以 STM32 HAL 為例)

// 串口中斷接收
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);
}

調試檢查清單

  1. ✅ 設備管理器確認 COM 口號
  2. ✅ 波特率、數據位、停止位、校驗位**雙端一致**
  3. ✅ GND 共地連接
  4. ✅ TX/RX 交叉連接
  5. ✅ 使用串口調試助手(如 SSCOM)先測通單片機回環
  6. ✅ MFC 端異步讀寫不阻塞 UI
  7. ✅ 協議幀同步機制(帧頭帧尾/長度/校驗)

總結

硬件:USB-TTL + 交叉接線 + 共地。
軟件:MFC 異步串口類 + 定義協議幀 + UI 線程分離。
單片機:環形緩衝區 + 中斷接收 + 幀解析 + 命令分發。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved