<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > STM32的ADC DMA USART綜合學(xué)習(xí)

          STM32的ADC DMA USART綜合學(xué)習(xí)

          作者: 時間:2016-12-02 來源:網(wǎng)絡(luò) 收藏
          學(xué)習(xí)STM32ADC轉(zhuǎn)換,在開發(fā)板上寫程序調(diào)試。

          四個任務(wù):

          本文引用地址:http://www.ex-cimer.com/article/201612/325054.htm

          1.AD以中斷方式(單次)采集一路

          2.AD以中斷方式連續(xù)采集四路

          3.AD以DMA方式采集一路,DMA深度為一級

          4.AD以DMA方式采集四路,每路DMA深度為28級,并濾波,說明濾波原理。

          總結(jié):

          第一個任務(wù):ADC以中斷方式采集一路ADC,通過配置ADC_InitStructure結(jié)構(gòu)體中的ADC_ScanConvMode,它規(guī)定模數(shù)轉(zhuǎn)換工作在掃描模式(多通道)還是單次模式(單通道),

          ADC_InitStructure.ADC_ScanConvMode=DISABLE,為單通道單次模式。

          ADC_ContinuousConvMode,定轉(zhuǎn)換是連續(xù)還是單次,ADC_ContinuousConvMode=DISABLE

          為單次,ADC_NbrOfChangnel規(guī)定ADC規(guī)則轉(zhuǎn)換的通道數(shù)。ADC_NbrOfChannel=1;//開啟1個通道數(shù)。

          ADC_RegularChannelConfig(ADC1,ADC_Channel_13, 1,ADC_SampleTime_55Cycles5);設(shè)置指定規(guī)則組的通道的采樣順序和轉(zhuǎn)換時間。這里以為只有一路通道,采用的是PC3引腳,對應(yīng)的通道數(shù)是13通道,采樣順序也就是1,。

          ADC_Cmd(ADC1,ENABLE);使能ADC

          ADC_ITConfig(ADC1, ADC_IT_EOC,ENABLE);開啟ADC轉(zhuǎn)換結(jié)束中斷。

          ADC_ResetCalibration(ADC1);//重置校驗寄存器

          while(ADC_GetResetCalibrationStatus(ADC1));//等待重置校驗成功

          ADC_StartCalibration(ADC1);//開始ADC校驗

          while(ADC_GetCalibrationStatus(ADC1));//等待ADC校驗好

          ADC_SoftwareStartConvCmd(ADC1, ENABLE);//軟件觸發(fā)開始轉(zhuǎn)換

          因為ADC有一個16位的規(guī)則組數(shù)據(jù)寄存器(ADC_DR),采用一路轉(zhuǎn)換時可以不用通過DMA傳輸。這里就沒有配置DMA。

          void ADC_IRQHandler(void)

          {

          ADCConvertedValue=ADC_GetConversionValue(ADC1);

          ADC_ClearITPendingBit(ADC1, ADC_IT_EOC);

          }

          當(dāng)一次轉(zhuǎn)換結(jié)束,DAC產(chǎn)生中斷,在中斷函數(shù)里,讀取ADC_DR寄存器中的值,一定清除中斷標(biāo)志位。

          采集出來的數(shù)據(jù)是16進制數(shù),要經(jīng)過處理,變成10進制數(shù),具體如下:

          (value*100/4096)*33,value是從寄存器讀出來的十六進制的數(shù)據(jù),經(jīng)過此變換后就變成10進制數(shù),是個整數(shù),我們通過串口顯示的時候要把小樹部分也要顯示出來則有:((value*100/4096)*33)/1000,整數(shù)部分。

          ((value*100/4096)*33)%1000/100,((value*100/4096)*33)%100/10),小數(shù)部分,

          串口配置,我是通過STM32上的串口1與PC機通訊的,具體配置如下:

          void USART_Configuration(void)

          {

          USART_InitTypeDef USART_InitStructure;

          USART_InitStructure.USART_BaudRate=9600;波特率9600

          USART_InitStructure.USART_WordLength=USART_WordLength_8b;//8位數(shù)據(jù)位

          USART_InitStructure.USART_StopBits=USART_StopBits_1;1個停止位

          USART_InitStructure.USART_Parity=USART_Parity_No;無奇偶校驗

          USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;

          USART_Init(USART1,&USART_InitStructure);初始化串口配置

          USART_Cmd(USART1,ENABLE);使能串口

          }

          int fputc(int ch,FILE *f)

          {

          USART_SendData(USART1, (u8)ch);

          while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET)//檢查發(fā)送是否完成

          {

          }

          return ch;

          }此函數(shù),是把printf輸出函數(shù)定向到USART。

          第一個任務(wù)大概就是這個過程,在后面的任務(wù)有相同之處,就不重復(fù)敘述了。

          第二個任務(wù):ADC以中斷方式連續(xù)采集四路。

          首先配置4路模擬輸入,我配置的是PC0、PC1、PC2、PC3四個IO口,輸入方式為模擬輸入,速度采用2M,它們對應(yīng)的ADC通道分別是10、11、12、13通道。

          在第一個任務(wù)說了,ADC規(guī)則轉(zhuǎn)換多路采樣時,ADC的數(shù)據(jù)寄存器只有一個16位寄存器,所以必須采用DMA來傳輸數(shù)據(jù),DMA配置如下:

          DMA_InitStructure.DMA_PeripheralBaseAddr=DR_ADDRESS; //DMA對應(yīng)的外設(shè)基地址

          DMA_InitStructure.DMA_MemoryBaseAddr=(u32)&Buf; //內(nèi)存存儲基地址,定義的一個數(shù)組

          DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralSRC; //DMA轉(zhuǎn)換模式為SRC模式,由外設(shè)搬移到內(nèi)存

          DMA_InitStructure.DMA_BufferSize=4; // DMA緩存大小,4個(設(shè)置DMA在傳輸時緩沖區(qū)的長度)

          DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable; //接收一次數(shù)據(jù)后,設(shè)備地址禁止后移(設(shè)置DMA的外設(shè)遞增模式)

          DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable; //關(guān)閉接收一次數(shù)據(jù)后,目標(biāo)內(nèi)存地址后移(設(shè)置DMA的內(nèi)存遞增模式)

          DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_HalfWord;//定義外設(shè)數(shù)據(jù)長度

          DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord;

          DMA_InitStructure.DMA_Mode=DMA_Mode_Circular;

          //循環(huán)模式開啟,Buf寫滿后,自動回到初始地址開始傳輸

          DMA_InitStructure.DMA_Priority=DMA_Priority_High;//優(yōu)先級高

          DMA_InitStructure.DMA_M2M=DMA_M2M_Disable;

          ADC配置:

          //ADC配置

          ADC_InitStructure.ADC_Mode=ADC_Mode_Independent;//獨立轉(zhuǎn)換模式

          ADC_InitStructure.ADC_ScanConvMode=ENABLE;//開啟掃描模式

          ADC_InitStructure.ADC_ContinuousConvMode=ENABLE;//開啟連續(xù)轉(zhuǎn)換模式

          ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;//ADC外部開關(guān),關(guān)閉狀態(tài)

          ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;//對齊方式,右對齊方式

          ADC_InitStructure.ADC_NbrOfChannel=4;//開啟通道數(shù),4個

          ADC_Init(ADC1,&ADC_InitStructure);//初始化ADC

          ADC_RegularChannelConfig(ADC1,ADC_Channel_10,1,ADC_SampleTime_55Cycles5);

          ADC_RegularChannelConfig(ADC1,ADC_Channel_11,2,ADC_SampleTime_55Cycles5);

          ADC_RegularChannelConfig(ADC1, ADC_Channel_12,3,ADC_SampleTime_55Cycles5);

          ADC_RegularChannelConfig(ADC1,ADC_Channel_13,4,ADC_SampleTime_55Cycles5);;

          //ADC通道組,第10、11、12、13個通道,采樣順序分別是1,2,3,4轉(zhuǎn)換時間55.5個周期

          ADC_DMACmd(ADC1, ENABLE);//使能ADC1模塊DMA

          ADC_Cmd(ADC1, ENABLE);//打開ADC1

          ADC_ResetCalibration(ADC1);//重置ADC1校準(zhǔn)寄存器

          while(ADC_GetResetCalibrationStatus(ADC1));//等待ADC1校準(zhǔn)重置完成

          ADC_StartCalibration(ADC1);//開始ADC1校準(zhǔn)

          while(ADC_GetCalibrationStatus(ADC1));//等待ADC1校準(zhǔn)完成

          ADC_SoftwareStartConvCmd(ADC1,ENABLE);//使能ADC1軟件開始轉(zhuǎn)換

          中斷是采用DMA中斷,當(dāng)DMA第一輪傳輸結(jié)束時,設(shè)一個標(biāo)志位,當(dāng)標(biāo)志位為1時,表明第一輪轉(zhuǎn)化和傳輸完成,此時就可以讀取數(shù)組中的數(shù)據(jù),經(jīng)過處理就可以通過串口顯示出來。

          void DMAChannel1_IRQHandler(void)

          {

          ADC_DMA_OK=1;

          DMA_ClearITPendingBit(DMA1_IT_TC1);

          }中斷函數(shù)。

          第二個任務(wù)大概就這樣子。

          第三個任務(wù):AD以DMA方式采集一路,DMA深度為一級。

          這個任務(wù)不難,關(guān)鍵要理解到DMA深度,用自己的語言來理解哈DMA深度吧,當(dāng)ADC以一路采集時,ADC轉(zhuǎn)換完成就自動把轉(zhuǎn)換結(jié)果通過DMA傳給目的地址,如果傳輸一次結(jié)束DMA就產(chǎn)生中斷的話,DMA的深度就為一級,如果連續(xù)傳輸N次,DMA的深度就位N級,當(dāng)然這個N是又范圍的,因為受目的地址的內(nèi)存大小控制和數(shù)據(jù)寬度,這個大家應(yīng)該豆明白的。

          這個任務(wù)在第一個任務(wù)的基礎(chǔ)上我通過DMA傳輸,意思是AD配置沒什么區(qū)別。DMA配置和第二個任務(wù)的區(qū)別就是DMA_BufferSize的寬度不同。

          #defineDR_ADDRESS(u32)0x4001244cADC的地址

          #defineDMA_Count1DMA深度,也就是連續(xù)傳輸?shù)拇螖?shù)

          #defineADC_Channle1ADC通道

          數(shù)據(jù)處理和串口通訊這里不重復(fù)敘述。DMA中斷和任務(wù)二的類似。

          第四個任務(wù):AD以DMA方式采集四路,每路DMA深度為128級,并濾波,說明濾波原理。

          這個任務(wù)和是個綜合性任務(wù),只要弄懂前面三個任務(wù),難點是再如何濾波,開始的時候我也不知道怎么濾波,同事提醒我才知道怎么濾波的,我大概說哈我的理解,把四路通道采集的數(shù)據(jù)分別放到四個數(shù)組中,然后給他來個排序,降序,升序都行,把首位兩個數(shù)丟掉,然后加起來求平均值。但是我這里因為DMA的深度為128級,也就是四個通道分別采樣了128次,大家都知道,數(shù)據(jù)越多,求平均值就越準(zhǔn)確,所以我就沒有采用什么排序法了,直接給他們分別求平均值,具體如下:

          #defineDR_ADDRESS(u32)0x4001244cADC的地址

          #defineDMA_Count128DMA深度,也就是連續(xù)傳輸?shù)拇螖?shù)

          #defineADC_Channle4ADC通道

          for(i=0;i<(ADC_Channle*DMA_Count);i+=4)

          {

          Value1[j]=Buf[i+0];

          Sum1+=Value1[j];

          Value2[j]=Buf[i+1];

          Sum2+=Value2[j];

          Value3[j]=Buf[i+2];

          Sum3+=Value3[j];

          Value4[j]=Buf[i+3];

          Sum4+=Value4[j];

          j++;

          }

          Valu1=Sum1/DMA_Count;

          Valu2=Sum2/DMA_Count;

          Valu3=Sum3/DMA_Count;

          Valu4=Sum4/DMA_Count;

          Delay(100000);

          printf("rn當(dāng)前AD_0值:0x%x,電壓值:%d.%d%dVnr",

          Valu1,((Valu1*100/4096)*33)/1000,((Valu1*100/4096)*33)%1000/100,((Valu1*100/4096)*33)%100/10);

          Delay(100000);

          printf("rn當(dāng)前AD_1值:0x%x,電壓值:%d.%d%dVnr",

          Valu2,((Valu2*100/4096)*33)/1000,((Valu2*100/4096)*33)%1000/100,((Valu2*100/4096)*33)%100/10);

          Delay(100000);

          printf("rn當(dāng)前AD_2值:0x%x,電壓值:%d.%d%dVnr",

          Valu3,((Valu3*100/4096)*33)/1000,((Valu3*100/4096)*33)%1000/100,((Valu3*100/4096)*33)%100/10);

          Delay(100000);

          printf("rn當(dāng)前AD_3值:0x%x,電壓值:%d.%d%dVnr",

          Valu4,((Valu4*100/4096)*33)/1000,((Valu4*100/4096)*33)%1000/100,((Valu4*100/4096)*33)%100/10);

          Delay(100000);

          關(guān)于ADC配置和DMA配置這里不重復(fù)敘述了。



          關(guān)鍵詞: STM32ADCDMAUSAR

          評論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();