1、準備材料 開發板(正點原子stm32f407探索者開發板V2.4) STM32CubeMX軟體(Version 6.10.0) 野火DAP模擬器 keil µVision5 IDE(MDK-Arm) ST-LINK/V2驅動 一臺示波器 邏輯分析儀nanoDLA 2、實驗目標 使用STM32Cu ...
1、準備材料
STM32CubeMX軟體(Version 6.10.0)
keil µVision5 IDE(MDK-Arm)
一臺示波器
邏輯分析儀nanoDLA
2、實驗目標
使用STM32CubeMX軟體配置STM32F407開發板的DAC OUT1實現輸出0-3.3V 周期為12.8ms的正弦波形
3、實驗流程
3.0、前提知識
由於STM32F407的兩個DAC輸出通道只能自動生成三角波和雜訊波,因此如果想要輸出其他的波形可以自己手動定義一個周期內DAC要輸出的值,並選擇定時器的更新事件作為DAC輸出的觸發源按順序輸出
這樣按照波形採樣值的順序,在每一個觸發源到來的時候,手動指定DAC將要輸出的值,理論上就可以輸出任何我們想要輸出的波形,比如正弦波,本實驗將以正弦波為例,講解如何通過DAC的DMA輸出正弦波型
當DAC參考電源引腳VREF+接VDDA(3.3V)時,可設置的DAC輸出寄存器值範圍為0~4095,而DAC的輸出範圍為0-3.3V,要輸出的正弦波sin(x)波形幅值範圍為-1~1,因此可以對該波形做一些平移伸縮,將其幅值範圍縮放到DAC設置範圍0~4095內,變換後的正弦波公式為:y=2047*(sin(x)+1)
在該正弦波形的一個周期0-2pi內平均取128個採樣點,然後按照時間先後順序定義在數組中,每當0.1ms觸發源到來的時候,我們就遞歸的從數組中取出一個值將其設置為DAC的輸出值,直到128個採樣點全部設置完畢,然後再反覆從第一個重新設置,這樣就可以大致實現正弦波型
因為需要頻繁的從記憶體取出數據然後寫入DAC外設,因此這裡比較合適的做法是使用DMA的方式進行,通過上述設置的DAC輸出的正弦波形的周期應該為0.1ms*128=12.8ms,正弦波的幅值範圍應該為0-3.3V
3.1、CubeMX相關配置
3.1.0、工程基本配置
打開STM32CubeMX軟體,單擊ACCESS TO MCU SELECTOR選擇開發板MCU(選擇你使用開發板的主控MCU型號),選中MCU型號後單擊頁面右上角Start Project開始工程,具體如下圖所示
開始工程之後在配置主頁面System Core/RCC中配置HSE/LSE晶振,在System Core/SYS中配置Debug模式,具體如下圖所示
詳細工程建立內容讀者可以閱讀“STM32CubeMX教程1 工程建立”
3.1.1、時鐘樹配置
系統時鐘使用8MHz外部高速時鐘HSE,HCLK、PCLK1和PCLK2均設置為STM32F407能達到的最高時鐘頻率,具體如下圖所示
3.1.2、外設參數配置
在Pinout & Configuration頁面左邊功能分類欄目Analog中單擊其中DAC
在Mode中勾選OUT1 Configuration
選擇TIM6的外部觸發事件作為DAC OU1輸出的觸發源,不選擇波形生成模式,因為本實驗要生成自定義波形
具體配置如下圖所示
單擊Configuration中的DMA Settings選項卡對DAC的DMA請求進行設置
單擊ADD按鍵增加DMA請求,這裡可選的只有一個DAC1
選擇想要使用的DMA Stream,並設置優先順序,將DMA請求模式設置為迴圈模式,外設地址不增加,記憶體地址遞增,數據寬度選擇字Word
上述配置如下圖所示
3.1.3、外設中斷配置
在Pinout & Configuration頁面左邊System Core/NVIC中勾選DMA1 Stream5 全局中斷,然後選擇合適的中斷優先順序即可
3.2、生成代碼
3.2.0、配置Project Manager頁面
單擊進入Project Manager頁面,在左邊Project分欄中修改工程名稱、工程目錄和工具鏈,然後在Code Generator中勾選“Gnerate peripheral initialization as a pair of 'c/h' files per peripheral”,最後單擊頁面右上角GENERATE CODE生成工程,具體如下圖所示
詳細Project Manager配置內容讀者可以閱讀“STM32CubeMX教程1 工程建立”實驗3.4.3小節
3.2.1、外設初始化調用流程
在生成的工程代碼主函數中新增了MX_DMA_Init()函數,該函數對DAC使用的DMA1時鐘使能,由於啟用了該DMA的中斷,因此還對中斷優先順序及使能進行了配置,如下圖所示
DAC的初始化調用流程與“STM32CubeMX教程16 DAC - 輸出3.3V內任意電壓”實驗一致,只是因為本實驗配置了DMA,因此在HAL_DAC_MspInit()函數中增加了對使用的DAC1 DMA請求的相關配置代碼,如下圖所示
3.2.2、外設中斷調用流程
DMA全局中斷事件回調函數為一個函數指針,當使用HAL_DAC_Start_DMA()函數啟動DAC傳輸時,會將DMA全局中斷事件回調函數指針指向具體的函數,這裡指向了DAC_DMAConvCpltCh1()函數
在DAC_DMAConvCpltCh1()函數中最終調用了DAC OU1 DMA傳輸完成中斷回調函數HAL_DAC_ConvCpltCallbackCh1(),該函數為虛函數,需要用戶重新實現
啟用DMA的外設中斷調用流程可參考“STM32CubeMX教程12 DMA 直接記憶體讀取”實驗3.2.2、外設中斷調用流程小節,上述具體過程如下圖所述
3.2.3、添加其他必要代碼
採集正弦波y=2047*(sin(x)+1)的一個周期2pi內n個採樣點,並將其定義在一個uint32_t 數組中,筆者這裡定義了128個採樣點
為什麼非要正弦波函數為y=2047*(sin(x)+1)?
因為DAC的輸出範圍為0~4095,而sin(x)的輸出範圍為-1~1,因此需要採集的正弦波採樣點最好縮放到0-4095範圍,這樣輸出的波形更好顯示
源代碼如下所示 (註釋1)
/*正弦波數據,12bit,1個周期128個點, 0-4095之間變化*/
const uint32_t userWave[] =
{
2047, 2147, 2248, 2347, 2446, 2544, 2641, 2737,
2830, 2922, 3012, 3099, 3184, 3266, 3346, 3422,
3494, 3564, 3629, 3691, 3749, 3803, 3852, 3897,
3938, 3974, 4006, 4033, 4055, 4072, 4084, 4092,
4094, 4092, 4084, 4072, 4055, 4033, 4006, 3974,
3938, 3897, 3852, 3803, 3749, 3691, 3629, 3564,
3494, 3422, 3346, 3266, 3184, 3099, 3012, 2922,
2830, 2737, 2641, 2544, 2446, 2347, 2248, 2147,
2047, 1947, 1846, 1747, 1648, 1550, 1453, 1357,
1264, 1172, 1082, 995 , 910 , 828 , 748 , 672 ,
600 , 530 , 465 , 403 , 345 , 291 , 242 , 197 ,
156 , 120 , 88 , 61 , 39 , 22 , 10 , 2 ,
0 , 2 , 10 , 22 , 39 , 61 , 88 , 120 ,
156 , 197 , 242 , 291 , 345 , 403 , 465, 530 ,
600 , 672 , 748 , 828 , 910 , 995 , 1082, 1172,
1264, 1357, 1453, 1550, 1648, 1747, 1846, 1947
};
在dac.c中重新實現DAC OU1 DMA傳輸完成中斷回調函數HAL_DAC_ConvCpltCallbackCh1(),源代碼如下
/*DAC OUT1 DMA傳輸完成中斷回調函數*/
void HAL_DAC_ConvCpltCallbackCh1(DAC_HandleTypeDef *hdac)
{
/*翻轉RED_LED引腳狀態*/
HAL_GPIO_TogglePin(RED_LED_GPIO_Port,RED_LED_Pin);
}
在main.c文件主函數main中以DMA方式啟動DAC輸出,源代碼如下
HAL_DAC_Start_DMA(&hdac,DAC_CHANNEL_1,userWave,128,DAC_ALIGN_12B_R);
HAL_TIM_Base_Start(&htim6);
4、常用函數
/*以DMA啟動DAC輸出*/
HAL_StatusTypeDef HAL_DAC_Start_DMA(DAC_HandleTypeDef *hdac, uint32_t Channel, const uint32_t *pData, uint32_t Length,uint32_t Alignment)
/*停止以DMA啟動的DAC輸出*/
HAL_StatusTypeDef HAL_DAC_Stop_DMA(DAC_HandleTypeDef *hdac, uint32_t Channel)
/*DAC OUT1 DMA傳輸完成時間中斷回調函數*/
void HAL_DAC_ConvCpltCallbackCh1(DAC_HandleTypeDef *hdac)
5、燒錄驗證
燒錄程式,單片機上電後,將示波器的探頭掛鉤與DAC OUT1引腳PA4相連接,接地環與開發板上的GND引腳連接,將示波器每格電壓幅值調節為1.00V,將每格子採集時間調節為10ms,然後開啟示波器對DAC OU1輸出的波形採集
因為定時器溢出時間為0.1ms,而DMA傳輸的數據為正弦波一個周期內的128個樣本點,因此生成的正弦波周期為128*0.1ms=12.8ms,這與示波器採集到的正弦波波形周期一致,如下圖所示為示波器採集到的正弦波形
在DAC OUT1 DMA傳輸完成時間中斷回調函數中翻轉了RED_LED(PF9)引腳的狀態,經過上述分析知道,傳輸完成一次所需事件應該為輸出正弦波形的周期,也即12.8ms,因此使用邏輯分析儀器採集PF9引腳的狀態,發現PF9引腳確實12.8ms翻轉一次狀態,邏輯分析儀採集的波形如下圖所示
6、註釋詳解
註釋1:正弦波數組定義來源 DAC輸出正弦波帖子
更多內容請瀏覽 STM32CubeMX+STM32F4系列教程文章彙總貼