最近使用 NXP i.MX RT1020 的 ADC 功能,發現官方的 SDK 例程中只有兩個例程,polling 和 interrupt,沒有 DMA 的,所以就動手寫了一個 ADC DMA 傳輸的代碼,在這裡分享一下。
(1)配置思路:
- ADC 初始化,配置 ADC 的基本功能包括 ADC 引腳、 ADC 精度、採樣周期等等
- DMA 的初始化,配置 DMA 通道、源地址、目的地址、傳輸寬度和次數
(2) 首先我們先導出一個 evkmimxrt1020_adc_12b1msps_sar_polling 的例程
這個例程中 ADC 的基本配置已經可以了,我們需要在後面加上一個 ADC DMA 的使能,這樣才能使用 DMA:
(3) DMA 的配置:
配置 DMAMUX 模塊:
相關宏定義:
DMA 有很多通道,那麼每個通道對應的 DMA 請求是什麼呢?這裡 NXP 提供了 DMAMUX 模塊,這個就是可以配置通道對應的 DMA 請求, SDK 中相關枚舉定義如下:
(4)DMA 的初始化如下:
NXP 的 DMA 驅動都是以 handle 的方式來實現的,可以把 handle 理解為一個存儲各種信息的結構體,裡面可以有參數,也可以有函數,一個 handle 就包含了這個通道的所有信息,目的是為了統一管理使用,接下來就逐個介紹相關 API 的功能。
- EDMA CreateHandle
創建一個 handle ,第二參數指定了這是哪個 DMA 通道的 handle;
- EDMA SetCallback
指定該通道傳輸完成之後的中斷函數:該回調函數由用戶自定義,只需要把函數名給到第二個參數即可;
- EDMA ResetChannel
復位該通道相關參數,方便接下來的配置
- EDMA PrepareTransfer
這裡的配置實際上就是 DMA 描述符的配置,描述符裡面的信息比較通用,源地址、目的地址等等,注意這裡只是把相關信息賦值給了 transferConfig,但是並沒有實際寫進 DMA 的寄存器當中;
- EDMA TcdSetTransferConfig
這個函數第一個參數 tcdMemoryPoolptr 的定義如下,可以看到這是定義了一套完整的 TCD 寄存器,方便後續寫寄存器使用;
第 3 個參數 &tcdMemoryPoolptr[0] 則是指定當前傳輸完成一次後,下一次的傳輸描述符,這樣就不需要再次配置,相當於 DMA 會自動重裝載相關信息;
- EDMA TcdEnableInterrupts
使能 DMA 傳輸完成中斷
- EDMA InstalITCD
前面說了描述符參數存儲在結構體當中並未寫進實際寄存器,這個函數就將描述符的內容寫進了對應的寄存器當中,函數內部如下:
- EDMA StartTransfer
最後就是開始 DMA 傳輸,當有 DMA 請求的時候則會自動開始傳輸
(5)在主循環中,軟體觸發 ADC 採集
採集完成後就會有個 DMA 請求,將數據搬到對應的數組,在 DMA 完成中斷里置位標誌位,傳輸完成後則列印數據,ADC DMA 傳輸就可以正常使用了。
參考資料:
評論