Ⅰ、概述
上一篇文章講述的內容是:三通道逐次轉換(單次、單通道軟件觸發),也就是說3條通道要三次軟件觸發才能完成轉換,而且是通過軟件讀取轉換數值。
本文講述三通道DMA連續轉換(3通道、軟件單次觸發),也就是說3條通道只需要一次軟件觸發就能完成轉換,使用DMA保存在數值。
上一篇文章實例是使用間斷模式單次觸發單條通道采集,本文是使用DMA模式單次觸發三條通道采集。使用DMA傳輸的好處就是效率很高,我們直接讀取轉換的結果就是了,比如想做的示波器實例就是要求效率很高。
實例實驗效果:
本文的實驗效果和上一篇文章一樣,只是實現的方式不一樣。
通道1接地、通道2接1.5V電源、通道3接VCC
上一篇文章內容:
【ADC三通道逐次轉換(單次、單通道軟件觸發)】
本文講述的知識點相對較多,若初次學習STM32的ADC轉換功能,可以參考我另外一篇相對簡單一點的文章:
STM32F10x_ADC1單通道單次采集
關于本文的更多詳情請往下看。
Ⅱ、實例工程下載
筆者針對于初學者提供的例程都是去掉了許多不必要的功能,精簡了官方的代碼,對初學者一看就明白,以簡單明了的工程供大家學習。
筆者提供的實例工程都是在板子上經過多次測試并沒有問題才上傳至360云盤,歡迎下載測試、參照學習。
提供下載的軟件工程是基于Keil(MDK-ARM) V5版本、STM32F103ZE芯片,但F1其他型號也適用(適用F1其他型號: 關注微信,回復“修改型號”,或閱讀原文)。
STM32F10x_ADC三通道DMA連續轉換(3通道、軟件單次觸發)實例源代碼工程:
https://yunpan.cn/cBCmnZ58mI3Pp訪問密碼 f2ff
STM32F1資料:
https://yunpan.cn/crBUdUGdYKam2訪問密碼 ca90
Ⅲ、關于ADC
關于ADC的介紹及功能,請下載參考手冊查看,筆者這里講述幾點重要的知識:
1.12位分辨率
在STM32所有系列芯片中只有少部分是16位的,如:F373芯片。
12位分辨率意味著我們采集電壓的精度可以達到:Vref /4096。
采集電壓 = Vref * ADC_DR / 4096;
Vref:參考電壓
ADC_DR:讀取到ADC數據寄存器的值
由于寄存器是32位的,在配置的時候分左對齊和右對齊,一般我們使用右對齊,也就是對低12位數據為有效數據。
2.轉換模式
A.單次和連續轉換
單次:單通道單次轉換、多通道單次(分多次)轉換;
連續:單通道連續轉換、多通道連續(循環)轉換;
B.雙ADC模式
也就是使用到了兩個ADC,比如:ADC1和ADC2同時使用也就是雙ADC模式。在該模式下可以配置為如下一些模式:同步規則模式、同步注入模式、獨立模式等。
3.觸發源
觸發源就是觸發ADC轉換的來源,有外部中斷線、定時器、軟件等觸發源。我們初學者常用軟件觸發,也就是需要轉換一次,我們軟件啟動一次(本文提供實例也是軟件觸發)。
Ⅳ、本文實例描述
本文實例中關于ADC部分的配置及知識點,針對初學者相對比較多、理解起來也相對比較難一點。
根據題目“ADC三通道逐次轉換(單次、單通道軟件觸發)”我們不難理解其轉換的過程,但如何實現是一個難點。
1、三通道:我們定義了3條通道ADC1的ADC_Channel_1、ADC_Channel_2、ADC_Channel_3.
2.逐次轉換:我們使用的是間斷模式(規則組),也就是在規則組中定義了觸發轉換的序列。
3.單次:我們是每觸發一次轉換一次。
4.單通道:每次觸發只轉換一條通道。
以簡單的示意圖來說明其原理:
實例總共有三條通道通道1、通道2、通道3,分別對應順序,是1、2、3。我們是通過軟件來定義的順序:
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 2, ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 3, ADC_SampleTime_55Cycles5);
所以,我們轉換保存的順序:ADC_Buf[0]是通道1的數據、ADC_Buf[1]是通道2的數據、ADC_Buf[2]是通道3的數據
也是按照上面來的。當然,也可以更改順序。
Ⅴ、源代碼分析
筆者以F1標準外設庫(同時也建議初學者使用官方的標準外設庫)為基礎建立的工程,主要以庫的方式來講述(若您的F1芯片與提供工程不一樣,可微信回復“修改型號”)。
下面將講述ADC重要的幾點:
1.輸入引腳配置
該函數位于adc.c文件下面;
引腳與通道的對應關系請參看你使用芯片的數據手冊。
注意:
為什么是“ADC123_IN1”?而不是ADC1_IN1,或者ADC2_IN1?
原因是ADC1、ADC2和ADC3共用這些引腳。
2.DMA配置
該函數位于adc.c文件下面;
1.外設地址:DMA_PeripheralBaseAddr = (uint32_t)(&(ADC1->DR));
我們使用ADC數據寄存器地址作為DMA的外設地址;
2.內存地址:DMA_MemoryBaseAddr = (uint32_t)ADC_Buf;
這里就是我們定義保存采集值數組的地址;
3.傳輸方向:DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_DIR_PeripheralSRC:外設 -> 內存
DMA_DIR_PeripheralDST:內存 -> 外設
4.傳輸長度:DMA_BufferSize = ADC_BUF_SIZE;
ADC_BUF_SIZE是一個宏定義,等于3; 也就是說我們需要轉換并保存3組數據(3條通道的值)。
5.外設地址增長:DMA_PeripheralInc = DMA_PeripheralInc_Disable;
由于外設的地址都是ADC數據寄存器,沒有改變,所以不需要增長地址;
6.內存地址增長:DMA_MemoryInc = DMA_MemoryInc_Enable;
由于我們定義了一個數字,里面需要保存3個數值,所以需要增長;
【根據傳輸長度和循環模式,可以循環傳輸數據】
7.外設數據長度:DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_PeripheralDataSize_Byte:8位數據
DMA_PeripheralDataSize_HalfWord:16位數據
DMA_PeripheralDataSize_Word:32位數據
由于我們使用16位的數據,所以使用DMA_PeripheralDataSize_HalfWord;
8.內存數據長度:DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
和“外設數據長度”類似;
9.循環模式:DMA_Mode = DMA_Mode_Circular;
這里說的循環就是我們循環采集3組數據(更加傳輸長度來確定);
10.優先級:DMA_Priority = DMA_Priority_VeryHigh;
優先級應該都明白他的意思,我們只使用一組DMA這個優先級可高可低;
11.優先級:DMA_M2M = DMA_M2M_Disable;
內存傳輸到內存:否
注意:
為什么我們是使用DMA1_Channel1?
我們使用DMA通道是有要求的,需按照手冊提供的規則來(如下圖);請參看手冊:
3.ADC配置
該函數位于adc.c文件下面;
這個函數是本文的重點,下面依次來講述源代碼內容的意思;
A.初始化基本參數:
工作模式:ADC_Mode = ADC_Mode_Independent;
總共有10種,主要都是針對雙ADC下使用。針對初學者這里不多描述,感興趣的朋友可以先自行研究一下各個模式的使用。
瀏覽模式:ADC_ScanConvMode = ENABLE;
主要是針對多條通道而言,也就是說你是否有多條通道。
多通道:ENABLE;
單通道:DISABLE;
轉換模式:ADC_ContinuousConvMode = DISABLE;
這里是配置是否需要連續轉換。
連續轉換ENABLE:也就是只需要啟動(觸發)轉換一次,后面就不用再次啟動(觸發)就可以連續工作了。
單次轉換DISABLE:也就是根據一次轉換完后需要再次啟動(觸發)才能工作。
觸發方式:ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
觸發方式也就是使用什么方法觸發ADC轉換。喲定時器、外部觸發、軟件觸發,一般常用軟件觸發。這里有很多種觸發方式,詳情可以參考其參數。
對其方式:ADC_DataAlign = ADC_DataAlign_Right;
右對其:低12位數據為有效位(常用);
左對其:高12為數據為有效位;
通道數:ADC_NbrOfChannel = 3;
這個參數比較簡單,我們定義工作的通道數量。
B.設置規則組通道:
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 2, ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 3, ADC_SampleTime_55Cycles5);
我們定義通道1的轉換順序為第1、通道2的轉換順序為第2、通道3的轉換順序為第3;
C.校驗:
ADC_ResetCalibration(ADC1); //校驗復位
while(ADC_GetResetCalibrationStatus(ADC1)); //等待復位完成
ADC_StartCalibration(ADC1); //開始ADC1校準
while(ADC_GetCalibrationStatus(ADC1)); //等待校驗完成
建議每次上電校正一次。
ADC有一個內置自校準模式。校準可大幅減小因內部電容器組的變化而造成的準精度誤差。在校準期間,在每個電容器上都會計算出一個誤差修正碼(數字值),這個碼用于消除在隨后的轉換中每個電容器上產生的誤差。
Ⅵ、說明
關于STM32的ADC轉換這一塊功能確實交強大也相對來說比較復雜,或許文中講述的還不夠清楚,若有不清楚的可以關注微信,在微信上留言。
關于筆者提供的軟件工程實例,可閱讀文章最下面的“閱讀原文”,或在會話框回復“關于工程”,有關于工程結構描述、型號修改等講述。
以上總結僅供參考,若有不對之處,敬請諒解。
Ⅶ、最后
更多精彩文章我將第一時間在微信公眾號里面分享,該文有什么疑問可留言。
本著免費分享的原則,方便大家手機學習知識,定期在微信平臺分享技術知識。如果你覺得分享的內容對你有用,又想了解更多相關的文章,請用微信搜索“EmbeddDeveloper” 或者掃描下面二維碼、關注,將有更多精彩內容等著你。
贊是一種鼓勵、分享是最好的支持!
原文標題:STM32F10x_ADC三通道DMA連續轉換(3通道、軟件單次觸發)
文章出處:【微信公眾號:strongerHuang】歡迎添加關注!文章轉載請注明出處。
-
adc
+關注
關注
97文章
6302瀏覽量
542488 -
STM32
+關注
關注
2258文章
10828瀏覽量
352546 -
STM32F10x
+關注
關注
1文章
81瀏覽量
20632
發布評論請先 登錄
相關推薦
評論