上個(gè)章節(jié)介紹了ADC的基本框架和用法,本章節(jié)會(huì)較為全面地講解如何靈活地使用ADC功能。
通常來(lái)說(shuō),外設(shè)執(zhí)行的各種命令都是由CPU發(fā)出的,比如我們需要進(jìn)行AD轉(zhuǎn)換,就通過(guò)某個(gè)寄存器標(biāo)志位啟動(dòng)ADC,隨后用判斷函數(shù)去檢測(cè)執(zhí)行情況,亦或是開(kāi)啟中斷功能,轉(zhuǎn)換完成之后會(huì)提示CPU,再由CPU判斷接下來(lái)該做什么。
這當(dāng)然沒(méi)問(wèn)題,不過(guò)有些時(shí)候,我們需要實(shí)現(xiàn)一些循環(huán)重復(fù)的功能,比如在做傅里葉分析的時(shí)候,需要按照固定間隔采集一定數(shù)量的數(shù)據(jù),比如采樣率1000Hz,共采集1024個(gè)數(shù)據(jù)。為了實(shí)現(xiàn)這個(gè)目標(biāo),當(dāng)然可以使用軟件定時(shí)實(shí)現(xiàn),也可以使用定時(shí)器外設(shè),在中斷服務(wù)函數(shù)中直接進(jìn)行AD轉(zhuǎn)換來(lái)定時(shí)獲取數(shù)據(jù),但數(shù)據(jù)很多,若是還要進(jìn)行快速傅里葉變換,CPU會(huì)在定時(shí)器中斷中花費(fèi)很多時(shí)間來(lái)采集數(shù)據(jù),留給計(jì)算的時(shí)間就少了很多。有一種方案可以完美解決這類(lèi)問(wèn)題,不僅可以保證數(shù)據(jù)采集的精確性,還幾乎不需要CPU參與,那就是使用定時(shí)器觸發(fā)ADC轉(zhuǎn)換,而AD轉(zhuǎn)換完成之后會(huì)由DMA進(jìn)行數(shù)據(jù)搬運(yùn),若CPU需要使用這批數(shù)據(jù),直接訪(fǎng)問(wèn)數(shù)據(jù)進(jìn)行讀取即可 。具體的邏輯關(guān)系如下圖所示。

這種組合涉及到DMA、ADC、定時(shí)器的使用,文章將詳細(xì)介紹上圖的聯(lián)動(dòng)過(guò)程。
- 按照順序,首先是定時(shí)器觸發(fā)AD轉(zhuǎn)換。
前文也提到過(guò),一般來(lái)講可以用軟件開(kāi)關(guān)去啟動(dòng)AD轉(zhuǎn)換,此處并沒(méi)有用到這一功能,而是使用定時(shí)器觸發(fā),這是一種硬件觸發(fā)方式,且觸發(fā)源不屬于ADC外設(shè)本身,故而也是一種外部觸發(fā)方式。在ADC外設(shè)的配置項(xiàng)中,可以設(shè)置AD轉(zhuǎn)換的開(kāi)啟是否由外部信號(hào)觸發(fā),只要ADC能正常使用,再配置好外部觸發(fā)源,我們就能用外部硬件信號(hào)觸發(fā)AD采集了。
注意!在實(shí)際使用中,外部觸發(fā)源不一定非得是定時(shí)器,它也可以是某個(gè)片外模塊提供的事件電平(完成事件會(huì)改變指定IO的電平,就和中斷一樣),最簡(jiǎn)單的就是按鍵觸發(fā)的IO中斷。
- 接下來(lái)是第二個(gè)部分,DMA功能的配置。
DMA,全名叫直接存儲(chǔ)器訪(fǎng)問(wèn),這個(gè)外設(shè)可以像CPU一樣訪(fǎng)問(wèn)單片機(jī)內(nèi)部的各個(gè)存儲(chǔ)區(qū)(包括RAM和外設(shè)寄存器),但它只能做一件事情,就是數(shù)據(jù)搬運(yùn)。通俗來(lái)說(shuō),數(shù)據(jù)存放在0-9共10個(gè)格子里面,DMA可以把這10個(gè)數(shù)據(jù)搬運(yùn)到其他地方(并不會(huì)改變?cè)镜闹担Ч?lèi)似賦值語(yǔ)句),而其他地方可以是同一個(gè)地方(將10個(gè)數(shù)據(jù)按順序搬運(yùn)10次,最終一層層覆蓋到同一個(gè)地址),也可以是不同地方(將10個(gè)數(shù)據(jù)搬運(yùn)10次并最終存放在10個(gè)不同地址的存儲(chǔ)空間)。
總體上來(lái)講DMA只做搬運(yùn)這一個(gè)功能,除了搬運(yùn)轉(zhuǎn)換完成的AD數(shù)據(jù),他還能用于各種數(shù)據(jù)接口(比如UART、SPI等),或是其他需要大量賦值的場(chǎng)合。
注意!****DMA并不能完全代替CPU進(jìn)行數(shù)據(jù)轉(zhuǎn)移,因?yàn)?/em>DMA*不像* CPU那樣擁有全部存儲(chǔ)區(qū)域的訪(fǎng)問(wèn)權(quán)限。
- 最后是定時(shí)器的配置,這一部分沒(méi)什么變化,就是選擇一個(gè)可以用來(lái)觸發(fā)AD采集的定時(shí)器,按需求配置即可。不過(guò)需要注意的是,記得把溢出中斷打開(kāi),這個(gè)是AD轉(zhuǎn)換的啟動(dòng)開(kāi)關(guān) 。
介紹完了每一步需要做的事情,下面說(shuō)說(shuō)代碼應(yīng)該怎么寫(xiě)。我會(huì)貼出主要代碼,對(duì)于一些變量我會(huì)做說(shuō)明但不做代碼展示(變量什么的自己隨便定義一個(gè)就行了呀?。?/em>

這段就是正常配置一個(gè)定時(shí)器,本案例中選擇的是通用定時(shí)器2,根據(jù)手冊(cè),它可以觸發(fā)AD采集。

除最后一行,其余代碼與上一章節(jié)的初始化過(guò)程沒(méi)太大差別,只需把DMA功能開(kāi)啟即可。這里補(bǔ)充一下其他配置項(xiàng)的說(shuō)明:
- 時(shí)鐘頻率和采樣時(shí)鐘周期,如上一章說(shuō)到的,采樣時(shí)間當(dāng)然是越長(zhǎng)越好,其中的時(shí)鐘頻率就是ADC外設(shè)從內(nèi)部時(shí)鐘電路獲得的時(shí)鐘信號(hào),頻率越高,ADC速度越快,這個(gè)時(shí)鐘速度一定程度上決定了一個(gè)ADC的最大采樣速率(1秒內(nèi)完成的轉(zhuǎn)換次數(shù))。
- 右對(duì)齊設(shè)置。AD轉(zhuǎn)換的結(jié)果是存放在一個(gè)寄存器里面的,它本質(zhì)上是個(gè)二進(jìn)制數(shù),右對(duì)齊就是將轉(zhuǎn)換結(jié)果的第0位放到最右邊,高位不為1的補(bǔ)0,若仍不清楚,可自行百度。
- 轉(zhuǎn)換結(jié)果累加。為滿(mǎn)足一些需求,ADC結(jié)果可能需要進(jìn)行數(shù)據(jù)處理來(lái)減小誤差,求加權(quán)平均值是一種很常用的辦法,該功能開(kāi)啟之后,每次轉(zhuǎn)換的結(jié)果都會(huì)直接累加,方便開(kāi)發(fā)者取出后直接求平均值(所以實(shí)際上不要這個(gè)功能也可以)。
- 我們使用的是定時(shí)器觸發(fā)采樣,所以只需要使用單次采集模式就行了,ADC會(huì)在每次轉(zhuǎn)換完成之后停止并等待下一次采集的啟動(dòng)信號(hào)(定時(shí)器溢出中斷)。
總的來(lái)說(shuō),一定記住要把外部觸發(fā)打開(kāi)并綁定定時(shí)器2,隨后只要定時(shí)器2的標(biāo)志位被置位一次,ADC就會(huì)啟動(dòng)一次。
相對(duì)來(lái)說(shuō)比較麻煩的是DMA的配置,要配置一個(gè)DMA,首先需要確定數(shù)據(jù)搬運(yùn)的起點(diǎn)和終點(diǎn) ,我們搬運(yùn)的起點(diǎn)只有一個(gè),就是ADC轉(zhuǎn)換結(jié)果寄存器,搬運(yùn)的終點(diǎn)是一個(gè)1024大小的數(shù)組,其中起點(diǎn)被稱(chēng)為源地址,終點(diǎn)被稱(chēng)為目標(biāo)地址,且這兩個(gè)地址都可以設(shè)置成自增模式(完成一次搬運(yùn)之后,地址自動(dòng)+1)。

關(guān)于DMA的初始化,DMA通常會(huì)有不止一個(gè)通道,每個(gè)通道都能獨(dú)立進(jìn)行數(shù)據(jù)搬運(yùn),初始化函數(shù)需要開(kāi)啟DMA的時(shí)鐘總線(xiàn),打開(kāi)要用的DMA通道的中斷。

關(guān)于DMA的啟動(dòng)和配置:
傳輸模式 :DMA幫助CPU進(jìn)行數(shù)據(jù)搬運(yùn),這難免會(huì)出現(xiàn)DMA和CPU傳輸沖突的情況,非鎖定傳輸會(huì)在DMA搬運(yùn)數(shù)據(jù)的間隔內(nèi)預(yù)留時(shí)間間隙,必要時(shí)候CPU會(huì)搶占對(duì)外設(shè)的訪(fǎng)問(wèn)權(quán)限,屆時(shí)CPU可進(jìn)行數(shù)據(jù)傳輸,DMA只能等待CPU放棄對(duì)該外設(shè)的使用權(quán)限后才能繼續(xù)自己的數(shù)據(jù)傳輸。相對(duì)應(yīng)的,還有鎖定傳輸,具體的功能在用戶(hù)手冊(cè)DMA章節(jié)有詳細(xì)介紹。
傳輸位寬 :根據(jù)需要搬運(yùn)的數(shù)據(jù)長(zhǎng)度進(jìn)行選擇即可。
觸發(fā)方式和觸發(fā)源 :由于我們需要的是在AD轉(zhuǎn)換完成之后立刻進(jìn)行數(shù)據(jù)搬運(yùn),所以DMA的觸發(fā)方式選擇為硬件觸發(fā),觸發(fā)源應(yīng)該設(shè)置為ADC轉(zhuǎn)化為完成,這會(huì)讓DMA在每次ADC轉(zhuǎn)換完成之后都進(jìn)行一次數(shù)據(jù)搬運(yùn),且不論ADC處于什么模式。
源地址和目標(biāo)地址 :源地址設(shè)置為ADC數(shù)據(jù)寄存器,具體的地址有兩種辦法來(lái)獲取,一種是用圖中的辦法,對(duì)寄存器取地址,另一種辦法是直接查用戶(hù)手冊(cè),找到ADC數(shù)據(jù)寄存器的基地址和偏移量計(jì)算得到地址(這種辦法最終填進(jìn)去的是一個(gè)hex數(shù))。目標(biāo)地址也是直接取地址數(shù)組即可。
地址自增 :我們不希望源地址有變動(dòng),故源地址設(shè)置成不自增;目標(biāo)地址是一個(gè)數(shù)組,所以每搬運(yùn)一次數(shù)據(jù)都要讓目標(biāo)地址自增一個(gè)元素,這樣下一次搬運(yùn)的時(shí)候,數(shù)據(jù)就會(huì)被正確寫(xiě)入下一個(gè)格子。
傳輸次數(shù) :需求是采集1024個(gè)數(shù)據(jù),那傳輸次數(shù)自然是1024次。
全部配置完后完成DMA的功能初始化,隨后只需要啟動(dòng)ADC、定時(shí)器、DMA功能即可,圖中代碼做了一個(gè)開(kāi)關(guān)啟動(dòng),方便隨時(shí)關(guān)閉。關(guān)閉的時(shí)候清零定時(shí)器計(jì)數(shù)器是為了在下次啟動(dòng)的時(shí)候讓定時(shí)采集依然準(zhǔn)確。
準(zhǔn)備工作基本完成,接下來(lái)還剩一些小細(xì)節(jié)需要處理,我們打開(kāi)了DMA和定時(shí)器的中斷功能,他們會(huì)在完成搬運(yùn)之后進(jìn)入中斷服務(wù)函數(shù),至少得寫(xiě)個(gè)清除標(biāo)志位的語(yǔ)句,除此之外還要加一些小功能。


定時(shí)器的中斷服務(wù)函數(shù)只需要清除標(biāo)志位即可,DMA的中斷函數(shù)除了清除標(biāo)志位,還需要將采樣功能關(guān)掉(至少得把定時(shí)器關(guān)了)。如果使用的不是定時(shí)器觸發(fā),而是ADC的連續(xù)采樣模式,需要在這里手動(dòng)關(guān)閉ADC,不然即使DMA完成了搬運(yùn),ADC還會(huì)繼續(xù)進(jìn)行AD轉(zhuǎn)換,由于DMA搬運(yùn)已經(jīng)完成了,自增的地址也不會(huì)自己變回去,之后就會(huì)出現(xiàn)“意想不到的”DMA錯(cuò)誤搬運(yùn),但本案例中使用的是單次采集模式,ADC只在啟動(dòng)之后采集一次,所以不必?fù)?dān)心ADC會(huì)連續(xù)采樣導(dǎo)致程序異常的問(wèn)題。
現(xiàn)在快速編寫(xiě)一個(gè)按鍵檢測(cè)函數(shù)并調(diào)用剛剛寫(xiě)好的啟動(dòng)代碼,其中的key_down變量會(huì)在按鍵中斷服務(wù)函數(shù)中被置位。


再在main函數(shù)中循環(huán)調(diào)用這個(gè)按鍵檢測(cè)函數(shù),按鍵按下抬起后就會(huì)自動(dòng)采集ADC數(shù)據(jù),這里我用vofa+上位機(jī)顯示一下采集的數(shù)據(jù)。

我這里采集的是單片機(jī)上定時(shí)器1輸出的50Hz方波,占空比為50%,周期為20ms,效果還不錯(cuò)。

審核編輯 黃宇
-
ADC
+關(guān)注
關(guān)注
0文章
223瀏覽量
16845 -
CW32
+關(guān)注
關(guān)注
1文章
281瀏覽量
1678
發(fā)布評(píng)論請(qǐng)先 登錄
【有那么點(diǎn)詳細(xì)的CW32學(xué)習(xí)筆記】單片機(jī)啟動(dòng)\庫(kù)函數(shù)構(gòu)成
【有那么點(diǎn)詳細(xì)的CW32學(xué)習(xí)筆記】通用定時(shí)器——輸出比較
【有那么點(diǎn)詳細(xì)的CW32學(xué)習(xí)筆記】看手冊(cè)配置時(shí)鐘樹(shù)
【有那么點(diǎn)詳細(xì)的CW32學(xué)習(xí)筆記】模數(shù)轉(zhuǎn)換器
【應(yīng)用筆記】CW32 自舉程序中使用的 ISP 協(xié)議
應(yīng)用筆記(二)| 武漢芯源CW32自舉程序中使用的ISP協(xié)議
cw32和gd32的區(qū)別
應(yīng)用筆記-CW32 自舉程序中使用的 ISP 協(xié)議
【有那么點(diǎn)詳細(xì)的CW32學(xué)習(xí)筆記】通用異步收發(fā)器—發(fā)送篇
【有那么點(diǎn)詳細(xì)的CW32學(xué)習(xí)筆記】IIC接口-主機(jī)發(fā)送
【有那么點(diǎn)詳細(xì)的CW32學(xué)習(xí)筆記】IIC接口-OLED驅(qū)動(dòng)

【有那么點(diǎn)詳細(xì)的CW32學(xué)習(xí)筆記】ADC“自動(dòng)模式”
評(píng)論