使用STM32 micros的 模擬數字轉換器(ADC) 后,接下來要處理的明顯內部硬件模塊是 數字到模擬轉換器(DAC) 。顧名思義,該模塊僅具有ADC的補充功能。它將數字二進制值轉換為模擬電壓輸出。 DAC模塊具有多種用途,包括音頻生成,波形生成等。通常在大多數8位微控制器中,該模塊不可用,并且 脈沖寬度調制(PWM)可以稍微滿足其需求。 》 塊。部分原因是由于它們的硬件資源和運行速度相對較低。所有STM32單片機都具有PWM模塊,但大容量STM32也具有DAC模塊。 STM32 DAC模塊不是很復雜,并且在工作原理方面與ADC模塊相似。下面的簡化框圖顯示了STM32 DAC模塊的主要組件。
再次請注意低密度STM32微處理器沒有任何內置DAC。對于這個問題,我使用了Waveshare的帶有STM32F103ZET6 micro的Port103Z(http://www.wvshare.com/product/Port103Z.htm)開發板。該STM32 micro具有兩個帶獨立轉換器的DAC通道,并包含大量其他硬件資源。像這樣的大多數高端微控制器至少帶有兩個DAC通道。立體聲音頻生成需要兩個DAC通道-一個非常常見的基于DAC的應用程序。開發板經過精心設計,可將DAC輸出連接至LED,以直接可視化DAC輸出。
STM32 DAC模塊的主要功能
STM32 micros的DAC模塊既可以與8-位或12位分辨率。后者的精度更高,而前者的性能要比后者更高。
每個通道都有自己的轉換器,并且不依賴于其他轉換器。在STM32F103ZET6中,有兩個帶有兩個獨立轉換器的DAC通道輸出。
與其他微控制器的DAC不同,STM32微控制器的DAC具有兩個附加功能,它們是偽隨機的噪聲和三角波形生成功能。這些功能有助于信號處理和定制信號生成。
為進一步提高精度并進一步控制輸出電壓,DAC模塊可與基準電壓源相連,通常在2.4V之間到3.3V DC。
可以使用左右兩端的合理輸入。
DA轉換可以觸發事件。此功能有很多應用。
就像其他任何硬件一樣,DAC也具有DMA功能。
DAC模塊集成了可用于降低輸出阻抗并直接驅動外部負載的輸出緩沖器,而無需添加外部運算放大器。緩沖可確保原始信號不會因負載效應而衰減或失真。
可能具有獨立或雙重操作模式。
功能描述
STM32 micros的DAC可以通過多種方式進行操作。如前所述,我們可以在獨立和雙重模式下使用它。除此之外,我們還可以通過外部事件觸發這些DAC。如果不使用觸發選項,則在一個時鐘周期后更新DAC輸出。如果使用任何觸發選項,則在3 – 4個時鐘周期后更新輸出。 DAC模塊的輸出可以獨立或同時更新。 DAC的最大分辨率為12位。 DAC輸出的電壓公式如下:
其中n是位數。
除非使用觸發功能,否則操作DAC非常簡單。我們將必須打開所需的輸出通道并僅寫入數字數據值。但是,如果相反,則會出現很多可能性。 STM32F10x參考手冊在雙模式操作部分中陳述了所有這些可能性。盡管我不會詳細介紹所有這些操作,但是這些操作很簡單。
輸出可以在內部進行緩沖,從而無需外部運算放大器緩沖器,從而減少了外部組件數量和成本。成本。我強烈建議使用內部緩沖器,以確保并保持精度,同時避免輸出負載問題。
STM32 DAC模塊隨附的另外兩個玩具是白噪聲和三角形波形發生器。首先,這些功能可能會讓您感到驚訝,甚至可能使您覺得它們是不必要的。但是,當我們需要為各種應用(包括音樂,音調等)生成任意波形或在信號中注入噪聲以進行調試時,這些東西會派上用場。從字面上看,我們可以模擬現實生活中嘈雜的電子電路環境。三角波形發生器可用于將可變幅度三角波形分量添加到給定信號。此處有更多詳細信息:http://www.st.com/web/en/resource/technical/document/application_note/CD00259245.pdf。
在STM32F103ZET6中,DAC輸出1和2引腳位于GPIOA PA4 和 PA5 。盡管這些引腳在與DAC模塊一起使用時用作輸出,但ST建議將它們設置為模擬輸入,以避免寄生消耗–這是要考慮的重要點。
在STM32 micros中,我們只需要處理三個寄存器-一個用于配置,一個用于選擇軟件觸發,另一個用于設置DAC輸出。 。我們沒有其他寄存器要處理。
DAC控制寄存器(DAC_CR) 是我們唯一需要的寄存器配置DAC。配置該寄存器使我們能夠啟用/禁用DAC通道,設置輸出類型,啟用DMA支持以及執行其他操作。 STM32 micro的兩個DAC都單獨使用此寄存器進行配置。
下一組寄存器是數據寄存器。在這些地方,我們將編寫數字數據,這些數據最終將轉換為縮放的模擬輸出。 DAC數據寄存器可以接受三種整數格式的數據-8位,12位右對齊和12位左對齊。這些都有專用的寄存器。檢出 DAC數據保存寄存器(DAC_DHRx) 。對于雙模式DAC檢出 DAC_DHRD 寄存器。然后,將 DAC_DHRx 寄存器中的數據加載一個或幾個周期后,取決于是否使用任何觸發器,將其加載到 DAC_DORx 寄存器中或不。 DAC_DORx 寄存器不能直接寫入。
最后有一個寄存器稱為 DAC軟件觸發寄存器(DAC_SWTRIGR) ,用于設置軟件觸發。
就像以前一樣,我們不再需要我已經將我的SPL版本與代碼示例集成在一起,因此可以處理寄存器。我仍然建議讀者對它們有所了解。
硬件連接
下圖概述了我們將在代碼示例中使用的GPIO引腳。
代碼示例
請注意,在STM32 micro的其他內部模塊上,我們需要先啟用DAC模塊的外設時鐘,然后通過設置正確的寄存器來配置所需的操作,最后啟用所需的硬件。這是我們應始終保持的順序。在設置DAC本身之前,應按照建議啟用和配置所需的GPIO端口引腳。檢查一下我在所有示例中使用的時鐘配置。
DAC Basic Demo
這是STM32 DAC的最原始演示。不使用觸發。 DAC引腳輸出參考偏移的正弦和余弦波形。由于在我的示例中DAC的參考源與電源(VDD)的參考源相同-3.3V,因此輸出移位1.65V,以覆蓋整個正弦變化。 MikroC的C Math庫用于三角函數。與DAC輸出引腳相連的LED逐漸淡入并發光,表明它們兩端的電壓變化平穩。
#include “DAC.h” #include “GPIO.h” #define radian_per_degree 0.0174532925 void setup(); void GPIO_setup(); void DAC_setup(); void main() { signed int temp1 = 0; signed int temp2 = 0; unsigned int degree = 0; setup(); while(1) { for(degree = 0; degree 《 360; degree++) { temp1 = (2047 * cos(radian_per_degree * degree)); temp1 = (2048 - temp1); DAC_DHR12R1 = ((unsigned int)temp1); temp2 = (2047 * sin(radian_per_degree * degree)); temp2 = (2048 - temp2); DAC_DHR12R2 = ((unsigned int)temp2); delay_ms(6); } }; } void setup() { GPIO_setup(); DAC_setup(); } void GPIO_setup() { enable_GPIOA(true); pin_configure_low(GPIOA_CRL, 4, analog_input); pin_configure_low(GPIOA_CRL, 5, analog_input); } void DAC_setup() { enable_DAC(true); DAC_reset(); set_DAC1_buffer(enable); set_DAC2_buffer(enable); enable_DAC1_channel(true); enable_DAC2_channel(true); }
視頻鏈接:https://www.youtube.com/watch?v=JW6e-oHBCPQ。
三角波形生成
STM32 DAC模塊的一個很酷的獨特功能就是它能夠生成對稱的三角波形。該波形可以疊加在其他慢速波形或穩定的DC信號上。不需要任何波表或方程來生成三角波。內部計數器負責生成波形。我們可以根據需要設置三角波的幅度或峰值。為了使用三角波形,我們需要在 DAC_CR 寄存器中設置波形類型和觸發選項。三角波的頻率取決于兩個因素:波幅和觸發頻率。在軟件觸發的情況下,我們需要考慮代碼內部的延遲。這些延遲包括延遲函數調用,代碼執行時間和其他因素。到目前為止,我注意到以下公式似乎給出了輸出波形的大致時間段:
2 是由于DAC計數從最小或0開始到最大幅度計數,然后以與上升相同的方式達到最小計數這一事實。因此,根據上面的公式,我們可以推斷出三角形波形的頻率。
例如,讓我們考慮一種情況,其中我們將使用軟件觸發作為這樣每60μs觸發一次,最大DAC計數幅度為2047。在這種情況下,三角波的時間段為
#include “DAC.h” #include “GPIO.h” void setup(); void DAC_setup(); void GPIO_setup(); void main() { bit time; unsigned long peak = Triangle_Amplitude_equal_to_4095; setup(); while(1) { set_DAC1_software_trigger(enable); set_DAC2_software_trigger(enable); if(get_input(GPIOF_IDR, 14) == 0) { while(get_input(GPIOF_IDR, 14) == 0); peak++; if(peak 》 Triangle_Amplitude_equal_to_4095) { peak = Triangle_Amplitude_equal_to_1; } enable_DAC1_channel(false); enable_DAC2_channel(false); set_DAC1_triangle_waveform_amplitude(peak); set_DAC2_triangle_waveform_amplitude(peak); enable_DAC1_channel(true); enable_DAC2_channel(true); } if(get_input(GPIOF_IDR, 13) == 0) { while(get_input(GPIOF_IDR, 13) == 0); time = ~time; } switch(time) { case 1: { delay_us(600); break; } default: { delay_us(60); break; } } }; } void setup() { GPIO_setup(); DAC_setup(); } void DAC_setup() { enable_DAC(true); DAC_reset(); set_DAC1_buffer(enable); enable_DAC1_trigger(true); select_DAC1_trigger_source(Software_trigger); select_DAC1_wave_type(triangle_wave_generation_enabled); set_DAC1_triangle_waveform_amplitude(Triangle_Amplitude_equal_to_4095); enable_DAC1_channel(true); set_DAC2_buffer(enable); enable_DAC2_trigger(true); select_DAC2_trigger_source(Software_trigger); select_DAC2_wave_type(triangle_wave_generation_enabled); set_DAC2_triangle_waveform_amplitude(Triangle_Amplitude_equal_to_4095); enable_DAC2_channel(true); } void GPIO_setup() { enable_GPIOA(true); enable_GPIOF(true); pin_configure_low(GPIOA_CRL, 4, analog_input); pin_configure_low(GPIOA_CRL, 5, analog_input); pin_configure_high(GPIOF_CRH, 13, digital_input); pin_configure_high(GPIOF_CRH, 14, digital_input); pull_up_enable(GPIOF_ODR, 13); pull_up_enable(GPIOF_ODR, 14); }
在本演示中,我們可以使用連接到GPIO PF14引腳的按鈕來改變從兩個DAC輸出通道輸出的三角波的幅度。連接到GPIO PF13引腳的按鈕可用于選擇時間段。
視頻鏈接:https://www.youtube.com/watch?v=eX3zRjr8bQo。
產生白噪聲
白噪聲生成模塊的設置與三角波形發生器的設置類似。除了波形以外,唯一不同的是產生白噪聲的算法。這不在我的解釋范圍內。我們只需要知道我們可以使用該模塊生成可變幅度的偽隨機噪聲。為了更好地理解,請查看https://en.wikipedia.org/wiki/Linear_feedback_shift_register。我們所需要做的就是根據需要屏蔽LFSR。
#include “DAC.h” #include “GPIO.h” void setup(); void DAC_setup(); void GPIO_setup(); void main() { setup(); while(1) { set_DAC2_software_trigger(enable); delay_us(10); }; } void setup() { GPIO_setup(); DAC_setup(); } void DAC_setup() { enable_DAC(true); DAC_reset(); set_DAC2_buffer(enable); enable_DAC2_trigger(enable); select_DAC2_trigger_source(Software_trigger); select_DAC2_wave_type(noise_wave_generation_enabled); set_DAC2_LFSR_mask(0x3FF); enable_DAC2_channel(true); } void GPIO_setup() { enable_GPIOA(true); pin_configure_low(GPIOA_CRL, 5, analog_input); }
視頻鏈接:https://www.youtube.com/watch?v=ylxTQXLa-D4。
8位DAC與12位DAC
此示例旨在顯示分辨率,速度和精度及其影響。 DAC1配置為12位DAC,而DAC2配置為8位DAC。我試圖證明,對于相同的輸出,12位分辨率將更精確,但比不那么精確的8位分辨率要慢。您會注意到,在相同的時間間隔和相同的輸出下,8位輸出會在12位輸出之前飽和。如果您注意到快照,您會發現這兩個輸出都有不同的斜率,這就是精度和速度發揮作用的地方。
#include “DAC.h” #include “GPIO.h” void setup(); void GPIO_setup(); void DAC_setup(); void main() { signed int temp = 0; setup(); while(1) { for(temp = 0; temp 《 4096; temp++) { DAC_DHR12R1 = temp; if((temp 》 0) && (temp 《 256)) { DAC_DHR8R2 = temp; } delay_us(90); } for(temp = 4095; temp 》 -1; temp--) { DAC_DHR12R1 = temp; if((temp 》 0) && (temp 《 256)) { DAC_DHR8R2 = temp; } delay_us(90); } }; } void setup() { GPIO_setup(); DAC_setup(); } void GPIO_setup() { enable_GPIOA(true); pin_configure_low(GPIOA_CRL, 4, analog_input); pin_configure_low(GPIOA_CRL, 5, analog_input); } void DAC_setup() { enable_DAC(true); DAC_reset(); set_DAC1_buffer(enable); set_DAC2_buffer(enable); enable_DAC1_channel(true); enable_DAC2_channel(true); }
視頻鏈接:https://www.youtube.com/watch?v=jBfzgFGs7JM。
雙模DAC
雙模DAC為多種可能性開辟了道路。 STM32F10x參考手冊討論了在雙模式下操作DAC的各種方法。我的感覺使它變得更加簡單。我們只需要分別處理兩個DAC通道。如果兩個DAC具有相同的觸發源,則可以說它們同時或同步更新,否則它們是獨立的。兩個DAC可以輸出相同或不同的波形,具體取決于它們的配置方式。在本示例中,我將一個DAC配置為輸出疊加在可變DC分量上的三角波,而將另一個DAC配置為在由ADC調用時輸出白噪聲信號。 GPIO PA9 引腳上的外部中斷。
#include “DAC.h” #include “GPIO.h” #include “AFIO.h” #include “Ex_Int.h” void setup(); void GPIO_setup(); void AFIO_setup(); void DAC_setup(); void ext_int() iv IVT_INT_EXTI9_5 ics ICS_AUTO { if(read_pending_reg(9) != 0) { pending_clr(9); bit_clr(GPIOA_ODR, 6); delay_ms(200); bit_set(GPIOA_ODR, 6); } } void main() { signed int value = 0; setup(); while(1) { if(get_input(GPIOF_IDR, 13) == 0) { delay_ms(10); value++; } if(get_input(GPIOF_IDR, 14) == 0) { delay_ms(10); value--; } if(value 》 2047) { value = 2047; } if(value 《 0) { value = 0; } set_DAC1_software_trigger(enable); DAC_DHR12RD = (((unsigned int)value) | 0x00FF0000); }; } void setup() { GPIO_setup(); AFIO_setup(); DAC_setup(); } void GPIO_setup() { enable_GPIOA(true); pin_configure_low(GPIOA_CRL, 4, analog_input); pin_configure_low(GPIOA_CRL, 5, analog_input); pin_configure_low(GPIOA_CRL, 6, (output_mode_low_speed | GPIO_PP_output)); enable_GPIOF(true); pin_configure_high(GPIOF_CRH, 13, digital_input); pin_configure_high(GPIOF_CRH, 14, digital_input); pull_up_enable(GPIOF_ODR, 13); pull_up_enable(GPIOF_ODR, 14); } void AFIO_setup() { AFIO_enable(true); pin_configure_high(GPIOA_CRH, 9, digital_input); pull_up_enable(GPIOA_ODR, 9); bit_set(GPIOA_ODR, 6); set_EXTI8_11(9, PA_pin); falling_edge_selector(9); interrupt_mask(9); NVIC_IntEnable(IVT_INT_EXTI9_5); EnableInterrupts(); } void DAC_setup() { enable_DAC(true); DAC_reset(); set_DAC1_buffer(enable); enable_DAC1_trigger(true); select_DAC1_trigger_source(Software_trigger); select_DAC1_wave_type(triangle_wave_generation_enabled); set_DAC1_triangle_waveform_amplitude(Triangle_Amplitude_equal_to_511); enable_DAC1_channel(true); set_DAC2_buffer(enable); enable_DAC2_trigger(true); select_DAC2_trigger_source(EXTI9_event); select_DAC2_wave_type(noise_wave_generation_enabled); set_DAC2_LFSR_mask(0x3AA); enable_DAC2_channel(true); DAC_DHR12RD = 0x00FF0000; }
視頻鏈接:https://www.youtube.com/watch?v = 2rQQXBaYLMk。
MikroC DAC庫示例
考慮到許多基于ARM的微型計算機都內置了DAC模塊,因此Mikroelektronika還將易于使用的DAC庫與MikroC編譯器集成在一起。該庫支持帶DAC模塊的STM32 micro中通常具有的大多數功能,這就是代碼保護程序的原因。以下是配置和使用DAC所需的一些功能。
DACx_Init
DACx_Advanced_Chy_Output
DACx_Chy_Output
DAC1_Dual_Output
DACx_Deinit
函數在其編譯器的手冊和幫助文檔中進行了詳細說明。
在我的示例中,我還使用了MikroC的GPIO庫–用于配置GPIO引腳的另一個有用的庫。在最后一個示例中,我演示了DAC的原始用法。我使用了兩個按鈕來交替增加和減少連接到DAC輸出的兩個LED的亮度。
void setup(); void main() { signed int value = 2047; setup(); while(1) { if(GPIOF_IDRbits.IDR13 == 0) { value++; } if(GPIOF_IDRbits.IDR14 == 0) { value--; } if(value 》= 4095) { value = 4095; } if(value 《= 0) { value = 0; } DAC1_Ch1_Output(value); DAC1_Ch2_Output((4095 - value)); delay_ms(1); }; } void setup() { GPIO_Clk_Enable(&GPIOA_BASE); GPIO_Clk_Enable(&GPIOF_BASE); GPIO_Config(&GPIOA_BASE, (_GPIO_PINMASK_4 | _GPIO_PINMASK_5), _GPIO_CFG_MODE_ANALOG); GPIO_Config(&GPIOF_BASE, (_GPIO_PINMASK_13 | _GPIO_PINMASK_14), (_GPIO_CFG_MODE_INPUT | _GPIO_CFG_PULL_UP)); DAC1_Init(_DAC_DUAL_MODE_ENABLE); }
責任編輯:wv
-
STM32
+關注
關注
2270文章
10915瀏覽量
356758 -
數模轉換器
+關注
關注
14文章
1016瀏覽量
83275
發布評論請先 登錄
相關推薦
評論