今天回答一個朋友的問題吧,ADC如何使用DMA采集多通道模擬電壓。
1寫在前面
這個問題其實之前寫過一些相關文章,原理我之前也有相關描述。如果想要徹底弄明白其原理,建議閱讀《參考手冊》、結合標準外設庫來理解。
現在很多人習慣使用STM32CubeMX來直接生成初始化代碼,如果沒有掌握STM32CubeMX、HAL庫,使用STM32CubeMX生成的代碼,或許就不能滿足你的應用。
同時,STM32CubeMX生成的代碼,想要根據代碼進一步了解其原理,其實很難
ADC轉換一些基礎原理,我這里就不過多描述了,請直接看下面標準外設庫源碼、及后面給的注釋。
下面寫2點:ADC軟件單次觸發轉換,和連續轉換。
2ADC,DMA,單次觸發轉換
這里以ADC,使用DMA,通過軟件單次觸發轉換為例。主要需注意幾個相關參數即可。
1.GPIO配置
2.DMA配置
3.ADC配置
4.ADC單次觸發轉換
5.源代碼
/* 靜態變量 ------------------------------------------------------------------*/
static volatile uint16_t sADC_Buf[3];
/************************************************
函數名稱 : ADC_GPIO_Configuration
功 能 : ADC引腳配置
參 數 : 無
返 回 值 : 無
作 者 : strongerHuang
*************************************************/
void ADC_GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* 使能時鐘 */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模擬輸入
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
/************************************************
函數名稱 : ADC_DMA_Configuration
功 能 : ADC DMA配置
參 數 : 無
返 回 值 : 無
作 者 : strongerHuang
*************************************************/
void ADC_DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
/* 使能時鐘 */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
/* 配置DMA */
DMA_InitStructure.DMA_Channel = DMA_Channel_0;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&(ADC1->DR));//外設地址
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)(&sADC_Buf[0]); //內存地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; //傳輸方向:外設 -> 內存
DMA_InitStructure.DMA_BufferSize = 3; //傳輸長度
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_Normal; //正常模式
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //優先級
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream0, &DMA_InitStructure);
}
/************************************************
函數名稱 : ADC_Configuration
功 能 : ADC參數配置
參 數 : 無
返 回 值 : 無
作 者 : strongerHuang
*************************************************/
void ADC_Configuration(void)
{
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
/* 使能時鐘 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
/* ADC配置 */
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
ADC_CommonInit(&ADC_CommonInitStructure);
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = ENABLE; //瀏覽模式(多通道)
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //連續轉化模式
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //數據右對齊
ADC_InitStructure.ADC_NbrOfConversion = 3; //轉換通道數
ADC_Init(ADC1, &ADC_InitStructure);
/* 通道配置 */
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_3Cycles);
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 2, ADC_SampleTime_3Cycles);
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 3, ADC_SampleTime_3Cycles);
ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
ADC_DMACmd(ADC1, ENABLE); //使能ADC的DMA功能
ADC_Cmd(ADC1, ENABLE); //使能ADC
}
/************************************************
函數名稱 : ADC_Initializes
功 能 : ADC初始化
參 數 : 無
返 回 值 : 無
作 者 : strongerHuang
*************************************************/
void ADC_Initializes(void)
{
ADC_GPIO_Configuration();
ADC_DMA_Configuration();
ADC_Configuration();
}
/************************************************
函數名稱 : ADC_Get
功 能 : 轉換
參 數 : 無
返 回 值 : 無
作 者 : strongerHuang
*************************************************/
void ADC_Get(void)
{
DMA_Cmd(DMA2_Stream0, DISABLE); //關閉DMA
//內存地址
DMA_MemoryTargetConfig(DMA2_Stream0, (uint32_t)sADC_Buf, DMA_Memory_0);
DMA_ClearFlag(DMA2_Stream0, DMA_FLAG_TCIF0); //清除標志位
DMA_Cmd(DMA2_Stream0, ENABLE); //使能DMA
ADC_SoftwareStartConv(ADC1); //啟動轉換
while(RESET == DMA_GetFlagStatus(DMA2_Stream0, DMA_FLAG_TCIF0)); //等待轉換完成
//得到3條通道轉換結果:sADC_Buf
//進行相關換算,處理...
}
提示:以上源代碼只為方便學習和理解,請結合實際應用修改、或增減代碼。
3ADC,DMA,連續轉換
我這里寫的連續,是ADC連續轉換,同時,DMA循環存儲。大部分配置和上面差不多,這種方式也用的比較多,寫給大家。
1.DMA配置
2.ADC配置
3.源代碼
/* 靜態變量 ------------------------------------------------------------------*/
static volatile uint16_t sADC_Buf[3];
/************************************************
函數名稱 : ADC_GPIO_Configuration
功 能 : ADC引腳配置
參 數 : 無
返 回 值 : 無
作 者 : strongerHuang
*************************************************/
void ADC_GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* 使能時鐘 */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模擬輸入
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
/************************************************
函數名稱 : ADC_DMA_Configuration
功 能 : ADC DMA配置
參 數 : 無
返 回 值 : 無
作 者 : strongerHuang
*************************************************/
void ADC_DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
/* 使能時鐘 */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
/* 配置DMA */
DMA_InitStructure.DMA_Channel = DMA_Channel_0;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&(ADC1->DR));//外設地址
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)(&sADC_Buf[0]); //內存地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; //傳輸方向:外設 -> 內存
DMA_InitStructure.DMA_BufferSize = 3; //傳輸長度
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_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream0, &DMA_InitStructure);
}
/************************************************
函數名稱 : ADC_Configuration
功 能 : ADC參數配置
參 數 : 無
返 回 值 : 無
作 者 : strongerHuang
*************************************************/
void ADC_Configuration(void)
{
ADC_InitTypeDef ADC_InitStructure;
上一篇:STM32中斷,及FreeRTOS中斷優先級配置
下一篇:你ADC采集的數據都準確嗎?
推薦閱讀
史海拾趣
AAEON公司是一家總部位于臺灣的全球性電子公司,專注于提供嵌入式計算解決方案和人工智能應用平臺。以下是關于該公司發展的五個相關故事:
公司成立和初期發展: AAEON公司成立于1992年,最初主要從事電腦主板的設計和生產。公司在成立初期致力于提供高質量、高性能的計算解決方案,迅速在臺灣本地市場建立了良好的聲譽。
技術創新和產品多樣化: 隨著技術的發展和市場需求的變化,AAEON開始進行技術創新,并逐步擴展產品線。公司不僅持續改進和推出新型的嵌入式計算產品,還積極涉足人工智能領域,開發智能邊緣計算平臺和解決方案。
國際市場拓展: 為了進一步擴大業務規模,AAEON積極拓展國際市場。公司與全球各地的合作伙伴建立了廣泛的合作關系,產品銷售網絡覆蓋了亞洲、歐洲、北美和其他地區。公司還在一些國家設立了分支機構和辦事處,加強了對當地市場的開拓和服務。
合作伙伴關系和生態系統建設: AAEON與眾多的合作伙伴建立了緊密的合作關系,共同推動產品的創新和市場拓展。公司與主流的芯片廠商、系統集成商、軟件開發商等建立了長期穩定的合作關系,共同打造了完善的生態系統。
未來展望和發展方向: AAEON將繼續致力于技術創新和產品升級,加強在嵌入式計算和人工智能領域的領先地位。公司將不斷推出符合市場需求的新產品和解決方案,為客戶提供更優質的服務和支持。同時,AAEON將繼續加強與合作伙伴之間的合作,共同推動行業的發展和進步。
質量是企業生存和發展的根本。福聲科技自成立之初就高度重視產品質量管理,通過引入ISO9001質量管理體系,建立了完善的質量管理體系。公司從原材料采購、生產過程控制到成品檢驗,每一個環節都嚴格按照標準執行,確保產品質量的穩定性和可靠性。這一舉措不僅贏得了客戶的信賴和好評,也為公司贏得了更多的市場份額。
隨著產品質量的不斷提升和市場份額的逐步擴大,ACCUTEK公司開始將目光投向國際市場。公司積極參加國際電子展會和技術交流活動,與全球多家知名企業建立了合作關系。同時,公司還在海外設立了多個分支機構,以便更好地服務當地客戶。這些舉措不僅提升了公司的國際影響力,也為公司的長遠發展注入了新的活力。
面對全球對環保和可持續發展的關注,一家新興顯示技術公司致力于研發綠色環保的顯示技術。他們通過優化生產工藝、采用環保材料等方式,成功降低了顯示屏生產過程中的能耗和廢棄物排放。同時,他們還研發出了可回收、可降解的顯示屏材料,為電子行業的可持續發展做出了積極貢獻。
DSMI Electronics SA公司始于20世紀90年代末,由一群志同道合的電子工程師和科研人員創立。在創業初期,公司就明確了自己的技術定位:專注于電子元件和模塊的研發與生產,特別是針對嵌入式系統和工業自動化領域。他們憑借深厚的技術積累和不懈的努力,成功開發出了一系列性能穩定、質量可靠的電子元件,贏得了市場的初步認可。
在全球經濟一體化的大背景下,Hitachi Metals積極應對各種挑戰,通過戰略并購不斷壯大自身實力。近年來,公司先后并購了多家在電子材料、自動化零件等領域具有領先地位的企業,如Waupaca公司、SH cooper銅業等。這些并購不僅拓寬了日立金屬的產品線,還增強了其在全球市場的競爭力。通過整合并購企業的資源和優勢,Hitachi Metals在電子行業的地位進一步鞏固和提升。
// extern void DelayMs(unsigned int);// extern void Read24c02(unsigned char *RamAddress,unsigned char RomAddress,unsigned char bytes);// extern void Write24c02(unsigned char *RamAddress,unsigned char RomAddress,unsigned char bytes ...… 查看全部問答∨ |
|
wince上電自啟動,如何不出現桌面,直接出現我的程序界面? 我現在用注冊表的方式,讓我的程序(窗口程序)在gwes,explore之后啟動。這樣會先出現桌面2,3秒再出現我的程序。 如果希望不出現桌面,要怎么做。… 查看全部問答∨ |
|
MDK 3.80 STM32F107 調試時,外設沒有CAN部分,我在網上聽說別人的有,我估計是不是安裝了什么插件。請教!上圖求真相! 下載 (31.08 KB) 2009-12-22 17:33 … 查看全部問答∨ |
|
各位大俠,幫小弟看看這個問題: 我想用430做數據采集,雙通道數據采集,每個通道采集64個點之后,通過IO口來發送,現在是ADC這塊都有問題。采樣頻率為20KHz以上,使用TIMERA.OUT1為觸發源。 問題是:我單步運行運行到ADCTL0 |= ADC12SC;這條語句 ...… 查看全部問答∨ |
|
在百度百科中看到 電壓跟隨器的其中一個好處是,提高了輸入阻抗,這樣,輸入電容的容量可以大幅度減小,為應用高品質的電容提供了前提保證。 為什么可以說:輸入電容的容量可以大幅度減小? 小弟初入模擬電子的世界,還請各位幫忙解釋一下,非 ...… 查看全部問答∨ |