|
基于STM32F4的多通道ADC采集
單片機(jī)源程序如下:
- #include "sys.h"
- #include "delay.h"
- #include "usart.h"
- #include "led.h"
- #include "fliter.h"
- #include "adc.h"
- #include "oled.h"
- extern u8 AD_Flag; //AD轉(zhuǎn)換完成標(biāo)志位
- extern u16 ADC_ConvertedValue[NOFCHANEL]; //用于存放ADC的轉(zhuǎn)換值
- extern float ADC_Final_DisplayValue[NOFCHANEL]; //用于存放最終顯示值
- extern u16 ADC_filter_Value[NOFCHANEL];
- int main()
- {
-
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//設(shè)置系統(tǒng)中斷優(yōu)先級分組2
- delay_init(168); //初始化延時(shí)函數(shù)
- uart_init(115200); //初始化串口波特率為115200
- ADC_X_Init(); //ADC初始化
- LED_Init(); //LED燈初始化
- OLED_Init(); //OLED初始化
-
- /************一開始的顯示*************/
- OLED_ShowCHinese(12,0,0,1); //輸
- OLED_ShowCHinese(24,0,1,1); //入
- OLED_ShowCHinese(36,0,4,1); //電
- OLED_ShowCHinese(48,0,5,1); //壓
- OLED_ShowCHinese(60,0,10,1); //:
- OLED_ShowCHinese(12,12,2,1); //輸
- OLED_ShowCHinese(24,12,3,1); //出
- OLED_ShowCHinese(36,12,6,1); //電
- OLED_ShowCHinese(48,12,7,1); //流
- OLED_ShowCHinese(60,12,10,1); //:
- OLED_ShowString(12,24,"DAC:",12);
- OLED_Refresh_Gram();//更新顯示到OLED
-
- while(1)
- {
- AD_Flag=AD_voltage; ADC_filter_Value[0]=middleValueFilter();
- AD_Flag=AD_current; ADC_filter_Value[1]=middleValueFilter();
- AD_Flag=AD_DAC; ADC_filter_Value[2]=middleValueFilter();
- ADC_Final_DisplayValue[0] =(double) ADC_filter_Value[0]/4096*3.3*6; //電壓檢測
- ADC_Final_DisplayValue[1] =(double) ADC_filter_Value[1]/4096*3.3; //電流檢測
- ADC_Final_DisplayValue[2] =(double) ADC_filter_Value[2]/4096*3.3; //DAC檢測
- OLED_ShowFloatNum_12(72,0,ADC_Final_DisplayValue[0],2,12);
- OLED_ShowFloatNum_12(72,12,ADC_Final_DisplayValue[1],2,12);
- OLED_ShowFloatNum_12(72,24,ADC_Final_DisplayValue[2],2,12);
- OLED_Refresh_Gram();//更新顯示到OLED
-
- delay_ms(500);
-
- }
- }
復(fù)制代碼
- #include "usart.h"
- #include "adc.h"
- #include "delay.h"
- #include "fliter.h"
- #include "led.h"
- extern u8 AD_Flag; //AD轉(zhuǎn)換完成標(biāo)志位
- extern u16 ADC_ConvertedValue[NOFCHANEL]; //用于存放ADC的轉(zhuǎn)換值
- extern float ADC_Final_DisplayValue[NOFCHANEL]; //用于存放最終顯示值
- u16 ADC_filter_Value[NOFCHANEL];
- extern u16 ADC_ConvertedValue[NOFCHANEL];
- // 軟件延時(shí)
- void Delay_ruan(__IO uint32_t nCount)
- {
- for(; nCount != 0; nCount--);
- }
- //中位值濾波
- //方法:連續(xù)采樣N次(N取奇數(shù))把N次采樣值按大小排列取中間值為本次有效值
- //優(yōu)點(diǎn):能有效克服因偶然因素引起的波動干擾;對溫度、液位等變化緩慢的被測參數(shù)有良好的濾波效果
- //缺點(diǎn):對流量,速度等快速變化的參數(shù)不宜
- #define N 30
- u16 middleValueFilter() //會獲取30個(gè)ADC轉(zhuǎn)換值,然后取中間的一個(gè)作為本次采樣周期的輸出值
- {
- u16 value_buf[N];
- u16 i,j,k,temp;
- for( i = 0; i < N; ++i)
- {
- value_buf[i] = getValue();
-
- }
- for(j = 0 ; j < N-1; ++j)
- {
- for(k = 0; k < N-j-1; ++k)
- {
- //從小到大排序,冒泡法排序
- if(value_buf[k] > value_buf[k+1])
- {
- temp = value_buf[k];
- value_buf[k] = value_buf[k+1];
- value_buf[k+1] = temp;
- }
- }
- }
-
- return value_buf[(N-1)/2];
- }
- /*******************獲得ADC轉(zhuǎn)換的值*******************/
- u16 getValue()
- {
- Delay_ruan(5); //軟件延時(shí)一下再獲取ADC的值,但是這個(gè)時(shí)間怎么確定呢?
-
- if(AD_Flag==AD_voltage) //獲取ADC電壓的值
- {
- return ADC_ConvertedValue[0]; //因?yàn)锳DC1的數(shù)據(jù)數(shù)據(jù)寄存器地址連接到了ADC_ConvertedValue數(shù)組上,所以ADC1采集到的值會傳輸?shù)綌?shù)組中,
- }
-
- if(AD_Flag==AD_current) //獲取ADC采集電流的值
- {
- return ADC_ConvertedValue[1];
-
- }
-
- if(AD_Flag==AD_DAC) //獲取DAC的值
- {
- return ADC_ConvertedValue[2];
-
- }
- }
- //**************疑問*************//
- //ADC1用了兩個(gè)通道,我怎么知道什么時(shí)候電流或者電壓的值存放到數(shù)組里?是否存到了對應(yīng)的位置?
- //因?yàn)榇鎯Φ刂肥沁B續(xù)的,所以ADC采集獲得的值會根據(jù)順序存入到數(shù)組中
復(fù)制代碼- #include "adc.h"
- #include "delay.h"
- u8 AD_Flag; //AD轉(zhuǎn)換完成標(biāo)志位
- u16 ADC_ConvertedValue[NOFCHANEL]={0}; //用于存放ADC的轉(zhuǎn)換值
- float ADC_Final_DisplayValue[NOFCHANEL]; //用于存放最終顯示值
- /*********************IO口復(fù)用為ADC******************/
- void ADC_GPIO_Config(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure; //結(jié)構(gòu)體定義
- /*=====================通道1======================*/
- /********** 使能 GPIO 時(shí)鐘****/
- RCC_AHB1PeriphClockCmd(ADC_GPIO_CLK1,ENABLE);
- /********配置 IO************/
- GPIO_InitStructure.GPIO_Pin = ADC_GPIO_PIN1;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //引腳復(fù)用時(shí),作為ADC或者DAC,不能選復(fù)用,必須選模擬輸入,其他的都是復(fù)用
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
- /*******初始化IO口*********/
- GPIO_Init(ADC_GPIO_PORT1, &GPIO_InitStructure);
- /*=====================通道2======================*/
- /********** 使能 GPIO 時(shí)鐘****/
- RCC_AHB1PeriphClockCmd(ADC_GPIO_CLK2,ENABLE);
- /********配置 IO************/
- GPIO_InitStructure.GPIO_Pin = ADC_GPIO_PIN2;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //引腳復(fù)用時(shí),作為ADC或者DAC,不能選復(fù)用,必須選模擬輸入,其他的都是復(fù)用
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
- /*******初始化IO口*********/
- GPIO_Init(ADC_GPIO_PORT2, &GPIO_InitStructure);
-
-
- //// /*=====================通道3=======================*/
- /********** 使能 GPIO 時(shí)鐘****/
- RCC_AHB1PeriphClockCmd( ADC_GPIO_CLK3,ENABLE);
- /********配置 IO************/
- GPIO_InitStructure.GPIO_Pin =ADC_GPIO_PIN3;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //引腳復(fù)用時(shí),作為ADC或者DAC,不能選復(fù)用,必須選模擬輸入,其他的都是復(fù)用
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
- /*******初始化IO口*********/
- GPIO_Init(ADC_GPIO_PORT3, &GPIO_InitStructure);
- }
- /***********配置ADC和DMA*************/
- void ADC_Mode_Config(void)
- {
- DMA_InitTypeDef DMA_InitStructure; // DMA初始化結(jié)構(gòu)體
- ADC_InitTypeDef ADC_InitStructure; // ADC初始化結(jié)構(gòu)體
- ADC_CommonInitTypeDef ADC_CommonInitStructure;
-
- /*-------------------DMA Iint 結(jié)構(gòu)體參數(shù) 初始化---------------------*/
- /************開啟DMA時(shí)鐘*************************/
- RCC_AHB1PeriphClockCmd(DMAX_CLK, ENABLE);
- // 外設(shè)基址為:ADC 數(shù)據(jù)寄存器地址
- DMA_InitStructure.DMA_PeripheralBaseAddr =(u32)&ADC_X->DR; //外設(shè)的數(shù)據(jù)寄存器地址怎么確定,(u32)&name->DR(name為外設(shè)名)
- // 存儲器地址,實(shí)際上就是一個(gè)內(nèi)部SRAM的變量
- DMA_InitStructure.DMA_Memory0BaseAddr =(u32)ADC_ConvertedValue; //存放ADC轉(zhuǎn)換值的數(shù)組地址(可以理解為存放ADC轉(zhuǎn)換值的寄存器與這個(gè)數(shù)組直接連接在一起)
- // 數(shù)據(jù)傳輸方向?yàn)橥庠O(shè)到存儲器
- DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; //確定方向很重要
- // 緩沖區(qū)大小為,指一次傳輸?shù)臄?shù)據(jù)量
- DMA_InitStructure.DMA_BufferSize = NOFCHANEL; //存放ADC轉(zhuǎn)換值的數(shù)組的數(shù)據(jù)量
- // 外設(shè)寄存器只有一個(gè),地址不用遞增
- DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
- // 存儲器地址固定(這里明明寫的是增加,為什么還說固定,是錯(cuò)誤了么)
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //(這里應(yīng)該是增加,因?yàn)橐讯鄠(gè)數(shù)據(jù)存到一個(gè)數(shù)組里,地址應(yīng)該是變化的)
- // // 外設(shè)數(shù)據(jù)大小為半字,即兩個(gè)字節(jié)
- DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //這里指的是一個(gè)數(shù)據(jù)的大小,STM32是32位的,所以一個(gè)字是32位,半字是16位
- // 存儲器數(shù)據(jù)大小也為半字,跟外設(shè)數(shù)據(jù)大小相同
- DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //外設(shè)數(shù)據(jù)大小是不是要和存儲器數(shù)據(jù)大小相同?是的
- // 循環(huán)傳輸模式 (ADC要不斷采集數(shù)據(jù),所以要循環(huán)模式)
- DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
- // DMA 傳輸通道優(yōu)先級為高,當(dāng)使用一個(gè)DMA通道時(shí),優(yōu)先級設(shè)置不影響
- DMA_InitStructure.DMA_Priority = DMA_Priority_High;
- // 禁止DMA FIFO ,使用直連模式
- DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
-
- // FIFO 大小,F(xiàn)IFO模式禁止時(shí),這個(gè)不用配置
- DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
- DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
- DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
-
- // 選擇 DMA 通道,通道存在于流中
- DMA_InitStructure.DMA_Channel =DMA_Channel__x;
- //初始化DMA流,流相當(dāng)于一個(gè)大的管道,管道里面有很多通道
- DMA_Init(DMA_Stream__x, &DMA_InitStructure);
-
- /****使能DMA流*********/
- DMA_Cmd(DMA_Stream__x, ENABLE);
-
- /*-------------ADC_X 初始化------------------*/
- /***************使能ADC時(shí)鐘*****************************/
- RCC_APB2PeriphClockCmd(ADC_CLK_ENABLE, ENABLE);
-
- /*-------------------ADC Common 結(jié)構(gòu)體 參數(shù) 初始化---------------*/
- // 獨(dú)立ADC模式
- ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
- // 時(shí)鐘為fpclk x分頻
- ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;
- // 禁止DMA直接訪問模式
- ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
- // 采樣時(shí)間間隔
- ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles;
- //初始化ADC Common 結(jié)構(gòu)體
- ADC_CommonInit(&ADC_CommonInitStructure);
-
- /* -------------------ADC Init 結(jié)構(gòu)體 參數(shù) 初始化-----------------*/
- // ADC 分辨率
- ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
- // 掃描模式,多通道采集需要
- ADC_InitStructure.ADC_ScanConvMode = ENABLE;
- // 連續(xù)轉(zhuǎn)換
- ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
- //禁止外部邊沿觸發(fā)
- ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
- //外部觸發(fā)通道,本例子使用軟件觸發(fā),此值隨便賦值即可
- ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
- //數(shù)據(jù)右對齊
- ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
- //轉(zhuǎn)換通道NOFCHANEL個(gè)
- ADC_InitStructure.ADC_NbrOfConversion = NOFCHANEL;
-
- /******ADC 結(jié)構(gòu)體初始化*********/
- ADC_Init(ADC_X, &ADC_InitStructure);
-
- /*----------------配置 ADC 通道轉(zhuǎn)換順序和采樣時(shí)間周期-----------------*/
- // 配置 ADC 通道轉(zhuǎn)換順序和采樣時(shí)間周期
- ADC_RegularChannelConfig(ADC_X,ADC_CHANNEL1, 1, ADC_SampleTime_56Cycles); //ADC通道1引腳是GPIOB_Pin_0
- ADC_RegularChannelConfig(ADC_X,ADC_CHANNEL2, 2, ADC_SampleTime_56Cycles); //ADC通道2引腳是GPIOB_Pin_1
- ADC_RegularChannelConfig(ADC_X,ADC_CHANNEL3, 3, ADC_SampleTime_56Cycles); //ADC通道3引腳是GPIOA_Pin_6
- // 使能DMA請求 after last transfer (Single-ADC mode)
- ADC_DMARequestAfterLastTransferCmd(ADC_X, ENABLE);
-
- /*************使能ADC DMA*************/
- ADC_DMACmd(ADC_X, ENABLE);
- /*************使能ADC******************/
- ADC_Cmd(ADC_X, ENABLE);
-
- //開始adc轉(zhuǎn)換,軟件觸發(fā)
- ADC_SoftwareStartConv(ADC_X);
-
- }
- void ADC_X_Init(void)
- {
- ADC_GPIO_Config();
- ADC_Mode_Config();
- }
復(fù)制代碼
所有資料51hei提供下載:
STM32F4 多通道DMAADC.7z
(644.37 KB, 下載次數(shù): 278)
2019-10-11 17:03 上傳
點(diǎn)擊文件名下載附件
基于STM32F4的多通道ADC采集,采用DMA形式,里面注釋詳細(xì),有利于初學(xué)者學(xué)習(xí) 下載積分: 黑幣 -5
|
評分
-
查看全部評分
|