打印

DMA的数据采集问题

[复制链接]
2715|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,问题已经初步解决了。

使用特权

评论回复
5
lisn1234| | 2013-6-9 10:59 | 只看该作者
ticomi 发表于 2013-6-7 08:37
我用的是STM32F205,问题已经初步解决了。

我查了一下,205和407关于SPI和DMA的固件库函数基本一样,楼主能不能给我看一下DMA和SPI配置的那一部分函数呢?我弄了几天了DMA都不行啊,小弟感激不尽~~

使用特权

评论回复
6
lisn1234| | 2013-6-9 11:00 | 只看该作者
lisn1234 发表于 2013-6-9 10:59
我查了一下,205和407关于SPI和DMA的固件库函数基本一样,楼主能不能给我看一下DMA和SPI配置的那一部分函 ...

还有就是,改成stream0也不行……

使用特权

评论回复
7
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

使用特权

评论回复
8
ticomi|  楼主 | 2013-6-9 11:05 | 只看该作者
lisn1234 发表于 2013-6-9 11:00
还有就是,改成stream0也不行……

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

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

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

        /* 在使能DMA Stream前检查其是否被禁用,这一步非常重要当Stream用于其它复用时:启用、禁用、再
           启用禁用,这种情况下DMA的Stream禁用将会影响到正在传输的数据,而且在再次使能前不能正确配置
           被硬件清除的位,如果Streanm只被使用一次,这个步骤可以省略跳过        */
        while (DMA_GetCmdStatus(DMA2_Stream0) != DISABLE);  
       
        DMA_InitStructure.DMA_Channel = DMA_Channel_3;                                                //选择通道3
        DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32)(&(SPI1->DR));                //SPI1_BASE+0x0c寄存器地址,(uint32_t)(SPI1_BASE+0x0c)
        DMA_InitStructure.DMA_Memory0BaseAddr = (uint32)ADC_RX_BUFFER;                //SPI接收ADC的数据地址
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;                                //外设到内存
        DMA_InitStructure.DMA_BufferSize = (uint32)(ADC_RX_BUFFER_SIZE * 3);        //DMA的接收缓冲区大小
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;        //外设地址不增加
        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_Normal;                        //正常模式,非循环读取
        DMA_InitStructure.DMA_Priority = DMA_Priority_High;                //优先级高
        DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;        //关闭FIFO模式        
        DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
        DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
        DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
        DMA_Init(DMA2_Stream0, &DMA_InitStructure);                //配置DMA及Stream0并初始化
   
        /*        配置DMA2、通道3、stream0传输完成产生中断
        **        DMA_IT_TC        传输完成产生DMA中断
        **        DMA_IT_HT        传输一半产生DMA中断
        **        DMA_IT_TE        传输错误产生DMA中断
        **        DMA_IT_DME
        **        DMA_IT_FE        FIFO传输错误*/       
        DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE);       
        DMA_Cmd(DMA2_Stream0, DISABLE);                                        //先关闭DMA2_Stream0
  
        /* 配置DMA2、channel3、stream0中断向量表 */
        NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);     


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

    while ( DMA_GetCmdStatus(DMA2_Stream3) != DISABLE);

    DMA_InitStructure.DMA_Channel = DMA_Channel_3;
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32)(&(SPI1->DR));        //SPI->DR寄存器地址
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32)ADC_TX_BUFFER;                //ADC发送数据起始地址
    DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;                                //内存到外设
    DMA_InitStructure.DMA_BufferSize = (uint32)ADC_TX_BUFFER_SIZE;                //DMA发送缓冲区大小
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;        //外设地址不增加
    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_Normal;
    DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
    DMA_InitStructure.DMA_FIFOMode =DMA_FIFOMode_Disable;
    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

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

        /* 配置DMA2 channe3 stream3的中断向量 */
    NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);         

使用特权

评论回复
9
ticomi|  楼主 | 2013-6-9 11:06 | 只看该作者
lisn1234 发表于 2013-6-9 11:00
还有就是,改成stream0也不行……

我的使用DMA配合SPI,也出现一些问题,目前仍在调试中

使用特权

评论回复
10
sun1238898| | 2013-6-9 11:53 | 只看该作者
你每次发送完数据,需要清除buffer的大小。

使用特权

评论回复
11
ticomi|  楼主 | 2013-6-9 11:56 | 只看该作者
sun1238898 发表于 2013-6-9 11:53
你每次发送完数据,需要清除buffer的大小。
DMA_Cmd(DMA2_Stream3, DISABLE);                
    DMA_SetCurrDataCounter(DMA2_Stream3, ADC_TX_BUFFER_SIZE);


是这样清除发送buffer吗?DMA接收完成后再次接收数据,是否需要清除接收缓冲区呢?如何清除?请帮忙指点下!非常感谢!

使用特权

评论回复
12
sun1238898| | 2013-6-9 12:06 | 只看该作者
DMA_SetCurrDataCounter(DMA2_Stream3, ADC_TX_BUFFER_SIZE);

使用特权

评论回复
13
sun1238898| | 2013-6-9 12:07 | 只看该作者
  
DMA_SetCurrDataCounter(DMA2_Stream3, ADC_TX_BUFFER_SIZE);
你要把这个设置为0

使用特权

评论回复
14
ticomi|  楼主 | 2013-6-9 13:35 | 只看该作者
sun1238898 发表于 2013-6-9 12:07
DMA_SetCurrDataCounter(DMA2_Stream3, ADC_TX_BUFFER_SIZE);
你要把这个设置为0

我测试了,这样不行。设置为0后不能正常读取SPI的数据

使用特权

评论回复
15
sun1238898| | 2013-6-9 15:25 | 只看该作者
设置为0,表示清除上一次数据,然后再设置为你想要的数据,然后使能,我说错了,有点。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

50

主题

852

帖子

4

粉丝