上個(gè)章節(jié)介紹了ADC的基本框架和用法,本章節(jié)會(huì)較為全面地講解如何靈活地使用ADC功能。
通常來說,外設(shè)執(zhí)行的各種命令都是由CPU發(fā)出的,比如我們需要進(jìn)行AD轉(zhuǎn)換,就通過某個(gè)寄存器標(biāo)志位啟動(dòng)ADC,隨后用判斷函數(shù)去檢測(cè)執(zhí)行情況,亦或是開啟中斷功能,轉(zhuǎn)換完成之后會(huì)提示CPU,再由CPU判斷接下來該做什么。
這當(dāng)然沒問題,不過有些時(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)換來定時(shí)獲取數(shù)據(jù),但數(shù)據(jù)很多,若是還要進(jìn)行快速傅里葉變換,CPU會(huì)在定時(shí)器中斷中花費(fèi)很多時(shí)間來采集數(shù)據(jù),留給計(jì)算的時(shí)間就少了很多。有一種方案可以完美解決這類問題,不僅可以保證數(shù)據(jù)采集的精確性,還幾乎不需要CPU參與,那就是使用定時(shí)器觸發(fā)ADC轉(zhuǎn)換,而AD轉(zhuǎn)換完成之后會(huì)由DMA進(jìn)行數(shù)據(jù)搬運(yùn),若CPU需要使用這批數(shù)據(jù),直接訪問數(shù)據(jù)進(jìn)行讀取即可 。具體的邏輯關(guān)系如下圖所示。
這種組合涉及到DMA、ADC、定時(shí)器的使用,文章將詳細(xì)介紹上圖的聯(lián)動(dòng)過程。
- 按照順序,首先是定時(shí)器觸發(fā)AD轉(zhuǎn)換。
前文也提到過,一般來講可以用軟件開關(guān)去啟動(dòng)AD轉(zhuǎn)換,此處并沒有用到這一功能,而是使用定時(shí)器觸發(fā),這是一種硬件觸發(fā)方式,且觸發(fā)源不屬于ADC外設(shè)本身,故而也是一種外部觸發(fā)方式。在ADC外設(shè)的配置項(xiàng)中,可以設(shè)置AD轉(zhuǎn)換的開啟是否由外部信號(hào)觸發(fā),只要ADC能正常使用,再配置好外部觸發(fā)源,我們就能用外部硬件信號(hào)觸發(fā)AD采集了。
注意!在實(shí)際使用中,外部觸發(fā)源不一定非得是定時(shí)器,它也可以是某個(gè)片外模塊提供的事件電平(完成事件會(huì)改變指定IO的電平,就和中斷一樣),最簡單的就是按鍵觸發(fā)的IO中斷。
- 接下來是第二個(gè)部分,DMA功能的配置。
DMA,全名叫直接存儲(chǔ)器訪問,這個(gè)外設(shè)可以像CPU一樣訪問單片機(jī)內(nèi)部的各個(gè)存儲(chǔ)區(qū)(包括RAM和外設(shè)寄存器),但它只能做一件事情,就是數(shù)據(jù)搬運(yùn)。通俗來說,數(shù)據(jù)存放在0-9共10個(gè)格子里面,DMA可以把這10個(gè)數(shù)據(jù)搬運(yùn)到其他地方(并不會(huì)改變?cè)镜闹?,效果類似賦值語句),而其他地方可以是同一個(gè)地方(將10個(gè)數(shù)據(jù)按順序搬運(yùn)10次,最終一層層覆蓋到同一個(gè)地址),也可以是不同地方(將10個(gè)數(shù)據(jù)搬運(yùn)10次并最終存放在10個(gè)不同地址的存儲(chǔ)空間)。
總體上來講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ū)域的訪問權(quán)限。
- 最后是定時(shí)器的配置,這一部分沒什么變化,就是選擇一個(gè)可以用來觸發(fā)AD采集的定時(shí)器,按需求配置即可。不過需要注意的是,記得把溢出中斷打開,這個(gè)是AD轉(zhuǎn)換的啟動(dòng)開關(guān) 。
介紹完了每一步需要做的事情,下面說說代碼應(yīng)該怎么寫。我會(huì)貼出主要代碼,對(duì)于一些變量我會(huì)做說明但不做代碼展示(變量什么的自己隨便定義一個(gè)就行了呀!)
這段就是正常配置一個(gè)定時(shí)器,本案例中選擇的是通用定時(shí)器2,根據(jù)手冊(cè),它可以觸發(fā)AD采集。
除最后一行,其余代碼與上一章節(jié)的初始化過程沒太大差別,只需把DMA功能開啟即可。這里補(bǔ)充一下其他配置項(xiàng)的說明:
- 時(shí)鐘頻率和采樣時(shí)鐘周期,如上一章說到的,采樣時(shí)間當(dā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é)果累加。為滿足一些需求,ADC結(jié)果可能需要進(jìn)行數(shù)據(jù)處理來減小誤差,求加權(quán)平均值是一種很常用的辦法,該功能開啟之后,每次轉(zhuǎn)換的結(jié)果都會(huì)直接累加,方便開發(fā)者取出后直接求平均值(所以實(shí)際上不要這個(gè)功能也可以)。
- 我們使用的是定時(shí)器觸發(fā)采樣,所以只需要使用單次采集模式就行了,ADC會(huì)在每次轉(zhuǎn)換完成之后停止并等待下一次采集的啟動(dòng)信號(hào)(定時(shí)器溢出中斷)。
總的來說,一定記住要把外部觸發(fā)打開并綁定定時(shí)器2,隨后只要定時(shí)器2的標(biāo)志位被置位一次,ADC就會(huì)啟動(dòng)一次。
相對(duì)來說比較麻煩的是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)被稱為源地址,終點(diǎn)被稱為目標(biāo)地址,且這兩個(gè)地址都可以設(shè)置成自增模式(完成一次搬運(yùn)之后,地址自動(dòng)+1)。
關(guān)于DMA的初始化,DMA通常會(huì)有不止一個(gè)通道,每個(gè)通道都能獨(dú)立進(jìn)行數(shù)據(jù)搬運(yùn),初始化函數(shù)需要開啟DMA的時(shí)鐘總線,打開要用的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è)的訪問權(quán)限,屆時(shí)CPU可進(jìn)行數(shù)據(jù)傳輸,DMA只能等待CPU放棄對(duì)該外設(shè)的使用權(quán)限后才能繼續(xù)自己的數(shù)據(jù)傳輸。相對(duì)應(yīng)的,還有鎖定傳輸,具體的功能在用戶手冊(cè)DMA章節(jié)有詳細(xì)介紹。
傳輸位寬 :根據(jù)需要搬運(yùn)的數(shù)據(jù)長度進(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ù)寄存器,具體的地址有兩種辦法來獲取,一種是用圖中的辦法,對(duì)寄存器取地址,另一種辦法是直接查用戶手冊(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ì)被正確寫入下一個(gè)格子。
傳輸次數(shù) :需求是采集1024個(gè)數(shù)據(jù),那傳輸次數(shù)自然是1024次。
全部配置完后完成DMA的功能初始化,隨后只需要啟動(dòng)ADC、定時(shí)器、DMA功能即可,圖中代碼做了一個(gè)開關(guān)啟動(dòng),方便隨時(shí)關(guān)閉。關(guān)閉的時(shí)候清零定時(shí)器計(jì)數(shù)器是為了在下次啟動(dòng)的時(shí)候讓定時(shí)采集依然準(zhǔn)確。
準(zhǔn)備工作基本完成,接下來還剩一些小細(xì)節(jié)需要處理,我們打開了DMA和定時(shí)器的中斷功能,他們會(huì)在完成搬運(yùn)之后進(jìn)入中斷服務(wù)函數(shù),至少得寫個(gè)清除標(biāo)志位的語句,除此之外還要加一些小功能。
定時(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)致程序異常的問題。
現(xiàn)在快速編寫一個(gè)按鍵檢測(cè)函數(shù)并調(diào)用剛剛寫好的啟動(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文章
113瀏覽量
16845 -
CW32
+關(guān)注
關(guān)注
1文章
218瀏覽量
751
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
【有那么點(diǎn)詳細(xì)的CW32學(xué)習(xí)筆記】單片機(jī)啟動(dòng)\庫函數(shù)構(gòu)成
![【<b class='flag-5'>有</b><b class='flag-5'>那么點(diǎn)</b><b class='flag-5'>詳細(xì)</b>的<b class='flag-5'>CW32</b><b class='flag-5'>學(xué)習(xí)</b><b class='flag-5'>筆記</b>】單片機(jī)啟動(dòng)\庫函數(shù)構(gòu)成](https://file1.elecfans.com/web2/M00/90/03/wKgaomTUVG2ANVRbAA577myiy30508.png)
【有那么點(diǎn)詳細(xì)的CW32學(xué)習(xí)筆記】通用定時(shí)器——輸出比較
![【<b class='flag-5'>有</b><b class='flag-5'>那么點(diǎn)</b><b class='flag-5'>詳細(xì)</b>的<b class='flag-5'>CW32</b><b class='flag-5'>學(xué)習(xí)</b><b class='flag-5'>筆記</b>】通用定時(shí)器——輸出比較](https://file1.elecfans.com/web2/M00/B9/59/wKgZomWM6KeAOkNXAACbzsh_phs727.png)
【有那么點(diǎn)詳細(xì)的CW32學(xué)習(xí)筆記】看手冊(cè)配置時(shí)鐘樹
![【<b class='flag-5'>有</b><b class='flag-5'>那么點(diǎn)</b><b class='flag-5'>詳細(xì)</b>的<b class='flag-5'>CW32</b><b class='flag-5'>學(xué)習(xí)</b><b class='flag-5'>筆記</b>】看手冊(cè)配置時(shí)鐘樹](https://file1.elecfans.com/web2/M00/90/EA/wKgaomTdwDyAKxhFAAK8fsm0RSI617.png)
【有那么點(diǎn)詳細(xì)的CW32學(xué)習(xí)筆記】模數(shù)轉(zhuǎn)換器
![【<b class='flag-5'>有</b><b class='flag-5'>那么點(diǎn)</b><b class='flag-5'>詳細(xì)</b>的<b class='flag-5'>CW32</b><b class='flag-5'>學(xué)習(xí)</b><b class='flag-5'>筆記</b>】模數(shù)轉(zhuǎn)換器](https://file1.elecfans.com/web2/M00/C1/D0/wKgZomXe2xGACIsPAAORHVtF7mQ820.png)
【應(yīng)用筆記】CW32 自舉程序中使用的 ISP 協(xié)議
應(yīng)用筆記(二)| 武漢芯源CW32自舉程序中使用的ISP協(xié)議
![應(yīng)用<b class='flag-5'>筆記</b>(二)| 武漢芯源<b class='flag-5'>CW32</b>自舉程序中使用的ISP協(xié)議](https://file.elecfans.com/web2/M00/52/78/pYYBAGLL2paAVDK6AAAektoL06g510.png)
cw32和gd32的區(qū)別
應(yīng)用筆記-CW32 自舉程序中使用的 ISP 協(xié)議
【有那么點(diǎn)詳細(xì)的CW32學(xué)習(xí)筆記】通用異步收發(fā)器—發(fā)送篇
![【<b class='flag-5'>有</b><b class='flag-5'>那么點(diǎn)</b><b class='flag-5'>詳細(xì)</b>的<b class='flag-5'>CW32</b><b class='flag-5'>學(xué)習(xí)</b><b class='flag-5'>筆記</b>】通用異步收發(fā)器—發(fā)送篇](https://file1.elecfans.com/web2/M00/B0/AC/wKgZomVXMlOAcHnhAAB6IPl3PBc244.jpg)
【有那么點(diǎn)詳細(xì)的CW32學(xué)習(xí)筆記】IIC接口-主機(jī)發(fā)送
![【<b class='flag-5'>有</b><b class='flag-5'>那么點(diǎn)</b><b class='flag-5'>詳細(xì)</b>的<b class='flag-5'>CW32</b><b class='flag-5'>學(xué)習(xí)</b><b class='flag-5'>筆記</b>】IIC接口-主機(jī)發(fā)送](https://file1.elecfans.com/web2/M00/BB/FE/wKgZomWeiQWAKEeBAACrG_jJKww287.jpg)
【有那么點(diǎn)詳細(xì)的CW32學(xué)習(xí)筆記】IIC接口-OLED驅(qū)動(dòng)
![【<b class='flag-5'>有</b><b class='flag-5'>那么點(diǎn)</b><b class='flag-5'>詳細(xì)</b>的<b class='flag-5'>CW32</b><b class='flag-5'>學(xué)習(xí)</b><b class='flag-5'>筆記</b>】IIC接口-OLED驅(qū)動(dòng)](https://file1.elecfans.com/web2/M00/BC/E9/wKgaomWeiuOAVdmyAAd8-3dPvG4290.jpg)
評(píng)論