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

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > MCU怎么做一個簡單的ADC?

          MCU怎么做一個簡單的ADC?

          作者: 時間:2018-08-03 來源:網絡 收藏

            STM32的優(yōu)點在哪里?除去宣傳環(huán)節(jié),細細分析,STM32時鐘不算快,72MHZ,也不能擴展大容量的RAM FLASH,同樣沒有DSP那樣強大的指令集。它的優(yōu)勢在哪里呢?

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

            ---就在快速采集數據,快速處理上。

            ARM的特點就是方便?!∵@個快速采集,高性能的就是一個很好的體現,12位精度,最快1uS的轉換速度,通常具備2個以上獨立的控制器,這意味著,STM32可以同時對多個模擬量進行快速采集,這個特性不是一般的具有的。以上高性能的,配合相對比較塊的指令集和一些特色的算法支持,就構成了STM32在電機控制上的強大特性。

            好了,正題,怎么做一個簡單的ADC?

            注意是簡單的,ADC是個復雜的問題,涉及硬件設計,電源質量,參考電壓,信號預處理等等問題。我們只就如何在內完成一次ADC作討論。

            談到ADC,我們還要第一次引入另外一個重要的設備DMA。DMA是什么東西呢。

            通常在8位單片機時代,很少有這個概念。在外置資源越來越多以后,我們把一個內部分為 主處理器 和 外設兩個部分。主處理器當然是執(zhí)行我們指令的主要部分,外設則是 串口 I2C ADC 等等用來實現特定功能的設備,回憶一下,8位時代,我們的主處理器最常干的事情是什么?邏輯判斷?不是。那才幾個指令計算算法?不是。大部分時候算法都很簡單?!∈聦嵣希魈幚砥骶褪亲鱾€搬運工,

            把USART的數據接收下來,存起來

            把ADC的數據接收下來,存起來

            把要發(fā)送的數據,存起來,一個個的往USART里放。

            …………

            為了解決這個矛盾,人們想到一個辦法,讓外設和內存間建立一個通道,在主處理器允許下,讓外設和內存直接 讀寫,這樣就釋放了主處理器,這個東西就是DMA。

            打個比方:

            一個MCU是個公司。老板就是主處理器員工是外設,倉庫就是內存.

            從前 倉庫的東西都是老板管的。員工需要原料工作,就一個個報給老板,老板去倉庫里一個一個拿。員工作好的東西,一個個給老板,老板一個個放進倉庫里。老板很累,雖然老板是超人,也受不了越來越多的員工和單子。

            最后老板雇了一個倉庫保管員,它就是DMA

            他專門負責 入庫和出庫,只需要把出庫 和入庫計劃給老板過目老板說OK,就不管了。

            后面的入庫和出庫過程,員工只需要和這個倉庫保管員打交道就可以了。

            --------閑話,馬七時常想,讓設備與設備之間開DMA,豈不更牛X,比喻完成。

            ADC是個高速設備,前面提到。而且ADC采集到的數據是不能直接用的。即使你再小心的設計外圍電路,測的離譜的數據總會出現。那么通常來說,是采集一批數據,然后進行處理,這個過程就是軟件濾波。

            DMA用到這里就很合適。讓ADC高速采集,把數據填充到RAM中,填充一定數量,比如32個,64個MCU再來使用。

            -----多一句,也可以說,單次ADC毫無意義。

            下面我們來具體介紹,如何使用DMA來進行ADC操作。初始化函數包括兩部分,DMA初始化和 ADC初始化我們有多個管理員--DMA,一個管理員當然不止管一個DMA操作。所以DMA有多個Channel

            //ADC with DMA Init

            #define ADC_Channel ADC_Channel0

            #define ADC1_DR_Address ((u32)0x4001244C)

            void ADCWithDMAInit()

            {

            //DMA init; Using DMA channel 1

            DMA_DeInit(DMA1_Channel1); //開啟DMA1的第一通道

            DMA_InitStruct.DMA_PeripheralBaseAddr = ADC1_DR_Address; //DMA對應的外設基地址,這個地址走Datasheet查

            DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //轉換結果的數據大小

            DMA_InitStruct.DMA_MemoryBaseAddr = (unsigned long)&ADC_ConvertedValue; //

            DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC; //DMA的轉換模式是SRC模式,就是從外設向內存中搬運,

            DMA_InitStruct.DMA_M2M = DMA_M2M_Disable; //M2M模式禁止,memory to memory,這里暫時用不上,以后介

            紹

            DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //DMA搬運的數據尺寸,注意ADC是12位的,

            HalfWord就是16位

            DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Disable; //接收一次數據后,目標內存地址是否后移--重

            要概念,用來采集多個數據的

            DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //接收一次數據后,設備地址是否后移

            DMA_InitStruct.DMA_Mode = DMA_Mode_Circular; //轉換模式,循環(huán)緩存模式,常用,M2M果果開啟了,這個模式失效

            。

            DMA_InitStruct.DMA_Priority = DMA_Priority_High; //DMA優(yōu)先級,高

            DMA_InitStruct.DMA_BufferSize = 1; //DMA緩存大小,1個

            DMA_Init(DMA1_Channel1,&DMA_InitStruct);

            // Enable DMA1

            DMA_Cmd(DMA1_Channel1, ENABLE);

            }

            void ADCx_Init(unsigned char ADC_Channel)

            {

            ADC_DeInit(ADC1); //開啟ADC1

            ADC_InitStruct.ADC_Mode = ADC_Mode_Independent; //轉換模式,為獨立轉換。轉換模式太多了,以后深究

            ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right; //對齊方式,ADC結果是12位的,顯然有個對齊左邊還是右邊

            的問題。一般是右對齊

            ADC_InitStruct.ADC_ConTInuousConvMode = ENABLE; //連續(xù)轉換模式開啟

            ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //ADC外部出發(fā)開關,關閉

            ADC_InitStruct.ADC_NbrOfChannel = 2; //開啟通道數,2個

            ADC_InitStruct.ADC_ScanConvMode = ENABLE; //掃描轉換模式開啟

            ADC_Init(ADC1, &ADC_InitStruct);

            ADC_RegularChannelConfig(ADC1, ADC_Channel, 1, ADC_SampleTIme_239Cycles5); //規(guī)則組通道設置,關鍵函數 轉

            換器ADC1,選擇哪個通道channel,規(guī)則采樣順序,1到16,以后解釋詳細含義,最后一個參數是轉換時間,越長越準越穩(wěn)定

            // ADC1 to DMA, Enable

            ADC_DMACmd(ADC1, ENABLE); //ADC命令,和DMA關聯。

            //ADC1 Enable

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

            //Reset the CalibraTIon of ADC1

            ADC_ResetCalibraTIon(ADC1); //重置校準

            //wait until the Calibration‘s finish

            while(ADC_GetResetCalibrationStatus(ADC1)) //等待重置校準完成

            ;

            ADC_StartCalibration(ADC1); //開始校準

            while(ADC_GetCalibrationStatus(ADC1)) //等待校準完成

            ;

            ADC_SoftwareStartConvCmd(ADC1, ENABLE); //連續(xù)轉換開始,從選擇開始,MCU可以不用管了,ADC將通過DMA不斷刷新

            制定RAM區(qū)

            // Attach them;

            }

            最后講講濾波算法

            濾波的方法以后會開個專題。

            特別提一下---沒有完美的濾波算法,只有合適的濾波算法。

            需要綜合考慮信號特點,噪聲特點,控制對象等等,

            這里用個最簡單的濾波算法,均值濾波。

            采樣16次,取平均值,吼吼,在豆皮上跳動還是蠻小的,合適,吼吼

            //16ms finish a ADC detection

            // return mv

            unsigned int ADC_filter(void)

            {

            unsigned int result=“0”;

            unsigned char i;

            for(i=16;i》0;i--)

            {

            Delay_xms(1);

            result += ADC_ConvertedValue;

            }

            return (unsigned int)(((unsigned long)(result》》4))*3300》》12);

            }



          關鍵詞: MCU ADC

          評論


          相關推薦

          技術專區(qū)

          關閉
          看屁屁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); })();