色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

兩個月嵌入式編程DIY示波器和信號發生器

電子森林 ? 來源:電子森林 ? 作者:電子森林 ? 2021-04-01 10:24 ? 次閱讀

今天隨機分享4篇基于第一個平臺的項目:

“寒假在家一起練”(1) - 兩個月嵌入式編程DIY示波器信號發生器,玩起來就免購板費

本文為中國科技大學王赫男同學完成并分享的項目內容。。

1 項目需求

完成對板上音頻信號的采集和波形顯示,可以通過手機播放音樂或App產生音頻信號的方式提供聲音信號源,通過板上電路的放大、MCUADC的采集以后將波形顯示在OLED屏幕上,可以通過板上按鍵的操作在兩個方向(橫軸 - 時間;縱軸 - 幅度)來擴展、壓縮波形的顯示,按鍵的功能可自行定義;

實現信號發生器的功能,能夠產生2KHz以內的正弦波、三角波、方波三種常用波形,通過按鍵的操作能夠實現頻率可調、幅度可調,通過調整板上的R、C的值,可以最高生成200KHz的模擬信號;

能夠通過Ain管腳測量外部模擬信號(0-3.3V,DC-200KHz),并能夠對外部的周期性波形測量其周期和峰-峰值;

能夠對采集到的信號進行FFT變換,并在屏幕上顯示其基頻及低次諧波(比如2、3、4、5次)的分量。

2 完成的功能及達到的性能

2.1 波形顯示

顯示波形時,按下L提高采樣率,按下R降低采樣率,采樣率取值范圍為1kHz、2.5kHz、5kHz、10kHz、25kHz、50kHz、100kHz、250kHz、500kHz、1MHz,通過改變采樣率來實現橫軸的縮放。

Y軸(幅度范圍)默認為自動調整,即程序自動根據采樣序列調整Y軸中心電壓值和縮放范圍,使波形完整顯示在屏幕上。通過菜單可以改為手動模式,即手動調整Y軸中心電壓值和Y軸縮放范圍。

左下角顯示波形參數,可以顯示時間軸分度值、信號峰峰值、直流分量和頻率。

正下方顯示當前狀態,包含輸入通道、觸發狀態和前述的Y軸縮放方式(A:自動縮放,MO (Manual Offset):U/D按鍵調整Y軸中心電壓值,MS (Manual Scale):U/D按鍵調整Y軸縮放范圍。

按下OK鍵可以暫停波形刷新,再按可以繼續刷新。

2.2 觸發顯示和觸發菜單

程序默認為上升沿觸發,觸發電平為1.68V。顯示波形且觸發開啟時,屏幕正下方顯示當前觸發邊沿(上升沿、下降沿)和觸發狀態(箭頭點亮為觸發成功、背景點亮為觸發失敗)。

長按R鍵打開觸發菜單,在觸發菜單中可以開啟/關閉觸發,選擇觸發邊沿,選擇自動觸發還是單次觸發。

2.3 示波器菜單

長按OK鍵打開示波器菜單,示波器菜單共有4項,分別是:波形/頻譜顯示切換、Y軸縮放方式、波形參數切換、通道切換(麥克風與板上信號輸入)。LRUD四個按鍵用來對上述四項功能進行切換。

2.4 頻譜顯示

通過菜單切換至頻譜顯示時,屏幕顯示信號的頻譜,顯示頻率范圍為直流至采樣頻率的一半。同樣按下L提高采樣率,按下R降低采樣率。左下角顯示頻率軸分度值。

2.5 信號輸出

長按L鍵打開輸出菜單,在輸出菜單中,可以開啟/關閉信號輸出,增加/降低輸出信號的頻率(步長100Hz,上限2kHz)、峰峰值(步長0.1V,上限3.3V)和調整輸出波形(正弦波、三角波、方波)。

3 實現思路

ADC對模擬輸入進行采樣,采樣由定時器觸發,采樣結果由DMA搬運;

將采樣得到的ADC量化值映射到屏幕坐標點上,實現波形顯示;

按下按鍵調整采樣頻率,實現波形在時間軸上的擴展與壓縮;

對采樣序列進行FFT變換,繪制頻譜;

信號參數的顯示,如峰峰值、直流分量、信號頻率等;

輸出PWM波并通過RC低通濾波實現方波、正弦波、三角波的生成,通過按鍵改變PWM波的頻率與占空比,從而改變輸出信號的頻率和幅度。

4 實現過程

4.1 程序流程圖

ba846f0a-9245-11eb-8b86-12bb97331649.png

注:每個框圖右下角名稱為執行該功能的主要文件

4.2 ADC對數據進行采樣

為了方便進行FFT計算,ADC共采集256個采樣點。每次ADC轉換由定時器1觸發,觸發頻率最高為1MHz,即ADC采樣率最高為1Msps。ADC的轉換結果直接由DMA搬運至內存。

ADC轉換開始函數(定義位置:sample.c,調用位置:main.c):

/** * @brief Start a new sample sequence. * @param[in] ADCValue Array to store incoming sample values. * @retval None */ void start_sample(uint16_t *ADCValue) { HAL_Delay(1); HAL_ADCEx_Calibration_Start(&hadc1); HAL_ADC_Start_DMA(&hadc1, (uint32_t *)ADCValue, SAMPLE_POINTS); }

256次轉換結束后進入中斷,置位結束標志位,進入后續的數據處理程序。

ADC轉換結束中斷回調函數(定義位置:adc.c):

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) { if(hadc == &hadc1) { finish_sample(); } }

4.3 采樣結果的處理

得到256個采樣的ADC量化值后,根據觸發電平選擇波形起始點,返回起始點在數組中的下標,顯示從起始點開始的100個點。

波形觸發部分代碼(定義位置:wave.c,調用位置:app.c,其中total_points=256, GRAPH_WIDTH=101):

/** * @brief Wave trigger. * @param[in] ADCValue Array of sampled ADC values. * @param[in] total_points Total sampled points. * @retval Index of the trigger start point(》1)。 0 means trigger off or failed. */ uint16_t trigger(uint16_t *ADCValue, uint16_t total_points) { uint16_t i; uint16_t trigger_value = VOL2ADC(1.68); if (!is_trigger_on()) return 0; for (i = 1; i 《 total_points - GRAPH_WIDTH + 2; i++) { if (get_trigger_edge()) // falling edge { if (ADCValue[i-1] 》 trigger_value && ADCValue[i] 《= trigger_value) { trigger_success(); if (is_trigger_single()) pause(); return i; } } else { if (ADCValue[i-1] 《= trigger_value && ADCValue[i] 》 trigger_value) { trigger_success(); if (is_trigger_single()) pause(); return i; } } } trigger_fail(); return 0; }

取起始點后100個采樣值使其顯示在OLED屏幕上(一次性刷新)。為此需要將ADC量化值與OLED屏幕上的坐標進行線性映射。在自動模式(自動縮放y軸)中,程序自動找出量化值中的最大最小值,并使最大最小值也能不超出繪制范圍以外,這樣屏幕就可以顯示完整的波形。

自動縮放y軸代碼(定義位置:wave.c,調用位置:app.c):

/** * @brief Automatically find the central/max/min voltage on y-axis. * @param[in] ADCValue Array of sampled ADC values. * @note The function calculates the min/max voltage of the sampled signal, * then find a proper scale voltage and a central voltage on y-axis. * @retval None */ void auto_scale(uint16_t *ADCValue) { uint16_t a_max_value, a_min_value, a_pp_value; float exact_voltage, floor_voltage, ceil_voltage; get_max_min_pp_value(ADCValue, &a_max_value, &a_min_value, &a_pp_value); voltage_range_auto_select(ADC2VOL(a_pp_value/2)); exact_voltage = ADC2VOL(a_max_value + a_min_value) / 2; floor_voltage = (uint8_t)(ADC2VOL((a_max_value + a_min_value)*5)) / 10.0; //keep one decimal ceil_voltage = floor_voltage + 0.1; // round center_voltage volt_on_y_axis.center_voltage = ceil_voltage - exact_voltage 《 exact_voltage - floor_voltage ? ceil_voltage : floor_voltage; volt_on_y_axis.max_voltage = volt_on_y_axis.center_voltage + v_scale_list[v_scale_index]; volt_on_y_axis.min_voltage = volt_on_y_axis.center_voltage - v_scale_list[v_scale_index]; }

坐標映射代碼(定義位置:wave.c,調用位置:app.c):

/** * @brief Generate y-coordinates of the wave. * @param[in] ADCValue Array of sampled ADC values. * @param[out] y Y-coordinate array of the wave. * @note The function map ADCValues to OLED y coordinates. * @retval None */ void generate_wave(uint16_t *ADCValue, uint8_t *y) { // Quantize y-axis min/max/central voltages to ADC values. int16_t a_max_value = VOL2ADC(volt_on_y_axis.max_voltage); int16_t a_min_value = VOL2ADC(volt_on_y_axis.min_voltage); uint8_t i; // Linearly map every ADC value to its coordinate. for (i = 0; i 《 GRAPH_WIDTH - 1; i++) { if (ADCValue[i] 《= a_max_value && ADCValue[i] 》= a_min_value) y[i] = (GRAPH_HEIGHT - 1) * (a_max_value - ADCValue[i]) / (a_max_value - a_min_value) + GRAPH_START_Y; else if (ADCValue[i] 》 a_max_value) y[i] = GRAPH_START_Y; else if (ADCValue[i] 《 a_min_value) y[i] = GRAPH_HEIGHT + GRAPH_START_Y - 1; } }

波形顯示代碼(定義位置:display.c,調用位置:app.c):

/** * @brief Display wave on OLED. * @param[in] y Y-coordinate array of the wave. * @retval None */ void display_wave(const uint8_t *y) { uint8_t x; for (x = GRAPH_START_X; x 《 GRAPH_WIDTH - 1; x++) OLED_DrawLine(x, y[x-GRAPH_START_X], x + 1, y[x-GRAPH_START_X+1], 1); OLED_DrawPoint(x, y[x-GRAPH_START_X], 1); }

在手動模式中,可以手動調節y軸的縮放范圍和y軸中心電壓值,但此時波形不一定會完整顯示。得到采樣點坐標后,使用OLED的繪制直線函數,連接屏幕上各個離散的點,就可以得到信號的波形。

當需要顯示頻譜時,就需要對所有的ADC的量化值進行256點FFT變換,由于FFT變換結果關于中心點對稱,且屏幕x方向分辨率為128點,所以保留FFT需要為0~127的結果,進行線性映射后顯示在屏幕上。

FFT的代碼定義在fftutil.c中,對變換結果的處理及顯示分別定義在spectrum.c和display.c中。

4.4 信號發生器

板上有一個1Kohm的電阻和10nF的電容構成的低通濾波器,截止頻率為1.6KHz。若在該輸出端輸出頻率足夠的PWM信號,則輸出電壓大小就和PWM的占空比成正比。通過改變PWM的占空比就可以調節輸出電壓波形。通過實驗可知,當信號的每一個周期由500個PWM脈沖組成時,信號的紋波較小。

以正弦信號為例,在程序外,在電腦中生成一個正弦信號,并在一個周期中進行500次采樣,根據電壓和PWM占空比的正比關系可以計算出500個PWM脈沖的占空比。將其定義為長度為500的數組寫入程序。程序中使能PWM的DMA通道,這樣就可以在每個PWM脈沖結束后自動將數組中的元素載入定時器輸出比較寄存器,從而改變占空比。低通濾波器再將STM32產生的PWM脈沖轉變為模擬信號,即可重新生成正弦波。方波和三角波同理。

開啟PWM和DMA代碼(定義位置:source.c,調用位置:app.c,其中SIGNAL_LENGTH=500):

/** * @brief Start signal output at Aux. * @retval None */ void start_output(void) { HAL_TIM_PWM_Start_DMA(&htim2, TIM_CHANNEL_2, (uint32_t *)output_wave_value, SIGNAL_LENGTH); }

信號的幅度調節可以直接對上述數組每個元素乘一個常數來實現;頻率調節首先要調節定時器的自動重載值(ARR),改變PWM的頻率。為保證幅度不變,數組中每個元素也要同比例縮放。

5 遇到的主要難題

5.1 中斷與DMA

項目共有兩處使用DMA,分別用于儲存ADC采樣結果和調整輸出PWM定時器的自動重載值(ARR)。如果用中斷處理數據而非DMA,則會產生以下問題:

若在ADC轉換完成中斷中讀取轉換結果,則在一次采樣序列(256點)中,中斷頻率過于頻繁,且由于中斷耗時,無法得到很高的采樣率,最高只能達到幾十kHz。若使用DMA,則只需在整個采樣序列結束后進入中斷,不會對采樣造成影響。

若使用PWM中斷更新自動重載值,中斷耗時會使PWM頻率產生偏差,且會對OLED屏幕的SPI時序造成影響,導致屏幕無法正常顯示。若使用DMA更新自動重載值,則不需要PWM中斷,更新耗時相比于中斷有很大改善。

綜上所述,在頻率較高或需要頻繁更新數據的情況,中斷會帶來各種各樣的問題,而DMA則可以高效完成任務。

5.2 RAM和Flash大小(FFT優化)

項目使用的FFT算法根據Adafruit ZeroFFT修改而來。該算法最高可支持4096點FFT,其旋轉因子表、窗函數表和信號序列數組占用空間極大。而本項目使用的STM32G031G8只有64K的Flash和8K的RAM,資源極為有限,無法直接運行ZeroFFT。

為此需要對ZeroFFT的代碼進行優化。該項目只需256點FFT,刪去256點之外的部分,縮短查找表,能極大減小RAM和Flash占用。

具體的優化步驟:

將Adafruit_ZeroFFT.h中的宏定義ZERO_FFT_MAX改為512。(對應256點FFT)

刪去fftutil.c中ZeroFFT函數所有其他點數的FFT代碼,只保留256點FFT的代碼。同樣刪去窗函數中256點以外的部分和窗函數查找表。

此時fftutil.c中只調用了arm_common_tables.c中armBitRevTable和twiddleCoefQ15兩個查找表,刪去其他所有數組。

在fftutil.c中所有調用armBitRevTable和twiddleCoefQ15查找表的代碼下面添加printf,用PC運行FFT程序,打印調用的下標。

以twiddleCoefQ15數組為例,原長度為6144;對于256點FFT,只有其中384個值被調用。PC中編寫一個臨時程序,根據調用的下標,用printf打印一個新的長度為384的查找表替換掉原來的。另一個查找表同理。

fftutil.c中部分變量代表查找表的步進值,查找表改變后這些步進值也要改變。

此時FFT的代碼應該就可以在STM32G0上運行了~

此外,由于Flash和RAM的資源有限,在FFT之外的其他很多地方也需要對空間進行優化,比如刪去oled不需要的字庫等。

5.3 PWM輸出頻率

由于電容的充放電,由PWM經過低通濾波輸出的信號會有鋸齒,信號幅度較低時鋸齒更為明顯,并會造成波形顯示的不穩定。開始時輸出信號一個周期內有50個PWM脈沖,即PWM的頻率是信號頻率的50倍,當信號幅度較低時鋸齒極為明顯,對輸出波形造成極大干擾。將一個周期內PWM脈沖數提升至500,鋸齒密度變大,同時幅度減小,對輸出信號的干擾也減小。但同時儲存輸出信號幅度信息的查找表也變大10倍,消耗了更多的空間。

6 未來的計劃建議

該項目已經成功實現了簡易示波器和信號發生器的功能,并達到了預期指標。然而通過更換硬件,還有許多可以提升與擴展的地方:

板上的OLED屏幕分辨率較低,無法顯示信號細節與更多信息。可以使用分辨率更高的屏幕,或將波形信息直接發送給上位機,由上位機進行顯示。

主控芯片STM32G031的資源有限。可以更換更好的主控芯片,來提高采樣率,采樣點數等從而實現更高的性能。

可以對輸入信號進行衰減,從而增大輸入信號的電壓范圍。

增加模擬輸入的通道,并添加波形的數學運算功能,如波形之間的加減。

改變輸出端的RC值,擴展輸出信號頻率范圍。

不更換硬件可以提升與擴展的地方(懶得做的部分):

自動/手動調整觸發電平。

改變輸入信號耦合方式(直流/交流耦合)。

對輸入信號進行數字濾波。

信號源實現更高的頻率分辨率。

原文標題:如何在STM32G031上實現示波器和頻譜分析功能?

文章出處:【微信公眾號:FPGA入門到精通】歡迎添加關注!文章轉載請注明出處。

責任編輯:haq

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 示波器
    +關注

    關注

    113

    文章

    6240

    瀏覽量

    184801
  • STM32
    +關注

    關注

    2270

    文章

    10896

    瀏覽量

    355757
  • 信號發生器
    +關注

    關注

    28

    文章

    1472

    瀏覽量

    108739

原文標題:如何在STM32G031上實現示波器和頻譜分析功能?

文章出處:【微信號:xiaojiaoyafpga,微信公眾號:電子森林】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    信號發生器如何進行通訊設置#信號發生器#通訊設置#示波器#網絡分析儀#示波器維修

    信號發生器
    安泰儀器維修
    發布于 :2024年09月11日 17:44:09

    labview控制示波器信號發生器

    請問有沒有大神有labview控制示波器信號發生器的程序范例,我的示波器室Wavesurfer 4104HD,信號
    發表于 07-06 15:13

    信號發生器的使用方法 信號發生器的幅值是有效值嗎

    信號發生器是一種電子設備,用于生成具有特定特性的電信號,如正弦波、方波、鋸齒波等。信號發生器廣泛應用于測試和測量領域,如電子電路設計、通信系
    的頭像 發表于 06-03 10:56 ?2931次閱讀

    任意波形發生器和矢量信號發生器有什么區別

    在電子測試與測量領域,任意波形發生器(Arbitrary Waveform Generator,簡稱AWG)和矢量信號發生器種常見的信號
    的頭像 發表于 05-30 16:02 ?2848次閱讀

    任意波形發生器示波器怎么連接

    在電子測試領域中,任意波形發生器示波器種非常重要的測試設備。任意波形發生器能夠產生多種波形信號,用于模擬各種實際環境中的
    的頭像 發表于 05-15 15:38 ?1021次閱讀

    函數發生器示波器的區別

    在電子工程領域中,函數發生器示波器種不可或缺的工具。它們各自在電子信號的產生、觀測和分析中發揮著重要的作用。然而,盡管它們都與電子信號
    的頭像 發表于 05-15 11:46 ?891次閱讀

    信號發生器信號示波器的區別

    在電子測量和測試領域,信號發生器信號示波器種不可或缺的工具。它們各自在信號的產生、分析和測
    的頭像 發表于 05-10 15:51 ?1494次閱讀

    示波器信號發生器的使用方法

    示波器多為雙蹤示波器,有兩個輸入通道,分別為通道1(ch1)和通道2(ch2)。將示波器探頭分別接到這兩個通道上,再將
    的頭像 發表于 05-08 16:35 ?1782次閱讀

    示波器信號發生器怎么連接

    首先將信號發生器示波器分別與電源連接,并確保接地線正確連接,以確保有效的工作和安全性。
    的頭像 發表于 05-08 16:34 ?3543次閱讀

    proteus信號發生器怎么設置方波

    ,用于模擬和調試電子電路。它具有豐富的虛擬儀器庫,包括示波器信號發生器、函數發生器等。Proteus信號
    的頭像 發表于 02-23 16:44 ?9854次閱讀

    函數發生器信號發生器的區別和聯系

    函數發生器信號發生器是電子工程領域常用的種設備,它們在實驗室和工業制造領域中扮演著重要的角色。盡管者在名稱和功能上有一定的相似性,但它
    的頭像 發表于 02-23 16:10 ?2255次閱讀

    信號發生器是干什么用的 信號發生器示波器怎么連接

    信號發生器是一種用于產生各種電信號的設備,它在電子設備測試、電路調試、教學實驗等領域得到廣泛應用。信號發生器可以產生不同頻率、幅度、波形和相
    的頭像 發表于 01-30 10:08 ?2924次閱讀

    任意波形發生器信號幅值和示波器不一致是什么原因

    任意波形發生器(AWG)和示波器種常用的信號源和測量工具,它們在電子測量和測試中都發揮著重要的作用。
    的頭像 發表于 01-29 17:14 ?2415次閱讀

    波特率發生器使用哪個定時 波特率發生器的時鐘來源是什么

    波特率發生器是一種用于控制串行數據通信速率的設備,它可以生成特定波特率的時鐘信號。在嵌入式系統、通信設備和計算機硬件中,波特率發生器的使用十分常見。波特率
    的頭像 發表于 01-24 09:56 ?2166次閱讀

    信號發生器是干什么用的 信號發生器的使用方法

    信號發生器是一種電子測試儀器,用于產生各種類型的電信號。它可以在實驗室、工廠和其他領域提供標準化的、可重復的信號,用于測試和驗證其他電子設備的性能。
    的頭像 發表于 01-19 14:51 ?3109次閱讀
    主站蜘蛛池模板: 91精品一区二区三区在线观看 | 欧美精品3atv一区二区三区| MD传媒MD0021在线观看| 日韩亚洲不卡在线视频| 狠狠狠色丁香婷婷综合久久| 最新无码二区日本专区| 日韩欧美中文字幕在线| 九九99热久久精品在线6| 99青草青草久热精品视频| 我和妽妽在厨房里的激情区二区| 久久女婷五月综合色啪| 国产AV高清怡春院| 综合精品欧美日韩国产在线| 色一欲一性一乱一区二区三区 | 日韩午夜影院| 久久亚洲精品AV成人无码| 动漫美女人物被黄漫在线看| 亚洲色图影院| 色偷偷超碰97人人澡人人| 久久伊人影视| 国产无遮挡又黄又爽在线视频| 999资源站| 亚洲人成77777| 少妇系列之白嫩人妻| 美女张开腿露出尿口扒开来摸动漫| 芳草地社区在线视频| 99re5.久久热在线视频| 文中字幕一区二区三区视频播放| 老湿影院色情a| 花蝴蝶在线高清视频观看免费播放| 超碰最新地址| 999www成人免费视频| 伊人久久青草| 亚洲国产在线视频中文字| 三级aa久久| 青年医生插曲| 嫩草影院地址一地址二| 久久免费高清| 久久久无码精品亚洲A片软件 | 日韩亚洲欧美中文高清在线| 免费三级黄色|