找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6079|回复: 2
收起左侧

关于STM32串口1IDLE模式兼DMA接收数据会丢失数据的问题

[复制链接]
ID:241423 发表于 2018-11-24 19:55 | 显示全部楼层 |阅读模式
本人想用STM32的DMA和串口1 的ILDE模式接收不定长数据帧,遇到一个奇怪的现象,当串口助手V2.0(正点原子的)手动发送所需要的数据包时,误包率很高,而改为60ms自动发送就几乎没有出现误包的问题,所谓的误包问题要不出现功能码出错,要不帧长度出现错误了。
  1. void Configuration_GPIO()
  2. {
  3.     GPIO_InitTypeDef  GPIO_InitStructure;
  4. // USART1_TX:PA9
  5.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;        
  6.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  7.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        
  8.         GPIO_Init(GPIOA, &GPIO_InitStructure);           
  9.         // USART1_RX:PA10
  10.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  11.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  12.         GPIO_Init(GPIOA, &GPIO_InitStructure);
  13. }
复制代码
  1. #include "Configuration_DMA.h"

  2. u8 RecBuffer[RecLength]  = {0};
  3. u8 Usart1_Rec_Cnt        = 0;

  4. void Configuration_DMA_USART()
  5. {
  6.         DMA_InitTypeDef DMA_InitStructure;
  7.         
  8.         /* 该DMA用于USART快速传输一帧数据,单字节时不需要 */
  9.         DMA_DeInit(DMA1_Channel5);
  10.         DMA_InitStructure.DMA_PeripheralBaseAddr = (u32) &USART1->DR;
  11.         DMA_InitStructure.DMA_MemoryBaseAddr = (u32) &RecBuffer;//这是初始化时候配置,可以根据程序运行重新设置。
  12.         DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
  13.         DMA_InitStructure.DMA_BufferSize = RecLength;
  14.         DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  15.         DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  16.         DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  17.         DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  18.         DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
  19.         DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
  20.         DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  21.         DMA_Init(DMA1_Channel5, &DMA_InitStructure);
  22.         DMA_Cmd(DMA1_Channel5, ENABLE);
  23. }


复制代码
  1. void Control_NVIC_USART1(FunctionalState NewStatus)
  2. {
  3.     NVIC_InitTypeDef NVIC_InitStructure;
  4.     // 设置NVIC中断分组4:4位抢占优先级,0位响应优先级
  5.     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);        
  6.    
  7.     NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
  8.         NVIC_InitStructure.NVIC_IRQChannelCmd = NewStatus;
  9.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  10.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  11.         NVIC_Init(&NVIC_InitStructure);
  12. }
复制代码
  1. void Configuration_USART(u32 baudrate)
  2. {
  3.         USART_InitTypeDef USART_InitStructure;

  4.         USART_InitStructure.USART_BaudRate = baudrate;
  5.         USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  6.         USART_InitStructure.USART_StopBits = USART_StopBits_1;
  7.         USART_InitStructure.USART_Parity = USART_Parity_No;
  8.         USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  9.         USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  10.         USART_Init(USART1, &USART_InitStructure);               
  11.         USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);           // 不使能接收中断
  12.     USART_ITConfig(USART1, USART_IT_TC, DISABLE);             // 不使能发送中断
  13.     USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);            // 使能空闲中断
  14.     USART_ClearFlag(USART1, USART_FLAG_TC);
  15.     USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
  16.         USART_Cmd(USART1, ENABLE);
  17.     // 防止首字节丢失
  18.     while(USART_GetFlagStatus(USART1,USART_FLAG_TC) == RESET);
  19. }

  20. void USART1_SendByte(uint8_t c)
  21. {
  22.     USART_SendData(USART1, (uint8_t)c);
  23.         while(USART_GetFlagStatus(USART1,USART_FLAG_TC) == RESET);
  24. }

  25. void USART1_SendNByte(u8 *pData,u8 Length)
  26. {
  27.     while(Length--)
  28.     {
  29.         USART1_SendByte(*pData);
  30.         pData++;
  31.     }
  32. }

  33. void USART1_IRQHandler(void)
  34. {        
  35.     u8 i;
  36.         if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)  
  37.         {
  38.         // 关闭USART1 TX DMA1 所指示的通道
  39.                 DMA_Cmd(DMA1_Channel5, DISABLE);
  40.                 // 读取数据 注意:这句必须要,否则不能够清除中断标志位。我也不知道为啥!
  41.                 USART_ReceiveData(USART1);
  42.         // 算出接本帧数据长度
  43.                 Usart1_Rec_Cnt = RecLength - DMA_GetCurrDataCounter(DMA1_Channel5);        
  44.         if(Usart1_Rec_Cnt != 8)
  45.             Usart1_Rec_Cnt = 0;
  46.                 /*------------------------串口测试段--------------------------------*/
  47.         for(i = 0;i < Usart1_Rec_Cnt;i++)
  48.         RecBuffer1[i] = RecBuffer[i];
  49.                 //***********帧数据处理函数************//
  50. //                printf ("The lenght:%d\r\n",Usart1_Rec_Cnt);
  51. //                printf ("The data:\r\n");
  52. //                USART1_SendNByte(RecBuffer, Usart1_Rec_Cnt);
  53. //                printf ("\r\nOver! \r\n");
  54.                 //*************************************//
  55.         
  56.                 // 清除中断标志
  57.                 USART_ClearITPendingBit(USART1, USART_IT_IDLE);         
  58.         // DMA通道的DMA缓存的大小
  59.                 DMA_SetCurrDataCounter(DMA1_Channel5, RecLength);
  60.         // 使能USART1 TX DMA1 所指示的通道
  61.                 DMA_Cmd(DMA1_Channel5, ENABLE);  
  62.      }
  63. }
复制代码
以上是我的GPIO。DMA、USART和中断的配置,请遇到过类似问题的大佬能够伸出援手,在下感激不尽!
回复

使用道具 举报

ID:451691 发表于 2019-2-15 20:39 来自手机 | 显示全部楼层
楼主解决了吗,我也遇到过了这问题
回复

使用道具 举报

ID:277574 发表于 2019-12-25 20:42 | 显示全部楼层
遇到类似问题,用串口助手自动发送,一样丢包
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表