📌 前言

在嵌入式系統開發中,Bit-banging 是一種常見的軟體模擬技術,用於實現各種通訊協定,如 SPI、I2C 等。透過直接控制 GPIO 腳位的電平變化,軟體可以模擬出硬體通訊協定的行為。然而,當資料量增加或通訊速度要求較高時,Bit-banging 的效率可能會成為瓶頸。這時,使用 SPI + DMA 的硬體加速方式就顯得尤為重要。

🔧 Bit-banging 的實現

範例程式,展示使用 Bit-banging 輸出 CLOCK 和 DATA 訊號:

    // Test Clock
    LCM_Printf(0, "Clock Test");    
    LCM_Printf(1, "...");  
    U16 serial_pattern[] = {0x55aa, 0x1234, 0x7fff, 0x0001, \
        0x4000, 0x2244, 0x6688, 0xffff};
    PU16 pattern = serial_pattern;	
    U16 data;
	U16 mask = ((1UL << (15 - 1)));    
    // prepeare power for VDD pin
	if (skt_vdd_prepare(4000, 500)!=SKT_OK) {
		return SKT_FAIL;
	}
    skt_pkg_pin_cfg_cio();	
    skt_vdd_pwr_on(); 	TM_Delay_US(500);
    while (1) {
        if ((*pattern)==0xffff) break;	
        data = *pattern++;	
        mask = 0x4000;
        // send data 
        for (U8 i=0; i<15; i++, mask>>=1) {
            CLK_LO();  TM_Delay_US(1);
            if (data & mask) { DO_HI();} 
            else  { DO_LO();} 	
            TM_Delay_US(1);      
            CLK_HI();  TM_Delay_US(1); 
        }	
        CLK_LO();  TM_Delay_US(1);  DO_LO();
    }
    LCM_Printf(1, "End");

使用邏輯分析儀觀察到的 CLOCK 和 DATA 波型如下所示:

放大後可以看到,由於 Bit-banging 是由軟體控制 GPIO 腳位,每次的切換有延遲,以及由於考慮 Setup Time 和 Hold Time,和無法抵消 MCU 處理迴圈控制邏輯所產生的額外開銷,導致 Clock 的 Duty Cycle 無法達到完美的 50%。

🚀 進階方案:SPI + DMA 的通訊

為了提升通訊效率解放 MCU,可以使用內建的 SPI 模組搭配 DMA 進行資料傳輸。這樣可以讓 SPI 硬體自動處理資料的傳輸,而不需要 MCU 持續地控制 GPIO 腳位。

// 準備好一串燒錄指令波形
uint8_t program_cmd[] = {0xAA, 0xBB, 0xCC}; 
// 直接交給硬體發送,CPU 可以去跑別的邏輯或準備下一段資料
HAL_SPI_Transmit_DMA(&hspi1, program_cmd, 3);