1. 程式人生 > 其它 >STC8H開發(八): NRF24L01無線傳輸音訊(對講機原型)

STC8H開發(八): NRF24L01無線傳輸音訊(對講機原型)

STC8H使用NRF24L01無線傳輸音訊, 傳送部分需要實現的是8kHz取樣, 並通過NRF24L01將每秒的8000位元組資料傳送出去. 語音輸入MAX9814. NRF24L01在設定為1Mbps頻寬時實際傳輸速度能達到23k位元組每秒, 因此對於8bit 8kHz取樣的傳輸是沒問題的. 因為NRF24L01傳輸時的響應和重發機制, 在訊號不好時, 容易卡頓, 為了避免中間傳輸時間的波動影響, 在實際實現中使用了雙陣列做緩衝.

目錄

關於PWM, DAC和音訊

PWM是脈衝寬度調製的縮寫, 因為介紹的文章很多, 自己做功課即可, 參考

大部分低端MCU不帶DAC轉換, 但是可以使用PWM模擬, 對於音訊傳輸

  1. 人普通談話的聲波頻率在500-2000Hz之間, 人耳可以聽到的聲波的頻率範圍在20Hz至20kHz之間
  2. 用於通話, 8kHz的頻寬就能達到較好的語音傳輸效果
  3. 通過PWM模擬DAC, 因為PWM是方波, 其頻率會引入底噪, 底噪的頻率是PWM頻率的倍數
  4. PWM頻率在8KHz時, 在聽感上底噪很大, 與傳輸的音訊一樣明顯, 將PWM的頻率調節到16kHz以上才能有效抑制底噪

通過MCU實現無線音訊傳輸的實現

傳送部分

接收部分

以下實現的是單聲道 8kHz 8bit 取樣的音訊訊號傳輸

傳送部分

傳送部分需要實現的是8kHz取樣, 並通過NRF24L01將每秒的8000位元組資料傳送出去.

語音輸入

語音輸入可以使用駐極體話筒加S9013放大輸入或者直接使用MAX9814. 在測試階段建議使用後者, 可以保證取樣輸入不失真, 在調通後再用駐極體話筒電路替換.

ADC音訊取樣

因為ADC取樣需要實現準確的每秒8000取樣, 所以不能用DMA方式, 在STC8H(包括STM32等其它MCU)下, 無法在DMA情況下精確調節每秒的取樣個數, 因為ADC的取樣頻率, 取樣週期和轉換週期在不同MCU中都是固定的, 所以很難正好做到8kHz的取樣. 具體的實現中有兩種方式:

1.定時器驅動採集

通過定時器設定為8kHz, 在中斷中發起ADC轉換, 是比較容易實現的. 這時候需要將ADC也實現為中斷方式, 因為ADC的轉換時間比較長, 如果在定時器中斷中做同步的ADC轉換, 容易影響主程序. 需要有定時器的中斷處理和ADC的中斷處理, 定時器的中斷處理單純用於發起轉換, ADC的中斷才用於讀出結果.

2.連續採集定時讀取

通過定時器設定為8kHz, 將ADC的採集設定為迴圈方式(中斷採集, 但是在中斷時再次發起), 在定時器中斷中僅僅讀取採集結果. 這種方式也能實現8kHz的取樣. 因為這種方式實際上會多消耗電量, 所以使用中還是使用了前一種方法.

NRF24L01傳送

NRF24L01在設定為1Mbps頻寬時實際傳輸速度能達到23k位元組每秒, 因此對於8bit 8kHz取樣的傳輸是沒問題的. 因為NRF24L01傳輸時的響應和重發機制, 在訊號不好時, 容易卡頓, 為了避免中間傳輸時間的波動影響, 在實際實現中使用了雙陣列做緩衝. 取樣到傳送之間的邏輯為

  1. 兩個256位元組陣列作為全域性變數, 同時定義變數指向當前寫入的陣列編號和寫入位置
  2. ADC中斷讀取結果時, 往當前編號的陣列和位置中寫入並移動位置, 當寫滿一個數組時, 將此陣列標記為可傳送, 並切換到下一個陣列繼續寫入
  3. 在主程序中, 判斷當前是否有可傳送的陣列, 如果可傳送, 則在迴圈中按32個位元組一組將資料全部發送.

因為在正常收發的訊號強度下, NRF24L01的傳送速度是比取樣速度快的, 所以基本上NRF24L01的傳送是傳送 -> 等待 -> 傳送的狀態

接收部分

接收部分要實現的是將NRF24L01接收到的資料進行儲存, 並按照8kHz的頻率, 將每個值設為PWM輸出的佔空比, 實現DAC模擬

RNF24L01接收

因為NRF24L01傳送是集中傳送, 所以在接收時也需要有緩衝, 接收的機制和傳送相似

  1. 兩個256位元組陣列作為全域性變數, 同時定義變數指向當前寫入的陣列編號和寫入位置
  2. NRF24L01通過中斷接收資料, 在接收時, 往當前編號的陣列和位置中寫入並移動位置, 當寫滿一個數組時, 將此陣列標記為可用, 並切換到下一個陣列繼續寫入

PWM模擬DAC還原

初始化一個PWM輸出, PWM週期為256對應8bit的佔空比調節範圍, 確保PWM頻率不低於16kHz. 在8kHz定時器的中斷中, 判斷當前讀取的陣列和位置, 每次讀取一個值, 並將其設定為PWM佔空比. 如果陣列不可用, 就不做任何操作, 如果此時將佔空比設為0, 會產生噪音.

音訊輸出

測時階段, 可以在PWM輸出上串聯一個200R的電阻後值連喇叭, 可以聽到輸出的音訊. 這個電阻不能太小, 測試中如果阻值小於100R, 會導致MCU供電不足反覆重啟. 在確定音訊輸出沒問題後, 可以替換為 PAM8403 音訊放大模組.

在使用 PAM8403 模組時

  1. 模組需要獨立供電, 測試中如果與MCU都使用USB2TTL供電, 會使MCU供電不足而導致聲音輸出異常
  2. 模組與MCU的輸出可以不共地, 即模組MCU的PWM輸出和地, 可以直接接入PAM8403的音訊輸入
  3. 因為是單聲道訊號, 所以只能用PAM8403的一個聲道, L或者R都可以

演示程式碼

接線說明

在測試中傳送部分使用的是 STC8H3K32S2, 接收部分使用的是 STC8H1K08, 你可以使用STC8H系列的任意一個型號

共同的連線部分(NRF24L01)

   8H3K32S2/8H1K08  NRF24L01
   P35(SS, Ignored) => CSN    16
   P34(MOSI)        => MOSI   15
   P33(MISO)        => MISO   14
   P32(SPCLK)       => CLK    13
   P36(INT2)        => IRQ    17
   P37(IO)          => CE     18

傳送部分

STC8H3K32S2         MAX9814
   P11(ADC1)        => MIC
   3.3V             => VDD
   3.3V             => GAIN
   GND              => A/R
   GND              => GND

ADC, 如果是STC8H3K32S2, 使用ADC取樣需要將AVcc, AGnd 和 ADC_Vref+ 正確連線

   AVcc             => 3.3V
   AGnd             => GND
   ADC_Vref+        => 3.3V
   P11              => Output(MAX9814) or MIC

接收部分

STC8H1K08           PAM8403
   P10(PWM1P)       => 200R => L or R Input
   GND              => _|_ Input
   Ext 3.3V/5V      => VCC
   Ext GND          => GND

注意:

  1. MCU的pin腳佈局不一定相同, STC8H3K32S2和STC8H1K08都是20pin的封裝, 但是pin腳佈局就不一樣
  2. 燒錄傳送部分和接收部分時, 注意要調換 nrf24l01.c 中的 RX_ADDRESS 和 TX_ADDRESS

效果演示

B站視訊 https://www.bilibili.com/video/BV1kZ4y1Z78v