系統架構
外設傳感器 --SPI--> STM32F407 --USB (CDC/虛擬串口)--> PC 上位機
分步驟調試策略 (核心原則:單模塊驗證 → 集成)
階段 1:SPI 主機模式讀取傳感器
- 查閱傳感器數據手冊:時序、寄存器地址、讀取命令。
- CubeMX 配置 SPI1/2/3:
Mode: Full-Duplex Master, Baud Rate: ≤ 傳感器最大 (如 10MHz),
Data Size: 8-bit, First Bit: MSB, CPOL/CPHA: 模式 0/3 視傳感器。
- 編寫
SPI_ReadReg(uint8_t reg, uint8_t *buf, uint16_t len) 封裝 HAL_SPI_TransmitReceive。
- **驗證**:用邏輯分析儀/示波器抓 CS/SCLK/MISO 波形;串口打印讀出的 WHO_AM_I 寄存器,確認通信正常。
階段 2:USB CDC (虛擬串口) 枚舉與收發
- CubeMX 中間件啟用 USB_DEVICE → Class For FS: Communication Device Class (Virtual Port Com)。
- 生成代碼後,
USBD_CDC_Transmit_FS(buf, len) 發送數據到 PC。
- **驗證**:PC 設備管理器出現「STMicroelectronics Virtual COM Port (COMx)」,串口助手收到開發板主動上報的心跳包。
階段 3:數據流串聯 (雙緩衝 + DMA 推薦)
// 環形緩衝區
#define BUF_SIZE 1024
uint8_t spi_buf[2][BUF_SIZE];
volatile uint8_t buf_ready[2] = {0};
volatile uint8_t wr_idx = 0, rd_idx = 0;
// SPI DMA 接收完成回調
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi) {
buf_ready[wr_idx] = 1;
wr_idx ^= 1; // 切換緩衝區
HAL_SPI_Receive_DMA(hspi, spi_buf[wr_idx], BUF_SIZE); // 重啟接收
}
// 主循環發送
while (1) {
if (buf_ready[rd_idx]) {
USBD_CDC_Transmit_FS(spi_buf[rd_idx], BUF_SIZE);
buf_ready[rd_idx] = 0;
rd_idx ^= 1;
}
}
階段 4:PC 上位機
- Python
pyserial / C# SerialPort / Qt QSerialPort 讀取 COM 口,解析二進制幀,繪圖/存檔。
- 推薦幀格式:
Header(0xAA 0x55) + Len + Cmd + Data + CRC16。
關鍵配置提示
| 項目 | 建議值 | 說明 |
| SPI 速率 | 1-10 MHz | 根據傳感器手冊,杜邦線較長降低速率 |
| USB 端點 | Bulk IN (EP1) | CDC 默認,最大 64 字節/包 (FS) |
| DMA 通道 | SPI_RX + SPI_TX | 釋放 CPU,實現零拷貝 |
| 時鐘 | HSE 25MHz + PLL 168MHz | F407 最大主頻,USB 需 48MHz 精確 |
常見坑點
- **USB 時鐘不準** → HSE 必須 25MHz/12MHz/8MHz 等標準值,PLL 配置使 USBclk=48MHz。
- **SPI 讀寫順序錯** → 先發命令字節,再讀數據字節,CS 保持低電平。
- **CDC 發送阻塞** →
Transmit_FS 返回 BUSY 時需重試或隊列緩衝。
- **PC 端讀取粘包** → 應用層協議幀同步解析,不可假設一次 Read 即一幀。
參考資源
- ST 官方例程:
STM32Cube_FW_F4_V1.x.x/Projects/STM32F4xx_EVAL/Applications/USB_Device
- 《STM32 開發指南——庫函數版本》第 12、13 章 (SPI/USB)。
- GitHub 搜索
STM32F4 USB CDC SPI DMA 現成工程。
- 上一篇文章: C# 簡易日記本程序參考實現:加密存儲、查找、字體設置
- 下一篇文章: Android 顯示多張圖片 OOM 解決:Bitmap 采樣率與內存復用
Copyright ©
程式碼之家 All Rights Reserved