DMA 接收溢出的问题

[复制链接]
7281|30
 楼主| cb0035071 发表于 2009-4-22 16:02 | 显示全部楼层 |阅读模式
请教各位高手 如果DMA接收设置为4个字节,但发了5个字节时,会吧数组前面的字节覆盖掉,等下一次在发送4个字节的时候,DMA接收数组还是串了一个字节?怎么解决呢?
香水城 发表于 2009-4-22 16:16 | 显示全部楼层

什么芯片?

 楼主| cb0035071 发表于 2009-4-22 17:21 | 显示全部楼层

stm32103

stm32103
香水城 发表于 2009-4-22 18:36 | 显示全部楼层

对方发送多于DMA设置的数目,多出的数据应该不会覆盖前面

除非你使用了DMA的循环模式。

多出的数据应该还在接收数据寄存器中,下次接收时,重新初始化一下接收通道即可。


你也真懒,使用的是什么接收通道都不说!
 楼主| cb0035071 发表于 2009-4-22 20:00 | 显示全部楼层

谢谢香主给我解答

谢谢香主给我解答
我用的DMA1_Chanel5 做的串口接收,循环模式和普通模式都试过了,重新初始化了,一旦有一次接收数据溢出,以后接收的数据都会错位
McuPlayer 发表于 2009-4-22 20:35 | 显示全部楼层

不要用环形缓冲区模式

 楼主| cb0035071 发表于 2009-4-22 20:57 | 显示全部楼层

用普通模式也覆盖

用普通模式也覆盖
 楼主| cb0035071 发表于 2009-4-22 22:19 | 显示全部楼层

用普通模式也覆盖

用普通模式也覆盖 
香水城 发表于 2009-4-23 07:47 | 显示全部楼层

用普通模式也覆盖?不大可能

仔细检查你的程序,操作、设置不当。
 楼主| cb0035071 发表于 2009-4-23 12:59 | 显示全部楼层

麻烦香主帮忙看下我的程序那出了问题

 RCC_Configuration();
       
  /* NVIC configuration */
  NVIC_Configuration();

  /* Configure the GPIO ports */
  GPIO_Configuration();

  /* Configure the DMA */
  //DMA_Configuration();
  

  /* DMA Channel4 (triggered by USART1 Tx event) Config */
  DMA_DeInit(DMA1_Channel4);
  DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_DR_Base;
  DMA_InitStructure.DMA_MemoryBaseAddr = (u32)TxBuffer1;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
  DMA_InitStructure.DMA_BufferSize = TxBufferSize1;
  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_M2M = DMA_M2M_Disable;
  DMA_Init(DMA1_Channel4, &DMA_InitStructure);

  DMA_DeInit(DMA1_Channel5);  
  DMA_InitStructure1.DMA_PeripheralBaseAddr = USART1_DR_Base;
  DMA_InitStructure1.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure1.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure1.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  DMA_InitStructure1.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  DMA_InitStructure1.DMA_Mode = DMA_Mode_Normal;
  DMA_InitStructure1.DMA_Priority = DMA_Priority_VeryHigh;
  DMA_InitStructure1.DMA_M2M = DMA_M2M_Disable;
  DMA_InitStructure1.DMA_MemoryBaseAddr = (u32)&RxBuffer[0];
  DMA_InitStructure1.DMA_DIR = DMA_DIR_PeripheralSRC;
  DMA_InitStructure1.DMA_BufferSize = 4;
  DMA_Init(DMA1_Channel5, &DMA_InitStructure1);
 SetupUSART();
  /* Enable USART1 DMA TX request */
  USART_DMACmd(USART1, USART_DMAReq_Tx|USART_DMAReq_Rx, ENABLE);
  /* Enable DMA Channel5 Transfer Complete interrupt */
  DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE);
  DMA_ITConfig(DMA1_Channel4, DMA_IT_TC, ENABLE);
  /* Enable the USART1 Receive Interrupt */
  //USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

   /* Enable DMA Channel4 */
  //DMA_Cmd(DMA1_Channel4, ENABLE);
  /* Enable DMA Channel5 */
  DMA_Cmd(DMA1_Channel5, ENABLE);
 CurrDataCounter_End = DMA_GetCurrDataCounter(DMA1_Channel5);

  /* Wait until DMA_Channel 4 Transfer Complete */
  while(1)
  {
  ;        
  }

void DMAChannel5_IRQHandler(void)
{
if(DMA_GetITStatus(DMA1_IT_TC5))

        
        DMA_ClearITPendingBit(DMA1_IT_GL5);
        //CurrDataCounter_End = DMA_GetCurrDataCounter(DMA1_Channel5);
        DMA_Cmd(DMA1_Channel5, DISABLE);

        DMA_DeInit(DMA1_Channel5);  
       
        DMA_Init(DMA1_Channel5, &DMA_InitStructure1);

        /* Enable DMA Channel5 Transfer Complete interrupt */
        DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE);
        DMA_Cmd(DMA1_Channel5, ENABLE);
        DMA_ClearITPendingBit(DMA1_IT_GL5);         
        dmaflag = 1;
        for(i=0;i<5;i++)
           RxBuffer1=0;

    }
}
 楼主| cb0035071 发表于 2009-4-23 14:23 | 显示全部楼层

香主帮忙看下,谢谢

香主帮忙看下,谢谢
香水城 发表于 2009-4-23 14:32 | 显示全部楼层

你在哪里重新初始化接收通道了?

请看我在4楼的说明:多出的数据应该还在接收数据寄存器中,下次接收时,重新初始化一下接收通道即可。

你怎么知道覆盖的数据不是上次通信多出来的?
 楼主| cb0035071 发表于 2009-4-23 14:43 | 显示全部楼层

进入DMA中断后初始化的

        DMA_DeInit(DMA1_Channel5);  
        DMA_Init(DMA1_Channel5, &DMA_InitStructure1);

        /* Enable DMA Channel5 Transfer Complete interrupt */
        DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE);
        DMA_Cmd(DMA1_Channel5, ENABLE);
        DMA_ClearITPendingBit(DMA1_IT_GL5); 



        DMA_InitStructure1结构体没有重新付值因为我没有改变过结构体的值  
 楼主| cb0035071 发表于 2009-4-23 15:01 | 显示全部楼层

谢谢香主

DMA_Init(DMA1_Channel5, &DMA_InitStructure1);
这个函数是初始化接收通道吧,我测试了,是上次接收的数据覆盖了这次的数据,可是怎么把上次接收到的数据清掉呢
 楼主| cb0035071 发表于 2009-4-23 15:45 | 显示全部楼层

香主帮下忙

您看我初始化的对不对?
香水城 发表于 2009-4-23 15:50 | 显示全部楼层

请重新初始化你的通信通道,不是DMA通道

数据是从通信通道过来的,DMA通道没有数据!
 楼主| cb0035071 发表于 2009-4-23 16:11 | 显示全部楼层

串口1重新初始化了

串口1重新初始化了 也不行
 楼主| cb0035071 发表于 2009-4-24 08:14 | 显示全部楼层

没人遇到过类试的情况吗

没人遇到过类试的情况吗
香水城 发表于 2009-4-24 08:27 | 显示全部楼层

如何重新初始化UART1?

应该Disable,然后再Enable。


如果下次操作读到了上次多出的数据,说明重新初始化操作不对,重新初始化应能够把上次多出剩余在接收寄存器中的数据。重新初始化之后,接收缓冲器应该为空。

你也可以在DMA传输结束后,通过判断接收缓冲器是否为空,来判断对方是否多发了数据,如果对方确实多发了数据,也可以通过读出数据寄存器清除多出的数据。
 楼主| cb0035071 发表于 2009-4-24 09:22 | 显示全部楼层

是这么做的

是这么做的,先Disable,然后再Enable,在开启DMA后 出现接收乱的数据
您需要登录后才可以回帖 登录 | 注册

本版积分规则

5

主题

192

帖子

0

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