#define adNum 10000
u16 adsample[adNum];
//#define DMA1_Channel4_IRQn_EN 1//DMA 电压采集中断
#ifdef DMA1_Channel4_IRQn_EN
#define DMA1_Channel4_IRQn_PreemptionPriority 1
#define DMA1_Channel4_IRQn_SubPriority 1
u16 Flag,FlagTemp;
void DMA1_Channel1_IRQHandler(void)
{
if(DMA_GetITStatus(DMA1_IT_TC1)!=RESET)
{
DMA_ClearITPendingBit(DMA1_IT_TC1);
Flag++;
}
}
#endif
void ADCDMAInit(void)
{
u8 ADC_SampleTime;
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_ADCCLKConfig(RCC_PCLK2_Div8);//RCC_PCLK2_Div6//12M
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1|RCC_APB2Periph_GPIOC,ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Pin =(GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3);
GPIO_Init(GPIOC,&GPIO_InitStructure);
/* DMA channel1 configuration ---------------------------*/
DMA_DeInit(DMA1_Channel1); //将DMA的通道1寄存器重设为缺省值
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&ADC1->DR;//DMA外设ADC基地址
DMA_InitStructure.DMA_MemoryBaseAddr =(u32)&adsample[0]; //DMA内存基地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //内存作为数据传输的目的地
DMA_InitStructure.DMA_BufferSize =adNum; //DMA通道的DMA缓存的大小
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址寄存器不变
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器递增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //数据宽度为16位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //数据宽度为16位
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//正常模式!!!!
DMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMA通道 x拥有高优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x没有设置为内存到内存传输
DMA_Init(DMA1_Channel1, &DMA_InitStructure); //根据DMA_InitStruct中指定的参数初始化DMA的通道
#ifdef DMA1_Channel4_IRQn_EN
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=DMA1_Channel4_IRQn_PreemptionPriority ;//抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = DMA1_Channel4_IRQn_SubPriority; //子优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
DMA_ITConfig(DMA1_Channel1,DMA_IT_TC,ENABLE);
#endif
ADC_InitStructure.ADC_Mode=ADC_Mode_RegSimult;
ADC_InitStructure.ADC_ContinuousConvMode=ENABLE;
ADC_InitStructure.ADC_ScanConvMode=ENABLE;
ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel=5;
ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;
ADC_Init(ADC1,&ADC_InitStructure);
ADC_SampleTime=ADC_SampleTime_71Cycles5;//ADC_SampleTime_71Cycles5;//ADC_SampleTime_55Cycles5;//ADC_SampleTime_239Cycles5;//ADC_SampleTime_1Cycles5;//ADC_SampleTime_13Cycles5;//
ADC_RegularChannelConfig(ADC1, ADC_Channel_10,1, ADC_SampleTime);//L1
ADC_RegularChannelConfig(ADC1, ADC_Channel_11,2, ADC_SampleTime);//L2
ADC_RegularChannelConfig(ADC1, ADC_Channel_12,3, ADC_SampleTime);//L3
ADC_RegularChannelConfig(ADC1, ADC_Channel_13,4, ADC_SampleTime);//V
ADC_RegularChannelConfig(ADC1, ADC_Channel_17,5, ADC_SampleTime);//内部参考电压
ADC_DMACmd(ADC1, ENABLE);
ADC_Cmd(ADC1,ENABLE);
DMA_Cmd(DMA1_Channel1, ENABLE);
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}
#ifdef DMA1_Channel4_IRQn_EN
if(Flag!=Flagtemp)
{
Flagtemp=Flag;
DMA_Cmd(DMA1_Channel1, DISABLE); //关闭DMA
ADC_Cmd(ADC1,DISABLE); //关闭ADC
ProcessUData();//数据处理
DMA_SetCurrDataCounter(DMA1_Channel1,adNum); //传输数据变成0,必须重新设置
DMA_Cmd(DMA1_Channel1,ENABLE); //开DMA1
ADC_Cmd(ADC1,ENABLE); //开ADC
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //触发转换
}
#endif
if(DMA_GetFlagStatus(DMA1_IT_TC1)!=RESET)
{
DMA_ClearFlag(DMA1_IT_TC1);
DMA_Cmd(DMA1_Channel1, DISABLE); //关闭DMA
ADC_Cmd(ADC1,DISABLE); //关闭ADC
ProcessUData();//数据处理
DMA_SetCurrDataCounter(DMA1_Channel1,adNum); //传输数据变成0,必须重新设置
DMA_Cmd(DMA1_Channel1,ENABLE); //开DMA1
ADC_Cmd(ADC1,ENABLE); //开ADC
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //触发转换
}
1、DMA工作在DMA_Mode_Normal模式下传输完成后需要重新设定DMA_MemoryDataSize。设定该参数就需要先关闭DMA,然后再开启。
没有这一步操作,DMA只能传输一次。
2、DMA传输完成后要先关闭ADC,再开启ADC,然后再ADC_SoftwareStartConvCmd-ENABLE。没有这个过程,通道数据将会打乱
3、DMA1_Channel4_IRQn_EN 配置DMA中断或查询
DMA_Cmd(DMA1_Channel1, DISABLE); //关闭DMA
ADC_Cmd(ADC1,DISABLE); //关闭ADC
DMA_SetCurrDataCounter(DMA1_Channel1,adNum);
DMA_Cmd(DMA1_Channel1,ENABLE);
ADC_Cmd(ADC1,ENABLE);
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //触发转换