STM32F1xx 系列 多通道ADC DMA採集與非DMA採集
阿新 • • 發佈:2018-12-04
ADC 多通道 DMA 採集
#include "ADcx.h" #include <stdio.h> #include "stm32f10x.h" #include "stm32f10x_rcc.h" #include "stm32f10x_adc.h" #include "stm32f10x_gpio.h" void ADcDMA_Configuration(void); u16 AD_Value[8][8]; //ADC資料快取 //初始化 void ADcx_Init(){ ADC_InitTypeDef ADC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC|RCC_APB2Periph_ADC1,ENABLE);//使能ADC時鐘和相關GPIO時鐘 RCC_ADCCLKConfig(RCC_PCLK2_Div6);//配置ADC時鐘72M/6=12,最大不能超過14 //GPIO配置 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN; GPIO_Init(GPIOA,&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN; GPIO_Init(GPIOC,&GPIO_InitStructure); ADC_DeInit(ADC1);//復位ADC ADC_InitStructure.ADC_Mode=ADC_Mode_Independent;//獨立工作模式 ADC_InitStructure.ADC_ScanConvMode=ENABLE;//啟動多通道掃描(單通道不要開啟) ADC_InitStructure.ADC_ContinuousConvMode=ENABLE;//啟動連續轉換 ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;//軟體觸發 ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;//右對齊 ADC_InitStructure.ADC_NbrOfChannel=8;//掃描8個通道 ADC_Init(ADC1,&ADC_InitStructure);//根據引數初始化ADC1 //指定8個通道的掃描順訊 ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_239Cycles5); ADC_RegularChannelConfig(ADC1,ADC_Channel_1,2,ADC_SampleTime_239Cycles5); ADC_RegularChannelConfig(ADC1,ADC_Channel_2,3,ADC_SampleTime_239Cycles5); ADC_RegularChannelConfig(ADC1,ADC_Channel_3,4,ADC_SampleTime_239Cycles5); ADC_RegularChannelConfig(ADC1,ADC_Channel_10,5,ADC_SampleTime_239Cycles5); ADC_RegularChannelConfig(ADC1,ADC_Channel_11,6,ADC_SampleTime_239Cycles5); ADC_RegularChannelConfig(ADC1,ADC_Channel_12,7,ADC_SampleTime_239Cycles5); ADC_RegularChannelConfig(ADC1,ADC_Channel_13,8,ADC_SampleTime_239Cycles5); ADC_DMACmd(ADC1,ENABLE); ADC_Cmd(ADC1,ENABLE);//使能ADC ADC_ResetCalibration(ADC1);//使能復位校準 while(ADC_GetResetCalibrationStatus(ADC1));//等待校準完成 ADC_StartCalibration(ADC1);//使能ADC校準 while(ADC_GetCalibrationStatus(ADC1));//等待校準完成 ADC_SoftwareStartConvCmd(ADC1,ENABLE);//啟動一次ADC轉換 ADcDMA_Configuration(); //測試 ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能ADC轉換 DMA_Cmd(DMA1_Channel1, ENABLE); //使能DMA搬移 } void ADcDMA_Configuration(void) { DMA_InitTypeDef DMA_InitStructure; DMA_DeInit(DMA1_Channel1); //復位DMA通道,ADC1專用DMA通道為DMA1-1 DMA_InitStructure.DMA_PeripheralBaseAddr =(u32)&ADC1->DR; //DMA從ADC1的DR處搬移 DMA_InitStructure.DMA_MemoryBaseAddr =(u32)&AD_Value; //搬移到AD_Value處 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//目的地址為記憶體 DMA_InitStructure.DMA_BufferSize = 64; //單次搬移數目 DMA_InitStructure.DMA_PeripheralInc =DMA_PeripheralInc_Disable; //搬移地址不累計 DMA_InitStructure.DMA_MemoryInc =DMA_MemoryInc_Enable; //目的地址逐次加1 DMA_InitStructure.DMA_PeripheralDataSize =DMA_PeripheralDataSize_HalfWord; //外圍資料大小為半個位元組(16位) DMA_InitStructure.DMA_MemoryDataSize =DMA_MemoryDataSize_HalfWord; //記憶體資料大小為半個位元組(16位) DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //設定迴圈工作模式 DMA_InitStructure.DMA_Priority =DMA_Priority_High; //設定DMA1_Channel1高優先順序 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //禁止記憶體到記憶體傳輸 DMA_Init(DMA1_Channel1, &DMA_InitStructure); }
非DMA模式
#include "ADcx.h" #include <stdio.h> #include "stm32f10x.h" #include "stm32f10x_rcc.h" #include "stm32f10x_adc.h" #include "stm32f10x_gpio.h" void ADcDMA_Configuration(void); u16 AD_Value[8][8]; //ADC資料快取 //初始化 void ADcx_Init(){ ADC_InitTypeDef ADC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC|RCC_APB2Periph_ADC1,ENABLE);//使能ADC時鐘和相關GPIO時鐘 RCC_ADCCLKConfig(RCC_PCLK2_Div6);//配置ADC時鐘72M/6=12,最大不能超過14 //GPIO配置 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN; GPIO_Init(GPIOA,&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN; GPIO_Init(GPIOC,&GPIO_InitStructure); ADC_DeInit(ADC1);//復位ADC ADC_InitStructure.ADC_Mode=ADC_Mode_Independent;//獨立工作模式 ADC_InitStructure.ADC_ScanConvMode=ENABLE;//啟動多通道掃描(單通道不要開啟) ADC_InitStructure.ADC_ContinuousConvMode=ENABLE;//啟動連續轉換 ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;//軟體觸發 ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;//右對齊 ADC_InitStructure.ADC_NbrOfChannel=8;//掃描8個通道 ADC_Init(ADC1,&ADC_InitStructure);//根據引數初始化ADC1 //指定8個通道的掃描順訊 ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_239Cycles5); ADC_RegularChannelConfig(ADC1,ADC_Channel_1,2,ADC_SampleTime_239Cycles5); ADC_RegularChannelConfig(ADC1,ADC_Channel_2,3,ADC_SampleTime_239Cycles5); ADC_RegularChannelConfig(ADC1,ADC_Channel_3,4,ADC_SampleTime_239Cycles5); ADC_RegularChannelConfig(ADC1,ADC_Channel_10,5,ADC_SampleTime_239Cycles5); ADC_RegularChannelConfig(ADC1,ADC_Channel_11,6,ADC_SampleTime_239Cycles5); ADC_RegularChannelConfig(ADC1,ADC_Channel_12,7,ADC_SampleTime_239Cycles5); ADC_RegularChannelConfig(ADC1,ADC_Channel_13,8,ADC_SampleTime_239Cycles5); ADC_Cmd(ADC1,ENABLE);//使能ADC ADC_ResetCalibration(ADC1);//使能復位校準 while(ADC_GetResetCalibrationStatus(ADC1));//等待校準完成 ADC_StartCalibration(ADC1);//使能ADC校準 while(ADC_GetCalibrationStatus(ADC1));//等待校準完成 ADC_SoftwareStartConvCmd(ADC1,ENABLE);//啟動一次ADC轉換 } //獲取ADC通道的值 void ADCValue(void) { u16 tempADC[8];//ADC資料存放地 ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能ADC轉換 while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));//等待轉換完成 tempADC[0]=ADC_GetConversionValue(ADC1); ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能ADC轉換 while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));//等待轉換完成 tempADC[1]=ADC_GetConversionValue(ADC1); ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能ADC轉換 while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));//等待轉換完成 tempADC[2]=ADC_GetConversionValue(ADC1); ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能ADC轉換 while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));//等待轉換完成 tempADC[3]=ADC_GetConversionValue(ADC1); ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能ADC轉換 while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));//等待轉換完成 tempADC[4]=ADC_GetConversionValue(ADC1); ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能ADC轉換 while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));//等待轉換完成 tempADC[5]=ADC_GetConversionValue(ADC1); ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能ADC轉換 while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));//等待轉換完成 tempADC[6]=ADC_GetConversionValue(ADC1); ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能ADC轉換 while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));//等待轉換完成 tempADC[7]=ADC_GetConversionValue(ADC1); ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能ADC轉換 while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));//等待轉換完成 tempADC[8]=ADC_GetConversionValue(ADC1); } 讀取指定通道值 uint16_t read_adc_value(uint8_t ch) { uint16_t adc_val = 0; ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 ); ADC_SoftwareStartConvCmd(ADC1, ENABLE); while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC )){}; adc_val = ADC_GetConversionValue(ADC1); return adc_val; }
關於間斷模式採集介紹
ADC_DiscModeChannelCountConfig(ADC1, 1); //對 ADC 規則組通道配置間斷模式
ADC_DiscModeCmd(ADC1, ENABLE); //使能指定的 ADC 規則組通道的間斷模式
這兩個庫函式就是配置ADC為間斷的模式,
配置為間斷模式之後,每一次軟體轉換啟動後,讀取的就是相應轉換的通道資料。
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能或者失能指定的ADC的軟體轉換啟動功能
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)); //等待轉換完成
adc1 = ADC_GetConversionValue(ADC1); //返回最近一次 ADCx 規則組的轉換結果