這一期,我們接着上一期的內容,來看看ADC實驗與DMA實驗在實際的應用中的結合使用。就比如我們可以使用在自制遙控器的搖桿值的獲取和傳輸上。

下面舉例一個兩個搖桿的遙控器的搖桿獲取的代碼的ADC配置部分。

ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;        //獨立模式
ADC_InitStructure.ADC_ScanConvMode = ENABLE;              //使能掃描模式
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;        //使能連續模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;    //軟件觸發
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;    //右對齊
ADC_InitStructure.ADC_NbrOfChannel = 6;                   //6個ADC轉換在規則序列中
ADC_Init(ADC1, &ADC_InitStructure);

ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_56Cycles);    //PC0
ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_56Cycles);    //PC1
ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 3, ADC_SampleTime_56Cycles);    //PC2
ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 4, ADC_SampleTime_56Cycles);    //PC3
ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 5, ADC_SampleTime_56Cycles);    //PC4
ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 6, ADC_SampleTime_56Cycles);    //PC5

ADC_DMACmd(ADC1, ENABLE);                //使能ADC模塊的DMA傳輸功能
ADC_DMALastTransferCmd(ADC1, ENABLE);    //使能ADC的DMA方式並在最後一次傳輸結束後終止傳輸請求
ADC_Cmd(ADC1, ENABLE);                   //使能ADC1

我們在遙控的搖桿獲取中需要使用到ADC1的6個通道,每3個負責一個搖桿值的獲取。上面的配置大部分在上一期的ADC實驗中都是講過的,這裏還有一些要講解和強調的點以及幾個新的函數要給大家介紹一下。

首先是這個掃描模式,掃描模式就是循環掃描我們使能的通道,按我們設置的順序進行循環轉換。因為我們在這裏使用了6個通道來獲取我們遙控的搖桿值,這6個通道是需要不斷循環進行轉換的,所以我們需要開啓掃描模式使一個通道轉換完成後自動開啓下一個通道的轉換。

其次是這個連續轉換模式,這個大家應該都很清楚,但是還是要強調一下。連續轉換模式就是和單次轉換模式相對的,連續轉換模式是該通道完成一次轉換後接着進行下一次轉換。因為我們的遙控是需要一直獲取我們的搖桿值的,所以我們要使能這個連續轉換模式。

還有就是兩個新函數,先將ADC_DMACmd()函數。該函數用於配置 ADC 模塊的 DMA 傳輸功能,可以將 ADC 採樣結果自動傳輸到指定的內存區域,減少 CPU 的負擔,提高系統效率。在這裏就體現到 ADC 和 DMA 的聯繫了,通過使用這個函數使能 ADC 模塊的 DMA 功能,就可以在獲取採樣值之後自動傳輸到指定的內存區域,在這期間不需要 CPU 的參與。

還有一個新的函數是ADC_DMALastTransferCmd(),這個函數是在使用 ADC 的 DMA 模式下控制 DMA 傳輸終止的函數。當我們使用 ADC 模塊採集數據,並通過 DMA 方式將採集到的數據存儲到內存中時,可以通過這個函數使 DMA 在最後一次數據傳輸完畢後自動停止傳輸請求,以減少資源佔用。當啓用 DMA 傳輸模式時,每當 ADC 轉換完成後即會通過 DMA 請求傳輸數據。ADC_DMALastTransferCmd 函數默認情況下是禁止的,因此,在最後一次數據轉換完成後,DMA 仍然會繼續完成一次數據傳輸請求。而如果啓用了 ADC_DMALastTransferCmd 函數,當最後一次轉換完成後,DMA 僅會傳輸最後一次的轉換結果,並切換到空閒狀態,使得 DMA 完成傳輸請求,同時不會接收新的 DMA 傳輸請求,從而實現 DMA 在最後一次傳輸後自動停止傳輸請求的功能。這個函數在使用 STM32F1 的 ADC 和 DMA 進行數據採集時非常有用,可以避免多餘的 DMA 傳輸請求和佔用過多的系統資源,提高了系統的穩定性和效率。

介紹完ADC部分,下面我們來看看DMA部分的配置吧。DMA的部分與前面上一期DMA傳輸實驗的相比沒有新的東西,只有一些配置要根據需要進行相應的使用需求做一些改變罷了。

DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(ADC1->DR);    //外設地址為ADC_DR
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC_Value;   //內存地址為創建的數組ADC_Value
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;                   //傳輸方向為外設到存儲器
DMA_InitStructure.DMA_BufferSize = 6;                                //與通道數一樣
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;     //外設地址不變
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;              //內存地址遞增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //外設數據為半字
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;  //內存數據大小也為半字
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;                      //循環傳輸模式
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;                //優先級為中等
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                         //不使能內存到內存方向
DMA_Init(DMA_CHx, &DMA_InitStructure);

上面的配置就是遙控的搖桿值獲取的ADC和DMA傳輸的設置了,通過這樣的設置之後就可以實現獲取遙控的搖桿值數據後直接進行DMA傳輸到我們劃分出來的內存區域中,且CPU不參與數據的處理。我們剩下要做的就是對內存區域中的搖桿值數據進行處理,比如數據的轉化、計算、2.4G無線通信或藍牙通信等傳輸到其他設備的處理。

本期的內容到這裏就結束了!同時,從下一期開始我們將進入一個非常重要的專題學習了。有的小夥伴應該猜到這個專題是什麼了。