STM32HAL库串口中断同时收发卡死

2023-05-16

在使用HAL库的过程中发现在串口中断的回显功能(将串口接收到的数据再发送出来),总是执行几次后程序卡死,无法正常回显。经过一系列查找后发现原因是STM32 HAL库在处理接收的时候会锁一下串口一会,导致变成某个短时间的“半双工”。尝试网上的教程太过繁琐,而且cubemx生成代码后又会将修改部分覆盖,很是麻烦。知道出现问题的原因后直接参考标准库在usart.c和usart.h中添加以下代码,完美解决问题。

usart.h中添加如下代码



/* USER CODE BEGIN Includes */
#include "stm32f1xx_hal.h"
#include "stdio.h"

/*宏定义*/

#define USART_IT_PE                          ((uint16_t)0x0028)
#define USART_IT_TXE                         ((uint16_t)0x0727)
#define USART_IT_TC                          ((uint16_t)0x0626)
#define USART_IT_RXNE                        ((uint16_t)0x0525)
#define USART_IT_IDLE                        ((uint16_t)0x0424)
#define USART_IT_LBD                         ((uint16_t)0x0846)
#define USART_IT_CTS                         ((uint16_t)0x096A)
#define USART_IT_ERR                         ((uint16_t)0x0060)
#define USART_IT_ORE                         ((uint16_t)0x0360)
#define USART_IT_NE                          ((uint16_t)0x0260)
#define USART_IT_FE                          ((uint16_t)0x0160)
#define IT_Mask                   ((uint16_t)0x001F)  /*!< USART Interrupt Mask */

/* USER CODE END Includes */


/* USER CODE BEGIN Prototypes */
/*函数申明*/
void USART_SendData(USART_TypeDef* USARTx, uint8_t *pData);
ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT);
uint16_t USART_ReceiveData(USART_TypeDef* USARTx);
void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState);
/* USER CODE END Prototypes */

在usart.c中复制标准库函数原型

/**
  * @brief  Transmits single data through the USARTx peripheral.
  * @param  USARTx: Select the USART or the UART peripheral. 
  *   This parameter can be one of the following values:
  *   USART1, USART2, USART3, UART4 or UART5.
  * @param  Data: the data to transmit.
  * @retval None
  */
void USART_SendData(USART_TypeDef* USARTx, uint8_t *pData)
{

  /* Transmit Data */

	USARTx->DR = *pData;
	while (!(USARTx->SR & UART_FLAG_TC)){};
}
/**
  * 函数功能: 重定向c库函数printf到DEBUG_USARTx
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明:无
  */
int fputc(int ch, FILE *f)
{
  USART_SendData(USART1, (uint8_t *)&ch);
  return ch;
}
 
/**
  * 函数功能: 重定向c库函数getchar,scanf到DEBUG_USARTx
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明:无
  */
int fgetc(FILE *f)
{
  uint8_t ch = 0;
  USART_ReceiveData(USART1);
  return ch;
}

/**
  * @brief  Checks whether the specified USART interrupt has occurred or not.
  * @param  USARTx: Select the USART or the UART peripheral. 
  *   This parameter can be one of the following values:
  *   USART1, USART2, USART3, UART4 or UART5.
  * @param  USART_IT: specifies the USART interrupt source to check.
  *   This parameter can be one of the following values:
  *     @arg USART_IT_CTS:  CTS change interrupt (not available for UART4 and UART5)
  *     @arg USART_IT_LBD:  LIN Break detection interrupt
  *     @arg USART_IT_TXE:  Tansmit Data Register empty interrupt
  *     @arg USART_IT_TC:   Transmission complete interrupt
  *     @arg USART_IT_RXNE: Receive Data register not empty interrupt
  *     @arg USART_IT_IDLE: Idle line detection interrupt
  *     @arg USART_IT_ORE:  OverRun Error interrupt
  *     @arg USART_IT_NE:   Noise Error interrupt
  *     @arg USART_IT_FE:   Framing Error interrupt
  *     @arg USART_IT_PE:   Parity Error interrupt
  * @retval The new state of USART_IT (SET or RESET).
  */



ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT)
{
  uint32_t bitpos = 0x00, itmask = 0x00, usartreg = 0x00;
  ITStatus bitstatus = RESET;
  /* Check the parameters */
  assert_param(IS_USART_ALL_PERIPH(USARTx));
  assert_param(IS_USART_GET_IT(USART_IT));
  /* The CTS interrupt is not available for UART4 and UART5 */ 
  if (USART_IT == UART_FLAG_CTS)
  {
    assert_param(IS_USART_123_PERIPH(USARTx));
  }   
  
  /* Get the USART register index */
  usartreg = (((uint8_t)USART_IT) >> 0x05);
  /* Get the interrupt position */
  itmask = USART_IT & IT_Mask;
  itmask = (uint32_t)0x01 << itmask;
  
  if (usartreg == 0x01) /* The IT  is in CR1 register */
  {
    itmask &= USARTx->CR1;
  }
  else if (usartreg == 0x02) /* The IT  is in CR2 register */
  {
    itmask &= USARTx->CR2;
  }
  else /* The IT  is in CR3 register */
  {
    itmask &= USARTx->CR3;
  }
  
  bitpos = USART_IT >> 0x08;
  bitpos = (uint32_t)0x01 << bitpos;
  bitpos &= USARTx->SR;
  if ((itmask != (uint16_t)RESET)&&(bitpos != (uint16_t)RESET))
  {
    bitstatus = SET;
  }
  else
  {
    bitstatus = RESET;
  }
  
  return bitstatus;  
}



/**
  * @brief  Returns the most recent received data by the USARTx peripheral.
  * @param  USARTx: Select the USART or the UART peripheral. 
  *   This parameter can be one of the following values:
  *   USART1, USART2, USART3, UART4 or UART5.
  * @retval The received data.
  */
uint16_t USART_ReceiveData(USART_TypeDef* USARTx)
{
  /* Check the parameters */
  assert_param(IS_USART_ALL_PERIPH(USARTx));
  
  /* Receive Data */
  return (uint16_t)(USARTx->DR & (uint16_t)0x01FF);
}



/**
  * @brief  Enables or disables the specified USART interrupts.
  * @param  USARTx: Select the USART or the UART peripheral. 
  *   This parameter can be one of the following values:
  *   USART1, USART2, USART3, UART4 or UART5.
  * @param  USART_IT: specifies the USART interrupt sources to be enabled or disabled.
  *   This parameter can be one of the following values:
  *     @arg USART_IT_CTS:  CTS change interrupt (not available for UART4 and UART5)
  *     @arg USART_IT_LBD:  LIN Break detection interrupt
  *     @arg USART_IT_TXE:  Transmit Data Register empty interrupt
  *     @arg USART_IT_TC:   Transmission complete interrupt
  *     @arg USART_IT_RXNE: Receive Data register not empty interrupt
  *     @arg USART_IT_IDLE: Idle line detection interrupt
  *     @arg USART_IT_PE:   Parity Error interrupt
  *     @arg USART_IT_ERR:  Error interrupt(Frame error, noise error, overrun error)
  * @param  NewState: new state of the specified USARTx interrupts.
  *   This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState)
{
  uint32_t usartreg = 0x00, itpos = 0x00, itmask = 0x00;
  uint32_t usartxbase = 0x00;
  /* Check the parameters */
  assert_param(IS_USART_ALL_PERIPH(USARTx));
  assert_param(IS_USART_CONFIG_IT(USART_IT));
  assert_param(IS_FUNCTIONAL_STATE(NewState));
  /* The CTS interrupt is not available for UART4 and UART5 */
  if (USART_IT == UART_FLAG_CTS)
  {
    assert_param(IS_USART_123_PERIPH(USARTx));
  }   
  
  usartxbase = (uint32_t)USARTx;

  /* Get the USART register index */
  usartreg = (((uint8_t)USART_IT) >> 0x05);

  /* Get the interrupt position */
  itpos = USART_IT & IT_Mask;
  itmask = (((uint32_t)0x01) << itpos);
    
  if (usartreg == 0x01) /* The IT is in CR1 register */
  {
    usartxbase += 0x0C;
  }
  else if (usartreg == 0x02) /* The IT is in CR2 register */
  {
    usartxbase += 0x10;
  }
  else /* The IT is in CR3 register */
  {
    usartxbase += 0x14; 
  }
  if (NewState != DISABLE)
  {
    *(__IO uint32_t*)usartxbase  |= itmask;
  }
  else
  {
    *(__IO uint32_t*)usartxbase &= ~itmask;
  }
}




/* USER CODE END 1 */

串口中断函数如下

void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */
	char c;
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
	{
		/* 把数据读出来存入环形缓冲区 */
		c = USART_ReceiveData(USART1);
	}
	printf("%c",c);
  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);  //此处不用修改,即使删除了,cubemx生成代码后又会将此处覆盖
  /* USER CODE BEGIN USART1_IRQn 1 */

  /* USER CODE END USART1_IRQn 1 */
}

添加完上述代码后,在串口初始化后使能相应的中断即可

 

测试数据如下

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32HAL库串口中断同时收发卡死 的相关文章

  • windows server 2008 R2服务器系统密码破密

    问题 xff1a 管理员administrator密码忘记 前提 xff1a 服务器型号Dell S130 2 系统2008R2 3 系统带有阵列驱动 准备工具 xff1a 1 2008R2系统光盘 xff0c 2016 R2系统光盘 2
  • Java 经典例题:生产者/消费者问题

    Java 经典例题 xff1a 生产者 消费者问题 1 问题2 分析3 demo 1 问题 生产者 Productor 将产品交给店员 Clerk xff0c 而消费者 Customer 从店员处取走产品 xff0c 店员一次只能持有固定数
  • angular2如何识别字符串中的html标签,并按照html来显示视图

    这个源于一个需求 xff1a 从后台拿到用户评论的内容 xff0c 该内容是字符串的 xff0c 但是里面包含了html代码 要求显示的时候按照html来显示 xff0c 不是按照字符串来显示 并且要求任意的段文字添加样式 xff1b 思路
  • 使用虚拟机安装kali Linux遇到的运行问题

    最近在虚拟机上安装Linux xff0c 谁知道在运行安装的时候 xff0c 竟然报这个错误 xff0c 唯恐以后学习中再次遇到同样的问题 xff0c 以至于手忙脚乱 xff0c 所以在此做下收录 出现此类问题是因为360安全防护中心的In
  • 安装kali2.0之后,如何从Windows中通过SecureCRT工具远程到kali中呢?

    xfeff xfeff 1 在kali的终端输入 etc init d ssh status 回车 xff0c 用来查看kali中SSH服务状态 xff1b 由上图可知 xff0c kali Linux 默认情况下SSH服务是inactiv
  • 虚拟机权限不足,无法访问文件

    今天在使用虚拟机的时候 xff0c 出现了一个报错 xff0c 一下子懵逼了 xff0c 找度娘百度了一下 xff0c 各种答案五花八门 xff0c 但是根本木有卵用 xff0c 问题如下图 xff1a 解决方案是 xff1a 现在关掉虚拟
  • 如何使用英文界面的JMETER

    如何使用英文界面的JMETER JMETER启动时会自动判断操作系统的 locale 并选择合适的语言启动 xff0c 所以 xff0c 我们启动JMETER 后 xff0c 会出现一个倍感亲切的中文界面 但由于JMETER 本身的汉化工作
  • 在CMD命令行模式下运行.py文件,提示:无法初始化设备PRN

    在CMD命令行模式下运行 py文件 xff0c 提示 xff1a 无法初始化设备PRN 问题的重现步骤 xff1a 首次学习python xff0c 不知道 py文件是如何创建的 xff0c 故新建了一个txt文件 xff0c 添加完内容之
  • office 2010 Word,Excel的功能区突然消失了

    office 2010 Word Excel的功能区突然消失了 xff0c 点击展开功能区无效 在网上搜了很久没有找到解决办法 Office都卸载重装过还是无法解决 在网上找到一个方法 xff1a 将com加载项的ntkofficecont
  • IndentationError:expected an indented block

    xfeff xfeff 在用python写判断语句时 xff0c 报错 错误语句写法如下 xff1a 报错信息如下 xff1a 解决方案如下 xff1a 在print前面加上Tab 问题迎刃而解
  • kindeditor使用可能遇到的问题

    1 音视频上传不能播放问题 xff08 使用自定义video标签 xff09 更改kindeditor all min js中的 mediaImg方法 function mediaImg blankPath attrs if attrs s
  • manjaro21折腾笔记

    1 换源以及更新 1 1 配置镜像源 span class token function sudo span pacman mirrors i c China m rank 输入后会出现源列表选项 xff0c 全选即可 1 2 设置源 打开
  • 最简nvim配置

    1 安装nvim span class token function sudo span span class token function apt get span span class token function install sp
  • 竟然可以在Windows下用Nvim写代码?2.nvim基础插件配置

    在windows下用nvim写代码 使用wsl和terminal简直不要太方便 保姆级教学 一篇就够了 一 下载plug 可以用指令安装 curl fLo config nvim autoload plug vim create dirs
  • vscode国内源下载

    https az764295 vo msecnd net stable ea3859d4ba2f3e577a159bc91e3074c5d85c0523 VSCodeUserSetup x64 1 52 1 exe 将官方下载地址的域名更换
  • linux下搜狗拼音隐藏悬浮状态栏

    打开配置文件 vim config sogoupinyin conf env ini 找到以下内容 并修改为0 StatusAppearance 61 0 重启fcitx状态栏就消失了 killall fcitx fcitx
  • JavaScript笔记(2)

    7 对象 xff1a 对象的三种声明与调用方法 span class token comment 第一种声明方法 span span class token keyword let span ObjectName span class to
  • C++类与对象笔记

    C 43 43 类与对象笔记 本章主要讲了面向对象三大特性 xff1a 封装 xff0c 继承 xff0c 多态 C 43 43 认为万事万物都皆为对象 xff0c 对象上有其属性和行为 例如 xff1a 人可以作为对象 xff0c 属性有
  • C++基础笔记

    C 43 43 基础笔记 本章主要讲了在c的基础上 xff0c c 43 43 的拓扑基础的部分 xff0c 还有内存的分配 1 内存分区模型 C 43 43 程序在执行时 xff0c 将内存大方向划分为4个区域 1 代码区 xff1a 存
  • linux文件名匹配(通配符使用)

    当在使用命令行时 xff0c 有很多时间都用来查找你所需要的文件 xff0c 如ls find等 S h e l l提供了一套完整的字符串模式匹配规则 xff0c 或者称之为元字符 xff0c 当s h e l l遇到上述字符时 xff0c

随机推荐

  • Android指纹识别,兼容Android 6.0 - Android 11

    目录 前言 概览 1 类 2 权限 详细介绍 1 BiometricManager 属性和方法 是否可用的状态码 方法 2 BiometricPrompt 属性和方法 验证的结果常用错误码 不全 方法 实战 第一步 引入支持库 第二步 检查
  • Lottie-Android详解

    Lottie是什么 Lottie是Airbnb开源的一套跨平台的 完整的动画效果解决方案 xff0c 适用于 Android iOS Web 和 Windows 平台 xff0c 它解析使用 Bodymovin 导出为 json 的 Ado
  • 组合问题,n个元素分成k组-5

    题目要求 P n k 代表将n个元素分成k个非空分组集合的总集 例如 xff0c 当L 61 1 2 3 P xff08 3 xff0c 2 xff09 61 12 3 13 2 1 23 我们就假设此n个元素是从1到n P 4 3 61
  • FTPClient踩过的坑

    一 ftpClient enterLocalPassiveMode public static final int PASSIVE LOCAL DATA CONNECTION MODE 61 2 官网关于该常量的说明 xff1a A con
  • Camera基本属性了解及设置

    将camera肯定是要有预览界面来配合着才有激情 xff0c 不然无图无真相 那就讲的没有太大的激情 我们对camera的使用一般是在app里面有用到设置获取图片的时候提供一个拍照功能 xff0c 一般是跳转到系统的拍照界面使用camera
  • 验证码不显示的解决方法

    方法一 xff1a 出现上面的情况 xff0c 最基本的一个错误就是你很可能在php里面忘记安装gd模块了 window环境下面只需要在php ini文件里面找到 把前面的分号去掉就可以了 xff0c 重启apache后 xff0c 你就可
  • 纯NumPy代码从头实现简单的卷积神经网络

    在某些情况下 xff0c 使用 ML DL 库中已经存在的模型可能会很便捷 但为了更好地控制和理解模型 xff0c 你应该自己去实现它们 本文展示了如何仅使用 NumPy 库来实现 CNN 卷积神经网络 xff08 CNN xff09 是分
  • 一文搞懂结构体变量占用多大内存空间(详细)

    一 首先做一道例题感受一下 请问下面定义的结构体变量aa在计算机内存中占用多少字节 xff1f span class token macro property span class token directive hash span spa
  • harbor+trivy的安装使用——筑梦之路

    环境依赖 xff1a docker ce docker compose 这些部分的安装这里就不再赘述 创建证书和私钥 mkdir opt harbor ssl p 生成CA证书私钥 ca key openssl genrsa out ca
  • Thinkphp 6.0响应输出和重定向

    本节课我们来学习一下响应操作 xff0c 响应输出和重定向 一 xff0e 响应操作 1 响应输出 xff0c 有好几种 xff1a 包括 return json 和 view 等等 xff1b 2 默认输出方式是以 html 格式输出 x
  • log4net配置经验教训

    第一点 xff1a 权限问题 xff0c 一定要给要写入日志文件的目录宽松的权限 本人就是因为权限问题浪费了很多时间 xff08 因为iis user 的权限是相对低的 xff0c log4net又需要创建文件 xff0c 所以权限一定要给
  • Linux的目录结构

    目录说明bin存放二进制可执行文件 ls cat mkdir等 boot存放用于系统引导时使用的各种文件dev用于存放设备文件etc存放系统配置文件home存放所有用户文件的根目录lib存放跟文件系统中的程序运行所需要的共享库及内核模块mn
  • Python tkinter多进程多线程前邮箱,再用pyinstaller编译成exe

    写博客记录一下Python 用tkinter 多进程线程写成的邮箱应用 xff0c 只是一个简单的应用 xff0c 尝试进程调度 xff0c 并用pyinstaller打包成exe 注意 xff1a 1 平台环境win7 Python3 6
  • 终极解决python安装包时需要Microsoft Visual C++ 14.0的问题

    问题 Windows平台在pip install wordcloud包时需要安装 Microsoft Visual C 43 43 14 0 xff0c 而Microsoft Visual C 43 43 14 0 对应的是Microsof
  • Ubuntu18.04屏幕分辨率问题

    Ubuntu18 04屏幕分辨率问题 起因 本来昨天还好好的 xff0c 过了一夜 xff0c 就变了 xff0c 像极了咳咳 自行脑补 redwallbot 2小车上固定的屏幕 xff0c 屏幕分辨率本来应该是1920x1080的 xff
  • Android解决No toolchains found in the NDK toolchains folder for ABI with prefix: mips64el-linux-and问题。

    问题说明 xff1a 导入下载的项目编译报错 错误如下 xff1a No toolchains found in the NDK toolchains folder for ABI with prefix mips64el linux an
  • Ubuntu Vim设置

    cp etc vim vimrc vimrc vi etc vim vimrc 针对所有用户 vi vimrc 针对user 34 关闭兼容功能 set nocompatible 34 显示行号 set number 34 编辑时 back
  • STM32CubeMX在freeRTOS中使用printf函数

    在usart h中添加 inlcude 34 stdio h 34 Includes include 34 main h 34 USER CODE BEGIN Includes include 34 stdio h 34 USER CODE
  • CUBEMX建立freeRTOS工程编译报错

    Middlewares Third Party FreeRTOS Source portable RVDS ARM CM3 portmacro h 167 error unknown type name 39 forceinline 39
  • STM32HAL库串口中断同时收发卡死

    在使用HAL库的过程中发现在串口中断的回显功能 xff08 将串口接收到的数据再发送出来 xff09 xff0c 总是执行几次后程序卡死 xff0c 无法正常回显 经过一系列查找后发现原因是STM32 HAL库在处理接收的时候会锁一下串口一