#include "adc.h"
#include "stm32f4xx.h"
__IO uint16_t ADC_ConvertValue[3]={10,10,10};//定义一个数组存储数字电压,ADC_ConvertValue[0]存储ADC1的数据,ADC_ConvertValue[1]存储ADC2的数据
//一定要配置为16位的数据,因为每一次传输的数据都是16位半字的
//ADC引脚功能配置-----PB组的引脚存在问题,具体我也不太清楚为什么
static void ADC_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
//RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//使能GPIOB时钟--对应PB1
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能GPIOA时钟--对应PA5
//PA1-ADC1_CH1
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;//模拟输入
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//不上下拉
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化
//PA6-ADC2_CH6
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;//模拟输入
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//不上下拉
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化
//PA0-ADC3_CH0
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;//模拟输入
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//不上下拉
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化
}
//ADC模式配置
static void ADC_Mode_Config(void)
{
/********DMA配置********/
DMA_InitTypeDef DMA_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//开启DMA2时钟,ADC的DMA通道都在DMA2下,查DMA表,在中文参考手册里面
// DMA_DeInit(DMA2_Stream0);//重置DMA2的流2,在多重ADC模式下,只要配置ADC1的流就行,因为ADC1是主ADC
DMA_InitStructure.DMA_PeripheralBaseAddr=(uint32_t)ADC_CDR_ADDR;//外设基地址:CDR寄存器
DMA_InitStructure.DMA_Memory0BaseAddr=(u32)ADC_ConvertValue;//存储器基地址,注意一定要是32位的,其它位数的则必须转换一下
DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralToMemory;//数据传输方向,外设到存储器
DMA_InitStructure.DMA_BufferSize=3;//一次传输数据的量,因为我使用的是ADC的DMA模式1,所以每次都是只传输1个数据
DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;//外设地址不递增
DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;//存储器地址递增
DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_HalfWord;//外设传输数据的宽度,16位,半字,2字节
DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord;//存储器的数据大小也要和外设一样,在使用FIFO模式时可以不一样
DMA_InitStructure.DMA_Mode=DMA_Mode_Circular;//DMA模式,这里选择循环传输
DMA_InitStructure.DMA_Priority=DMA_Priority_High;//DMA传输通道优先级设置,因为只使用了一个DMA通道,所以不用管优先级
//以下是DMA的FIFO功能配置,是不需要的,所以失能,其它配置不用管
DMA_InitStructure.DMA_FIFOMode=DMA_FIFOMode_Disable;//未使用FIFO模式,所以不使能
DMA_InitStructure.DMA_FIFOThreshold=DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_MemoryBurst=DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst=DMA_PeripheralBurst_Single;
DMA_InitStructure.DMA_Channel=DMA_Channel_0;//DMA的通道选择,因为ADC1使用DMA2,数据流0,通道0,这个是手册固定死的
DMA_Init(DMA2_Stream0,&DMA_InitStructure);//初始化DMA所有参数
DMA_Cmd(DMA2_Stream0,ENABLE);//使能DMA流,此后DMA可用
/************ADC配置***********/
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);//开启ADC1的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2,ENABLE);//开启ADC2的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3,ENABLE);//开启ADC3的时钟
RCC_AHB2PeriphResetCmd(RCC_APB2Periph_ADC1, ENABLE); // ADC1复位
RCC_AHB2PeriphResetCmd(RCC_APB2Periph_ADC1, DISABLE); // 复位结束
RCC_AHB2PeriphResetCmd(RCC_APB2Periph_ADC2, ENABLE); // ADC2复位
RCC_AHB2PeriphResetCmd(RCC_APB2Periph_ADC2, DISABLE); // 复位结束
//----------------------ADC Common结构体初始化-------------------------------------
ADC_CommonInitStructure.ADC_Mode=ADC_TripleMode_RegSimult;//ADC模式,三重ADC规则同步模式
ADC_CommonInitStructure.ADC_Prescaler=ADC_Prescaler_Div4;//ADC时钟分频:4分频
ADC_CommonInitStructure.ADC_DMAAccessMode=ADC_DMAAccessMode_1;//ADC的DMA传输模式1,参考中文参考手册可知
ADC_CommonInitStructure.ADC_TwoSamplingDelay=ADC_TwoSamplingDelay_5Cycles;//两个ADC采样时间间隔,,交替模式才有效
ADC_CommonInit(&ADC_CommonInitStructure);//初始化ADC通用参数部分
//-----------------------ADC Init结构体初始化-------------------------------
ADC_StructInit(&ADC_InitStructure);//初始化一遍ADC_InitStructure,使其有原始值
ADC_InitStructure.ADC_Resolution=ADC_Resolution_12b;//ADC分辨率,使用12位分辨率,最大值是4096
ADC_InitStructure.ADC_ScanConvMode=DISABLE;//不使用ADC通道扫描模式,因为每个ADC只有一个通道参与转换
ADC_InitStructure.ADC_ContinuousConvMode=ENABLE;//开启连续转换模式
ADC_InitStructure.ADC_ExternalTrigConvEdge=ADC_ExternalTrigConvEdge_None;//不是使用外部边沿触发
ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_T1_CC1;//外部触发通道选择。因为使用了软件触发,这个选项随便选就行
ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;//对齐方式选择右对齐
ADC_InitStructure.ADC_NbrOfConversion=1;//转换通道数目,每个ADC只有1个
//ADC1的结构体初始化
ADC_Init(ADC1,&ADC_InitStructure);
ADC_RegularChannelConfig(ADC1,ADC_Channel_1,1,ADC_SampleTime_3Cycles);//配置ADC1,通道8,通道转换顺序1,采样时间为3个时钟周期
//ADC2的结构体初始化
ADC_Init(ADC2,&ADC_InitStructure);
ADC_RegularChannelConfig(ADC2,ADC_Channel_6,1,ADC_SampleTime_3Cycles);//配置ADC2,通道9,通道转换顺序1,采样时间为3个时钟周期
//ADC3的结构体初始化
ADC_Init(ADC3,&ADC_InitStructure);
ADC_RegularChannelConfig(ADC3,ADC_Channel_0,1,ADC_SampleTime_3Cycles);//配置ADC2,通道9,通道转换顺序1,采样时间为3个时钟周期
ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);//使能多重ADC模式下的DMA传输请求after last transfer (multi-ADC mode)
ADC_DMACmd(ADC1,ENABLE);//使能ADC1的DMA功能
ADC_Cmd(ADC1,ENABLE);//使能ADC1
ADC_Cmd(ADC2,ENABLE);//使能ADC2
ADC_Cmd(ADC3,ENABLE);//使能ADC3
ADC_SoftwareStartConv(ADC1);//软件触发开始转换,只用触发ADC1即可,ADC23自动打开
}
void MY_ADC_Init(void)
{
ADC_GPIO_Config();
ADC_Mode_Config();
}
遇到的问题描述:
三重ADC,单通道采样,规则同时。
ADC1-CH1,ADC2-CH6,ADC3-CH0
出现的问题:
初次用三重ADC时,选用的是PB引脚做ADC的输入,但是发现数据非常乱,完全不符合实际数据,出现了两个电压数据完全相同、一个电压数据为0无变化的情况,以为是DMA和ADC在配置的时候错误,没有配置正确,但是对照网上的例子和野火、正点原子的例程发现配置是不应该有问题的,于是我选择换一个引脚组进行配置,PA组,更换之后数据开始正确采集,也没有错误,迷一样的问题呀
#include "adc.h"
#include "stm32f4xx.h"
__IO uint16_t ADC_ConvertValue[3]={10,10,10};//定义一个数组存储数字电压,ADC_ConvertValue[0]存储ADC1的数据,ADC_ConvertValue[1]存储ADC2的数据
//一定要配置为16位的数据,因为每一次传输的数据都是16位半字的
//ADC引脚功能配置-----PB组的引脚存在问题,具体我也不太清楚为什么
static void ADC_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
//RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//使能GPIOB时钟--对应PB1
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能GPIOA时钟--对应PA5
//PA1-ADC1_CH1
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;//模拟输入
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//不上下拉
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化
//PA6-ADC2_CH6
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;//模拟输入
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//不上下拉
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化
//PA0-ADC3_CH0
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;//模拟输入
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//不上下拉
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化
}
//ADC模式配置
static void ADC_Mode_Config(void)
{
/********DMA配置********/
DMA_InitTypeDef DMA_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//开启DMA2时钟,ADC的DMA通道都在DMA2下,查DMA表,在中文参考手册里面
// DMA_DeInit(DMA2_Stream0);//重置DMA2的流2,在多重ADC模式下,只要配置ADC1的流就行,因为ADC1是主ADC
DMA_InitStructure.DMA_PeripheralBaseAddr=(uint32_t)ADC_CDR_ADDR;//外设基地址:CDR寄存器
DMA_InitStructure.DMA_Memory0BaseAddr=(u32)ADC_ConvertValue;//存储器基地址,注意一定要是32位的,其它位数的则必须转换一下
DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralToMemory;//数据传输方向,外设到存储器
DMA_InitStructure.DMA_BufferSize=3;//一次传输数据的量,因为我使用的是ADC的DMA模式1,所以每次都是只传输1个数据
DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;//外设地址不递增
DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;//存储器地址递增
DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_HalfWord;//外设传输数据的宽度,16位,半字,2字节
DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord;//存储器的数据大小也要和外设一样,在使用FIFO模式时可以不一样
DMA_InitStructure.DMA_Mode=DMA_Mode_Circular;//DMA模式,这里选择循环传输
DMA_InitStructure.DMA_Priority=DMA_Priority_High;//DMA传输通道优先级设置,因为只使用了一个DMA通道,所以不用管优先级
//以下是DMA的FIFO功能配置,是不需要的,所以失能,其它配置不用管
DMA_InitStructure.DMA_FIFOMode=DMA_FIFOMode_Disable;//未使用FIFO模式,所以不使能
DMA_InitStructure.DMA_FIFOThreshold=DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_MemoryBurst=DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst=DMA_PeripheralBurst_Single;
DMA_InitStructure.DMA_Channel=DMA_Channel_0;//DMA的通道选择,因为ADC1使用DMA2,数据流0,通道0,这个是手册固定死的
DMA_Init(DMA2_Stream0,&DMA_InitStructure);//初始化DMA所有参数
DMA_Cmd(DMA2_Stream0,ENABLE);//使能DMA流,此后DMA可用
/************ADC配置***********/
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);//开启ADC1的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2,ENABLE);//开启ADC2的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3,ENABLE);//开启ADC3的时钟
RCC_AHB2PeriphResetCmd(RCC_APB2Periph_ADC1, ENABLE); // ADC1复位
RCC_AHB2PeriphResetCmd(RCC_APB2Periph_ADC1, DISABLE); // 复位结束
RCC_AHB2PeriphResetCmd(RCC_APB2Periph_ADC2, ENABLE); // ADC2复位
RCC_AHB2PeriphResetCmd(RCC_APB2Periph_ADC2, DISABLE); // 复位结束
//----------------------ADC Common结构体初始化-------------------------------------
ADC_CommonInitStructure.ADC_Mode=ADC_TripleMode_RegSimult;//ADC模式,三重ADC规则同步模式
ADC_CommonInitStructure.ADC_Prescaler=ADC_Prescaler_Div4;//ADC时钟分频:4分频
ADC_CommonInitStructure.ADC_DMAAccessMode=ADC_DMAAccessMode_1;//ADC的DMA传输模式1,参考中文参考手册可知
ADC_CommonInitStructure.ADC_TwoSamplingDelay=ADC_TwoSamplingDelay_5Cycles;//两个ADC采样时间间隔,,交替模式才有效
ADC_CommonInit(&ADC_CommonInitStructure);//初始化ADC通用参数部分
//-----------------------ADC Init结构体初始化-------------------------------
ADC_StructInit(&ADC_InitStructure);//初始化一遍ADC_InitStructure,使其有原始值
ADC_InitStructure.ADC_Resolution=ADC_Resolution_12b;//ADC分辨率,使用12位分辨率,最大值是4096
ADC_InitStructure.ADC_ScanConvMode=DISABLE;//不使用ADC通道扫描模式,因为每个ADC只有一个通道参与转换
ADC_InitStructure.ADC_ContinuousConvMode=ENABLE;//开启连续转换模式
ADC_InitStructure.ADC_ExternalTrigConvEdge=ADC_ExternalTrigConvEdge_None;//不是使用外部边沿触发
ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_T1_CC1;//外部触发通道选择。因为使用了软件触发,这个选项随便选就行
ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;//对齐方式选择右对齐
ADC_InitStructure.ADC_NbrOfConversion=1;//转换通道数目,每个ADC只有1个
//ADC1的结构体初始化
ADC_Init(ADC1,&ADC_InitStructure);
ADC_RegularChannelConfig(ADC1,ADC_Channel_1,1,ADC_SampleTime_3Cycles);//配置ADC1,通道8,通道转换顺序1,采样时间为3个时钟周期
//ADC2的结构体初始化
ADC_Init(ADC2,&ADC_InitStructure);
ADC_RegularChannelConfig(ADC2,ADC_Channel_6,1,ADC_SampleTime_3Cycles);//配置ADC2,通道9,通道转换顺序1,采样时间为3个时钟周期
//ADC3的结构体初始化
ADC_Init(ADC3,&ADC_InitStructure);
ADC_RegularChannelConfig(ADC3,ADC_Channel_0,1,ADC_SampleTime_3Cycles);//配置ADC2,通道9,通道转换顺序1,采样时间为3个时钟周期
ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);//使能多重ADC模式下的DMA传输请求after last transfer (multi-ADC mode)
ADC_DMACmd(ADC1,ENABLE);//使能ADC1的DMA功能
ADC_Cmd(ADC1,ENABLE);//使能ADC1
ADC_Cmd(ADC2,ENABLE);//使能ADC2
ADC_Cmd(ADC3,ENABLE);//使能ADC3
ADC_SoftwareStartConv(ADC1);//软件触发开始转换,只用触发ADC1即可,ADC23自动打开
}
void MY_ADC_Init(void)
{
ADC_GPIO_Config();
ADC_Mode_Config();
}
遇到的问题描述:
三重ADC,单通道采样,规则同时。
ADC1-CH1,ADC2-CH6,ADC3-CH0
出现的问题:
初次用三重ADC时,选用的是PB引脚做ADC的输入,但是发现数据非常乱,完全不符合实际数据,出现了两个电压数据完全相同、一个电压数据为0无变化的情况,以为是DMA和ADC在配置的时候错误,没有配置正确,但是对照网上的例子和野火、正点原子的例程发现配置是不应该有问题的,于是我选择换一个引脚组进行配置,PA组,更换之后数据开始正确采集,也没有错误,迷一样的问题呀
举报