DMA的数据采集问题

[复制链接]
3178|14
 楼主| ticomi 发表于 2013-6-6 18:11 | 显示全部楼层 |阅读模式
我是一DMA配合SPI采集数据多路数据,现在遇到问题每次切换通道后DMA中都有上一次通道中的数据,虽然只有几条数据,但是不确定量是多少给数据处理带来不少麻烦。

我想求助下,每次启动DMA读取时是否需要清空DMA的缓存区数据?DMA该如何设置才能确保不会残留上次的数据?

非常感谢!
lisn1234 发表于 2013-6-6 20:17 | 显示全部楼层
楼主用的哪个芯片?我最近在用407做DMA配合SPI的采集,也遇到了一些问题。可以交流下
mmuuss586 发表于 2013-6-6 20:22 | 显示全部楼层
没用过,我用的查询。
 楼主| ticomi 发表于 2013-6-7 08:37 | 显示全部楼层
lisn1234 发表于 2013-6-6 20:17
楼主用的哪个芯片?我最近在用407做DMA配合SPI的采集,也遇到了一些问题。可以交流下 ...

我用的是STM32F205,问题已经初步解决了。
lisn1234 发表于 2013-6-9 10:59 | 显示全部楼层
ticomi 发表于 2013-6-7 08:37
我用的是STM32F205,问题已经初步解决了。

我查了一下,205和407关于SPI和DMA的固件库函数基本一样,楼主能不能给我看一下DMA和SPI配置的那一部分函数呢?我弄了几天了DMA都不行啊,小弟感激不尽~~
lisn1234 发表于 2013-6-9 11:00 | 显示全部楼层
lisn1234 发表于 2013-6-9 10:59
我查了一下,205和407关于SPI和DMA的固件库函数基本一样,楼主能不能给我看一下DMA和SPI配置的那一部分函 ...

还有就是,改成stream0也不行……
 楼主| ticomi 发表于 2013-6-9 11:05 | 显示全部楼层
lisn1234 发表于 2013-6-9 10:59
我查了一下,205和407关于SPI和DMA的固件库函数基本一样,楼主能不能给我看一下DMA和SPI配置的那一部分函 ...

这个是SPI配置:
SPI_InitTypeDef  SPI_InitStructure;                //SPI初始化配置结构体       

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE);                //开启SPI1时钟

        ADC_DESELECTED;                //初始化后,不选择SPI从机器件ADC
        FLASH_DESELECTED;        //初始化后,不选择SPI从机器件FLASH

        /* 配置SPI2工作模式并初始化 */
        SPI_I2S_DeInit(SPI1);        //配置SPI1的外部寄存器到复位后的默认状态
        SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;        //全双工通信
        SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                //主机模式
        SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;        //8位传输
        SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;                        //时钟低位时空闲
        SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;                //数据在第二个时钟沿被采样
        SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                        //软件配置CS引脚
        SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;        //2分频,24MHz / 2 = 12MHz
        SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;        //数据传输高位在前
        SPI_InitStructure.SPI_CRCPolynomial = 1;                        //默认是7
        SPI_Init(SPI1, &SPI_InitStructure);                                        //初始化SPI1

        //SPI_CalculateCRC(SPI1,DISABLE);                                //不计算SPI1的传输CRC校验

        /* 配置SPI1的中断,不启动中断 */
        SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_TXE, DISABLE);
        SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_RXNE, DISABLE);

        /* 配置SPI的DMA请求模式 */
    SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);
    SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx, ENABLE);

        SPI_Cmd(SPI1, DISABLE);                //禁用SPI1
 楼主| ticomi 发表于 2013-6-9 11:05 | 显示全部楼层
lisn1234 发表于 2013-6-9 11:00
还有就是,改成stream0也不行……

这个是DMA配置:
  1. DMA_InitTypeDef  DMA_InitStructure;                //DMA配置初始化结构体
  2.   
  3.         RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);        //开启DMA2时钟  
  4.        

  5.         /* 配置DMA1的Channel3 stream0,        用于接收ADC的SPI传输数据 */

  6.         DMA_DeInit(DMA2_Stream0);        //复位DMA2的Stream0的寄存器到复位默认状态

  7.         /* 在使能DMA Stream前检查其是否被禁用,这一步非常重要当Stream用于其它复用时:启用、禁用、再
  8.            启用禁用,这种情况下DMA的Stream禁用将会影响到正在传输的数据,而且在再次使能前不能正确配置
  9.            被硬件清除的位,如果Streanm只被使用一次,这个步骤可以省略跳过        */
  10.         while (DMA_GetCmdStatus(DMA2_Stream0) != DISABLE);  
  11.        
  12.         DMA_InitStructure.DMA_Channel = DMA_Channel_3;                                                //选择通道3
  13.         DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32)(&(SPI1->DR));                //SPI1_BASE+0x0c寄存器地址,(uint32_t)(SPI1_BASE+0x0c)
  14.         DMA_InitStructure.DMA_Memory0BaseAddr = (uint32)ADC_RX_BUFFER;                //SPI接收ADC的数据地址
  15.         DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;                                //外设到内存
  16.         DMA_InitStructure.DMA_BufferSize = (uint32)(ADC_RX_BUFFER_SIZE * 3);        //DMA的接收缓冲区大小
  17.         DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;        //外设地址不增加
  18.         DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                                //内存地址增加
  19.         DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;        //外设按照字节传输
  20.         DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;                        //内存按照字节传输
  21.         DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                        //正常模式,非循环读取
  22.         DMA_InitStructure.DMA_Priority = DMA_Priority_High;                //优先级高
  23.         DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;        //关闭FIFO模式        
  24.         DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
  25.         DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  26.         DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  27.         DMA_Init(DMA2_Stream0, &DMA_InitStructure);                //配置DMA及Stream0并初始化
  28.    
  29.         /*        配置DMA2、通道3、stream0传输完成产生中断
  30.         **        DMA_IT_TC        传输完成产生DMA中断
  31.         **        DMA_IT_HT        传输一半产生DMA中断
  32.         **        DMA_IT_TE        传输错误产生DMA中断
  33.         **        DMA_IT_DME
  34.         **        DMA_IT_FE        FIFO传输错误*/       
  35.         DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE);       
  36.         DMA_Cmd(DMA2_Stream0, DISABLE);                                        //先关闭DMA2_Stream0
  37.   
  38.         /* 配置DMA2、channel3、stream0中断向量表 */
  39.         NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;
  40.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  41.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  42.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  43.         NVIC_Init(&NVIC_InitStructure);     


  44.         /* 配置DMA2 channe3 stream3 SPI的数据发送 */
  45.         DMA_DeInit(DMA2_Stream3);        //复位DMA2的Stream0的寄存器到复位默认状态

  46.     while ( DMA_GetCmdStatus(DMA2_Stream3) != DISABLE);

  47.     DMA_InitStructure.DMA_Channel = DMA_Channel_3;
  48.     DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32)(&(SPI1->DR));        //SPI->DR寄存器地址
  49.     DMA_InitStructure.DMA_Memory0BaseAddr = (uint32)ADC_TX_BUFFER;                //ADC发送数据起始地址
  50.     DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;                                //内存到外设
  51.     DMA_InitStructure.DMA_BufferSize = (uint32)ADC_TX_BUFFER_SIZE;                //DMA发送缓冲区大小
  52.     DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;        //外设地址不增加
  53.     DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                                //内存地址增加
  54.     DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;        //外设字节传输
  55.     DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;                        //内存字节传输
  56.     DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
  57.     DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
  58.     DMA_InitStructure.DMA_FIFOMode =DMA_FIFOMode_Disable;
  59.     DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
  60.     DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  61.     DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

  62.     DMA_Init(DMA2_Stream3, &DMA_InitStructure);                //配置DMA的Stream3并初始化               
  63.     DMA_ITConfig(DMA2_Stream3, DMA_IT_TC, ENABLE);        //配置DMA传输完成产生中断
  64.     DMA_Cmd(DMA2_Stream3, DISABLE);                                        //先关闭DMA的Stream3

  65.         /* 配置DMA2 channe3 stream3的中断向量 */
  66.     NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream3_IRQn;
  67.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  68.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  69.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  70.     NVIC_Init(&NVIC_InitStructure);         
 楼主| ticomi 发表于 2013-6-9 11:06 | 显示全部楼层
lisn1234 发表于 2013-6-9 11:00
还有就是,改成stream0也不行……

我的使用DMA配合SPI,也出现一些问题,目前仍在调试中
sun1238898 发表于 2013-6-9 11:53 | 显示全部楼层
你每次发送完数据,需要清除buffer的大小。
 楼主| ticomi 发表于 2013-6-9 11:56 | 显示全部楼层
sun1238898 发表于 2013-6-9 11:53
你每次发送完数据,需要清除buffer的大小。
  1. DMA_Cmd(DMA2_Stream3, DISABLE);               
  2.     DMA_SetCurrDataCounter(DMA2_Stream3, ADC_TX_BUFFER_SIZE);


是这样清除发送buffer吗?DMA接收完成后再次接收数据,是否需要清除接收缓冲区呢?如何清除?请帮忙指点下!非常感谢!
sun1238898 发表于 2013-6-9 12:06 | 显示全部楼层
DMA_SetCurrDataCounter(DMA2_Stream3, ADC_TX_BUFFER_SIZE);
sun1238898 发表于 2013-6-9 12:07 | 显示全部楼层
  
DMA_SetCurrDataCounter(DMA2_Stream3, ADC_TX_BUFFER_SIZE);
你要把这个设置为0
 楼主| ticomi 发表于 2013-6-9 13:35 | 显示全部楼层
sun1238898 发表于 2013-6-9 12:07
DMA_SetCurrDataCounter(DMA2_Stream3, ADC_TX_BUFFER_SIZE);
你要把这个设置为0

我测试了,这样不行。设置为0后不能正常读取SPI的数据
sun1238898 发表于 2013-6-9 15:25 | 显示全部楼层
设置为0,表示清除上一次数据,然后再设置为你想要的数据,然后使能,我说错了,有点。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

50

主题

852

帖子

4

粉丝
快速回复 在线客服 返回列表 返回顶部