野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 10291|回复: 11

关于 AD采集 DMA传送的问题

[复制链接]
发表于 2017-6-12 01:50:17 | 显示全部楼层 |阅读模式
本帖最后由 gzhlove 于 2017-6-12 10:13 编辑

芯片 STM32F429
开发板 F429 挑战者
采用 PA3 采集 50 Hz 正弦交流电压  (信号源为 信号发生器 )
信号源.jpg
直流偏压为1.6V

采集方法  ADC 采用 定时器 TIM2 TRGO触发  TIM2定时时间为 54us  在一个正弦波周期内 一共采集357次  
DMA 传输数据的数目也为357个 数据宽度选为字节 也就是8位  DMA传输完成后 进入中断  置标志位为 1
主函数判断标志位   = 1 时  并通过串口把这357个数据发送的上位机.
现在的问题是 上位机 只能接收到 178个数据  后面的 所有数据均为 0  下图是用EXCEL 恢复出来的波形

Excel 恢复波形

Excel 恢复波形

可以看出 在177位 就是无效数据了
程序 太多 打包上传吧

谁做过 或是 懂得的 谈谈看法 谢谢了

STM32F429_ADC_DMA.rar (670.73 KB, 下载次数: 43)
回复

使用道具 举报

发表于 2017-6-12 08:58:27 | 显示全部楼层
刚好一半,你是不是使用了 半传输完成中断
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-6-12 09:49:09 | 显示全部楼层
flyleaf 发表于 2017-6-12 08:58
刚好一半,你是不是使用了 半传输完成中断

我使用的是 TCIF中断标志  相关程序
static void ADCx_DMA_Config(void)
{
   DMA_InitTypeDef DMA_InitStructure;

   RCC_AHB1PeriphClockCmd(ADCx_DMA2_CLK, ENABLE);
            
   /*>! 外设地址  也就是ADC数据寄存器的地址   */     
   DMA_InitStructure.DMA_PeripheralBaseAddr = ADCx_DR_ADDR;
   
   /*>! 存储器 0 地址  也就是用于保存ADC数据的变量地址  */     
   DMA_InitStructure.DMA_Memory0BaseAddr    = (u32)&ADC_ConvertedValue;   
   
   /*>! 传输方向 外设到存储器 ADC 到 SRAM */     
   DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
   
   /*>! 数据数目  */     
   DMA_InitStructure.DMA_BufferSize = 357;      
  
   /*>! 外设递增   */   
   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
   
   /*>! 存储器0地址递增 使能 */     
   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
   
   /*>! 外设数据宽度 */
   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
   
   /*>! 存储器数据宽度 */
   DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;       
   
   /*>! 模式选择循环传输模式  */
   DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;     //循环模式
   
   /*>! 优先级  */
   DMA_InitStructure.DMA_Priority = DMA_Priority_High;
   
   /*>! 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 = ADCx_DMA2_CHANNEL;
   
   /*>! 写入DMA寄存器参数  */
   DMA_Init(ADCx_DMA2_STREAM, &DMA_InitStructure);
   /*>! 传输完成中断 TC 使能  */
   DMA_ITConfig(ADCx_DMA2_STREAM,DMA_IT_TC,ENABLE);
   /*>! 使能DMA  */
   DMA_Cmd(ADCx_DMA2_STREAM, ENABLE);        
}

中断程序

void  DMA2_Stream0_IRQHandler(void)
{
      if(DMA_GetFlagStatus(ADCx_DMA2_STREAM,DMA_FLAG_TCIF0) == SET)  
      {
         TIM_Cmd(TIMx_Number,DISABLE);              
         k++;
         if(k >= 20)
         {
           DMA_Flag = 1;
           k = 0;                 
         }
         else
            TIM_Cmd(TIMx_Number,ENABLE);
      }
      DMA_ClearFlag(ADCx_DMA2_STREAM,DMA_FLAG_TCIF0);
}
回复 支持 反对

使用道具 举报

发表于 2017-6-12 09:56:10 | 显示全部楼层
gzhlove 发表于 2017-6-12 09:49
我使用的是 TCIF中断标志  相关程序
static void ADCx_DMA_Config(void)
{

直接用软件触发,不用定时器触发试试
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-6-12 10:04:26 | 显示全部楼层
本帖最后由 gzhlove 于 2017-6-12 10:13 编辑
随风 发表于 2017-6-12 09:56
直接用软件触发,不用定时器触发试试

软件采用连续触发时  数据正确这个定时器波形
啊擦文件0.jpg

回复 支持 反对

使用道具 举报

发表于 2017-6-12 10:18:36 | 显示全部楼层
gzhlove 发表于 2017-6-12 10:04
软件采用连续触发时  数据正确这个定时器波形

那就是定时器触发它采样一半就关闭采样了?具体定时器触发我也没试过,你确认下定时器怎样控制ADC持续采样
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-6-12 10:29:18 | 显示全部楼层
随风 发表于 2017-6-12 10:18
那就是定时器触发它采样一半就关闭采样了?具体定时器触发我也没试过,你确认下定时器怎样控制ADC持续采 ...

那么我就记录下定时器 触发次数吧
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-6-12 20:30:08 | 显示全部楼层
发现了一个很奇怪的问题

就是这句话  我定义的数组大小就是357
/*>! 数据数目  */     
   DMA_InitStructure.DMA_BufferSize = 357;      
如果 DMA_InitStructure.DMA_BufferSize = 357 的话 那么AD读出的值就是357的一半 177

要是令 DMA_InitStructure.DMA_BufferSize = 357 * 2 + 1的话 那就 ADC就是读出357的数据
谁知道为什么
还有就是 我看了 定时器的中断数 没有错
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-6-14 02:33:57 | 显示全部楼层
应该有始有终  问题已找到  
还是写下问题的所在吧 也给遇到我这样问题的伙伴提供一个参考
发现的问题是 ADC单通道采集时 采用定时器触发  触发次数为357次 DMA传输数据到指定的内存空间
结果发现  DMA传输数据时 共357个数据 只有177个数据有效  后面的 全部为 0 也就是无效数据
经过三天的检测 发现问题 如下
DMA的 外设数据宽度 与  存储器数据宽度  定义如下  /*>! 外设数据宽度 */
   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;

   /*>! 存储器数据宽度 */
   DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
ADC分辨率也为 8位

  /*>! ADC分辨率 8位  */        
   ADC_InitStructure.ADC_Resolution           = ADC_Resolution_8b;

然而 我定义了保存ADC数据的数组为 uint16_t ADC_ConvertedValue[BUFFER_SIZE];   (#define BUFFER_SIZE       357               //数据项数)

就这导致了DMA传输数据只有一半有效 而后一半全部为0

把uint16_t ADC_ConvertedValue[BUFFER_SIZE];  改为 uint8_t ADC_ConvertedValue[BUFFER_SIZE];  数据类型改为uint8_t 后
数据全部正确 如下图
捕获.JPG
可以看出  和上面的图完成不一样
那么接下来就是滤波了
写的不好 大概就是这个意思吧


回复 支持 反对

使用道具 举报

发表于 2017-6-14 10:46:49 | 显示全部楼层
亲,这很正常的,存储数据长度不匹配,你将8为的数据用16位的格子来存,我有点怀疑,8位的数据,用16位的格子来存,读出来的结果(前半部分)值没有变吗?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-6-14 14:08:20 | 显示全部楼层
陈加勇 发表于 2017-6-14 10:46
亲,这很正常的,存储数据长度不匹配,你将8为的数据用16位的格子来存,我有点怀疑,8位的数据,用16位的格 ...

看第一个图表 前部份的值应该是没有变化 因为在输出的时候 只输出了每个数据的低八位  我想 后面为0的那部分数据 是存在了每个数组元素的高字节里了
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2025-1-16 05:38 , Processed in 0.031985 second(s), 26 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表