搜索
bottom↓
回复: 2

[已解决]求教, stm32f303启动ADC的DMA传输时有几十ms的延迟

[复制链接]

出0入362汤圆

发表于 2019-10-15 17:21:32 | 显示全部楼层 |阅读模式
本帖最后由 tomzbj 于 2019-10-16 15:59 编辑

程序如下, ADC和DMA配置部分略, 大概流程是先设置dc->config里的num_samples, 然后调用ADCDMA_StartTransmission, 启动DMA.
在DMA2_Channel1_IRQHandler里判断是全满还是半满中断, 然后调用 ADCDMA_IRQHandler来把DMA缓冲区内容交替保存到外部spi sram.

现在的问题是发现每次会丢最前面的几个数据, 刚好前几个数据还比较重要.
用gt.t1 / t2 / t3记录DWT->CYCCNT发现, 从t2到t3一直是准确的500ms没有问题, 但从t1到t2最少是503ms, 多的时候达到588ms. 不知道这几十ms的时间耗在哪里了?



  1. typedef struct { unsigned long t1, t2, t3; } tt_t;
  2. tt_t gt;

  3. void ADCDMA_StartTransmission(void)
  4. {
  5.     extern tt_t gt;
  6.     gt.t1 = DWT->CYCCNT;               // 记录起始时间

  7.     DMA_Cmd(DMA2_Channel1, DISABLE);
  8.     DMA2_Channel1->CMAR = (unsigned long)g.adc_buffer;
  9.     DMA2_Channel1->CNDTR = MAX_SAMPLES;
  10.     DMA_Cmd(DMA2_Channel1, ENABLE);
  11.     ADC_DMACmd(ADC2, ENABLE);
  12. }

  13. void ADCDMA_StopTransmission(void)
  14. {
  15.     ADC_DMACmd(ADC2, DISABLE);
  16.     printf("Data acquisition done!\n");
  17. }

  18. void ADCDMA_IRQHandler(int dma_type)
  19. {
  20.     DataConfig_t* pdc = DC_Get();
  21.     int size;
  22.     static unsigned long spisram_addr = 0;
  23.     unsigned short* buf;

  24.     buf = g.adc_buffer;
  25.     if(dma_type == DMA_IT_TC)
  26.         buf = &g.adc_buffer[MAX_SAMPLES / 2];

  27.     size = MAX_SAMPLES / 2;
  28.     if(pdc->config.num_samples < size)
  29.         size = pdc->config.num_samples;
  30.     extern tt_t gt;
  31.     if(spisram_addr == 0) {
  32.         gt.t2 = DWT->CYCCNT;          // 记录第一次进中断时间
  33.     }
  34.     else if(spisram_addr == size * sizeof(g.adc_buffer[0])) {
  35.         gt.t3 = DWT->CYCCNT;       // 记录第二次进中断时间
  36.     }

  37.     SPISRAM_FastWrite(spisram_addr, size * sizeof(g.adc_buffer[0]), buf);

  38.     putchar('.');    fflush(stdout);

  39.     pdc->config.num_samples -= size;
  40.     spisram_addr += size * sizeof(g.adc_buffer[0]);
  41.     if(pdc->config.num_samples <= 0) {
  42.         ADCDMA_StopTransmission();
  43.         spisram_addr = 0;
  44.     }
  45. }

  46. void DMA2_Channel1_IRQHandler(void)
  47. {
  48.     if(DMA_GetITStatus(DMA2_IT_TC1) != RESET) {
  49.         ADCDMA_IRQHandler(DMA_IT_TC);
  50.         DMA_ClearITPendingBit(DMA2_IT_TC1);
  51.     }
  52.     if(DMA_GetITStatus(DMA2_IT_HT1) != RESET) {
  53.         ADCDMA_IRQHandler(DMA_IT_HT);
  54.         DMA_ClearITPendingBit(DMA2_IT_HT1);
  55.     }
  56. }
复制代码


--------------------------已解决----------------
改为不用ADC_DMACmd, 只用DMA_Cmd(DMA2_Channel1, DISABLE)和DMA_Cmd(DMA2_Channel1, ENABLE)来控制启动和停止DMA传输, 可以了.
看来ADC_DMACmd之后确实会延迟一小段时间再启动传输.

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2019-10-15 21:04:39 | 显示全部楼层
初始化的时候时间有差异吧,t1赋值放在初始化结束试试

出0入362汤圆

 楼主| 发表于 2019-10-15 22:01:18 | 显示全部楼层
jueenkay 发表于 2019-10-15 21:04
初始化的时候时间有差异吧,t1赋值放在初始化结束试试

你说放在StartTransmission的结尾? 试了,没区别啊。
那几个函数都只是改几个标志位的事,没啥实质操作。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-24 00:39

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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