STM32ADC多通道DMA读取

程序给出了3种ADC读取方式,单通道,DMA单通道和DMA多通道,下面是ADC.h文件:
#ifndef __ADC_H
#define __ADC_H
#include "sys.h"
#include "delay.h"

//-------------单通道 ADC读取----------------
void Adc_Init(void);
u16 get_ADC_Values(u8 ch,u8 rank);
u16 get_ADC_Average(u8 ch,u8 rank,u8 count);

//-------------单通道 ADC DMA读取----------------
void ADC_DMA_Init(void);
u16 get_ADC_DMA_Average(u8 count);

//-------------多通道 ADC DMA读取----------------
void ADC_DMA_Multichannel_Init(u32 ADC_Buff); 

#endif


ADC.c实现上面定义的函数:
#include "adc.h"
//单通道 DMA adc数据
volatile u16 adc_values;

//-------------单通道 ADC读取----------------
void Adc_Init() {
    ADC_InitTypeDef ADC_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);
    RCC_ADCCLKConfig(RCC_PCLK2_Div6);//72/6 = 12MHz
    //ADC1通道11的转换时间为T=(239.5+12.5) x 1/12=21us。

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(GPIOA, &GPIO_InitStructure);



    ADC_DeInit(ADC1);//复位ADC1
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//ADC 独立模式
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;//单次扫描模式
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//单次转换模式
    ADC_InitStructure.ADC_Mode = ADC_Mode_RegSimult;//ADC1 和ADC2 工作在同步规则模式
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//软件触发
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//数据右对齐
    ADC_InitStructure.ADC_NbrOfChannel = 1 ;//进行规则转换的ADC通道数量
    ADC_Init(ADC1, &ADC_InitStructure);//初始化ADC1


    ADC_Cmd(ADC1, ENABLE);
    ADC_ResetCalibration(ADC1);//开启复位校准
    while(ADC_GetResetCalibrationStatus(ADC1));//等待复位校准成功
    ADC_StartCalibration(ADC1);//开始校验ADC1
    while(ADC_GetCalibrationStatus(ADC1));//等待校验成功

}

u16 get_ADC_Values(u8 ch, u8 rank) {

    //设置指定ADC规则通道,设置转换时间
    ADC_RegularChannelConfig(ADC1, ch, rank, ADC_SampleTime_239Cycles5);
    ADC_SoftwareStartConvCmd(ADC1, ENABLE); //开启软件转换
    while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)); //等待转换结束
    return 	ADC_GetConversionValue(ADC1);
}


//返回ADC平均值
u16 get_ADC_Average(u8 ch, u8 rank, u8 count) {
    u32 temp_val = 0;
    u8 i;

    for(i = 0; i < count; i++) {
        temp_val += get_ADC_Values(ch, rank);
        delay_ms(5);
    }
    return temp_val / count;

}


//-------------单通道 ADC DMA读取----------------
void ADC_DMA_Init() {
    GPIO_InitTypeDef GPIO_InitStructure;
    ADC_InitTypeDef ADC_InitStructure;
    DMA_InitTypeDef DMA_InitStructure;
	
    //使能DMA1时钟
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);  
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1,ENABLE);      
  
		//初始化IO 
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;        
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;  
    GPIO_Init(GPIOA,&GPIO_InitStructure);  

    //复位DMA1 通道1 ADC
    DMA_DeInit(DMA1_Channel1);
    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&ADC1->DR;//ADC内存基地址
    DMA_InitStructure.DMA_MemoryBaseAddr  = (u32)&adc_values;//变量基地址
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//外设到内存
    DMA_InitStructure.DMA_BufferSize = 1;//数据宽度
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设内存地址不变
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;//变量内存地址不变
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//16字节 12位ADC
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//16字节
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//循环模式
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;//高优先级
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//关闭内存到内存传输
    DMA_Init(DMA1_Channel1, &DMA_InitStructure);//初始化DMA1 通道1
    DMA_Cmd(DMA1_Channel1, ENABLE);//使能DMA 通道1

    ADC_DeInit(ADC1);//复位ADC1
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//独立模式
    ADC_InitStructure.ADC_ScanConvMode = DISABLE; //关闭扫描
    ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //开启连续转换 触发一次 持续转换
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//软件触发转换
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//数据右对齐
    ADC_InitStructure.ADC_NbrOfChannel = 1;//转换一个通道
    ADC_Init(ADC1, &ADC_InitStructure);//初始化ADC
		//ADC时钟 不能大于14MHz
		RCC_ADCCLKConfig(RCC_PCLK2_Div6);//72/6 = 12MHz 
		//设置指定ADC规则通道,设置转换时间
    ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5);
    //使能ADC DMA
		ADC_DMACmd(ADC1, ENABLE);
		//使能ADC
    ADC_Cmd(ADC1, ENABLE);
		
		ADC_ResetCalibration(ADC1);//复位校准寄存器  
    while(ADC_GetResetCalibrationStatus(ADC1));//等待校准寄存器复位完成  
  
    ADC_StartCalibration(ADC1);//ADC校准  
    while(ADC_GetCalibrationStatus(ADC1));//等待校准完成  
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);//由于没有采用外部触发,所以使用软件触发ADC转换 
		
}
//返回ADC平均值
u16 get_ADC_DMA_Average(u8 count) {
    u32 temp_val = 0;
    u8 i;

    for(i = 0; i < count; i++) {
        temp_val += adc_values;
        delay_ms(5);
    }
    return temp_val / count;

}
//-------------多通道 ADC DMA读取----------------
void ADC_DMA_Multichannel_Init(u32 ADC_Buff) {
    GPIO_InitTypeDef GPIO_InitStructure;
    ADC_InitTypeDef ADC_InitStructure;
    DMA_InitTypeDef DMA_InitStructure;
	
    //使能DMA1时钟
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);  
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1,ENABLE);      
  
		//初始化IO 
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;        
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;  
    GPIO_Init(GPIOA,&GPIO_InitStructure);  

    //复位DMA1 通道1 ADC
    DMA_DeInit(DMA1_Channel1);
    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&ADC1->DR;//ADC内存基地址
    DMA_InitStructure.DMA_MemoryBaseAddr  = ADC_Buff;//变量基地址
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//外设到内存
    DMA_InitStructure.DMA_BufferSize = 3;//数据宽度
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设内存地址不变
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//变量内存地址增长
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//16字节 12位ADC
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//16字节
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//循环模式
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;//高优先级
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//关闭内存到内存传输
    DMA_Init(DMA1_Channel1, &DMA_InitStructure);//初始化DMA1 通道1
    DMA_Cmd(DMA1_Channel1, ENABLE);//使能DMA 通道1

    ADC_DeInit(ADC1);//复位ADC1
    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 = 3;//转换3个通道
    ADC_Init(ADC1, &ADC_InitStructure);//初始化ADC
		
		//ADC时钟 不能大于14MHz
		RCC_ADCCLKConfig(RCC_PCLK2_Div6);//72/6 = 12MHz 
		//设置指定ADC规则通道,设置转换时间
    ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5);
		ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 2, ADC_SampleTime_239Cycles5);
		ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 3, ADC_SampleTime_239Cycles5);
    //使能ADC DMA
		ADC_DMACmd(ADC1, ENABLE);
		//使能ADC
    ADC_Cmd(ADC1, ENABLE);
		
		ADC_ResetCalibration(ADC1);//复位校准寄存器  
    while(ADC_GetResetCalibrationStatus(ADC1));//等待校准寄存器复位完成  
  
    ADC_StartCalibration(ADC1);//ADC校准  
    while(ADC_GetCalibrationStatus(ADC1));//等待校准完成  
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);//由于没有采用外部触发,所以使用软件触发ADC转换 
		
}


主函数调用:

#include "stm32f10x.h"
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "string.h"
#include "usart.h"
#include "adc.h"




//3个通道ADC值
u16 ADC_BUFF[3];

int main(void)
{
    u16 tep_val;
    float adc_v;
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    delay_init();
    //初始化串口IO
    uart_init(115200);
		//单通道ADC DMA初始化
//      ADC_DMA_Init(); 
	//-------------多通道 ADC DMA读取----------------
    ADC_DMA_Multichannel_Init((u32)ADC_BUFF);
    while(1)
    {
				//-------------单通道 ADC DMA读取----------------
			//ADC通道1 获取10次取平均值
//				tep_val = get_ADC_DMA_Average(10);
//        adc_v	= (float)tep_val * (3.3 / 4096);
//        printf("\r\nADC1 PA1 = %d\r\n", tep_val);
//        printf("ADC1 PA1 = %fV\r\n", adc_v);
				//-------------多通道 ADC DMA读取----------------
        tep_val = ADC_BUFF[0];//ADC 通道1
        adc_v	= (float)tep_val * (3.3 / 4096);
        printf("\r\nADC1 PA1 = %d\r\n", tep_val);
        printf("ADC1 PA1 = %fV\r\n", adc_v);

        tep_val = ADC_BUFF[1];//ADC 通道2
        adc_v	= (float)tep_val * (3.3 / 4096);
        printf("\r\nADC1 PA2 = %d\r\n", tep_val);
        printf("ADC1 PA2 = %fV\r\n", adc_v);


        tep_val = ADC_BUFF[2];//ADC 通道3
        adc_v	= (float)tep_val * (3.3 / 4096);
        printf("\r\nADC1 PA3 = %d\r\n", tep_val);
        printf("ADC1 PA3 = %fV\r\n", adc_v);

       delay_ms(500);

    }
}





你可能感兴趣的:(STM32)