你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32F103 串口DMA+IDLE收发,速率过快会造成overrun

[复制链接]
小耳朵1500922649 提问时间:2019-3-20 10:36 /
串口通讯是比较常用的通讯方式,本人以前都是单字节中断接收,再开启一个定时器做空闲判断,和PC端做2ms收发无压力。这样做在高速度通讯过程中MCU会频繁进入接收中断,故而想测试一下DMA+IDLE, 收发都通过DMA,DMA每次接收最大数是64,进入IDLE中断后,从串口缓冲拷贝数据。在27字节收发测试时,PC发送一帧(27字节)的速率10 ms以上时,数据收发正常,而低于10ms后,PC端接收的帧数明显少于发送的帧数,而当发送速率设置为2ms时,PC端就无任何数据接收了。STM32 DEBUG发现串口overrun err,数据溢出,也就是MCU还没来得及拷贝数据,下一帧数据就已经到来了。测试code如下:
//DMA发送
void Usart1SendData_DMA(uint8_t *pdata, uint16_t Length)
{
        HAL_StatusTypeDef res;
        uint8_t retry=0;
        //while(UsartType1.dmaSend_flag == USART_DMA_SENDING);
        //UsartType1.dmaSend_flag = USART_DMA_SENDING;
        do
        {
                UsartType1.dmaSend_flag = USART_DMA_SENDING;
                res = HAL_UART_Transmit_DMA(&huart1, pdata, Length);
                if(res == HAL_OK)
                {
                        UsartType1.dmaSend_flag = USART_DMA_SENDOVER;
                }
                       
                        if(retry++>4) //3次尝试发送
                        {
                                return;
                        }
        }while(res != HAL_OK);
}

//DMA发送完成
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
        __HAL_DMA_DISABLE(huart->hdmatx);//关闭发送DMA
}

//串口接收空闲中断,检测到一个byte的高电平触发
void UsartReceive_IDLE(UART_HandleTypeDef *huart)
{
        uint32_t temp;

        if((__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE) != RESET))
        {
                __HAL_UART_CLEAR_IDLEFLAG(&huart1);
                HAL_UART_DMAStop(&huart1);
                //temp = huart1.hdmarx->Instance->CNDTR;// 获取DMA中未传输的数据个数
                temp = __HAL_DMA_GET_COUNTER(huart1.hdmarx);// 获取DMA中未传输的数据个数
                UsartType1.rx_len =  RECEIVELEN - temp;
                DataCpy(UsartType1.usartDMA_rxBuf, UsartType1.rx_len);
                UsartType1.receive_flag=true;
                HAL_UART_Receive_DMA(&huart1,UsartType1.usartDMA_rxBuf,RECEIVELEN);
        }
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{

}


//主循环检测空闲并发送
while (1)
  {
  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */
        if(UsartType1.receive_flag)//如果产生了空闲中断
                {
                        UsartType1.receive_flag=false;//清零标记
                        Usart1SendData_DMA(uu_rxfifo.buffer ,27);//串口打印收到的数据。

                }
}

void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */
        UsartReceive_IDLE(&huart1);
  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */

  /* USER CODE END USART1_IRQn 1 */
}

收藏 评论2 发布时间:2019-3-20 10:36

举报

2个回答
奏奏奏 回答时间:2019-3-20 11:25:25
自己用RAM容量做消息队列缓存,并控制收与发的时间间隔。
xiaoxiao0932 回答时间:2019-8-16 09:40:25
楼主是否解决此问题,我也遇到类似问题,pc端10ms发送100字节,板子DMA乒乓方式接收后,发送到pc,PC端接收的数据和发送的数据个数不一致
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版