在ADC高速采集数据时,通过DMA一次性获取大量的转换数据。比如5个通道,一次获取1000组数据。获得1000组数据后再统一处理,然后触发下一次转换。在调试过程中发现获取的通道数据序号出错。经过一番折腾终于调通,程序如下
定义
#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
ADC&DMA初始化
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); //触发转换
上一篇:STM32学习之路:I2C的基本读写
下一篇:【STM32CUBEMX】 I2C Slave 实现
推荐阅读最新更新时间:2024-11-14 10:19
设计资源 培训 开发板 精华推荐
- IP6829磁吸一比一无线充
- HV857,用于 MP3 播放器的 1 灯通用灯驱动器
- AM30EW-2412DZ ¦12V 单路输出 DC/DC 转换器的典型应用
- EVAL-AD7605-4SDZ,用于评估 AD7605-4、16 位同步采样、4 通道、SAR ADC 的评估板
- my_Megu Pad_v2
- LTC7812HUH 宽输入范围至 5V/5A 低 IQ 级联升压 + 降压稳压器(VMID 升压至 10V)的典型应用电路
- LT3088IDD 并联稳压器的典型应用
- MC78M05ABDTRKG 5V 电流升压稳压器的典型应用
- VM800P43A-PL、FT800显示系统VM800P开发模块、5V/16MHz ATMEG328P、Micro-SD插座、4.3寸TFT LCD触摸屏、珍珠壳
- 用于并联稳压器的 TL431 可编程精密基准的典型应用