你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

关于ADC+DMA的疑问

[复制链接]
云鹤松 提问时间:2016-9-5 15:42 /
我用的是STM32F429芯片

首先贴代码:
void ADC1_CH6_DMA_Config(void)
{

  ADC_InitTypeDef       ADC_InitStructure;
  ADC_CommonInitTypeDef ADC_CommonInitStructure;
  DMA_InitTypeDef       DMA_InitStructure;
  GPIO_InitTypeDef      GPIO_InitStructure;

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);

//  DMA_DeInit(DMA2_Stream0);
  /* DMA2 Stream0 channe0 configuration **************************************/
  DMA_InitStructure.DMA_Channel = DMA_Channel_0;  
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_Address; //外设地址
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC_ConvertedValue;        //内存地址
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;       //dma传输方向单向
  DMA_InitStructure.DMA_BufferSize = 2; //设置DMA在传输时缓冲区的长度 word
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;      //设置DMA的外设递增模式,一个外设
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;       //设置DMA的内存递增模式,
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;   //外设数据字长
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;   //内存数据字长
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;       //设置DMA的传输模式:连续不断的循环模式
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;   //设置DMA的优先级别
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  DMA_Init(DMA2_Stream0, &DMA_InitStructure);
  DMA_Cmd(DMA2_Stream0, ENABLE);

  /* Configure ADC1 Channel6 pin as analog input ******************************/
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* ADC Common Init **********************************************************/
  ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;      //ADC工作模式:ADC1和ADC2工作在独立模式
  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;   //ADC时钟为APB2的4分频->84/4=21MHZ(F407ADC在2.4-3.6V供电电压下最大速率36M,稳定速度为30M)
  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
  ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
  ADC_CommonInit(&ADC_CommonInitStructure);

  /* ADC1 Init ****************************************************************/
  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//精度为12位   
  ADC_InitStructure.ADC_ScanConvMode = ENABLE;  //扫描方式
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;    //连续转换
  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;   //转换由软件而不是外部触发启动
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;        //ADC数据右对齐
  ADC_InitStructure.ADC_NbrOfConversion = 2;     //规定了顺序进行规则转换的ADC通道的数目
  ADC_Init(ADC1, &ADC_InitStructure);

  /* ADC1 regular channe6 configuration *************************************/
  ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 1, ADC_SampleTime_3Cycles);     //配置ADC1规则组(得出其单次采样时间为->(3+12)/21≈0.7us)
  ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 2, ADC_SampleTime_3Cycles);
/* Enable DMA request after last transfer (Single-ADC mode) */
  ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);

  /* Enable ADC1 DMA */
  ADC_DMACmd(ADC1, ENABLE);

  /* Enable ADC1 */
  ADC_Cmd(ADC1, ENABLE);

  /* Start ADC1 Software Conversion */
  ADC_SoftwareStartConv(ADC1);//软件启动转换
}



上面是我初始化ADC+DAM的代码。
下面我有3个问题。


问题1:
主函数中我是这样读取ADC值得
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ))//等待转换结束delay(1000);
    AD_value_1 = ADC_ConvertedValue[0];
    AD_value_2 = ADC_ConvertedValue[1];
    AD_value_1= (float)(AD_value_1/0xfff)*3.3;
    AD_value_2 = (float)(AD_value_2/0xfff)*3.3;


为什么我的程序老卡在  while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ))   这句上?


问题2:如何计算我的采样频率?

这点我不清楚,是2个通道每次采集用时0.7us还是每个通道都是0.7us.
还有就是,如何再提高下采集频率?



问题3:采集到的数据好多都是连着重复的,比如会有好多个0连着,还有好多2.632连着,数据根本不像正弦波。(我使用的是正弦波信号发生器,200KHZ,VPP=5V)。


收藏 1 评论6 发布时间:2016-9-5 15:42

举报

6个回答
回答时间:2016-9-5 16:55:25
1、等待DMA完成标志位,不是ADC的
2、每次采集
3、应该是程序中处理ADC导致的。先测试DMA正常后,再看看数据。

评分

参与人数 1ST金币 +2 收起 理由
zero99 + 2 赞一个!

查看全部评分

xmshao 回答时间:2016-9-5 17:10:37
1、程序老卡在  while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ))   这句?
什么情况下发生的? 不要用单步验证这点。

2、根据你的配置每次每个通道的转换时间为0.7us. 提高ADC时钟和减少采样时间可以提高采样频率。

3、硬件正确的情况下,还需配置合适采样周期。
另外,ADC直接可转换的最高电压为3.6V.如果高了的话你得做前期处理。

评分

参与人数 1ST金币 +2 收起 理由
zero99 + 2 很给力!

查看全部评分

云鹤松 回答时间:2016-9-5 18:44:20
xmshao 发表于 2016-9-5 17:10
1、程序老卡在  while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ))   这句?
什么情况下发生的? 不要用单步 ...

如何提高ADC的时钟?
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;  把4分频,变成ADC_Prescaler_Div2分频?除了这一点还能不能提高自身的ADC时钟?

配置合适采样周期
是不是满足采样定理就可以了?

我把ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 1, ADC_SampleTime_3Cycles); 里的 ADC_SampleTime_3Cycles改大些,是不是精度能提高?
云鹤松 回答时间:2016-9-7 11:54:11
有人么?帮我解答下吧!!!
云鹤松 回答时间:2016-9-9 09:32:22
结贴,STM32F4的ADC采集1K的信号还行,但是频率大些的不适合。最后决定采用AD的ADC芯片。

评分

参与人数 1ST金币 +2 收起 理由
zero99 + 2 结贴奖励

查看全部评分

maozheng110 回答时间:2016-9-10 16:14:32
学习一下 ADC+DMA

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版