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)
{
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
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 规则组的转换结果