0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

ADC的工作原理 ADC數(shù)據(jù)采集時(shí)的DMA技術(shù)詳解

冬至子 ? 來(lái)源:舊巷聞書(shū) ? 作者:駱駝聽(tīng)海 ? 2023-07-27 17:05 ? 次閱讀

在實(shí)際的開(kāi)發(fā)中需要使用各式各樣的傳感器,這些傳感器可以采集周?chē)沫h(huán)境信息,比如溫度、濕度、氣壓、光照等,這些信息本質(zhì)上是物理的模擬信號(hào),計(jì)算機(jī)處理信息時(shí)對(duì)數(shù)字信號(hào)比較敏感,因此把模擬信號(hào)轉(zhuǎn)換為數(shù)字信號(hào)是有必要的。ADC就起到了這樣的作用,本節(jié)將對(duì)ADC功能原理以及ADC數(shù)據(jù)采集時(shí)涉及到的DMA技術(shù)進(jìn)行詳解。

  • ADC的概念:Analog-to-Digital Converter的縮寫(xiě)。指模/數(shù)轉(zhuǎn)換器或者模擬/數(shù)字轉(zhuǎn)換器。是指將連續(xù)變量的模擬信號(hào)轉(zhuǎn)換為離散的數(shù)字信號(hào)的器件。
  • ADC的作用:采集傳感器的數(shù)據(jù),測(cè)量輸入電壓,檢查電池電量剩余,監(jiān)測(cè)溫濕度等。典型的模擬數(shù)字轉(zhuǎn)換器將模擬信號(hào)轉(zhuǎn)換為表示一定比例電壓值的數(shù)字信號(hào)。

圖片

  • ADC的性能指標(biāo):

量程:能測(cè)量的電壓范圍,一般來(lái)收量程越大越好

分辨率:ADC的分辨率通常以輸出二進(jìn)制數(shù)的位數(shù)表示,位數(shù)越多,分辨率越高,精度越大,外部微小的變化都可以被顯示。一般來(lái)說(shuō)分辨率越高,轉(zhuǎn)化時(shí)間越長(zhǎng)。

轉(zhuǎn)化時(shí)間:模擬輸入電壓在允許的最大變化范圍內(nèi),從轉(zhuǎn)換開(kāi)始到獲得穩(wěn)定的數(shù)字量輸出所需要的時(shí)間稱(chēng)為轉(zhuǎn)換時(shí)間,希望時(shí)間越短越好。

STM32F40X有3個(gè)ADC,每個(gè)可配置 12 位、10 位、8 位或 6 位分辨率

每個(gè)ADC 有16個(gè)外部通道。另外還有兩個(gè)內(nèi)部 ADC源(直接測(cè)量?jī)?nèi)部溫度和電壓信號(hào)) 和 V BAT 通道(測(cè)量電池的剩余電量)掛在 ADC1上

這些通道的 A/D 轉(zhuǎn)換可以單次、連續(xù)、掃描或間斷模式執(zhí)行。

ADC具有獨(dú)立模式(單個(gè)ADC工作)、雙重模式(兩個(gè)ADC配合工作完成采樣)和三重模式(三個(gè)ADC配合工作完成采樣),對(duì)于不同 AD轉(zhuǎn)換要求幾乎都有合適的模式可選

ADC 的結(jié)果可以左對(duì)齊或右對(duì)齊方式存儲(chǔ)在 16 位數(shù)據(jù)寄存器中。采集到的數(shù)據(jù)精度最大為12位,不夠16位,因此,需要選擇合適的存儲(chǔ)方式。

  • ADC功能框圖分析:

圖片

1、電壓輸入范圍:ADC 輸入范圍為:V REF- ≤ V IN ≤ V REF+ 。由 V REF- 、V REF+ 、V DDA 、V SSA 、這四個(gè)外部引腳決定。我們?cè)谠O(shè)計(jì)原理圖的時(shí)候一般把 V SSA 和 V REF- 接地,把 V REF+ 和 V DDA 接 3.3V,得到ADC 的輸入電壓范圍為:03.3V。如果我們想讓輸入的電壓范圍變寬,去到可以測(cè)試負(fù)電壓或者更高的正電壓,我們可以在外部加一個(gè)電壓調(diào)理電路(線性的轉(zhuǎn)換關(guān)系,如根據(jù)一定的轉(zhuǎn)換關(guān)系將-10V10V轉(zhuǎn)換為03.3V),把需要轉(zhuǎn)換的電壓抬升或者降壓到 03.3V,這樣 ADC 就可以測(cè)量了

2、輸入通道:每個(gè)ADC 有16個(gè)外部通道。特別是ADC1還有兩個(gè)內(nèi)部 ADC 源 和 V BAT 通道掛在 ADC1上,V BAT 通道也屬于內(nèi)部通道,兩個(gè)內(nèi)部 ADC 源沒(méi)有對(duì)應(yīng)外部管腳,直接測(cè)量?jī)?nèi)部信息。一個(gè)連接內(nèi)部溫度傳感器,主要測(cè)量CPU以及芯片內(nèi)部的一些關(guān)鍵電路的溫度。另一個(gè)連接VREFINT,測(cè)量電源模塊的電壓值,V BAT 通道用來(lái)測(cè)量備用電池的電池容量。

圖片

3、轉(zhuǎn)換順序

a.規(guī)則通道組:顧名思意,規(guī)則通道就是很規(guī)矩的意思,我們平時(shí)一般使用的就是這個(gè)通道。相當(dāng)于正常運(yùn)行的程序,最多16個(gè)通道,在使用過(guò)程中按順序進(jìn)行轉(zhuǎn)換,按順序采集完一個(gè)通道進(jìn)行轉(zhuǎn)換后再采集下一個(gè)通道進(jìn)行轉(zhuǎn)換。規(guī)則通道和它的轉(zhuǎn)換順序在ADC_SQRx寄存器中選擇,規(guī)則組轉(zhuǎn)換的總數(shù)應(yīng)寫(xiě)入ADC_SQR1寄存器的L[3:0]中。

圖片

圖片

圖片

ADC像這樣的規(guī)則序列寄存器有3個(gè),每個(gè)規(guī)則序列寄存器都能設(shè)定第n次轉(zhuǎn)換的具體通道,共有16個(gè)外部通道,最多設(shè)置16次。如上圖,規(guī)則序列寄存器3(ADC_SQR3)可以設(shè)定第一次到第六次順序轉(zhuǎn)換的通道,規(guī)則序列寄存器2(ADC_SQR2)可以設(shè)定第七次到第十二次順序轉(zhuǎn)換的通道,規(guī)則序列寄存器1(ADC_SQR1)可以設(shè)定第十三次到第十六次順序轉(zhuǎn)換的通道,且ADC_SQR1寄存器的L[3:0]中(20位到23位)用來(lái)設(shè)定要順序轉(zhuǎn)換的通道個(gè)數(shù)。例:有如下轉(zhuǎn)換順序要求,有4個(gè)通道,第一次轉(zhuǎn)換通道2,第二次轉(zhuǎn)換通道3,第三次轉(zhuǎn)換通道4,第四次轉(zhuǎn)換通道1,則ADC_SQR1寄存器的L[3:0]的值位0100,ADC_SQR3中SQ1的值設(shè)為2,SQ2的值設(shè)為3,SQ3的值設(shè)為4,SQ4的值設(shè)為1。具體的操作在Cube MX中可以配置

b.注入通道組:注入,可以理解為插入,插隊(duì)的意思,是一種不安分的通道。相當(dāng)于中斷。最多4個(gè)通道。把某一通道配置位注入通道時(shí),它的優(yōu)先級(jí)就比規(guī)則通道高,暫停規(guī)則通道組的工作,優(yōu)先轉(zhuǎn)換注入通道組采集到的信號(hào)。注入組和它的轉(zhuǎn)換順序在ADC_JSQR寄存器中選擇。注入組里轉(zhuǎn)化的總數(shù)應(yīng)寫(xiě)入ADC_JSQR寄存器的L[1:0]中。該通道組的配置方法于規(guī)則通道組相同。

4、轉(zhuǎn)換時(shí)間:ADC 輸入時(shí)鐘 ADC_CLK 由 PCLK2 經(jīng)過(guò)分頻產(chǎn)生,最大值是 36MHz,即最大工作時(shí)鐘不能超過(guò)36MHz,典型值為30MHz。對(duì)于 STM32F407我們一般設(shè)置PCLK2=HCLK/2=84MHz,最少需要4分頻。所以程序一般使用 4分頻或者 6分頻。

圖片

ADC 的總轉(zhuǎn)換時(shí)間Tconv = 采樣時(shí)間 + 12個(gè)周期(轉(zhuǎn)換時(shí)間),采樣時(shí)間最少不小于3個(gè)ADC_CLK,轉(zhuǎn)換時(shí)間一般就是12個(gè)ADC_CLK,如果對(duì)時(shí)間沒(méi)有太過(guò)苛刻的要求,應(yīng)當(dāng)把采樣時(shí)間設(shè)置的稍長(zhǎng)一些,這樣得到的結(jié)果才會(huì)更加準(zhǔn)確。最小采樣時(shí)間: T =3 + 112= 15個(gè)周期=0.42us(ADC時(shí)鐘=36MHz下得到)。

圖片

5、數(shù)據(jù)寄存器:規(guī)則數(shù)據(jù)寄存器 ADC_DR

ADC_DR只有一個(gè),是一個(gè)32 位的寄存器,只有低 16 位有效并且只是用于獨(dú)立模式存放轉(zhuǎn)換完成數(shù)據(jù)。因?yàn)?ADC 的最大精度是 12 位,ADC_DR 是16 位有效,這樣允許 ADC存放數(shù)據(jù)時(shí)候選擇左對(duì)齊或者右對(duì)齊,具體是以哪一種方式存放,由 ADC_CR2的 11 位 ALIGN 設(shè)置。對(duì)于規(guī)則通道組來(lái)說(shuō),所有的規(guī)則通道都使用這一個(gè)數(shù)據(jù)寄存器,實(shí)際采樣點(diǎn)時(shí)候,如果開(kāi)啟了多個(gè)通道,每轉(zhuǎn)換完成一個(gè)通道要及時(shí)把數(shù)據(jù)從寄存器中取走。如果不及時(shí)取走,下一次轉(zhuǎn)換完成的數(shù)據(jù)就會(huì)覆蓋原數(shù)據(jù)。而對(duì)于注入通道組來(lái)說(shuō),每一個(gè)注入通道都對(duì)應(yīng)一個(gè)數(shù)據(jù)寄存器。

圖片

使用 DMA:由于規(guī)則通道組只有一個(gè)數(shù)據(jù)寄存器,因此,對(duì)于多個(gè)規(guī)則通道的轉(zhuǎn)換,使用 DMA 非常有幫助。這樣可以避免丟失在下一次寫(xiě)入之前還未被讀出的 ADC_DR 寄存器中的數(shù)據(jù)。在使能 DMA 模式的情況下(ADC_CR2 寄存器中的 DMA 位置 1),每完成規(guī)則通道組中的一個(gè)通道轉(zhuǎn)換后,都會(huì)生成一個(gè) DMA 請(qǐng)求。

6、中斷

a.轉(zhuǎn)換結(jié)束中斷:規(guī)則通道和注入通道的數(shù)據(jù)轉(zhuǎn)換結(jié)束后,都可以產(chǎn)生中斷。通道轉(zhuǎn)換完成后,ADC 狀態(tài)寄存器 ADC_SR的EOC位會(huì)置1,可以不斷輪詢此位來(lái)判斷是否觸發(fā)中斷,也可以使能中斷,完成后就根據(jù)此位的狀態(tài)觸發(fā)中斷。此中斷的使用是最多的,可以在此中斷處理程序中獲取我們想要采集的數(shù)據(jù)。

b.模擬看門(mén)狗中斷:當(dāng)被 ADC 轉(zhuǎn)換的模擬電壓低于低閾值或者高于高閾值時(shí),就會(huì)產(chǎn)生中斷

c.溢出中斷:如果發(fā)生 DMA傳輸數(shù)據(jù)丟失,會(huì)置位 ADC 狀態(tài)寄存器 ADC_SR的 OVR位,如果同時(shí)使能了溢出中斷,那在轉(zhuǎn)換結(jié)束后會(huì)產(chǎn)生一個(gè)溢出中斷。

d.DMA 請(qǐng)求:規(guī)則和注入通道轉(zhuǎn)換結(jié)束后,除了產(chǎn)生中斷外,還可以產(chǎn)生 DMA請(qǐng)求,把轉(zhuǎn)換好的數(shù)據(jù)直接存儲(chǔ)在內(nèi)存里面。

圖片

7、觸發(fā)源

a.軟件觸發(fā):ADC轉(zhuǎn)換可以由ADC 控制寄存器 2: ADC_CR2的 ADON這個(gè)位來(lái)控制,寫(xiě) 1的時(shí)候開(kāi)始轉(zhuǎn)換,寫(xiě) 0 的時(shí)候停止轉(zhuǎn)換。此方法使用最多

b.外部事件觸發(fā):觸發(fā)包括內(nèi)部定時(shí)器觸發(fā)和外部 IO觸發(fā)。觸發(fā)源有很多,具體選擇哪一種觸發(fā)源,由 ADC控制寄存器ADC_CR2的 EXTSEL[2:0]和 JEXTSEL[2:0]位來(lái)控制

  • ADC的工作模式

單次轉(zhuǎn)換模式:ADC每次工作只轉(zhuǎn)換一次,至于這一次轉(zhuǎn)換幾個(gè)通道并不關(guān)心,如果想要再次轉(zhuǎn)換,必須重新啟動(dòng)ADC。

連續(xù)轉(zhuǎn)換模式:在連續(xù)轉(zhuǎn)換模式下,ADC結(jié)束一個(gè)轉(zhuǎn)換后立即啟動(dòng)一個(gè)新的轉(zhuǎn)換,直到用戶想要停止為止。(僅適用于規(guī)則通道)。

掃描模式:該模式主要針對(duì)多個(gè)通道進(jìn)行轉(zhuǎn)換。例如使用單次轉(zhuǎn)換模式又開(kāi)啟掃描模式,從第1個(gè)通道開(kāi)始掃描,掃描第n個(gè)通道結(jié)束后不再掃描;如果使用單次轉(zhuǎn)換模式而不開(kāi)啟掃描模式,這多個(gè)通道很有可能只轉(zhuǎn)換第1個(gè)通道;使用連續(xù)轉(zhuǎn)換模式又開(kāi)啟掃描模式,從第1個(gè)通道開(kāi)始掃描,掃描第n個(gè)通道結(jié)束后再?gòu)牡?個(gè)通道開(kāi)始掃描,循環(huán)往復(fù)。

不連續(xù)采樣模式:有多個(gè)通道需要轉(zhuǎn)換,此模式下一次只轉(zhuǎn)換其中的幾個(gè),這個(gè)值n需要用戶自己設(shè)定,假設(shè)有0、1、2、3、6、7、9、10這幾個(gè)通道需要轉(zhuǎn)換,n設(shè)置為3,則

圖片

  • STM32ADC單通道采集實(shí)例

實(shí)驗(yàn):利用ADC采集FSM4中電位器的數(shù)據(jù)

說(shuō)明:電位器本質(zhì)上就是一個(gè)滑動(dòng)變阻器,通過(guò)調(diào)節(jié)電阻就可以輸出不同的電壓值,電壓值通過(guò)PC3進(jìn)入ADC的輸入通道。

圖片

步驟:

1.配置RCC,ADC依賴(lài)于時(shí)鐘APB2

2.配置PC3為ADC1的通道13

圖片

3.配置ADC1

圖片

圖片

4.使能中斷,轉(zhuǎn)換完成觸發(fā)中斷

圖片

5.編寫(xiě)代碼

//main.c 


uint32_t  adc_value  = 0;//全局變量外部才可以使用 
int main(){    
    HAL_Init();    
    SystemClock_Config();    
    MX_GPIO_Init();    
    MX_ADC1_Init();//ADC1初始化配置,仍然采用結(jié)構(gòu)體元素賦值的形式    
    MX_USART1_UART_Init();        
    while(){        
        /***方法一:輪詢采集ADC的值,也就是輪詢判斷EOC是否置位***/        
        //置位說(shuō)明轉(zhuǎn)換完成就可以讀值                

        //啟動(dòng)ADC1,軟件觸發(fā)方式,將對(duì)應(yīng)的啟動(dòng)位置位        
        HAL_ADC_Start(&hadc1);        
        //HAL_ADC_PollForConversion(&hadc1, 100)該函數(shù)內(nèi)部循環(huán)判斷        
        //EOC是否置位,沒(méi)有置位就一直等待,直到超時(shí)        
        if( HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK ){            
            adc_value = HAL_ADC_GetValue(&hadc1);//讀取數(shù)據(jù)寄存器里的值    
            printf("adc_value = %dn",adc_value);                
        }        
        HAL_Delay(1000);//每過(guò)1s鐘重新啟動(dòng)ADC                
        
        
        /***方法二:轉(zhuǎn)換完成后觸發(fā)中斷,在中斷中接收數(shù)值***/        
        HAL_ADC_Start_IT(&hadc1);//啟動(dòng)ADC1并使能中斷        
        HAL_Delay(1000);//每過(guò)1s鐘重新啟動(dòng)ADC              
    } 
}
//adc.c 
//重寫(xiě)轉(zhuǎn)換結(jié)束中斷回調(diào)函數(shù),這里對(duì)應(yīng)方法二 


extern uint32_t  adc_value;//全局變量 
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { 
    if(hadc- >Instance == ADC1) {             
        adc_value = HAL_ADC_GetValue(&hadc1);//讀取數(shù)據(jù)寄存器里的值             
        printf("adc_value = %dn",adc_value); 
    } 
}
  • STM32 ADC多通道采集實(shí)例

實(shí)驗(yàn)要求:利用ADC采集電位器及STM32內(nèi)部溫度傳感器的數(shù)據(jù)。

說(shuō)明:采集內(nèi)部溫度傳感器使用的是內(nèi)部專(zhuān)用通道,選擇通道16或者通道18均可采集內(nèi)部溫度,需要注意的是,實(shí)際中多路通道的采集一般使用DMA來(lái)進(jìn)行數(shù)據(jù)的搬移,因?yàn)橐?guī)則通道的數(shù)據(jù)寄存器只有一個(gè),如果不及時(shí)取走數(shù)據(jù),上一次采集的數(shù)據(jù)可能被覆蓋,DMA的知識(shí)將在后期進(jìn)行講解,因此本節(jié)仍采用輪詢的方式查詢標(biāo)志位,及時(shí)將數(shù)據(jù)取出。

圖片

步驟:

1.配置時(shí)鐘RCC

2.配置PC3位ADC1的通道13,配置內(nèi)部溫度傳感器通道.

圖片

3.配置ADC

圖片

圖片

4.編寫(xiě)代碼

//mian.c 


int main(){    
    uint32_t adc_value = 0;    
    uint8_t i;        

    HAL_Init();    
    SystemClock_Config();    
    MX_GPIO_Init();    
    MX_ADC1_Init();    
    MX_USART1_UART_Init();        

    while(){                
        //啟動(dòng)ADC1,軟件觸發(fā)方式,將對(duì)應(yīng)的啟動(dòng)位置位        
        HAL_ADC_Start(&hadc1);        
        for(i=0;i< 2;i++){    //使用了幾個(gè)通道就應(yīng)該輪詢幾次            
            //首先采集外部通道電位器的數(shù)值,第二次采集內(nèi)部溫度傳感器的值            
            //HAL_ADC_PollForConversion(&hadc1, 100)該函數(shù)內(nèi)部循環(huán)判斷            
            //EOC是否置位,沒(méi)有置位就一直等待,直到超時(shí)            
            if( HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK ){                
                adc_value = HAL_ADC_GetValue(&hadc1);//讀取數(shù)據(jù)寄存器里的值        
                printf("adc_value = %dn",adc_value);                    
            }        
        }        
        HAL_Delay(1000);//每過(guò)1s鐘重新啟動(dòng)ADC              
    }     
}

DMA專(zhuān)門(mén)用于數(shù)據(jù)搬運(yùn),在開(kāi)發(fā)中經(jīng)常會(huì)遇到外設(shè)與內(nèi)存、內(nèi)存與內(nèi)存進(jìn)行大量的數(shù)據(jù)交互的情況,這些情況一般都是由CPU進(jìn)行控制的,如果數(shù)據(jù)交互非常頻繁且數(shù)據(jù)量巨大,那么CPU就會(huì)被大量占用用于數(shù)據(jù)交互而無(wú)法完成其他工作,為了把CPU從這種單一繁瑣的工作中釋放出來(lái),很多微控制器中都有專(zhuān)門(mén)用于數(shù)據(jù)交互的器件,就是DMA。

DMA,全稱(chēng)為:Direct Memory Access,即直接存儲(chǔ)器訪問(wèn)。DMA 傳輸方式無(wú)需 CPU 直接控制傳輸,也沒(méi)有中斷處理方式那樣保留現(xiàn)場(chǎng)和恢復(fù)現(xiàn)場(chǎng)的過(guò)程,通過(guò)硬件為RAM 與 I/O 設(shè)備開(kāi)辟一條直接傳送數(shù)據(jù)的通路,無(wú)需CPU的參與,CPU將這條通路的控制權(quán)釋放,轉(zhuǎn)交由DMA控制器控制,能使 CPU 的效率大為提高。DMA控制器只用于數(shù)據(jù)交互,無(wú)其他功能。

圖片

  • STM32F4-DMA功能框圖分析

圖片

①外設(shè)通道:STM32F4xx 系列資源豐富,具有兩個(gè) DMA 控制器,同時(shí)外設(shè)繁多,為實(shí)現(xiàn)正常傳輸,DMA需要通道選擇控制。每個(gè) DMA控制器具有 8個(gè)數(shù)據(jù)流,每個(gè)數(shù)據(jù)流對(duì)應(yīng) 8個(gè)外設(shè)請(qǐng)求。

外設(shè)通道選擇要解決的主要問(wèn)題是決定哪一個(gè)外設(shè)作為該數(shù)據(jù)流的源地址或者目標(biāo)地址。宏觀上一個(gè)數(shù)據(jù)流的所有通道可以同時(shí)工作,微觀上通道異步前進(jìn)進(jìn)行工作,或者根據(jù)通道優(yōu)先級(jí)進(jìn)行工作

DMA1外設(shè)通道表如下:

圖片

DMA2外設(shè)通道表如下:

圖片

每個(gè)數(shù)據(jù)流都與一個(gè) DMA 請(qǐng)求相關(guān)聯(lián),此 DMA 請(qǐng)求可以從 8 個(gè)可能的通道請(qǐng)求中選出。此選擇由 DMA_SxCR 寄存器中的 CHSEL[2:0] 位控制,3位用來(lái)控制8個(gè)通道的選擇。

②數(shù)據(jù)流仲裁:一個(gè) DMA控制器對(duì)應(yīng) 8個(gè)數(shù)據(jù)流,數(shù)據(jù)流包含要傳輸數(shù)據(jù)的源地址、目標(biāo)地址、數(shù)據(jù)長(zhǎng)度等等信息。如果我們需要同時(shí)使用同一個(gè)DMA 控制器(DMA1 或 DMA2)多個(gè)外設(shè)請(qǐng)求時(shí),那必然需要同時(shí)使用多個(gè)數(shù)據(jù)流,那究竟哪一個(gè)數(shù)據(jù)流具有優(yōu)先傳輸?shù)臋?quán)利呢?這就需要仲裁器來(lái)管理判斷

每個(gè)數(shù)據(jù)流的優(yōu)先級(jí)都可以通過(guò)配置 DMA_SxCR寄存器 PL[1:0]位,設(shè)置為非常高、高、中和低四個(gè)級(jí)別,由于8個(gè)數(shù)據(jù)流只有4個(gè)優(yōu)先級(jí),如果兩個(gè)或以上數(shù)據(jù)流軟件設(shè)置優(yōu)先級(jí)一樣,則他們優(yōu)先級(jí)取決于數(shù)據(jù)流編號(hào),編號(hào)越低越具有優(yōu)先權(quán)。

③數(shù)據(jù)FIFO:每個(gè)數(shù)據(jù)流都有一個(gè)獨(dú)立的 4 字 FIFO(先進(jìn)先出存儲(chǔ)器緩沖區(qū)), DMA傳輸具有 FIFO模式和直接模式。

a.直接模式:每個(gè) DMA 請(qǐng)求會(huì)立即啟動(dòng)對(duì)存儲(chǔ)器的傳輸。當(dāng)在直接模式(禁止 FIFO)下將 DMA請(qǐng)求配置為以存儲(chǔ)器到外設(shè)模式傳輸數(shù)據(jù)時(shí),DMA 僅會(huì)將一個(gè)數(shù)據(jù)從存儲(chǔ)器預(yù)加載到內(nèi)部 FIFO,從而確保一旦外設(shè)觸發(fā) DMA 請(qǐng)求時(shí)則立即傳輸數(shù)據(jù)。

b.FIFO模式:可通過(guò)控制寄存器 DMA_SxFCR 的 FTH[1:0]位來(lái)設(shè)置FIFO 閾值級(jí)別為 FIFO 大小的 1/4、1/2 或 3/4。如果數(shù)據(jù)存儲(chǔ)量達(dá)到閾值級(jí)別時(shí),F(xiàn)IFO 內(nèi)容將傳輸?shù)侥繕?biāo)中。如果對(duì)傳輸速度要求不是很苛刻,建議使用此模式、直接模式傳輸效率太低,一次傳輸?shù)臄?shù)據(jù)量少而工作量大。

④存儲(chǔ)器端口:DMA 控制器提供兩個(gè) AHB 主端口,分別為AHB 存儲(chǔ)器端口(用于連接存儲(chǔ)器)和 AHB 外設(shè)端口(用于連接外設(shè))。存儲(chǔ)器端口用來(lái)連接外部存儲(chǔ)器,實(shí)現(xiàn)內(nèi)存與外存的數(shù)據(jù)交互。

⑤外設(shè)端口:用于連接外設(shè),實(shí)現(xiàn)內(nèi)存與外設(shè)的數(shù)據(jù)交互.

注意:DMA1 控制器 AHB 外設(shè)端口與 DMA2 控制器的情況不同,DMA1 控制器 AHB 外設(shè)端口沒(méi)有連接到總線矩陣,因此,僅 DMA2 數(shù)據(jù)流能夠執(zhí)行存儲(chǔ)器到存儲(chǔ)器的傳輸,DMA1 不能實(shí)現(xiàn)存儲(chǔ)器到存儲(chǔ)器傳輸。

  • STM32F4-DMA傳輸

1.傳輸模式 :DMA1 只有外設(shè)到存儲(chǔ)器和存儲(chǔ)器到外設(shè)兩種模式,DMA2 除前面兩種傳輸模式外還支持存儲(chǔ)器到存儲(chǔ)器的傳輸模式。模式選擇可以通過(guò) DMA_SxCR 寄存器的 DIR[1:0]位(方向選擇,規(guī)定誰(shuí)是源,誰(shuí)是目的)進(jìn)行控制。

圖片

2.DMA傳輸模式的源、目的、長(zhǎng)度:

a.DMA_SxPAR寄存器: 設(shè)置外設(shè)寄存器地址

b.DMA_SxM0AR寄存器:設(shè)置存儲(chǔ)器地址

c.DMA_SxCR 寄存器 :DIR[1:0]位配置數(shù)據(jù)的傳輸方向

d.DMA_CNDTRx 寄存器:寫(xiě)入需要傳輸?shù)臄?shù)據(jù)量, (0 到 65535),注意是數(shù)據(jù)的一個(gè)量,單位并不是字節(jié)

e.DMA_SxCR 寄存器中的 PSIZE 和 MSIZE 位:設(shè)置源和目的的數(shù)據(jù)寬度,兩邊的位寬盡量保持一致,位寬只一次傳輸多大的位寬(如一次傳輸2字節(jié),位寬16位),如果不能保持位寬,很有可能造成數(shù)據(jù)丟失,應(yīng)當(dāng)開(kāi)啟FIFO模式,保證數(shù)據(jù)不丟失。

3.DMA增量設(shè)置:

a.根據(jù)設(shè)置 DMA_SxCR 寄存器中 PINC 和 MINC 位的狀態(tài),外設(shè)和存儲(chǔ)器指針在每次傳輸后可以自動(dòng)向后遞增或保持常量。

b.當(dāng)設(shè)置為增量模式時(shí),下一個(gè)要傳輸?shù)牡刂穼⑹乔耙粋€(gè)地址加上增量值,增量值取決與所選的數(shù)據(jù)寬度為1字節(jié)(8位) 、2 字節(jié)(16位)或 4字節(jié)(32位) 。如果不啟動(dòng),每一次取很有可能只取首地址對(duì)應(yīng)數(shù)據(jù),而不會(huì)向后取值。

c.一般情況下外設(shè)并不需要遞增,每一次都是同一個(gè)地址,要不要配置外設(shè)的增量模式依具體情況而定。

圖片

4.DMA循環(huán)模式:

a.循環(huán)模式用于處理循環(huán)緩沖區(qū)和連續(xù)的數(shù)據(jù)傳輸 ( 如 ADC 的連續(xù)循環(huán)掃描模式 ) 。可以使用 DMA_SxCR 寄存器中的 CIRC 位使能此特性。

b.當(dāng)啟動(dòng)了循環(huán)模式,一組的數(shù)據(jù)傳輸完成時(shí),計(jì)數(shù)寄存器將會(huì)自動(dòng)地被恢復(fù)成配置該通道時(shí)設(shè)置的初值, DMA 操作將會(huì)繼續(xù)進(jìn)行。

5.DMA單次傳輸和突發(fā)傳輸:

a.DMA傳輸類(lèi)型有單次(Single)傳輸和突發(fā)(Burst)傳輸。DMA 控制器可以產(chǎn)生單次傳輸或 4 個(gè)、8 個(gè)和 16 個(gè)節(jié)拍的增量突發(fā)傳輸。一個(gè)節(jié)拍對(duì)應(yīng)著用戶配置的一個(gè)數(shù)據(jù)寬度,一般突發(fā)傳輸要配合FIFO來(lái)使用,突發(fā)傳輸?shù)臄?shù)據(jù)量不可能超過(guò)FIFO的大小

b.突發(fā)大小通過(guò)軟件針對(duì)兩個(gè) AHB 端口獨(dú)立配置,配置時(shí)使用 DMA_SxCR 寄存器中的MBURST[1:0] 和 PBURST[1:0] 位。

c.為確保數(shù)據(jù)一致性,形成突發(fā)的每一組傳輸都不可分割:在突發(fā)傳輸序列期間,AHB 傳輸會(huì)鎖定,并且 AHB 總線矩陣的仲裁器不解除對(duì) DMA 主總線的授權(quán)。

圖片

6.DMA中斷: 對(duì)于每個(gè) DMA 數(shù)據(jù)流,可在達(dá)到半傳輸、傳輸完成、傳輸錯(cuò)誤、FIFO 錯(cuò)誤(上溢、下溢或 FIFO 級(jí)別錯(cuò)誤)、直接模式錯(cuò)誤時(shí)產(chǎn)生中斷。這些標(biāo)志位都在中斷狀態(tài)寄存器DMA_xISR中設(shè)置。

圖片

  • ADC_DMA多路采集實(shí)例

實(shí)驗(yàn)要求:利用ADC采集電位器以及芯片內(nèi)部溫度傳感器的數(shù)據(jù),在main函數(shù)中啟動(dòng)ADC轉(zhuǎn)換以及DMA傳輸,最后在DMA完成中斷中打印采集到的數(shù)據(jù)。

說(shuō)明:之前使用ADC采集兩路數(shù)據(jù)是使用輪詢的方式判斷采集,需要CPU一直去判斷,消耗CPU資源,顯然這并不是ADC多路采集最好的辦法,ADC多路采集一般使用DMA來(lái)進(jìn)行傳輸,規(guī)則通道組采集數(shù)據(jù)時(shí)只有一個(gè)數(shù)據(jù)寄存器ADC_DR,讀取數(shù)據(jù)不及時(shí)很有可能發(fā)生數(shù)據(jù)覆蓋。

采用DMA傳輸,每當(dāng)一路數(shù)據(jù)采集完成后都會(huì)產(chǎn)生一個(gè)DMA請(qǐng)求,及時(shí)把數(shù)據(jù)寄存器中的值搬移到內(nèi)存中相應(yīng)的buffer中去

步驟:

1.配置RCC

2.配置PC3位ADC1的通道13,配置內(nèi)部溫度傳感器通道

圖片

3.配置DMA

圖片

4.配置ADC

圖片

圖片

5.配置中斷

圖片

5.編寫(xiě)代碼

//main.c 


uint16_t adc_value[2] = {0};//定義一個(gè)全局的接受區(qū)域,以便外部調(diào)用   
int mian(){    
    HAL_Init();    
    SystemClock_Config();        
    MX_GPIO_Init();    
    MX_DMA_Init();    
    MX_USART1_UART_Init();    
    MX_ADC1_Init();        
    printf("this is adc dma testn");        
    while(1){        
        //此函數(shù)既啟動(dòng)ADC,又使能DMA        
        HAL_ADC_Start_DMA(&hadc1, (uint32_t*) adc_value, 2);        
        //2表示傳輸了2個(gè)數(shù)據(jù)的量,一個(gè)量是我們?cè)O(shè)定的位寬        
        //內(nèi)部有一個(gè)專(zhuān)門(mén)的寄存器來(lái)記錄這個(gè)量,每傳輸完成一次,寄存器的值減1        
        //減到0就會(huì)觸發(fā)DMA的傳輸完成中斷        
        HAL_Delay(1000); //每過(guò)1s啟動(dòng)一次      
    } 
}

關(guān)于DMA傳輸完成中斷處理函數(shù)是哪一個(gè),先將函數(shù)HAL_ADC_Start_DMA(&hadc1, (uint32_t*) adc_value, 2);追進(jìn)去可以看到一段代碼設(shè)置了DMA傳輸完成的回調(diào)函數(shù),將這個(gè)函數(shù)賦給了一個(gè)指針,這個(gè)指針是DMA_Handle下的一個(gè)指針,DMA可以用于很多的外設(shè),不同的外設(shè)的轉(zhuǎn)換完成函數(shù)是不一樣的,DMA沒(méi)有一個(gè)固定的處理函數(shù),這個(gè)函數(shù)需要在外設(shè)配置的時(shí)候自己去初始化,DMA只提供一個(gè)接口,一個(gè)傳輸轉(zhuǎn)換完成的函數(shù)指針,不同的外設(shè)對(duì)這個(gè)結(jié)構(gòu)賦不同的處理函數(shù)的指針,這里對(duì)ADC來(lái)說(shuō)自己封裝了一個(gè)DMA傳輸完成處理中斷的函數(shù),當(dāng)DMA傳輸完成中斷觸發(fā)的時(shí)候自己去調(diào)用這個(gè)接口下的對(duì)應(yīng)的函數(shù)。ConvCplt的意思是ConverseComplete

圖片

將void DMA2_Stream0_IRQHandler(void)這個(gè)中斷處理函數(shù)入口追進(jìn)去可以看到DMA有各種不同的中斷處理請(qǐng)求,我們?cè)趥鬏斖瓿芍袛啵猅ransfer Complete Interrupt management***這一部分里可以看到hdma->XferCpltCallback(hdma);這樣一個(gè)指針函數(shù),但是用戶無(wú)法使用這個(gè)指針函數(shù),這個(gè)指針在HAL_ADC_Start_DMA(&hadc1, (uint32_t*) 這個(gè)函數(shù)中已經(jīng)賦值,實(shí)際上這個(gè)函數(shù)最終進(jìn)入了HAL_ADC_ConvCpltCallback函數(shù),也就是ADC傳輸完成函數(shù)。

圖片

//adc.c 
extern uint16_t adc_value[2] ; 
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {    
    //每一次采集完成后都會(huì)將數(shù)據(jù)傳輸?shù)剑觯幔欤酰逯?   
    if(hadc- >Instance == ADC1) { 
        printf("adc_value[0]=%d, adc_value[1]=%dn",adc_value[0],adc_value[1]);    
    } 
}
聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • dma
    dma
    +關(guān)注

    關(guān)注

    3

    文章

    561

    瀏覽量

    100583
  • STM32F4
    +關(guān)注

    關(guān)注

    3

    文章

    194

    瀏覽量

    28056
  • 模擬數(shù)字轉(zhuǎn)換器

    關(guān)注

    1

    文章

    74

    瀏覽量

    12485
  • ADC采樣電壓
    +關(guān)注

    關(guān)注

    0

    文章

    4

    瀏覽量

    2814
  • 信號(hào)采集傳感器

    關(guān)注

    0

    文章

    2

    瀏覽量

    1240
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    DMA傳輸打印ADC采集數(shù)據(jù)ADC采集直接打印數(shù)據(jù)不同,為什么?如何排查?

    現(xiàn)在發(fā)現(xiàn)利用DMAADC采集數(shù)據(jù)傳入數(shù)組打印與直接將ADC采集
    發(fā)表于 03-19 07:39

    STM32單ADC,多通道及DMA傳輸?shù)亩嗦?b class='flag-5'>數(shù)據(jù)采集程序介紹

    STM32 單ADC,多通道,DMA傳輸?shù)亩嗦?b class='flag-5'>數(shù)據(jù)采集
    發(fā)表于 06-14 10:11

    利用ADC技術(shù)的MCU系統(tǒng)數(shù)據(jù)采集

    數(shù)據(jù)采集系統(tǒng)的捕獲階段。捕獲復(fù)雜的混合信號(hào)MCU必須能夠從模擬世界中捕獲某些有用信息,并且能夠把連續(xù)時(shí)間信號(hào)轉(zhuǎn)換成離散的數(shù)字形式。模數(shù)轉(zhuǎn)換器(ADC)是完成這項(xiàng)任務(wù)最重要的MCU外設(shè),因此ADC的性能往往
    發(fā)表于 07-05 06:21

    Stm32的ADCDMA功能

    時(shí)間進(jìn)行ADC轉(zhuǎn)換,這樣每次都必須讀ADC數(shù)據(jù)寄存器,非常浪費(fèi)時(shí)間! 2)把ADC設(shè)置成連續(xù)轉(zhuǎn)換模式,同時(shí)對(duì)應(yīng)的DMA通道開(kāi)啟循環(huán)模式,這
    發(fā)表于 08-19 07:02

    怎么實(shí)現(xiàn)多通道ADC通過(guò)DMA數(shù)據(jù)采集?

    怎么實(shí)現(xiàn)多通道ADC通過(guò)DMA數(shù)據(jù)采集?
    發(fā)表于 11-18 06:46

    ADC數(shù)據(jù)采集的應(yīng)用

    摘要本文章基于國(guó)信長(zhǎng)天M4開(kāi)發(fā)板,講述了ADC數(shù)據(jù)采集的應(yīng)用,祝各位學(xué)生藍(lán)橋杯比賽取得好成績(jī)!M4開(kāi)發(fā)板 ADC部分原理圖又上圖可以看出,開(kāi)發(fā)板上有兩個(gè)可調(diào)電阻R37, R38,分別連接到PB15
    發(fā)表于 01-06 06:12

    雙通道ADC采集的相關(guān)資料分享

    一、準(zhǔn)備工作[PA4->AO1]、[PA5->AO2] 轉(zhuǎn)動(dòng)RP5、RP6可觀察到測(cè)得AD值變化二、原理圖關(guān)于ADC采集詳解,參考“STM32-AD
    發(fā)表于 01-11 08:01

    ADC工作原理與選型

    目錄1,淺談常用ADC工作原理與選型!2,ADC的選型(技術(shù)指標(biāo))3 轉(zhuǎn)換速率(Conversion Rate):1,淺談常用ADC
    發(fā)表于 01-13 06:36

    lvds 接口的ADC數(shù)據(jù)采集

    這是ADC的lvds時(shí)序圖,目前遇到的問(wèn)題時(shí),我用一片Artix-7系列fpga同時(shí)采集4篇上述的ADC值,單片adc數(shù)據(jù)采集是正常的,多篇
    發(fā)表于 04-17 15:28

    ADC—單通道(DMA

    程序簡(jiǎn)介 -工程名稱(chēng):ADC單通道(DMA) -實(shí)驗(yàn)平臺(tái): 秉火STM32 F429 開(kāi)發(fā)板 -MDK版本:5.16 -ST固件庫(kù)版本:1.5.1 【 !】功能簡(jiǎn)介: 使用ADC采集
    發(fā)表于 12-13 15:25 ?8次下載
    <b class='flag-5'>ADC</b>—單通道(<b class='flag-5'>DMA</b>)

    ADC—單通道(NO DMA

    程序簡(jiǎn)介 -工程名稱(chēng):ADC單通道(NO DMA) -實(shí)驗(yàn)平臺(tái): 秉火STM32 F429 開(kāi)發(fā)板 -MDK版本:5.16 -ST固件庫(kù)版本:1.5.1 【 !】功能簡(jiǎn)介: 使用ADC采集
    發(fā)表于 12-13 15:28 ?10次下載
    <b class='flag-5'>ADC</b>—單通道(NO <b class='flag-5'>DMA</b>)

    ADC—多通道(DMA

    程序簡(jiǎn)介 -工程名稱(chēng):ADC多通道(DMA) -實(shí)驗(yàn)平臺(tái): 秉火STM32 F429 開(kāi)發(fā)板 -MDK版本:5.16 -ST固件庫(kù)版本:1.5.1 【 !】功能簡(jiǎn)介: 使用ADC采集
    發(fā)表于 12-13 15:31 ?33次下載
    <b class='flag-5'>ADC</b>—多通道(<b class='flag-5'>DMA</b>)

    STM32F030 ADC DMA亂序問(wèn)題

    問(wèn)題描述通過(guò) uint16_t ConvData[8]保存DMA搬運(yùn)的ADC轉(zhuǎn)換數(shù)值,但是這個(gè)數(shù)組數(shù)值的順序總是和ADC不是順序?qū)?yīng)的。比如用7個(gè)通道的ADC,當(dāng)設(shè)置
    發(fā)表于 06-09 15:18 ?1534次閱讀

    基于STM32單片機(jī)ADC連續(xù)采集DMA循環(huán)轉(zhuǎn)換

    描述:用ADC連續(xù)采集11路模擬信號(hào),并由DMA傳輸?shù)絻?nèi)存。ADC配置為掃描并且連續(xù)轉(zhuǎn)換模式,ADC的時(shí)鐘配置為12MHZ。在每次轉(zhuǎn)換結(jié)束后
    發(fā)表于 10-22 15:28 ?1.9w次閱讀

    stm32g030多路adc DMA采集程序

    stm32g030_多路adc_DMA采集程序
    發(fā)表于 06-19 09:43 ?28次下載