0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

STM32 HAL库串口收发如何使用

科技绿洲 来源:矜辰所致 作者:矜辰所致 2023-06-22 10:38 次阅读
  • 前言
  • 一、 HAL 库串口收发
    • 1.1 串口发送
    • 1.2 串口接收
  • 二、 收发同时串口卡死?
    • 2.1 问题说明
    • 2.2 尝试的处理方式
  • 结语

前言

对于 STM32 串口的使用,确实很简单使用 STM32CubeMX 做好初始化,就可以直接使用了。

但是最近在某些产品上使用串口同时收发的时候,发现有时候串口会收不到数据了,但是发送正常,而且这个问题再数据量大的时候很容易出现,于是乎进行了好几天的问题测试……

一、 HAL 库串口收发

先简单回顾一下 STM32 HAL库串口收发是如何使用的。

1.1 串口发送

对于 STM32 来说,串口发送有3中方式:

  1. 轮询发送;
  2. 中断发送;
  3. DMA发送;

在实际产品上,大部分项目中都用的是 轮询 方式发送,本次出现接收卡死的问题的产品也是采用的轮询发送,所以我简单的说明一下轮询发送,其他两种方式为 STM32 学习的基础问题,这里就不过多讨论。

发送相对简单,在 HAL 库实际都是使用HAL_UART_Transmit函数:

图片

在这里插入图片描述

不管是哪个串口发送,都做了个简单的发送函数:

图片

在这里插入图片描述

发送没什么好说的,简单易用。

1.2 串口接收

和串口发送一样,串口接收有3中方式:

  1. 轮询接收;
  2. 中断接收;
  3. DMA接收;

在我们正常的项目使用中,一般都是 中断接收 或者 DMA 接收,基本上不会使用 轮询接收的方式。

那么对于本次出问题的产品,我采用的是 中断接收的方式。

但是相比较发送,在 HAL 库中 使用中断接收的方式就有点 “五花八门” 的感觉。

1.2.1 标准库接收

在标准库的时候,我们经常这么用,在串口初始化的时候使用下面的语句使能中断:

//在串口初始化代码之后加上中断使能
USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);

如果需要自动判断一帧数据,我们再开启一下 IDLE 中断:

USART_ITConfig(USART3, USART_IT_IDLE, ENABLE);

然后在对应的中断处理函数中,直接读取 DR 寄存器(STM32F103 而言为 DR,STM32L051 为RDR),然后当 IDLE 中断产生,也可以处理一下标志位:

//自己用的,用到了 USART_IT_IDLE 标志位,有时候不合适
void USART3_IRQHandler(void)                 //串口3中断服务程序
{
 u8 clear3=clear3;    //消除编译器没有用到的提醒
 // u8  Res;

 if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)  
  {
   USART_Enocean_BUF[Enocean_Data++] = USART3- >DR;
   USART3_RX_BUF[USART3_Data++] = USART_ReceiveData(USART3);
   // Res= USART_ReceiveData(USART3);
   // USART_SendData(USART1,Res);while(!(USART1- >SR&USART_FLAG_TXE)); 
  }

    else if(USART_GetITStatus(USART3, USART_IT_IDLE) != RESET)    
    {
   clear3=USART3- >SR; //读SR寄存器 可以清空寄存器
   clear3=USART3- >DR; //读DR寄存器(先读SR寄存器,再读DR,为了清除IDLE中断)      
   USART3_RX_STA=1;   //标记接收到了一帧数据
   //USART3_Data=0;
    }               //enocean是不是读不到一帧数据,不用一帧数据测试一下  
}

1.2.1 HAL库接收

HAL库接收方式一

在 HAL 库函数接收的时候,其实也可以使用标准库上一样的中断标志使能:

MX_LPUART1_UART_Init();
__HAL_UART_ENABLE_IT(&hlpuart1,UART_IT_RXNE);

IDLE 中断使能:

__HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE);

这种方式的处理方式,可以和标准库差不多。

在 HAL 库中,外设的中断的入口函数都放在stm32l0xx_it.c 这个文件夹中( 以STM32L051 为例),在这个文件中可以找到和标准库一样的 中断入口函数,我们可以进行如下处理:

void USART2_IRQHandler(void)
{
  /* USER CODE BEGIN USART2_IRQn 0 */

  /* USER CODE END USART2_IRQn 0 */
  HAL_UART_IRQHandler(&huart2);
  /* USER CODE BEGIN USART2_IRQn 1 */
  if(__HAL_UART_GET_FLAG(&huart2,UART_FLAG_RXNE) == SET){
      //  USART_Enocean_BUF[Enocean_Data++] = huart2.Instance- >RDR    
      //  RXNE 数据处理,直接读取数据      
  }
  if((__HAL_UART_GET_FLAG(&huart2,UART_FLAG_IDLE) != RESET))
  {
     __HAL_UART_CLEAR_IT(&huart2,UART_CLEAR_IDLEF); //Çå³ýÖÐ¶Ï  
     // ReceiveState = 1;
     // IDLE 数据处理,一帧数据接收标志位置位
  }
}
HAL库接收方式二

但是在于 HAL 中,还有一种比较常用的开启中断方法,不是直接使能中断,而是通过调用 HAL 库函数 HAL_UART_Receive_IT

图片

在这里插入图片描述

一般的使用方式步骤:

图片

在这里插入图片描述

对于本次需要说明的问题,就是使用了 HAL_UART_Receive_IT 函数导致的,下文我们会说明,这里列出了基本的使用步骤。

二、 收发同时串口卡死?

2.1 问题说明

最近测试部反馈,产品有些时候的下行没反应,这里所说的下行,其实就是串口接收。

霹雳扒拉一大堆多余的省略 ... ... 只说几个重点:

出问题的最后现象就是串口发送正常,但是永远接收不到数据了,其他程序正常运行。

出问题只存在于串口又有接收,又有发送的产品上。

产品发送一般是周期性的,但是接收是随机的,无线信号串口接收,所以产品的出问题的情况也是随机的,但是数据量大起来肯定就会出现永远接收不到的问题。

2.2 尝试的处理方式

因为所有的一些都是按照正常流程设计的,按理来说实在是不知道为什么会这样,所以网上查询测试了好久,现在我把尝试的处理方式以及步骤记录说明一下:

2.2.1 清除错误标志位

在使用 HAL 库的时候,有4个错误 flag,如下图:

图片

在这里插入图片描述

期初还以为是某些异常错误导致的,经过网上的的一些查询,刚开始是添加了清除错误标志位:

__HAL_UART_CLEAR_FLAG(&hlpuart1, UART_FLAG_PE);//清标志
 __HAL_UART_CLEAR_FLAG(&hlpuart1, UART_FLAG_FE);
 __HAL_UART_CLEAR_FLAG(&hlpuart1, UART_FLAG_NE);
 __HAL_UART_CLEAR_FLAG(&hlpuart1, UART_FLAG_ORE);

在需要的地方加上错误标志位清除,我是在清除串口缓存中处理的:

图片

在这里插入图片描述

2.2.2 串口溢出错误

其实串口溢出错误在上面的已经清除过标志位,因为这个问题着实搞得我头有点大,所以看到网上前人的处理方式和上面直接清除不一样,还是试了一把。

这里简单说明一下,我还特意去看了下自己的 CubeMX 设置,在设置的时候 有一个 Overrun 错误标志位,平时我们设置都不一定往下拉着看 = =!:

图片

在这里插入图片描述

然后确定了开启了串口溢出错误检测以后,我根据网上的方式,加了一个HAL_UART_ErrorCallback函数,其实就类似于HAL_UART_RxCpltCallback 函数:

图片

在这里插入图片描述

自己加了一个 出错处理函数,其实现在看来,当然也是没有用的。

2.2.3 HAL库的半双工处理?

折腾了好长一段时间,其实一开始就知道问题在于 同时收发会出问题的情况,那么继续上网找问题。

最终确定了一个问题就是:

我们都知道 STM32 串口是全双工的, STM32 HAL库在处理接收的时候会锁一下串口一会,导致变成某个短时间的“半双工”。

这个时候如果同时收发就会出现问题,最后解决的办法在这篇文章中看到了:STM32 F103串口同时收发出现死锁问题解决办法

问题在于我们使用的HAL_UART_Receive_IT函数中,有对串口加锁的操作:

图片虽然在后面有解锁:

图片

在这里插入图片描述

但是根据后期的解决方式来说,确实就是这个HAL_UART_Receive_IT函数的问题,最后使用的方式为,在产生一次中断以后开启的时候手动解锁:

图片

在这里插入图片描述

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  if(huart- >Instance == LPUART1){
    Enocean_Data++;
    if(Enocean_Data > 98)Enocean_Data = 0;
    while(HAL_UART_Receive_IT(&hlpuart1, (uint8_t *)&USART_Enocean_BUF[Enocean_Data], 1) != HAL_OK){
      hlpuart1.RxState = HAL_UART_STATE_READY;
      __HAL_UNLOCK(&hlpuart1);
    }
  }
  else if(huart- >Instance==USART1)
  {  
  }
}

终于,串口不再卡死 , 成功!

结语

没想到和 EEPROM 一样,一个简单的芯片,一个熟悉的串口 ,出了这种问题 = =!还好最后解决了问题。

踩过的坑都是积累与经验,加油。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • STM32
    +关注

    关注

    2270

    文章

    10897

    浏览量

    355862
  • 串口
    +关注

    关注

    14

    文章

    1551

    浏览量

    76473
  • HAL
    HAL
    +关注

    关注

    2

    文章

    70

    浏览量

    12610
收藏 人收藏

    评论

    相关推荐

    浅析STM32HAL串口处理

    STM32HAL串口处理—中断收发文章目录STM32HAL
    发表于 08-16 06:28

    STM32 HAL串口收发崩溃的原因

    的校验码后字节添加1-8字节随机数,每种字节长度测试10000次。以上测试初串口就会崩溃,只能发不能收,调试结果是,串口接收中断不再响应。源码中使用HAL_UART_Receive_I...
    发表于 08-23 08:58

    STM32F429标准串口收发通信程序的详细资料免费下载

    本文档的主要内容详细介绍的是STM32F429标准串口收发通信程序的详细资料免费下载,此程序可实现串口
    发表于 12-07 08:00 70次下载
    <b class='flag-5'>STM32</b>F429标准<b class='flag-5'>库</b><b class='flag-5'>串口</b>的<b class='flag-5'>收发</b>通信程序的详细资料免费下载

    STM32 串口使用IDLE中断+DMA接收(HAL库函数)

    STM32 串口使用IDLE中断+DMA接收(HAL库函数)一、开发环境单片机型号:STM32H743IIT6工程配置环境:STM32Cub
    发表于 12-02 21:06 41次下载
    <b class='flag-5'>STM32</b> <b class='flag-5'>串口</b>使用IDLE中断+DMA接收(<b class='flag-5'>HAL</b>库函数)

    HAL】Proteus+VSPD实现仿真stm32虚拟串口

    Proteus+VSPD仿真stm32串口工具软件准备Proteus工程CubeMX工程配置串口收发程序虚拟串口仿真工具软件准备
    发表于 12-06 18:36 41次下载
    【<b class='flag-5'>HAL</b><b class='flag-5'>库</b>】Proteus+VSPD实现仿真<b class='flag-5'>stm32</b>虚拟<b class='flag-5'>串口</b>

    串口通信小试牛刀~使用STM32CubeMX+ HAL点亮流水灯

    STM32CubeMX与Keil MDK配合HAL完成流水灯的点亮。目录一、STM32串口通信基础二、
    发表于 12-07 10:06 14次下载
    <b class='flag-5'>串口</b>通信小试牛刀~使用<b class='flag-5'>STM32</b>CubeMX+ <b class='flag-5'>HAL</b><b class='flag-5'>库</b>点亮流水灯

    STM32CubeMX基于HAL实现简单串口通信

    STM32CubeMX基于HAL实现简单串口通信板子:STM32F103C8编译工具:Keil+STM
    发表于 12-08 12:36 20次下载
    <b class='flag-5'>STM32</b>CubeMX基于<b class='flag-5'>HAL</b><b class='flag-5'>库</b>实现简单<b class='flag-5'>串口</b>通信

    HAL串口通信

    HAL入门之串口通信学习经验分享
    发表于 12-16 16:58 5次下载
    【<b class='flag-5'>HAL</b><b class='flag-5'>库</b>】<b class='flag-5'>串口</b>通信

    STM32HAL串口接收丢字节

    HAL串口数据收发前言使用cubeMX创建工程文件时,默认使用HAL。作为最新的主流
    发表于 12-17 18:36 8次下载
    <b class='flag-5'>STM32</b>之<b class='flag-5'>HAL</b><b class='flag-5'>库</b>的<b class='flag-5'>串口</b>接收丢字节

    STM32 HAL CubeMX教程(五)串口通信基础

    STM32 HAL CubeMX教程(五)串口通信基础串口通信简介CubeMX配置初始化程序分析程序编写UART: 通用异步
    发表于 12-24 18:49 12次下载
    <b class='flag-5'>STM32</b> <b class='flag-5'>HAL</b><b class='flag-5'>库</b> CubeMX教程(五)<b class='flag-5'>串口</b>通信基础

    STM32 HAL UART 串口读写功能笔记

    STM32L0 HAL UART 串口读写功能串口发送功能:uint8_t TxData[10]= “01234abcde”;
    发表于 12-27 19:11 13次下载
    <b class='flag-5'>STM32</b> <b class='flag-5'>HAL</b><b class='flag-5'>库</b> UART <b class='flag-5'>串口</b>读写功能笔记

    stm32 hal资料分享

    stm32 hal资料分享
    发表于 11-03 16:17 120次下载

    STM32 HAL的功能和使用方法 STM32 HAL和标准的区别

    和可维护性,从而节省开发成本和时间。STM32 HALSTM32系列芯片的HAL,由ST公
    发表于 08-08 18:21 4402次阅读

    STM32 HAL串口收发是如何使用的?

    STM32 HAL串口收发是如何使用的? STM32是一款高性能的微控制器,它拥有广泛的应用领
    的头像 发表于 10-26 17:42 1233次阅读

    STM32 HAL串口同时收发,接收卡死?

    STM32 HAL串口同时收发,接收卡死? 为什么STM32
    的头像 发表于 10-26 17:42 3513次阅读