打印

急问 stm32 串口使用dma接受的问题

[复制链接]
13404|24
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
chineser|  楼主 | 2009-9-17 01:31 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我是接受gps信息 一次接受500个 因为要接受一次处理一次 所有使用正常模式。
   但是我debug 只能接受一次的数据 我使用重新配置dma的方式 接受下一次  但是好像只是接受到一个字符 然后就像死机一样  再怎么运行 也接受不到数据  
   请香主 告知怎么 任意再次开启dma接受


太急了
沙发
bhsdlmj| | 2009-9-17 07:58 | 只看该作者
01:31发的贴啊啊 哈哈牛人!!

是这样的!!
你应该是没有仔细看文档。
文档中说的大概意思是需要重新初始化DMA的一个量(我忘记这个量是什么了,呵呵)
在中断中重新初始化这个量。

当然简单的方式是在中断里面对说有的DMA相关初始化都在中断里面重新初始化一遍。




          下面两句话是对那个量进行重新初始化的例子。(这是直接操作寄存器,大概不很直观哈哈 ,你看着办 (*^__^*) 嘻嘻……)
        (*((volatile unsigned long int *)0x40020064)) = (uint32_t)RxBuffer1;       
        (*((volatile unsigned long int *)0x4002005C)) = 30;

使用特权

评论回复
板凳
bhsdlmj| | 2009-9-17 08:03 | 只看该作者
上面两句后面还得从新使能DMA。 别忘记啦!!!



===================================================
最简单的方法是将初始化DMA的代码复制粘贴到中断服务程序的末尾,就可以了!!!



希望能解决你的问题啊

使用特权

评论回复
地板
newstary| | 2009-9-17 10:28 | 只看该作者
重新配置DMA之前必须先禁用DMA,修改CNT后再使能DMA。

使用特权

评论回复
5
chineser|  楼主 | 2009-9-17 10:32 | 只看该作者
我是这么做的 但是还是不行呢?
  大侠 能给个程序吗  必须要中断吗?

使用特权

评论回复
6
newstary| | 2009-9-17 10:57 | 只看该作者
DMA_Cmd(pDmaRxChannel, DISABLE);

    DMA_DeInit(pDmaRxChannel);
    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&(pUart->DR));
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)pRxAddr;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
    DMA_InitStructure.DMA_BufferSize = rxLen;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
    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(pDmaRxChannel, &DMA_InitStructure);

    USART_ClearFlag(pUart, USART_FLAG_RXNE);
    USART_DMACmd(pUart, USART_DMAReq_Rx, ENABLE);
    DMA_ITConfig(pDmaRxChannel, DMA_IT_TC, ENABLE);

    DMA_Cmd(pRxDmaChannel, ENABLE);

使用特权

评论回复
7
newstary| | 2009-9-17 11:03 | 只看该作者
另外为何一定要使用正常模式呢?循环模式应该更合适。

使用特权

评论回复
8
香水城| | 2009-9-17 11:24 | 只看该作者
在我们去年的巡回研讨会上,专门就这个问题有解说,请下载演讲稿看看:

STM32F10x常见应用解析(2008年9月)
http://www.stmicroelectronics.com.cn/stonline/mcu/MCU_Pages.htm

使用特权

评论回复
9
chineser|  楼主 | 2009-9-17 11:30 | 只看该作者
因为gps数据是一直发送过来的  要是循环模式 我接受完一次 在操作的时候  dma还在接受 不就把上次的覆盖了吗?

使用特权

评论回复
10
香水城| | 2009-9-17 11:36 | 只看该作者
使用循环模式结合缓冲区半满中断,在半满时处理前面已经收到的数据,同时DMA会继续接收后续数据;当缓冲区全满中断时,再处理后半区的数据,此时DMA会继续接收数据并从缓冲区开头存储。

只要处理半区数据的时间,小于接收满半区数据的时间,就不会发生数据丢失的情况。

使用特权

评论回复
11
chineser|  楼主 | 2009-9-17 11:52 | 只看该作者
恩 这个确实一个方法 也想过 但是关键 我的程序不能即时的响应他的标志位  也可能他置位很长时间了 我还没运行到那段程序

下面是我的程序:
RCC_Configuration();
  NVIC_Configuration();
  GPIO_Configuration();
USART_Configuration();
   DMA_Configuration();
while (1)
  {
          if(!DMA_GetFlagStatus(DMA1_FLAG_TC5) == RESET        )
          {                  DMA_ClearFlag(DMA1_FLAG_TC5);
             DMA_Cmd(DMA1_Channel5, DISABLE);
                   (*((volatile unsigned long int *)0x40020064)) = (u32)RxBuffer1;        
        (*((volatile unsigned long int *)0x4002005C)) = 500;
                           DMA_Cmd(DMA1_Channel5, ENABLE);
                }
  }

while 里面是判断 一次500接受完成  然后这里我没处理 直接开启下次转换

问题:
  第一次转换完成后 执行里面的
    DMA_ClearFlag(DMA1_FLAG_TC5);
             DMA_Cmd(DMA1_Channel5, DISABLE);
                   (*((volatile unsigned long int *)0x40020064)) = (u32)RxBuffer1;        
        (*((volatile unsigned long int *)0x4002005C)) = 500;
                           DMA_Cmd(DMA1_Channel5, ENABLE);
来开启下一次 转换  但是这个时候只能接受一个字节 从此以后在接受不到  

????????????????

使用特权

评论回复
12
chineser|  楼主 | 2009-9-17 13:08 | 只看该作者
还有就是 debug全速运行 如果此时硬件复位 他就会执行一次

使用特权

评论回复
13
newstary| | 2009-9-17 13:27 | 只看该作者
不介意的话把代码都放上来吧,我前阵子用过UART+DMA,中断里面开DMA,比你还复杂些:)

使用特权

评论回复
14
chineser|  楼主 | 2009-9-17 14:01 | 只看该作者
你的也是一直有数据过来吗?

void RCC_Configuration(void)
{
  /* RCC system reset(for debug purpose) */
  RCC_DeInit();

  /* Enable HSE */
  RCC_HSEConfig(RCC_HSE_ON);

  /* Wait till HSE is ready */
  HSEStartUpStatus = RCC_WaitForHSEStartUp();

  if(HSEStartUpStatus == SUCCESS)
  {
    /* Enable Prefetch Buffer */
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

    /* Flash 2 wait state */
    FLASH_SetLatency(FLASH_Latency_2);

    /* HCLK = SYSCLK */
    RCC_HCLKConfig(RCC_SYSCLK_Div1);
  
    /* PCLK2 = HCLK */
    RCC_PCLK2Config(RCC_HCLK_Div1);

    /* PCLK1 = HCLK/2 */
    RCC_PCLK1Config(RCC_HCLK_Div2);

    /* PLLCLK = 8MHz * 9 = 72 MHz */
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);

    /* Enable PLL */
    RCC_PLLCmd(ENABLE);

    /* Wait till PLL is ready */
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
    {
    }

    /* Select PLL as system clock source */
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

    /* Wait till PLL is used as system clock source */
    while(RCC_GetSYSCLKSource() != 0x08)
    {
    }
  }
   
  /* DMA1 clock enable */
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

  /* Enable USART1, GPIOA, GPIOx and AFIO clocks */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);

}

使用特权

评论回复
15
chineser|  楼主 | 2009-9-17 14:01 | 只看该作者
void GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;


  /* Configure USART1 Rx (PA.10) as input floating */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOA, &GPIO_InitStructure);


  
  /* Configure USART1 Tx (PA.09) as alternate function push-pull */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  
}

使用特权

评论回复
16
chineser|  楼主 | 2009-9-17 14:02 | 只看该作者
void DMA_Configuration(void)
{
  DMA_InitTypeDef DMA_InitStructure;

  /* DMA1 Channel4 (triggered by USART1 Tx event) Config */
  DMA_DeInit(DMA1_Channel5);  
  DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_DR_Base;
  DMA_InitStructure.DMA_MemoryBaseAddr = (u32)RxBuffer1;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
  DMA_InitStructure.DMA_BufferSize = TxBufferSize2;
  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_Channel5, &DMA_InitStructure);
           /* Enable DMA1 Channel5 */
  DMA_Cmd(DMA1_Channel5, ENABLE);
}
void USART_Configuration(void)
{         

USART_InitStructure.USART_BaudRate = 38400;
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  USART_InitStructure.USART_StopBits = USART_StopBits_1;
  USART_InitStructure.USART_Parity = USART_Parity_No;
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  
  /* Configure USART1 */
  USART_Init(USART1, &USART_InitStructure);
  /* Configure USART2 */


  /* Enable USART1 DMA Rx and TX request */
  USART_DMACmd(USART1, USART_DMAReq_Rx | USART_DMAReq_Tx, ENABLE);
         USART_Cmd(USART1, ENABLE);
  }

使用特权

评论回复
17
chineser|  楼主 | 2009-9-17 14:03 | 只看该作者
int main(void)
{
#ifdef DEBUG
  debug();
#endif

  /* System Clocks Configuration */
  RCC_Configuration();
      
  /* NVIC configuration */
  NVIC_Configuration();

  /* Configure the GPIO ports */
  GPIO_Configuration();
USART_Configuration();
  /* Configure the DMA */
  DMA_Configuration();
  while (1)
  {
          if(!DMA_GetFlagStatus(DMA1_FLAG_TC5) == RESET        )
          {                  DMA_ClearFlag(DMA1_FLAG_TC5);
               

                DMA_Cmd(DMA1_Channel5, DISABLE);
       (*((volatile unsigned long int *)0x40020064)) = (u32)RxBuffer1;        
        (*((volatile unsigned long int *)0x4002005C)) = 500;
                                 
                           DMA_Cmd(DMA1_Channel5, ENABLE);

                }
  }
}

使用特权

评论回复
18
newstary| | 2009-9-17 16:21 | 只看该作者
lz的情况我没有复现:L 每次收500个准时进入断点
原来怀疑RxBuffer1不够大的原因,但我改成TxBufferSize2也是正常的
建议搞个LED翻转下,看看到底能不能正常收

main.rar

3.34 KB

使用特权

评论回复
19
chineser|  楼主 | 2009-9-17 16:31 | 只看该作者
对啊 第一次是能收到 但是在打开dma  就接受不到了

使用特权

评论回复
20
chineser|  楼主 | 2009-9-17 16:34 | 只看该作者
你debug  也能每次都收到?

使用特权

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

本版积分规则

93

主题

261

帖子

0

粉丝