[STM32F1] STM32 USART1用DMA方式接收问题

[复制链接]
1438|3
 楼主| 雪迷深冬 发表于 2016-12-7 11:13 | 显示全部楼层 |阅读模式
由于使用串口数量较多,并且串口1接收的数据量较大,不想占用中断,所以使用dma方式接收,使用串口的空闲总线中断方式来判定是否接收完一帧数据。
问题描述:
使用上述方式接收数据帧结果每次收到数据后都要进串口中断溢出错误。
  1.        
  2. DMA_InitTypeDef DMA_InitStructure;
  3. [code]
  4. void USART1_IRQHandler(void)      //串口1 中断服务程序
  5. {
  6.         OS_CPU_SR  cpu_sr;
  7.          
  8.         OS_ENTER_CRITICAL();  //保存全局中断标志,关总中断// Tell uC/OS-II that we are starting an ISR
  9.           OSIntNesting++;
  10.        
  11.           OS_EXIT_CRITICAL();          //恢复全局中断标志
  12.        
  13.         if(USART_GetFlagStatus(USART1,USART_FLAG_ORE)==SET)
  14.         {
  15.                 USART_ClearFlag(USART1,USART_FLAG_ORE);
  16.                 USART_ReceiveData(USART1);
  17.         }
  18.         if(USART_GetFlagStatus(USART1,USART_FLAG_NE)==SET)
  19.         {
  20.                 USART_ClearFlag(USART1,USART_FLAG_NE);
  21.                 USART_ReceiveData(USART1);
  22.         }
  23.         if(USART_GetFlagStatus(USART1,USART_FLAG_FE)==SET)
  24.         {
  25.                 USART_ClearFlag(USART1,USART_FLAG_FE);
  26.                 USART_ReceiveData(USART1);
  27.         }
  28.         /*
  29.         if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)==SET)
  30.         {
  31.                 if(RxCnt1<200)
  32.                         RxCnt1++;
  33.                 else
  34.                         RxCnt1 = 0;
  35.                 RxBuf1[RxCnt1] = USART_ReceiveData(USART1);
  36.                
  37.         }
  38.         */
  39.        
  40.         if(USART_GetFlagStatus(USART1,USART_FLAG_IDLE)==SET)
  41.         {
  42.                 USART_ClearFlag(USART1,USART_FLAG_IDLE);
  43.                 USART_ReceiveData(USART1);                                //清除中断标志位
  44.                 DMA_Cmd(DMA1_Channel5,DISABLE);                        //关闭dma防止干扰
  45.                 OSMboxPost(UsartWS_MBOX,(void *)RxBuf1);        //发送邮箱供前台处理
  46.         }
  47.        
  48.     OSIntExit();  //在os_core.c文件里定义,如果有更高优先级的任务就绪了,则执行一次任务切换   
  49.   
  50. }
USART_InitTypeDef USART_InitStructure;

        /*dma配置*/
       
        DMA_Cmd(DMA1_Channel5,DISABLE);
        DMA_DeInit(DMA1_Channel5);                                                                                                        //恢复缺省值
        DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_DR_Addr;                                        //DMA外设基地址                       
        DMA_InitStructure.DMA_MemoryBaseAddr = (u32)RxBuf1;                                                      //DMA内存基地址
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;                                                //外设为数据源
        DMA_InitStructure.DMA_BufferSize = 255;                                                                                //DMA缓存大小        ,单位为DataSize的值  要大于实际接收最大值
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;                        //外设地址寄存器不变         
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                                        //传送内存地址递增
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;         //数据宽度为8位
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;                                   //传送的目的地址是8位宽度
        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);
        DMA_ClearFlag(DMA1_FLAG_GL5);                                                                                                //清除dma所有标志
        DMA_Cmd(DMA1_Channel5,ENABLE);
       
        USART_InitStructure.USART_BaudRate = 4800;                                                //速率4800bps
        USART_InitStructure.USART_WordLength = USART_WordLength_9b;                //数据位8位
        USART_InitStructure.USART_StopBits = USART_StopBits_1;                        //停止位1位
        USART_InitStructure.USART_Parity = USART_Parity_Even;                         //偶校验
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;        //无硬件流控
        USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;                                        //收发模式

        /* Configure USARTx */
        USART_Init(USART1, &USART_InitStructure);                                                 //配置串口参数函数
        /* Enable USARTx Receive and Transmit interrupts */
        USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);                                        //开启串口空闲中断

        /* Enable the USARTx */       
        USART_DMACmd( USART1,USART_DMAReq_Rx,ENABLE);                                //开启串口dma接收
        USART_Cmd(USART1, ENABLE);        [/code]
huzi2099 发表于 2016-12-7 13:49 | 显示全部楼层
dma配置好就不要再开串口中断了,收发的数据会传送到缓冲区,用dma的半满或全满中断(或标记)处理。
天灵灵地灵灵 发表于 2016-12-7 18:05 | 显示全部楼层
楼上讲的很明白
dongnanxibei 发表于 2016-12-7 22:06 | 显示全部楼层
没看懂楼主是提问还是介绍经验呢。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

4

主题

16

帖子

1

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