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

新手求助,三重adc情况下DMA有什么函数可以关闭传输的

[复制链接]
lyl5530330 提问时间:2018-5-28 21:49 /
我想请问下,就是我用三重ADC采集同一个通道的数据,用DMA传输到数组中,然后将数组的数据通过串口传出来。比如采集的是一个高斯波,因为ADC一直在采数据,所以数组中的数一直在变化,那么串口传出来的数就有问题,有没有什么函数是停止当前DMA传输的,停止了DMA传输,数组的数据就不会变化,也就可以传出一个完整的数据不会有问题。我的main函数是这样的
  1. #include "stm32f4xx.h"
  2. #include "usart.h"
  3. #include "delay.h"
  4. #include "dma.h"
  5. #include "delay.h"
  6. #include "adc.h"
  7. #include "led.h"
  8. #include "sys.h"

  9. #define NUM 100
  10. int main(void)
  11. {
  12.         u16 adcx1,adcx2;
  13.         u8 i,t,z=0;
  14.         u32 adc_value[NUM];
  15.         delay_init(168);
  16.         uart_init(115200);
  17.         LED_Init();
  18.         MYDMA_DMA_DIR_PeripheralToMemoryConfig(DMA2_Stream0,DMA_Channel_0,(u32)&ADC->CDR,(u32)adc_value,NUM);
  19.         MYADC_configure();

  20.        
  21. while(1)       
  22. {
  23.         DMA_Cmd(DMA2_Stream0, DISABLE);
  24.         for(i=0;i<NUM;i++)
  25.                 {                       
  26.                         adcx1=adc_value[i]&0xffff0000>>16;
  27.                         USART_SendData(USART1,(adcx1&0xff00)>>8);
  28.                         while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
  29.                         USART_SendData(USART1,adcx1&0xff);
  30.                         while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
  31.                        
  32.                         adcx2=adc_value[i]&0xffff;
  33.                         USART_SendData(USART1,(adcx2&0xff00)>>8);
  34.                         while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
  35.                         USART_SendData(USART1,adcx2&0xff);
  36.                         while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
  37.          }
  38.           DMA_Cmd(DMA2_Stream0, ENABLE);
  39.                 delay_ms(3000);
  40.           LED0=!LED0;
  41.          
  42. }
  43.        
  44. }

复制代码
我现在使用的DMA_Cmd(DMA2_Stream0, DISABLE);无法用,函数执行到这里,所有数组的数据都变成一样的了,具体原因不明
收藏 评论2 发布时间:2018-5-28 21:49

举报

2个回答
feixiang20 回答时间:2018-5-29 00:23:24
来,参考下这个
ADC采集到的数据都存储在一个固定的寄存器中。当常规采样方式采样多个通道时候,使用DMA可以较好地避免将采集到的数据丢失。当ADC的DMA功能被使能的时候,每个通道转换完毕时都会发出一个DMA请求。DMA方式也不能完全避免数据丢失问题,要实现数据不丢失需要在DMA的同时开启OVERRUN模式,当数据丢失时就停止数据转换,只需要检测是否有OVR时间发生,就能解决采样数据丢失造成的问题。比如,通道错位什么的。
在STM32F4的Reference manual中可以查到ADC1 的DMA映射在DMA1、CH0、Stream0上。
DMA方式采集单一通道数据
配置ADC1的DMA初始化设置如下:
//DMA初始化
DMA_InitStructure.DMA_BufferSize = 4;
DMA_InitStructure.DMA_Channel = DMA_Channel_0;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&adcvalue1;   //目标数据位
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_BASE+0x4C;  //ADC->DR地址
DMA_InitStructure.DMA_PeripheralBurst =DMA_PeripheralBurst_Single;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_Init(DMA2_Stream0,&DMA_InitStructure);
DMA_Cmd(DMA2_Stream0,ENABLE);
在ADC寄存器中开启DMA传输,使用两个函数一个是设置CR2的DDS位,使得每次ADC数据更新时开启DMA传输;
另一个是设置ADC CR2的DMA位,使能ADC的DMA传输。
分别使用以下两个函数:
ADC_DMARequestAfterLastTransferCmd(ADC1,ENABLE); //源数据变化时开启DMA传输
ADC_DMACmd(ADC1,ENABLE);//使能ADC的DMA传输
最后,还是在adcvalue中读出ADC的采样值,可以看到,没有使用函数ADC_GetConversionValue来读ADC的DR寄存器,照样能输出ADC采样到的值:
  while(1)
  {
    for(i = 0;i<10000;i++)
    {
        sum += adcvalue1;
      if(i ==9999)
      {
         avgvota = sum/10000;
         sum = 0;
        printf("avg vota is: %d\r\n",avgvota*3300/0xfff);
      }
    }
  }

DMA方式采集4个通道数据
同时采样两路数据首先要将ADC_InitStructyre中的ADC_NbrOfConversion 改变。之后再用ADC_RegularChannelConfig将通道0添加到扫描通道序列即可。
从一路变成4路,总共改了一行代码,添加3行代码:
ADC_InitStructyre.ADC_NbrOfConversion = 2;
ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_144Cycles);
ADC_RegularChannelConfig(ADC1,ADC_Channel_1,2,ADC_SampleTime_144Cycles);
ADC_RegularChannelConfig(ADC1,ADC_Channel_2,3,ADC_SampleTime_144Cycles);
ADC_RegularChannelConfig(ADC1,ADC_Channel_3,4,ADC_SampleTime_144Cycles);
实验时候,将PA0、PA1、PA2、PA3的输入接地或者接3.3伏电源,可在电脑端看到两个数据在跳变:0和3300.说明采样到了数据。
在对PA端口进行初始化的时候
GPIO_InitStructure.GPIO_Pin = GPIO_PinSource0 | GPIO_PinSource1 | GPIO_PinSource2 | GPIO_PinSource3;
GPIO_PinSource0 和 GPIO_Pin_0 是不一样的。引脚初始化的时候应该用GPIO_Pin_0。查看库里边的宏定义,两个值是不一样的。
GPIO_PinSource0 指的是引脚号,GPIO_Pin_0却是GPIo寄存器里边对应的位。

评分

参与人数 1蝴蝶豆 +4 收起 理由
zero99 + 4

查看全部评分

lyl5530330 回答时间:2018-5-29 16:36:40
feixiang20 发表于 2018-5-29 00:23
来,参考下这个
ADC采集到的数据都存储在一个固定的寄存器中。当常规采样方式采样多个通道时候,使用DMA可 ...

谢谢您,这个是单个ADC采集数据,这个我以前用过走通了的,就是在三个ADC的时候遇到了问题

所属标签

相似问题

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