1. 程式人生 > >STM32F1xx 系列 多通道ADC DMA採集與非DMA採集

STM32F1xx 系列 多通道ADC DMA採集與非DMA採集

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 規則組的轉換結果