|
本帖最后由 kkhkbb 于 2018-3-19 09:05 編輯
一、概述
1、ADC簡介
ADC是A/D轉(zhuǎn)換部件,單片機(jī)不能直接處理模擬量,所以需要ADC將模擬量轉(zhuǎn)換為數(shù)字量后,在進(jìn)行處理。在使用單片機(jī)進(jìn)行模擬數(shù)據(jù)處理的過程中,ADC至關(guān)重要。ADC以下幾種類型: - 積分型:積分型AD工作原理是將輸入電壓轉(zhuǎn)換成時間(脈沖寬度信號)或頻率(脈沖頻率),然后由定時器/計數(shù)器獲得數(shù)字值。其優(yōu)點是用簡單電路就能獲得高分辨率,抗干擾能力強(qiáng),但缺點是由于轉(zhuǎn)換精度依賴于積分時間,因此轉(zhuǎn)換速率極低。初期的單片AD轉(zhuǎn)換器大多采用積分型,現(xiàn)在逐次比較型已逐步成為主流。
- 逐次比較型:逐次比較型AD由一個比較器和DA轉(zhuǎn)換器通過逐次比較邏輯構(gòu)成,從MSB開始,順序地對每一位將輸入電壓與內(nèi)置DA轉(zhuǎn)換器輸出進(jìn)行比較,經(jīng)n次比較而輸出數(shù)字值。其電路規(guī)模屬于中等。其優(yōu)點是速度較高、功耗低,在低分辯率(<12位)時價格便宜,但高精度(>12位)時價格很高。
- 并行比較型/串并行比較型:并行比較型AD采用多個比較器,僅作一次比較而實行轉(zhuǎn)換,又稱FLash(快速)型。由于轉(zhuǎn)換速率極高,n位的轉(zhuǎn)換需要2n-1個比較器,因此電路規(guī)模也極大,價格也高,只適用于視頻AD轉(zhuǎn)換器等速度特別高的領(lǐng)域。串并行比較型AD結(jié)構(gòu)上介于并行型和逐次比較型之間,最典型的是由2個n/2位的并行型AD轉(zhuǎn)換器配合DA轉(zhuǎn)換器組成,用兩次比較實行轉(zhuǎn)換,所以稱為 Half flash(半快速)型。還有分成三步或多步實現(xiàn)AD轉(zhuǎn)換的叫做分級(Multistep/Subrangling)型AD,而從轉(zhuǎn)換時序角度又可稱為流水線(Pipelined)型AD,現(xiàn)代的分級型AD中還加入了對多次轉(zhuǎn)換結(jié)果作數(shù)字運算而修正特性等功能。這類AD速度比逐次比較型高,電路 規(guī)模比并行型小。
- Σ-Δ(Sigma delta)調(diào)制型:Σ-Δ型AD由積分器、比較器、1位DA轉(zhuǎn)換器和數(shù)字濾波器等組成。原理上近似于積分型,將輸入電壓轉(zhuǎn)換成時間(脈沖寬度)信號,用數(shù)字濾波器處理后得到數(shù)字值。電路的數(shù)字部分基本上容易單片化,因此容易做到高分辨率。主要用于音頻和測量。
- 電容陣列逐次比較型:電容陣列逐次比較型AD在內(nèi)置DA轉(zhuǎn)換器中采用電容矩陣方式,也可稱為電荷再分配型。一般的電阻陣列DA轉(zhuǎn)換器中多數(shù)電阻的值必須一致,在單芯片上生成高 精度的電阻并不容易。如果用電容陣列取代電阻陣列,可以用低廉成本制成高精度單片AD轉(zhuǎn)換器。最近的逐次比較型AD轉(zhuǎn)換器大多為電容陣列式的。
- 壓頻變換型:壓頻變換型(Voltage-Frequency Converter)是通過間接轉(zhuǎn)換方式實現(xiàn)模數(shù)轉(zhuǎn)換的。其原理是首先將輸入的模擬信號轉(zhuǎn)換成頻率,然 后用計數(shù)器將頻率轉(zhuǎn)換成數(shù)字量。從理論上講這種AD的分辨率幾乎可以無限增加,只要采樣的時間能夠滿足輸出頻率分辨率要求的累積脈沖個數(shù)的寬度。其優(yōu)點是分辯率高、功耗低、價格低,但是需要外部計數(shù)電路共同完成AD轉(zhuǎn)換。
2、ADC主要參數(shù)介紹 ADC主要參數(shù)有以下幾點: - 分辨率:數(shù)字量變化一個最小量時模擬量的變化量,定義為滿刻度與2n的比值。分辯率又稱精度,通常以數(shù)字信號的位數(shù)來表示。
- 轉(zhuǎn)換速率:完成一次A/D轉(zhuǎn)換所需要時間的倒數(shù),值越大表示轉(zhuǎn)換得越快。積分型AD的轉(zhuǎn)換時間是毫秒級屬低速AD,逐次比 較型AD是微秒級屬中速AD,全并行/串并行型AD可達(dá)到納秒級。
- 量化誤差:由于AD的有限分辯率而引起的誤差,即有限分辯率AD的階梯狀轉(zhuǎn)移特性曲線與無限分辯率AD(理想AD)的轉(zhuǎn)移特 性曲線(直線)之間的最大偏差。通常是1 個或半個最小數(shù)字量的模擬變化量,表示為1LSB、1/2LSB。
- 偏移誤差:輸入信號為零時輸出信號不為零的值,可外接電位器調(diào)至最小。
- 滿刻度誤差:滿度輸出時對應(yīng)的輸入信號與理想輸入信號值之差。
- 線性度:實際轉(zhuǎn)換器的轉(zhuǎn)移函數(shù)與理想直線的最大偏移。
3、STM32F407IGT6ADC介紹 STM32F407IGT6具有3個12位逐次逼近式ADC,共24個通道,可以配置成12位、8位、6位使用。可使用軟件對對要使用的ADC進(jìn)行使能和設(shè)置,進(jìn)行模擬量的采集。
二、硬件電路
圖9_0 ARM 電源監(jiān)測ADC使用圖 在iCore3雙核心開發(fā)板中,使用了個ADC進(jìn)行電源監(jiān)控分配如下表所示: ADC選用 | 監(jiān)測內(nèi)容 | ADC1-14通道 | 5V電壓 | ADC1-15通道 | 輸入電流 | ADC3-15通道 | 1.2V電壓 | ADC3-4通道 | 3.3V電壓 | ADC3-5通道 | 2.5V電壓 |
表9_0 ARM 電源監(jiān)測ADC使用分配表 三、實驗原理 使用ADC的5個通道,分別監(jiān)測5種電源信息,使用程序進(jìn)行相應(yīng)的轉(zhuǎn)換后,使用putty串口工具將采集到電源信息打印到PC機(jī)屏幕上,了解開發(fā)板的電源狀態(tài)。 STM32 內(nèi)部集成三個 12 位 ADC, iCore3 的所有電源經(jīng)過電阻分壓或者直接接入 STM32的 ADC 的輸出通道內(nèi), 輸入電流經(jīng)過高端電流檢測芯片 ZXCT1009F 輸入到 ADC 的輸入通道內(nèi),從而實現(xiàn)電源監(jiān)控功能。 電壓監(jiān)控硬件連接示意圖: 圖9_1電壓監(jiān)測硬件連接圖 由上圖可知:VCC =(1 + R1 / R2)*ADC_IN; 故知:VCC = (1 + 49.9K / 10K)*ADC_IN = 6*ADC_IN; 其他電源監(jiān)控同理可得:D3V3 = 2*ADC_IN; A2V5 =2*ADC_IN; D1V2 =ADC_IN。 電流監(jiān)控硬件連接示意圖如下圖: 圖9_2電流監(jiān)測硬件連接圖 由 ZXCT1009F 的原理可知:ADC_IN = 0.01 * (VCC - LOAD)*R2;
通過 R1 的電流:I = 100 *ADC_IN /R2 /R1;
帶入 R2 = 10K,R1 = 0.02:得出:I =ADC_IN / 2;
- //--------------------------- Include ---------------------------//
- #include "..\include\led.h"
- #include "..\include\main.h"
- #include "..\include\usart.h"
- #include "..\include\adc.h"
- #include "..\fwlib\inc\stm32f4xx_gpio.h"
- //---------------------------- Define ---------------------------//
- //-------------------------- Variable ---------------------------//
- //--------------------- Function Prototype ----------------------//
- //--------------------------- Function --------------------------//
- /*
- * Name : main
- * Description : ---
- * Author : ysloveivy.
- *
- * History
- * --------------------
- * Rev : 0.00
- * Date : 11/21/2015
- *
- * create.
- * --------------------
- */
- int main(void)
- {
- int i;
- //初始化
- led.initialize();
- LED_RED_ON;
- usart4.initialize(115200);
- adc.initialize();
- usart4.printf("\x0c"); //清屏
- usart4.printf("\033[1;32;40m"); //設(shè)置終端字體為綠色
- usart4.printf("\r\n\r\nhello! I am iCore3!\r\n\r\n\r\n");
- while(1){
- for(i = 0;i < 10000000;i++);
- //ADC 監(jiān)控電源
- for(i = 0;i < 5;i++){
- adc.read(i);
- }
- //打印系統(tǒng)供電電壓,
- usart4.printf(" [V] %4.2fV, ",adc.value[0] * 6);
- usart4.printf("[I] %3.0fmA , ",adc.value[1] / 2* 1000.);
- usart4.printf("[1.2V] %4.2fV, ",adc.value[2]);
- usart4.printf("[3.3V] %4.2fV, ",adc.value[3] * 2);
- usart4.printf("[2.5V] %4.2fV\r",adc.value[4] * 2);
- }
- }
復(fù)制代碼
2.ADC參數(shù)配置
- /*
- * Name : initialize
- * Description : ---
- * Author : ysloveivy.
- *
- * History
- * --------------------
- * Rev : 0.00
- * Date : 11/21/2015
- *
- * create.
- * --------------------
- */
- static int initialize(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- ADC_CommonInitTypeDef ADC_CommonInitStructure;
- ADC_InitTypeDef ADC_InitStructure;
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE);
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE);
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //使能ADC1時鐘
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE); //使能ADC3時鐘
- //ADC1_PC4<----->通道14, ADC1_PC5<----->通道15
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; //模擬輸入
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
- GPIO_Init(GPIOC, &GPIO_InitStructure);
- //ADC3_PF5<----->通道15, ADC3_PF6<----->通道4, ADC3_PF7<----->通道5
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; //模擬輸入
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
- GPIO_Init(GPIOF, &GPIO_InitStructure);
- ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; //ADC為獨立模式
- ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; //設(shè)置兩個采樣階段之間的延遲周期數(shù)為5個周期
- ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; //禁止DMA
- ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div6; //設(shè)置分頻系數(shù)為6分頻
- ADC_CommonInit(&ADC_CommonInitStructure);
- //初始化ADC
- ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; //ADC轉(zhuǎn)換分辨率12位
- ADC_InitStructure.ADC_ScanConvMode = DISABLE; //非掃描模式
- ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //關(guān)閉連續(xù)轉(zhuǎn)換模式
- ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; //禁止觸發(fā)檢測
- ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //右對齊方式
- ADC_InitStructure.ADC_NbrOfConversion = 1; //1個轉(zhuǎn)換在規(guī)則序列中
- ADC_Init(ADC1, &ADC_InitStructure);
- ADC_Init(ADC3, &ADC_InitStructure); //使能ADC
- ADC_Cmd(ADC1, ENABLE);
- ADC_Cmd(ADC3, ENABLE);
- return 0;
- }
- /*
- * Name : sort
- * Description : ---
- * Author : XiaomaGee.
- *
- * History
- * ----------------------
- * Rev : 0.00
- * Date : 11/21/2015
- *
- * create.
- * ----------------------
- */
- void sort(unsigned short int a[], int n)
- {
- int i, j, t;
- //元素從小到大排列
- for (i = 0; i < n - 1; i++) {
- for (j = 0; j < n - i - 1; j++) {
- if (a[j] > a[j + 1]) {
- t = a[j];
- a[j] = a[j + 1];
- a[j + 1] = t;
- }
- }
- }
- }
- /*
- * Name : read_adc
- * Description : ---
- * Author : ysloveivy.
- *
- * History
- * ----------------------
- * Rev : 0.00
- * Date : 11/21/2015
- *
- * create.
- * ----------------------
- */
- static int read_adc(int channel)
- {
- int i,k;
- unsigned long int temp[20] = {0};
- unsigned long int value;
- unsigned short int data[100];
- unsigned char channel_remap[5] = {ADC_Channel_14,ADC_Channel_15,ADC_Channel_15,ADC_Channel_4,ADC_Channel_5};
- //取得到的100個轉(zhuǎn)換值的中間20個的平均值作為結(jié)果
- //連續(xù)取20次這樣的平均值,再求平均值作為最終結(jié)果
- for(k = 0;k < 20;k++){
- for(i = 0;i < 100;i++){
- if(channel == 0 || channel == 1){
- ADC_RegularChannelConfig(ADC1, channel_remap[channel], 1, ADC_SampleTime_480Cycles); //ADC1規(guī)則通道為通道14,15,一個序列,采樣時間為480個周期
- ADC_SoftwareStartConv(ADC1); //使能指定的ADC1的軟件轉(zhuǎn)換啟動功能
- while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)); //等待轉(zhuǎn)換結(jié)束
- data[i] = ADC_GetConversionValue(ADC1); //將結(jié)果保存
- }else {
- ADC_RegularChannelConfig(ADC3, channel_remap[channel], 1, ADC_SampleTime_480Cycles); //ADC3規(guī)則通道為通道15,4,5,一個序列,采樣時間為480個周期
- ADC_SoftwareStartConv(ADC3);
- while(!ADC_GetFlagStatus(ADC3,
- ADC_FLAG_EOC));
- data[i] = ADC_GetConversionValue(ADC3);
- }
- }
- sort(data,100);
- for(i = 40;i < 60;i++){
- temp[k] += data[i];
- }
- temp[k] = temp[k] / 20;
- }
- value = 0;
- for(k = 0;k < 20;k++){
- value += temp[k];
- }
- value /= 20;
- adc.value[channel] = value * ADC_REF / 4096;
- return value;
- }
復(fù)制代碼 3.ADC參數(shù)配置說明- typedef struct
- {
- uint32_t ADC_Mode;
- uint32_t ADC_Prescaler;
- uint32_t ADC_DMAAccessMode;
- uint32_t ADC_TwoSamplingDelay;
- }ADC_CommonInitTypeDeftypedef ;
- typedef struct
- {
- uint32_t ADC_Resolution;
- FunctionalState ADC_ScanConvMode;
- FunctionalState ADC_ContinuousConvMode;
- uint32_t ADC_ExternalTrigConvEdge;
- uint32_t ADC_ExternalTrigConv;
- uint32_t ADC_DataAlign;
- uint8_t ADC_NbrOfConversion;
- }ADC_InitTypeDef;;
復(fù)制代碼ADC_Mode:工作模式, 分為獨立模式和混合模式,混合模式中包含了多種工作模式。 ADC_Prescaler: 分頻值, 用于配置ADC時鐘,有2、4、6、8四種分頻方式。 ADC_DMAAccessMode:DMX通道模式,分為:不使能、模式1、模式2、模式3。 ADC_TwoSamplingDelay:兩個采樣之間的延遲周期。 ADC_Resolution:分辨率,12、10、8、6位可設(shè)置。 FunctionalState ADC_ScanConvMode:用于是否開啟轉(zhuǎn)換模式。 FunctionalState ADC_ContinuousConvMode: 用于是否開啟連續(xù)轉(zhuǎn)換模式。 ADC_ExternalTrigConvEdge: 用來設(shè)置啟動規(guī)則轉(zhuǎn)換組轉(zhuǎn)換的外部事件。 ADC_ExternalTrigConv: 色孩子數(shù)據(jù)觸發(fā)檢測。 ADC_DataAlign: 用于設(shè)置數(shù)據(jù)對齊方式是左對齊還是右對齊。 ADC_NbrOfConversion:用來設(shè)置規(guī)則序列的長度 。 五、實驗現(xiàn)象 iCore3 雙核心板紅色 LED 常亮, 串口一直向終端輸出電源監(jiān)控的數(shù)據(jù)。 圖9_3實驗效果圖
六、代碼包下載
網(wǎng)盤:http://pan.baidu.com/s/1o7wSE06 |
-
-
iCore3_9_ADC.zip
2018-3-16 18:16 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
1.39 MB, 下載次數(shù): 41, 下載積分: 黑幣 -5
|