“模擬調(diào)試”這個(gè)標(biāo)題似乎有點(diǎn)神秘。嵌入式固件開發(fā)人員讀完后可能會(huì)產(chǎn)生認(rèn)知失調(diào);但相信我,稍后它就會(huì)有意義。標(biāo)題暗示的是處理微控制器中處理的信號(hào)的任務(wù)。許多涉及小型 MCU 的任務(wù)都與處理來自麥克風(fēng)、水聽器和壓力傳感器等傳感器的原始信號(hào)有關(guān)。其中一些信號(hào)需要清理然后進(jìn)行處理。
該處理可以使用多種數(shù)字信號(hào)處理(DSP)固件技術(shù),例如FIR和IIR濾波器、混頻器和FFT。隨著信號(hào)流經(jīng)微處理器,我們希望通過調(diào)試驗(yàn)證的數(shù)據(jù)可能會(huì)很廣泛。例如,信號(hào)通過濾波器后是什么樣子,或者當(dāng)信號(hào)通過相關(guān)器時(shí),相關(guān)器的輸出是什么。這就是模擬調(diào)試的用武之地。它允許您實(shí)時(shí)觀察信號(hào)。
較小的微控制器可能缺乏較大處理器所擁有的一些強(qiáng)大的調(diào)試工具,例如 BDM、J-Tag 和 SWD。較小的 MCU 也可以作為基礎(chǔ)金屬運(yùn)行,而不使用操作系統(tǒng),這意味著操作系統(tǒng)中可用的任何調(diào)試工具都會(huì)丟失。工具的缺乏和實(shí)時(shí)信號(hào)處理的復(fù)雜性可能會(huì)導(dǎo)致代碼調(diào)試出現(xiàn)問題。然而,調(diào)試需要深入了解微處理器內(nèi)部數(shù)據(jù)發(fā)生的情況,并且在處理流模擬信號(hào)時(shí),您可能希望查看這些信號(hào)在模擬域中的實(shí)際情況。
通常,在調(diào)試固件時(shí),工程師會(huì)使用微控制器上的串行端口(如果存在)打印出正在執(zhí)行的代碼的變量值或指示符。這里有很多問題。首先,在小型 MCU 中,由于內(nèi)存不足,可能沒有足夠的空間用于打印例程。其次,速度可能是一個(gè)問題。在 DSP 類型的處理中,我們通常會(huì)一個(gè)接一個(gè)樣本地對(duì)傳入信號(hào)進(jìn)行實(shí)時(shí)處理,并且我們無法停下來處理相當(dāng)長的打印調(diào)用。第三,打印例程通常會(huì)使用中斷,這可能會(huì)導(dǎo)致實(shí)時(shí)系統(tǒng)出現(xiàn)問題。,將數(shù)據(jù)轉(zhuǎn)儲(chǔ)到串行端口不會(huì)為您提供正在處理的數(shù)據(jù)的直接模擬視圖。
例如,假設(shè)您使用模數(shù)轉(zhuǎn)換器 (ADC) 從傳感器接收信號(hào)。您可以將示波器掛在傳感器的輸出端,并以模擬視圖查看信號(hào)和噪聲。但是,如果您通過串行端口查看相同的信號(hào),則在 MCU 讀取 ADC 并將其發(fā)送到該串行端口后,您會(huì)看到一堆數(shù)字?,F(xiàn)在,您可以將這些數(shù)字放入電子表格中并繪制圖表,或者設(shè)置另一臺(tái)帶有數(shù)字和模擬轉(zhuǎn)換器以及顯示器的設(shè)備以再次查看數(shù)據(jù)。但它似乎有點(diǎn)緩慢和乏味,而且肯定不是實(shí)時(shí)的。
現(xiàn)在,如果串行端口不可用或不適合調(diào)試,工程師可以使用連接到 MCU 的 LED,該 LED 可以根據(jù)正在調(diào)試的程序中的各種條件打開或關(guān)閉。示波器可以連接到 LED 或可用的 I/O 線,以通過切換固件中的 LED 或 I/O 線來查看狀態(tài)或測量狀態(tài)更改之間的時(shí)序。它工作得很好,但不符合獲得信號(hào)模擬視圖的想法,因?yàn)樾盘?hào)正在由濾波器、相關(guān)器、切片器和混頻器的各個(gè)階段進(jìn)行處理。
使用 DAC 進(jìn)行模擬調(diào)試
有一個(gè)連接示波器探頭的地方,我們可以在其中快速將處理過的樣本轉(zhuǎn)儲(chǔ)到固件中。那么,我們可以用什么呢?個(gè)想法是將數(shù)模轉(zhuǎn)換器 (DAC) 連接到 MCU,或者更好的是使用可用作 MCU 上的外設(shè)的轉(zhuǎn)換器。
為了嘗試這項(xiàng)技術(shù),我將 Analog Devices 的AD7801(一個(gè) 8 位 DAC)連接到我正在開發(fā)的Arduino Nano設(shè)計(jì)中。Nano 的是 Microchip ATmega328,它沒有板載 DAC。AD7801 使用 8 條數(shù)據(jù)線的并行輸入,這些數(shù)據(jù)線由另一條線計(jì)時(shí),寫入速度非常快。值得注意的是,我們可以使用此設(shè)置查看 8 位數(shù)據(jù),但 10 位、12 位或其他大小可以與其他 DAC 一起使用,或者可以縮放以適合 8 位 DAC。我將 8 條數(shù)據(jù)線連接到 Arduino 上的 DAC 端口,并將 WR 線連接到 Arduino 的 D13,如圖1所示。
裸機(jī)系統(tǒng)上模擬調(diào)試的關(guān)鍵選項(xiàng)
![wKgZomUIGUWAfhORAAEddYS-308680.png](https://file1.elecfans.com/web2/M00/A3/A2/wKgZomUIGUWAfhORAAEddYS-308680.png)
圖 1 DAC 通過 8 條數(shù)據(jù)線連接到 Arduino。
現(xiàn)在,要將數(shù)據(jù)發(fā)送到 DAC,只需要 3 行 Arduino IDE C 代碼:
PORTD=數(shù)據(jù);// 將數(shù)據(jù)字節(jié)放在 D0 到 D7 上
PORTB = PORTB & B11011111; //將D13拉低以將數(shù)據(jù)鎖存到AD7801中
端口 B = 端口 B | B00100000;// 將D13拉高
在 16 MHz Arduino 上,此代碼需要大約 5 個(gè)周期或大約 312 ns,DAC 的穩(wěn)定時(shí)間為 1.2 us。因此,您可以看到這種數(shù)據(jù)顯示方法可以相對(duì)快速地完成,無需中斷,也無需太多代碼??梢詫⒃摯a插入固件的適當(dāng)位置以查看感興趣的數(shù)據(jù)。將這 3 行代碼放入宏或函數(shù)中可能會(huì)更簡潔。如果您為此創(chuàng)建一個(gè)函數(shù),則應(yīng)該使用“always_inline”編譯指令來編譯它,以確保它運(yùn)行速度快。
現(xiàn)在連接了 DAC,讓我們看一些調(diào)試示例。請(qǐng)看圖 2。
![wKgZomUIGUuAPHF1AAKG3V3ooZU075.png](https://file1.elecfans.com/web2/M00/A3/A2/wKgZomUIGUuAPHF1AAKG3V3ooZU075.png)
裸機(jī)系統(tǒng)上模擬調(diào)試的關(guān)鍵選項(xiàng)
圖 2示波器快照顯示了在啟用 DAC 的設(shè)置中模擬調(diào)試的工作原理。
這是傳入傳感器信號(hào)的示波器快照 - 為了清晰起見,刪除了刻度線。底部跡線(粉色/紫色)是進(jìn)入 ATmega328 上 ADC 引腳時(shí)的原始信號(hào)。您可以在這條線上看到明顯的噪音。上面的跡線(黃色)是在 MCU 固件中進(jìn)行一些濾波和其他處理后的相同信號(hào)。
此流程中插入了 DAC 寫入調(diào)試代碼,因此 DAC 中的采樣時(shí)序與 ADC 相同。如果需要,您還可以對(duì) MCU 中的信號(hào)進(jìn)行抽取?,F(xiàn)在忽略信號(hào)中的“尖峰”,我們看到處理已經(jīng)消除了大部分噪聲。我們現(xiàn)在有了可以評(píng)估的清晰信號(hào)。應(yīng)該注意的是,DAC 輸出是連續(xù)的信號(hào)流,而不僅僅是一些短內(nèi)存緩沖捕獲。
但“尖峰”是什么?這些是我特意放入代碼中的一些調(diào)試功能,以查看處理的進(jìn)行情況。您看到的信號(hào)實(shí)際上是被信號(hào)介質(zhì)破壞的專有數(shù)字信號(hào)。該代碼的任務(wù)是通過以下方式讀取數(shù)字?jǐn)?shù)據(jù)包:
發(fā)現(xiàn)前導(dǎo)碼“數(shù)據(jù)包開始”符號(hào)序列
跟蹤樣本時(shí)間,以便我們可以在適當(dāng)?shù)臅r(shí)間切片樣本
繼續(xù)收集樣本直到數(shù)據(jù)包結(jié)。
這是已添加注釋的已處理信號(hào)的視圖。我在代碼中所做的是將信號(hào)從值 50 縮放到值 200。這允許在 256 個(gè)可用值中留出一些空間,以便在信號(hào)上方和下方添加“尖峰”。我們首先看到的是標(biāo)記為“檢測到前導(dǎo)碼”的“尖峰”。它是在代碼驗(yàn)證已找到前導(dǎo)碼 (B00000011) 時(shí)創(chuàng)建的,并且可以使用以下 Arduino IDE 代碼輕松生成:
端口 = 255; // 將 255 放在 D0 到 D7 上
PORTB = PORTB & B11011111; //將D13拉低以將數(shù)據(jù)鎖存到AD7801中
端口 B = 端口 B | B00100000;// 將D13拉高
它在示波器跡線上創(chuàng)建一個(gè) 312 ns 寬的標(biāo)記,其幅度等于 DAC 的電壓。
信號(hào)跡線內(nèi)向上和向下的“尖峰”是指示代碼確定符號(hào)邊界的位置的標(biāo)記。這對(duì)于在正確的時(shí)間對(duì)符號(hào)進(jìn)行切片非常重要,并且當(dāng)出現(xiàn)長時(shí)間的 0 或 1 時(shí),這一點(diǎn)變得至關(guān)重要。這是因?yàn)闆]有發(fā)現(xiàn)從 0 到 1 或 1 到 0 的轉(zhuǎn)換。在示波器上查看這些“尖峰”非常有用,因?yàn)樗刮覀兡軌蝌?yàn)證實(shí)際時(shí)間并驗(yàn)證沒有丟失。這些符號(hào)邊界“尖峰”是通過使用以下 Arduino IDE 代碼向 DAC 發(fā)送 127 來創(chuàng)建的,該代碼被插入到符號(hào)計(jì)時(shí)代碼中的適當(dāng)位置:
端口 = 127; // 將 127 放在 D0 到 D7 上
PORTB = PORTB & B11011111; //將D13拉低以將數(shù)據(jù)鎖存到AD7801中
端口 B = 端口 B | B00100000;// 將D13拉高
通過使用以下代碼向 DAC 發(fā)送 0,符號(hào)轉(zhuǎn)換被標(biāo)記為“尖峰”,該代碼被插入到監(jiān)視從 0 到 1 或 1 到 0 的符號(hào)轉(zhuǎn)換的代碼中:
端口=0;// 將 0 放在 D0 到 D7 上
PORTB = PORTB & B11011111; //將D13拉低以將數(shù)據(jù)鎖存到AD7801中
端口 B = 端口 B | B00100000;// 將D13拉高
您可以看到,使用 DAC 查看覆蓋在實(shí)際處理跟蹤上的調(diào)試信息可以極大地幫助調(diào)試代碼的各個(gè)部分。它比使用 LED、I/O 線和示波器強(qiáng)大許多倍。它也比串行端口發(fā)送數(shù)據(jù)作為定時(shí)信息更有用。
眼尖的人可能已經(jīng)注意到,在圖 3 的右邊緣,探頭衰減不是 x1 或 x10,而是 x53.5。這是一個(gè)可以在許多較新的示波器上完成的技巧,有時(shí)稱為自定義衰減設(shè)置。它設(shè)置為 53.5 的原因是它允許使用示波器的光標(biāo)直接讀取 DAC 的 8 位輸入值。也就是說,如果我將光標(biāo)向上滑動(dòng)到前導(dǎo)碼檢測“尖峰”的頂部,則示波器光標(biāo)讀數(shù)為 255,如果我將光標(biāo)移動(dòng)到符號(hào)邊界“尖峰”的末尾,則示波器光標(biāo)讀數(shù)為 127。
使用 8 位 DAC 時(shí),此設(shè)置的公式為 255/MaxVolts,即輸入二進(jìn)制輸入(本例中為 255)時(shí) DAC 的輸出電壓。因此,對(duì)于 5V 電源軌,自定義設(shè)置為 51.0——我的電源軌只有 4.77V,所以我的數(shù)字是 53.5。使用 10:1 探頭時(shí),在將其輸入示波器時(shí),您可能需要將該數(shù)字乘以 10。
這非常方便,因?yàn)槟梢灾苯幼x取 DAC 設(shè)置的數(shù)字;換句話說,內(nèi)部變量在調(diào)用 DAC 時(shí)使用的值。這點(diǎn)考慮一下吧。從本質(zhì)上講,您可以通過這種方式“實(shí)時(shí)”讀取變量,幾乎與 print 語句一樣好,但速度更快且非侵入性。請(qǐng)注意,示波器垂直刻度的噪聲和分辨率會(huì)降低精度,因此您可能只能得到實(shí)際值的 ±1 或 2 個(gè)計(jì)數(shù),但仍然相當(dāng)不錯(cuò)。
除了傳輸信號(hào)之外,使用這種技術(shù),8 位 DAC 還可以同時(shí)表示 8 個(gè)二進(jìn)制標(biāo)志的狀態(tài),或程序中 8 位變量的當(dāng)前值。換句話說,使用 8 位 DAC 為我們提供的信息是監(jiān)控單個(gè) I/O 線所提供的信息的 8 倍。
使用 PWM 進(jìn)行模擬調(diào)試
現(xiàn)在,如果您沒有 DAC 可以使用怎么辦?您可以使用微控制器上的脈寬調(diào)制器 (PWM) 外設(shè)來執(zhí)行類似的操作。許多小型 MCU 都有 PWM,即使有,通常也有多個(gè) — 通常是 6 個(gè)。 PWM 和 DAC 之間的區(qū)別之一是 PWM 輸出需要使用低通濾波器進(jìn)行濾波以轉(zhuǎn)換輸出到一個(gè)電壓水平。因此,當(dāng)您將信號(hào)樣本發(fā)送到 PWM 時(shí),電壓電平會(huì)重新創(chuàng)建可以在示波器上顯示的信號(hào),就像使用 DAC 所做的那樣??梢允褂煤唵蔚?RC 濾波器來執(zhí)行濾波。
但這里有一些注意事項(xiàng);低通濾波器意味著只能顯示低頻內(nèi)容的信號(hào),響應(yīng)速度較慢。因此,您應(yīng)該將 PWM 的頻率初始化為可用的頻率。在 16 MHz ATmega328 上,PWM 的頻率可以設(shè)置為 31 kHz 左右,因此低通信號(hào)可以設(shè)計(jì)為大約 3-4 kHz 的頻率內(nèi)容。
初始化后,使用 PWM 的 Arduino IDE 代碼甚至比 DAC 代碼更簡單。將 8 位值寫入 PWM 的代碼非常簡單:
AnalogWrite(PinNumber, 數(shù)據(jù))
這里“data”是8位采樣值,“PinNumber”是PWM輸出的引腳號(hào)。
盡管 PWM 可能不那么準(zhǔn)確或無法顯示更高頻率的信號(hào),但它具有一個(gè)有趣的功能。一些 MCU 具有多達(dá) 6 個(gè) PWM,這意味著多達(dá) 6 個(gè)輸出可以傳送實(shí)時(shí)數(shù)據(jù)。您可以使用 4 跡線示波器同時(shí)顯示 4 個(gè)變量,留下 2 個(gè)備用 PWM 輸出。此外,通過 2 個(gè)輸出(PWM 或 DAC),您可以提供 DSP 信號(hào)處理中常用的 I & Q 數(shù)據(jù),從而允許您探索負(fù)頻率。需要注意的是,就像 DAC 代碼一樣,PWM 代碼不需要中斷。
其他調(diào)試工具
可用于處理 DAC 或 PWM 傳遞的信號(hào)的另一個(gè)強(qiáng)大工具是頻譜。圖 4中的范圍屏幕截圖顯示了一個(gè)示例。上面的跡線顯示了微控制器中生成的波形。該信號(hào)實(shí)際上是兩個(gè)頻率(f1 = 165 Hz 和 f2 = 135 Hz)逐個(gè)樣本地混合或相乘,然后在生成時(shí)發(fā)送到 DAC。在頻率混合中,結(jié)果是頻率之和與頻率之差的頻率。原始生成頻率被混合操作抑制,如示波器跡線下半部分的 FFT 所示。大多數(shù)示波器,甚至是業(yè)余愛好者級(jí)別的示波器,都提供 FFT 作為數(shù)學(xué)運(yùn)算之一。
如果您的系統(tǒng)沒有 DAC 或 PWM,您仍然可以使用一些東西來獲取有關(guān)正在運(yùn)行的固件中的信號(hào)的一些信息。例如,您可以編寫代碼來對(duì) PWM 信號(hào)進(jìn)行位處理。盡管它對(duì)于低頻信號(hào)或緩慢變化的變量很可能有用。
希望模擬調(diào)試的想法現(xiàn)在更清晰了。從固件流式傳輸數(shù)據(jù)并將其顯示在示波器上的主要概念可以是一個(gè)強(qiáng)大的工具,可以加快信號(hào)處理固件調(diào)試的速度。如果可行,選擇帶有 DAC 外設(shè)的 MCU 或在您的個(gè)原型 PCB 中集成 DAC 可能會(huì)很有用。它始終可以在以后刪除或在物料清單 (BOM) 中設(shè)為 NO-POP。
評(píng)論