(二)ADC循環(huán)采集六路電壓,使用DMA.
這次實驗真的很郁悶,對DMA的不了解讓我深陷誤區(qū),明白之后,讓我更加佩服DMA的強(qiáng)大。
誤區(qū)就是:從實驗的目標(biāo)我們知道這次是用DMA把ADC轉(zhuǎn)換的數(shù)據(jù)傳送到內(nèi)存中的一個數(shù)組里存起來,因為是采集6個通道,這里使能了ADC的掃描模式。一旦啟動ADC,就會按順序轉(zhuǎn)換SQRX里選中的通道,問題就是我一開始以為ADC與DMA并不會協(xié)調(diào)工做,也就是ADC自己轉(zhuǎn)自己的,DMA自己傳自己的,這樣的話內(nèi)存里的數(shù)組就不是我想要的了,后來著實的研究了很長時間,在群里的一位兄弟的提醒下,我才知道,可能我想的復(fù)雜了,也許就可以在ADC轉(zhuǎn)一次,然后DMA把數(shù)據(jù)傳一次,Ok,經(jīng)過實驗得知,這個想法是正確的。
好了,說了這么多廢話,開始進(jìn)入正題。
這里使用了ADC1的六個規(guī)則通道分別是:CH0、CH1、CH2、CH3、CH14、CH15,
分別對應(yīng)的引腳為PA0、PA1、PA2、PA3、PC4、PC5。
關(guān)于ADC的配置:
啟動了ADC1的掃描模式,還有連續(xù)轉(zhuǎn)換模式,獨立工作模式(只用1個ADC),因為用的了DMA,所以也要使能DMA位,使用外部觸發(fā)(SWSTART),數(shù)據(jù)為右對齊。還有SQRX等等就不說了,這里不需要ADC中斷的。中斷在DMA里。
關(guān)于DMA的配置:
因為ADC請求規(guī)定在DMA1的第一個通道,所以這里使用DMA_CH1,外設(shè)地址為ADC唯一的數(shù)據(jù)寄存器(u32)&ADC1->DR,存儲器地址為(u32)SendBuff數(shù)組,這個數(shù)組可以存放6個元素。這里還有使能傳輸完中斷(TCIF),選擇從外設(shè)讀取,循環(huán)模式,外設(shè)地址非增量模式,存儲器地址增量模式,外設(shè)數(shù)據(jù)寬度16位,存儲器地址16位,非存儲器到存儲器模式。
關(guān)于DMA中斷函數(shù):
當(dāng)DMA傳輸完6次數(shù)據(jù)時,TCIF位自動置位,程序進(jìn)入中斷服務(wù)函數(shù),首先先關(guān)閉ADC的連續(xù)轉(zhuǎn)換,我們把數(shù)組的處理都放在了這里,處理完發(fā)送到串口,通過電腦的超級終端可以看到不停變化的6個引腳電壓的數(shù)據(jù)。別忘了一定要清楚中斷標(biāo)志位并置位ADC的連續(xù)轉(zhuǎn)換,然后再次啟動轉(zhuǎn)換。
主程序中只要初始化系統(tǒng)函數(shù),還有串口,然后配置好DMA,啟動規(guī)則轉(zhuǎn)換通道,并啟動DMA,然后等在死循環(huán)即可。
下面附上部分代碼
-------------------------------------------------------------------------------------------
void Adc_Init(void)
{
//先初始化IO口
RCC->APB2ENR|=1<<2; //使能PORTA口時鐘
RCC->APB2ENR|=1<<4; //使能PORTC口時鐘
GPIOA->CRL&=0XFFFF0000; //PA0 1 2 3 anolog輸入
GPIOC->CRL&=0XFF00FFFF; //PC4,5 anolog輸入
//通道10/11設(shè)置
RCC->APB2ENR|=1<<9; //ADC1時鐘使能
RCC->APB2RSTR|=1<<9; //ADC1復(fù)位
RCC->APB2RSTR&=~(1<<9); //復(fù)位結(jié)束
RCC->CFGR&=~(3<<14); //分頻因子清零
//SYSCLK/DIV2=12M ADC時鐘設(shè)置為12M,ADC最大時鐘不能超過14M!
//否則將導(dǎo)致ADC準(zhǔn)確度下降!
RCC->CFGR|=2<<14;
ADC1->CR1&=0XF0FFFF; //工作模式清零
ADC1->CR1|=0<<16; //獨立工作模式
ADC1->CR1|=1<<8; //掃描模式
ADC1->CR2|=1<<1; //啟用連續(xù)轉(zhuǎn)換
ADC1->CR2|=1<<8; //啟用DMA
// ADC1->CR2&=~(1<<1); //單次轉(zhuǎn)換模式
ADC1->CR2&=~(7<<17);
ADC1->CR2|=7<<17; //軟件控制轉(zhuǎn)換
ADC1->CR2|=1<<20; //使用用外部觸發(fā)(SWSTART)!!! 必須使用一個事件來觸發(fā)
ADC1->CR2&=~(1<<11); //右對齊
ADC1->SQR1&=~(0XF<<20);
ADC1->SQR1|=5<<20; //6個轉(zhuǎn)換在規(guī)則序列
ADC1->SQR3 = 0X00000000;
ADC1->SQR3|= 0X1EE18820;
//設(shè)置通道0~3,14,15的采樣時間
ADC1->SMPR1&=0XFFFC0FFF;//通道14,15采樣時間清空
ADC1->SMPR2&=0XFFFFF000;//通道0,1,2,3采樣時間清空
ADC1->SMPR1|=7<<15; //通道15 239.5周期,提高采樣時間可以提高精確度
ADC1->SMPR1|=7<<12; //通道14 239.5周期,提高采樣時間可以提高精確度
ADC1->SMPR2|=7<<9; //通道3 239.5周期,提高采樣時間可以提高精確度
ADC1->SMPR2|=7<<6; //通道2 239.5周期,提高采樣時間可以提高精確度
ADC1->SMPR2|=7<<3; //通道1 239.5周期,提高采樣時間可以提高精確度
ADC1->SMPR2|=7<<0; //通道0 239.5周期,提高采樣時間可以提高精確度
ADC1->CR2|=1<<0; //開啟AD轉(zhuǎn)換器
ADC1->CR2|=1<<3; //使能復(fù)位校準(zhǔn)
while(ADC1->CR2&1<<3); //等待校準(zhǔn)結(jié)束
//該位由軟件設(shè)置并由硬件清除。在校準(zhǔn)寄存器被初始化后該位將被清除。
ADC1->CR2|=1<<2; //開啟AD校準(zhǔn)
while(ADC1->CR2&1<<2); //等待校準(zhǔn)結(jié)束
//該位由軟件設(shè)置以開始校準(zhǔn),并在校準(zhǔn)結(jié)束時由硬件清除
}
void MYDMA_Config(DMA_Channel_TypeDef*DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)
{
u32 DR_Base; //做緩沖用,不知道為什么.非要不可
RCC->AHBENR|=1<<0; //開啟DMA1時鐘
DR_Base=cpar;
DMA_CHx->CPAR=DR_Base; //DMA1 外設(shè)地址
DMA_CHx->CMAR=(u32)cmar; //DMA1,存儲器地址
DMA1_MEM_LEN=cndtr; //保存DMA傳輸數(shù)據(jù)量
DMA_CHx->CNDTR=cndtr; //DMA1,傳輸數(shù)據(jù)量
DMA_CHx->CCR=0X00000000; //復(fù)位
DMA_CHx->CCR|=1<<1; //允許傳輸完中斷
DMA_CHx->CCR|=0<<4; //從外設(shè)讀
DMA_CHx->CCR|=1<<5; //循環(huán)模式
DMA_CHx->CCR|=0<<6; //外設(shè)地址非增量模式
DMA_CHx->CCR|=1<<7; //存儲器增量模式
DMA_CHx->CCR|=1<<8; //外設(shè)數(shù)據(jù)寬度為16位
DMA_CHx->CCR|=1<<10; //存儲器數(shù)據(jù)寬度16位
DMA_CHx->CCR|=1<<12; //中等優(yōu)先級
DMA_CHx->CCR|=0<<14; //非存儲器到存儲器模式
MY_NVIC_Init(1,3,DMA1_Channel1_IRQChannel ,2);
}
//開啟一次DMA傳輸
void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx)
{
DMA_CHx->CCR&=~(1<<0); //關(guān)閉DMA傳輸
DMA_CHx->CNDTR=DMA1_MEM_LEN; //DMA1,傳輸數(shù)據(jù)量
DMA_CHx->CCR|=1<<0; //開啟DMA傳輸
}
u16 ADC1_DR, adcx;
void DMAChannel1_IRQHandler(void)
{
u16 i;
u32 sum[6]={0},val=0;
LED0 =!LED0;
ADC1->CR2&=~(1<<1); //關(guān)閉連續(xù)轉(zhuǎn)換
for( i = 0; i<768 ;i+= 6)
{
sum[0] += SendBuff[i];
sum[1] += SendBuff[i+1];
sum[2] += SendBuff[i+2];
sum[3] += SendBuff[i+3];
sum[4] += SendBuff[i+4];
sum[5] += SendBuff[i+5];
}
for(i = 0;i <6 ;i++)
{
val = sum[i]/DMA_COUNT;
ADC1_DR = sum[i]/DMA_COUNT;
TEMP=(float)ADC1_DR*(3.3/4096);
adcx=TEMP;
LCD_ShowNum(149,70+i*20,adcx,1,16);//顯示電壓值
TEMP-=adcx;
TEMP*=1000;
LCD_ShowNum(165,70+i*20,TEMP,3,16);
}
delay_ms(200);
DMA1->IFCR |= 1<<1; //清零通道完成中斷標(biāo)志位
ADC1->CR2|=1<<1; //啟用連續(xù)轉(zhuǎn)換
ADC1->CR2|=1<<22; //啟動規(guī)則轉(zhuǎn)換通道
}
--------------------------------------------------------------------------------------
上一篇:ARM處理器啟動流程———S3C2440、S3C6410、S5PV210
下一篇:STM32 在 KEIL 下使用 SWV 輸出調(diào)試信息
推薦閱讀
史海拾趣
設(shè)計資源 培訓(xùn) 開發(fā)板 精華推薦
- 【DIY數(shù)控電源】入圍方案及后續(xù)活動安排!
- 有獎直播|魏德米勒 OMNIMATE® 聯(lián)接技術(shù)的創(chuàng)新發(fā)展
- 新春尋寶記,泰克送福利!快來開啟你的尋寶之旅~
- 又到一年總結(jié)時——EE社區(qū)送溫暖
- 【MPS有獎分享】便攜式多功能電工臺的核“芯”功能測試與結(jié)構(gòu)設(shè)計
- 報名參會三重禮 | 西門子車用半導(dǎo)體全棧解決方案直播
- TI 電機(jī)驅(qū)動應(yīng)用闖關(guān)答題賽
- 揭秘正確選擇探頭的5大要素 (泰克原裝探頭促銷,高貴不貴,199元起)
- 2024年STM32巡回研討會即將開啟?。?月3日-9月13日)
- 國內(nèi)外激光雷達(dá)盤點及核心產(chǎn)品介紹
- 面向商用車的人臉識別技術(shù)發(fā)展現(xiàn)狀及應(yīng)用展望
- 三星首款集成式汽車級ISOCELL圖像傳感器已投入量產(chǎn)
- 爭議不斷的動力電池暗戰(zhàn),究竟改變了什么?
- “機(jī)器人導(dǎo)游”上崗 為旅游增加新奇體驗
- 優(yōu)艾智合機(jī)器人再獲藍(lán)馳創(chuàng)投獨家領(lǐng)投的新一輪融資
- 英飛凌全新 EiceDRIVER柵極驅(qū)動 IC 助力 5G和LTE宏基站發(fā)展
- 新款14寸MacBook Pro有望今年3月問市,將搭載12核Apple Silicon
- 超表面技術(shù)能否讓半導(dǎo)體突破性能瓶頸
- 全球芯片IC設(shè)計Top10有所更新,華為跌出前十