那曲檬骨新材料有限公司

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

CKS32F4xx系列ADC多通道DMA電壓采集

jf_pJlTbmA9 ? 來源:中科芯MCU ? 作者:中科芯MCU ? 2023-11-06 16:53 ? 次閱讀

在上一講單通道ADC電壓采集的基礎上,本節主要介紹CKS32F4xx系列產品基于DMA傳輸的ADC多通道電壓采集轉換實現。

DMA傳輸在ADC中的應用

DMA是直接存儲器存取,通常在使用ADC時,需要通過MCU內核不停的讀取數據,如果使用DMA,那么讀取的過程會繞過MCU,減輕MCU內核的處理壓力,這樣有利于資源的充分利用,提高ADC數據的處理效率。由于ADC規則通道組只有一個數據寄存器中,當轉換多個通道時,使用DMA還可以避免丟失已經存儲在ADC_DR寄存器中的數據。在使能DMA模式的情況下,每完成規則通道組中的一個通道轉換后,都會生成一個DMA請求,便可將轉換的數據從ADC_DR寄存器傳輸到用指定的目標內存位置。這樣取代單通道實驗使用中斷服務的讀取方法,可以實現多通道ADC應用中高速高效的采集。

軟件設計要點

跟單通道例程一樣,編寫兩個ADC驅動文件,bsp_adc.h和bsp_adc.c,用來存放ADC所用IO引腳的初始化函數以及ADC和DMA相關配置函數,主要流程為:

(1)初始化配置ADC目標引腳為模擬輸入模式;

(2)使能ADC時鐘和DMA時鐘;

(3)配置DMA從ADC數據寄存器傳輸數據到指定的存儲區;

(4)配置通用ADC為獨立模式;

(5)設置ADC為12位分辨率,啟動掃描,連續轉換,不需要外部觸發;

(6)設置ADC轉換通道順序及采樣時間;

(7)使能DMA請求,DMA在AD轉換完自動傳輸數據到指定的存儲區;

(8)啟動ADC模塊;

(9)軟件使能觸發ADC轉換。

這里需要注意的是,在使用ADC+DMA功能時,如果在啟動ADC轉換之后使能DMA,ADC采樣數據可能會出現異常。因此建議先配置ADC及DMA相關參數,最后啟動ADC轉換。

代碼實現

受篇幅限制,這里只介紹核心的部分代碼,有些變量的設置,頭文件的包含等并沒有涉及到,完整的代碼請參考本課程配套的例程。相關核心代碼實現如下:

(1)ADC宏定義

#defineTEMP_NOFCHANEL3
/*=====================通道1IO======================*/
//PB0ADCIO宏定義,可用杜邦線接3V3或者GND來實驗
#defineTEMP_ADC_GPIO_PORT1GPIOB
#defineTEMP_ADC_GPIO_PIN1GPIO_Pin_0
#defineTEMP_ADC_GPIO_CLK1RCC_AHB1Periph_GPIOB
#defineTEMP_ADC_CHANNEL1ADC_Channel_8
/*=====================通道2IO======================*/
//PB1ADCIO宏定義,可用杜邦線接3V3或者GND來實驗
#defineTEMP_ADC_GPIO_PORT2GPIOB
#defineTEMP_ADC_GPIO_PIN2GPIO_Pin_1
#defineTEMP_ADC_GPIO_CLK2RCC_AHB1Periph_GPIOB
#defineTEMP_ADC_CHANNEL2ADC_Channel_9
/*=====================通道3IO======================*/
//PA6ADCIO宏定義,可用杜邦線接3V3或者GND來實驗
#defineTEMP_ADC_GPIO_PORT3GPIOA
#defineTEMP_ADC_GPIO_PIN3GPIO_Pin_6
#defineTEMP_ADC_GPIO_CLK3RCC_AHB1Periph_GPIOA
#defineTEMP_ADC_CHANNEL3ADC_Channel_6
//ADC序號宏定義
#defineTEMP_ADCADC1
#defineTEMP_ADC_CLKRCC_APB2Periph_ADC1
//ADCDR寄存器宏定義,ADC轉換后的數字值則存放在這里
#defineTEMP_ADC_DR_ADDR((u32)ADC1+0x4c)
//ADCDMA通道宏定義,使用DMA傳輸
#defineTEMP_ADC_DMA_CLKRCC_AHB1Periph_DMA2
#defineTEMP_ADC_DMA_CHANNELDMA_Channel_0
#defineTEMP_ADC_DMA_STREAMDMA2_Stream0

定義多個通道進行多通道ADC實驗,并且定義DMA相關配置。

(2)ADC GPIO初始化

staticvoidTemp_ADC_GPIO_Config(void)
{
GPIO_InitTypeDefGPIO_InitStructure;
/*=====================通道1======================*/
RCC_AHB1PeriphClockCmd(TEMP_ADC_GPIO_CLK1,ENABLE);//使能GPIO時鐘
GPIO_InitStructure.GPIO_Pin=TEMP_ADC_GPIO_PIN1;//配置IO
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;//不上拉不下拉
GPIO_Init(TEMP_ADC_GPIO_PORT1, GPIO_InitStructure);
/*=====================通道2======================*/
RCC_AHB1PeriphClockCmd(TEMP_ADC_GPIO_CLK2,ENABLE);//使能GPIO時鐘
GPIO_InitStructure.GPIO_Pin=TEMP_ADC_GPIO_PIN2;//配置IO
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;//不上拉不下拉
GPIO_Init(TEMP_ADC_GPIO_PORT2, GPIO_InitStructure);
/*=====================通道3=======================*/
RCC_AHB1PeriphClockCmd(TEMP_ADC_GPIO_CLK3,ENABLE);//使能GPIO時鐘
GPIO_InitStructure.GPIO_Pin=TEMP_ADC_GPIO_PIN3;//配置IO
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;//不上拉不下拉
GPIO_Init(TEMP_ADC_GPIO_PORT3, GPIO_InitStructure);
}

使用到GPIO時候都必須開啟對應的GPIO時鐘,GPIO用于AD轉換功能必須配置為模擬輸入模式。

(3)配置ADC工作模式

staticvoidTemp_ADC_Mode_Config(void)
{
DMA_InitTypeDefDMA_InitStructure;
ADC_InitTypeDefADC_InitStructure;
ADC_CommonInitTypeDefADC_CommonInitStructure;
//--------------DMAInit結構體參數初始化-------------
//ADC1使用DMA2,數據流0,通道0,
RCC_AHB1PeriphClockCmd(TEMP_ADC_DMA_CLK,ENABLE);//開啟DMA時鐘
DMA_InitStructure.DMA_PeripheralBaseAddr=TEMP_ADC_DR_ADDR;//外設基址為:ADC數據寄存器地址
DMA_InitStructure.DMA_Memory0BaseAddr=(u32)ADC_ConvertedValue;//AD值存儲地址
DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralToMemory;//數據傳輸方向為外設到存儲器
DMA_InitStructure.DMA_BufferSize=TEMP_NOFCHANEL;//緩沖區大小,指一次傳輸的數據量
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_High;//DMA傳輸通道優先級為高
DMA_InitStructure.DMA_FIFOMode=DMA_FIFOMode_Disable;//禁止DMAFIFO,使用直連模式
DMA_InitStructure.DMA_FIFOThreshold=DMA_FIFOThreshold_HalfFull;//FIFO大小,FIFO禁止時不用配置
DMA_InitStructure.DMA_MemoryBurst=DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst=DMA_PeripheralBurst_Single;
DMA_InitStructure.DMA_Channel=TEMP_ADC_DMA_CHANNEL;//選擇DMA通道,通道存在于流中
DMA_Init(TEMP_ADC_DMA_STREAM, DMA_InitStructure);//初始化DMA流,
DMA_Cmd(TEMP_ADC_DMA_STREAM,ENABLE);//使能DMA流

RCC_APB2PeriphClockCmd(TEMP_ADC_CLK,ENABLE);//開啟ADC時鐘
//-------------ADCCommon結構體參數初始化----------------
ADC_CommonInitStructure.ADC_Mode=ADC_Mode_Independent;//獨立ADC模式
ADC_CommonInitStructure.ADC_Prescaler=ADC_Prescaler_Div4;//時鐘為fpclkx分頻
ADC_CommonInitStructure.ADC_DMAAccessMode=ADC_DMAAccessMode_Disabled;//禁止DMA直接訪問模式
ADC_CommonInitStructure.ADC_TwoSamplingDelay=ADC_TwoSamplingDelay_20Cycles;//采樣時間間隔
ADC_CommonInit( ADC_CommonInitStructure);
//-------------------ADCInit結構體參數初始化--------------------------
ADC_StructInit( ADC_InitStructure);
ADC_InitStructure.ADC_Resolution=ADC_Resolution_12b;//ADC分辨率
ADC_InitStructure.ADC_ScanConvMode=ENABLE;//掃描模式,多通道采集需要
ADC_InitStructure.ADC_ContinuousConvMode=ENABLE;//連續轉換
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=TEMP_NOFCHANEL;//轉換通道3個
ADC_Init(TEMP_ADC, ADC_InitStructure);


//配置ADC通道轉換順序和采樣時間周期
ADC_RegularChannelConfig(TEMP_ADC,TEMP_ADC_CHANNEL1,1,ADC_SampleTime_3Cycles);
ADC_RegularChannelConfig(TEMP_ADC,TEMP_ADC_CHANNEL2,2,ADC_SampleTime_3Cycles);
ADC_RegularChannelConfig(TEMP_ADC,TEMP_ADC_CHANNEL3,3,ADC_SampleTime_3Cycles);

ADC_DMARequestAfterLastTransferCmd(TEMP_ADC,ENABLE);//使能DMA請求
ADC_DMACmd(TEMP_ADC,ENABLE);//使能ADCDMA
ADC_Cmd(TEMP_ADC,ENABLE);//使能ADC
ADC_SoftwareStartConv(TEMP_ADC);//開始ADC轉換,軟件觸發
}

首先,使用DMA_InitTypeDef定義了DMA初始化類型變量,另外使用ADC_InitTypeDef和ADC_CommonInitTypeDef結構體分別定義一個ADC初始化和ADC通用類型變量。

調用RCC_APB2PeriphClockCmd()開啟ADC時鐘以及RCC_AHB1PeriphClockCmd()開啟DMA時鐘。

對DMA進行必要的配置。首先設置外設基地址就是ADC的規則數據寄存器地址;存儲器的地址就是指定的數據存儲區空間,ADC_ConvertedValue是我們定義的一個全局數組名,它是一個無符號16位含有3個元素的整數數組;ADC規則轉換對應只有一個數據寄存器,所以地址不能遞增,而定義的存儲區是專門用來存放不同通道數據的,所以需要自動地址遞增。ADC的規則數據寄存器只有低16位有效,實際存放的數據只有12位而已,所以設置數據大小為半字大小。ADC配置為連續轉換模式,DMA也設置為循環傳輸模式。設置好DMA相關參數后就使能DMA的ADC通道。

接下來使用ADC_CommonInitTypeDef結構體變量ADC_CommonInitStructure來配置ADC為獨立模式、分頻系數4、20個周期的采樣延遲,并調用ADC_CommonInit函數完成ADC通用工作環境配置。

使用ADC_InitTypeDef結構體變量ADC_InitStructure來配置ADC1為12位分辨率、使能掃描模式、啟動連續轉換、使用內部軟件觸發無需外部觸發事件、使用右對齊數據格式、轉換通道為3,并調用ADC_Init函數完成ADC1工作環境配置。

ADC_RegularChannelConfifig函數用來綁定ADC通道轉換順序和采樣時間。分別綁定3個ADC通道引腳并設置相應的轉換順序。

ADC_DMARequestAfterLastTransferCmd函數控制是否使能ADC的DMA請求,如果使能請求,并調用ADC_DMACmd函數使能DMA,則在ADC轉換完成后就請求DMA實現數據傳輸。ADC_Cmd函數控制ADC轉換啟動和停止。

最后使用軟件觸發調用ADC_SoftwareStartConvCmd函數進行使能配置。

(4)Main程序

/**主函數*/
intmain(void)
{
Debug_USART_Config();
Temp_Init();
while(1)
{
ADC_ConvertedValueLocal[0]=(float)ADC_ConvertedValue[0]/4096*(float)3.3;
ADC_ConvertedValueLocal[1]=(float)ADC_ConvertedValue[1]/4096*(float)3.3;
ADC_ConvertedValueLocal[2]=(float)ADC_ConvertedValue[2]/4096*(float)3.3;
printf("rnPB0value=%fVrn",ADC_ConvertedValueLocal[0]);
printf("rnPB1value=%fVrn",ADC_ConvertedValueLocal[1]);
printf("rnPA6value=%fVrn",ADC_ConvertedValueLocal[2]);
Delay(0xffffff);
}
}

主函數先調用Debug_USART_Config函數配置調試串口相關參數,接下來調用Temp_Init函數進行ADC初始化配置并啟動ADC。配置了DMA數據傳輸,它會自動把ADC轉換完成后數據保存到數組ADC_ConvertedValue內,我們只要使用數組就可以了。經過簡單地計算就可以得到每個通道對應的實際電壓。

來源:中科芯MCU

審核編輯:湯梓紅
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 存儲器
    +關注

    關注

    38

    文章

    7528

    瀏覽量

    164337
  • adc
    adc
    +關注

    關注

    99

    文章

    6533

    瀏覽量

    545740
  • dma
    dma
    +關注

    關注

    3

    文章

    566

    瀏覽量

    100949
  • 電壓采集
    +關注

    關注

    2

    文章

    22

    瀏覽量

    14278
收藏 人收藏

    評論

    相關推薦

    MCU微課堂|CKS32F4xx系列產品時鐘配置

    作為MCU運行的基礎,時鐘是單片機各個模塊工作時序的最小時間單位,推動單片機的各指令執行,是MCU選型的一個重要指標。CKS32F4xx系列產品具有眾多的外設,但并非所有的外設均需要系統時鐘的高頻率
    發表于 12-12 10:17 ?881次閱讀

    CKS32F4xx系列ETH通信詳解

    CKS32F4xx系列芯片自帶以太網模塊,該模塊包括帶專用DMA控制器的MAC 802.3(介質訪問控制)控制器
    的頭像 發表于 11-10 11:13 ?1077次閱讀
    <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列</b>ETH通信詳解

    CKS32F4xx系列DSP功能介紹

    CKS32F4xx系列使用高性能的32位內核,支持浮點運算單元(FPU),同時還支持DSP指令以及存儲保護(MPU)用來加強應用的安全性。
    的頭像 發表于 03-04 13:43 ?1628次閱讀
    <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列</b>DSP功能介紹

    CKS32F4xx系列產品串口DMA傳輸

    在上一講,我們講過CKS32F4xx系列的6個串口都支持DMA傳輸。因此本節我們對CKS32F4xx系列
    的頭像 發表于 04-10 11:18 ?1102次閱讀

    CKS32F4xx系列RNG功能設置

    ? MCU 微課堂 CKS32F4xx 系 列RNG功能 隨機數發生器簡介 ? ? CKS32F4xx系列自帶了硬件隨機數發生器(RNG),RNG處理器是一個以連續模擬噪聲為基礎的隨機數發生器,在
    的頭像 發表于 09-08 10:01 ?666次閱讀
    <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列</b>RNG功能設置

    CKS32F4xx系列DAC功能

    CKS32F4xx系列DAC功能
    的頭像 發表于 11-06 16:56 ?906次閱讀
    <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列</b>DAC功能

    CKS32F4xx系列ADC通道電壓采集

    CKS32F4xx系列ADC通道電壓采集
    的頭像 發表于 11-06 16:54 ?1028次閱讀
    <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列</b><b class='flag-5'>ADC</b>單<b class='flag-5'>通道</b><b class='flag-5'>電壓</b><b class='flag-5'>采集</b>

    CKS32F4xx系列低功耗模式STANDBY模式

    CKS32F4xx系列低功耗模式STANDBY模式
    的頭像 發表于 11-06 16:57 ?524次閱讀
    <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列</b>低功耗模式STANDBY模式

    CKS32F4xx系列低功耗模式SLEEP模式

    CKS32F4xx系列低功耗模式SLEEP模式
    的頭像 發表于 11-06 16:59 ?721次閱讀
    <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列</b>低功耗模式SLEEP模式

    CKS32F4xx系列低功耗模式STOP模式

    CKS32F4xx系列低功耗模式STOP模式
    的頭像 發表于 11-06 17:08 ?667次閱讀
    <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列</b>低功耗模式STOP模式

    CKS32F4xx系列產品Timer的基本使用方法-比較輸出

    CKS32F4xx系列產品Timer的基本使用方法-比較輸出
    的頭像 發表于 11-09 17:39 ?913次閱讀
    <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列</b>產品Timer的基本使用方法-比較輸出

    CKS32F4xx系列產品Timer的基本使用方法-定時操作

    CKS32F4xx系列產品Timer的基本使用方法-定時操作
    的頭像 發表于 11-09 17:41 ?675次閱讀
    <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列</b>產品Timer的基本使用方法-定時操作

    MCU微課堂 | CKS32F4xx系列產品SPI通信

    MCU微課堂 | CKS32F4xx系列產品SPI通信
    的頭像 發表于 10-24 17:12 ?762次閱讀
    MCU微課堂 | <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列</b>產品SPI通信

    MCU微課堂 | CKS32F4xx系列產品GPIO口配置

    MCU微課堂 | CKS32F4xx系列產品GPIO口配置
    的頭像 發表于 10-24 15:14 ?851次閱讀
    MCU微課堂 | <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列</b>產品GPIO口配置

    CKS32F4xx系列FSMC功能簡介

    本課講為大家講解CKS32F4xx系列產品的FSMC應用實例,FSMC全稱是Flexible Static Memory Controller,讀作靈活的靜態存儲控制器,顧名思義,MCU可以通過FSMC擴展靜態內存
    的頭像 發表于 04-14 15:06 ?1042次閱讀
    <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列</b>FSMC功能簡介
    赌场百家乐的玩法技巧和规则| 众发国际娱乐| 太阳城团购| 百家乐平注法规则| 百家乐棋牌游戏币| 百家乐怎样下注| 全讯网hg9388.com| 大发888注册 大发888官网| 龙岩棋牌乐| 渑池县| 网上百家乐官网有没有假| 百家乐官网最新投注方法| 百家乐官网赌马| 属虎和属猴牛人做生意| 女神百家乐娱乐城| 全讯网新2| 百家乐888| 百家乐官网软件稳赚| 澳门百家乐官网娱乐场开户注册| 百家乐官网高手心得| 百家乐官网是娱乐场| 百家乐乐翻天| 皇冠现金网网址| 百家乐官网游戏解密| 百家乐官网网站排名| 澳门百家乐官网论坛| 百家乐技巧打| 亲朋棋牌刷金币| 百家乐官网娱乐城有几家| 百家乐官网微笑打| 网上百家乐记牌软件| 棋牌新闻| 大家旺百家乐官网娱乐城| 钱柜百家乐官网的玩法技巧和规则 | 免费百家乐官网倍投软件| 百家乐庄闲概率| 大发888打不开| 百家乐官网如何视频| 任你博百家乐官网娱乐城| 网络百家乐的玩法技巧和规则 | 免水百家乐的玩法技巧和规则|