STM32串口中断接收不定长报文并解析

2023-05-16

文章目录

  • 功能实现背景介绍
  • HAL库的中断接收函数
  • 状态机的运用

功能实现背景介绍

本项目中,需要使用STM32的USART6串口与FPGA板(下位机)通信,需要发送和接收数据,有报文应答机制。

使用的报文规则如表格所示

在这里插入图片描述

板间报文的通信协议,校验使用的是和校验

U8 TX_CheckSum(U8 *buf, U8 len) //buf为数组,len为数组长度
{ 
    U8 i, ret = 0;
    for(i=0; i<len; i++)
    {
        ret += *(buf++);
    }
     ret = ~ret;
    return ret;
}
U8 RX_CheckSum(U8 *buf, U8 len) //buf为数组,len为数组长度
{ 
    U8 i, ret = 0;
     for(i=0; i<len; i++)
    {
        ret += *(buf++);
    }
    ret = ret;
    return ret+1;
}

发送和接收的报文要满足不定长

HAL库的中断接收函数

如果要直接使用HAL库的中断接收函数,也就是HAL_UART_Receive_IT()函数

HAL_UART_Receive_IT(&huart6,UART6_RxBuffer,5);              //下位机FPGA

在使用时,选择串口,选择接收的缓冲区,选择接收长度。

/**
  * @brief  Receives an amount of data in non blocking mode.
  * @note   When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
  *         the received data is handled as a set of u16. In this case, Size must indicate the number
  *         of u16 available through pData.
  * @param  huart Pointer to a UART_HandleTypeDef structure that contains
  *               the configuration information for the specified UART module.
  * @param  pData Pointer to data buffer (u8 or u16 data elements).
  * @param  Size  Amount of data elements (u8 or u16) to be received.
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
  /* Check that a Rx process is not already ongoing */
  if (huart->RxState == HAL_UART_STATE_READY)
  {
    if ((pData == NULL) || (Size == 0U))
    {
      return HAL_ERROR;
    }

    /* Process Locked */
    __HAL_LOCK(huart);

    huart->pRxBuffPtr = pData;
    huart->RxXferSize = Size;
    huart->RxXferCount = Size;

    huart->ErrorCode = HAL_UART_ERROR_NONE;
    huart->RxState = HAL_UART_STATE_BUSY_RX;

    /* Process Unlocked */
    __HAL_UNLOCK(huart);

    /* Enable the UART Parity Error Interrupt */
    __HAL_UART_ENABLE_IT(huart, UART_IT_PE);

    /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */
    __HAL_UART_ENABLE_IT(huart, UART_IT_ERR);

    /* Enable the UART Data Register not empty Interrupt */
    __HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);

    return HAL_OK;
  }
  else
  {
    return HAL_BUSY;
  }
}

这个函数本质上其实不是中断接收函数,只是配置函数,配置开启中断的信息,并且接收多少定长的数据结束本数据接收,串口的中断接收还是在中断中进行。

我们本次的长度虽然也是定长,但是有两种长度数据的接收,所以还是从设计接收不定长的数据为最终效果。

状态机的运用

对于不定长数据的接收,使用了状态机,分两次中断来接收数据

在这里插入图片描述

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance == USART6)	                                 // 判断是由哪个串口触发的中断
	{
		if(StateMachine_USART6)                                      //状态机为1,都接收完毕,准备校验          
		{	
      if(re_flag6 == 1)
			{
				UART6_RxCounter = 6;
				re_flag6 = 0;
			}	
      else
			{
				len_counter6 = 2+5+UART6_RxBuffer[2]+(UART6_RxBuffer[3]<<8);  
			  if(UART6_RxBuffer[len_counter6 - 1] == 0x55 && UART6_RxBuffer[0] == 0xAA)	
			  {
				  UART6_RxCounter = len_counter6;
			  }	
        else
			  {
				  memset(UART6_RxBuffer,0,0x400);
					UART6_RxCounter = 0;
			  }		
			}				
      		
			StateMachine_USART6 = 0;                                   //状态机为0 
      len_counter6 = 0;			
			HAL_UART_Receive_IT(&huart6,UART6_RxBuffer,5);		
		}
		else                                                         //状态机为0,只接受到了前五个字节,继续接收后面的字节
		{					
			if(UART6_RxBuffer[0] == 0xAA)
			{
				StateMachine_USART6 = 1;
				UART6_RxCounter = 5;
				if(UART6_RxBuffer[2] == 0 && UART6_RxBuffer[3] == 0)
			  {
				  HAL_UART_Receive_IT(&huart6,(uint8_t*)&UART6_RxBuffer[5], 1);
					re_flag6 = 1;
			  }
			  else
			    HAL_UART_Receive_IT(&huart6,(uint8_t*)&UART6_RxBuffer[5], 2 + UART6_RxBuffer[2] + (UART6_RxBuffer[3] << 8));
			}
			else
			{
				memset(UART6_RxBuffer,0,0x400);
				UART6_RxCounter = 0;
				HAL_UART_Receive_IT(&huart6,UART6_RxBuffer,5);
			}
			
		}
	}
}

核心思想就是先接收报文的头,根据头来判断后面的长度,把应答报文和音量数据报文区分开,不合格的报文直接舍去同时开启新的接收。

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

STM32串口中断接收不定长报文并解析 的相关文章

  • 如何更改闪存的起始地址?

    我正在使用 STM32F746ZG 和 FreeRTOS Flash的起始地址是0x08000000 但我想把它改成0x08040000 我通过谷歌搜索了这个问题 但没有找到解决方案 我更改了链接器脚本 如下所示 MEMORY RAM xr
  • 在地址“0xXXXXXX”处中断,没有可用的调试信息,或在程序代码之外

    配置 使用 Nucleo L476RG 使用 GNU ARM Eclipse 我从 STM32CubeMX 生成了一个极简代码 我已经在我的板载 ST Link 中刷新了 J link 驱动程序 一直在尝试为我的代码运行调试器 但我的程序计
  • 以字符串形式接收数字(uart)

    我正在尝试通过 uart 接收一个包装为字符串的数字 我发送数字 1000 所以我得到 4 个字节 空字符 但是 当我使用 atoi 将数组转换为数字并将整数与 1000 进行比较时 我并不总是得到正确的数字 这是我用于接收号码的中断处理函
  • STM32 F072上的软件如何跳转到bootloader(DFU模式)?

    STM32应用笔记2606对此进行了讨论 但没有简单的代码示例 该答案已使用 IAR EWARM 在 STM32F072 Nucleo 板上进行了测试 这个答案使用 STM32标准外设库 仅此而已 请注意 验证您是否成功进入引导加载程序模式
  • CMSIS 库是否应该包含在版本控制中? [复制]

    这个问题在这里已经有答案了 通常 我曾经在版本控制中包含芯片供应商 ST 提供的设备特定标头和源以及 CMSIS Core 标头 数量不多 也没有更新的习惯 我使用STM32微控制器 但我不使用立方体框架 or the 标准外设库 最近 我
  • 134-基于stm32单片机矿井瓦斯天然气浓度温湿度检测自动通风系统Proteus仿真+源程序...

    资料编号 134 一 功能介绍 1 采用stm32单片机 LCD1602显示屏 独立按键 ds1302时钟 DHT11温湿度 电机 蜂鸣器 制作一个基于stm32单片机矿井瓦斯天然气浓度温湿度检测自动通风系统Proteus仿真 2 通过DH
  • rt-thread studio中新建5.0不能用

    文章目录 一 版本对比 二 文件和文件夹打斜杠 在使用RT Thread studio创建新工程5 0版本的时候 结果发现新建完成之后程序不能正常运行 但是创建4 10版本的时候却能运行 那肯定是新版本出现了BUG 一 版本对比 首先对比了
  • STM32F4 通过软复位跳转到引导加载程序,无需 BOOT0 和 BOOT1 引脚

    我问这个问题是因为可以在这里找到类似问题的答案 通过应用程序跳转到 STM32 中的引导加载程序 即从用户闪存在引导模式下使用引导 0 和引导 1 引脚 用户 JF002 JF002回答 当我想跳转到引导加载程序时 我在其中一个备份寄存器中
  • STM32F103

    提示 来源正点原子 参考STM32F103 战舰开发指南V1 3PDF资料 文章目录 前言 一 pandas是什么 二 使用步骤 1 引入库 2 读入数据 总结 前言 提示 这里可以添加本文要记录的大概内容 开发环境硬件普中科技 接线图在g
  • HAL库学习

    CMSIS简介 CMSIS Cortex Microcontroller Software Interface Standard 微控制器软件接口标准 由ARM和其合作的芯片厂商 ST NXP 软件工具厂商 KEIL IAR 共同制定的标准
  • [屏驱相关]【SWM166-SPI-Y1.28C1测评】+ 有点惊艳的开箱

    耳闻华芯微特许久了 看到论坛得评测活动赶紧上了末班车 毕竟对有屏幕得板子也是很喜欢得 京东快递小哥客客气气 微笑着把快递给了我 好评 直接拆了包 在此之前没看过视频号 所以这个圆盘盘得模具还是有点惊喜的 正面照如下 开机有灯光秀 还有动画
  • 硬件基础-电容

    电容 本质 电容两端电压不能激变 所以可以起到稳定电压作用 充放电 电容量的大小 想使电容容量大 使用介电常数高的介质 增大极板间的面积 减小极板间的距离 品牌 国外 村田 muRata 松下 PANASONIC 三星 SAMSUNG 太诱
  • 解决KEIL编译慢问题

    两种方案 使用v6版本的ARM Compiler 如果v6版本编译不过 必须使用v5版本的 则可以勾选掉Browse Information选项 提升很明显 1分多钟能优化到几秒 看代码量 但是这个有个弊端 在KEIL中会影响函数跳转 建议
  • 1.69寸SPI接口240*280TFT液晶显示模块使用中碰到的问题

    1 69寸SPI接口240 280TFT液晶显示模块使用中碰到的问题说明并记录一下 在网上买了1 69寸液晶显示模块 使用spi接口 分辨率240 280 给的参考程序是GPIO模拟的SPI接口 打算先移植到FreeRtos测试 再慢慢使用
  • STM32F4XX的12位ADC采集数值超过4096&右对齐模式设置失败

    文章目录 一 前言 二 问题1 数值超过4096 三 问题1的排错过程 四 问题2 右对齐模式设置失败 五 问题2的解决方法 5 1 将ADC ExternalTrigConv设置为0 5 2 使用ADC StructInit 函数 一 前
  • 嵌入式开发--STM32G4系列片上FLASH的读写

    这个玩意吧 说起来很简单 就是几行代码的事 但楞是折腾了我大半天时间才搞定 原因后面说 先看代码吧 读操作 读操作很简单 以32位方式读取的时候是这样的 data IO uint32 t 0x0800F000 需要注意的是 当以32位方式读
  • systick定时器

    systick定时器 文章目录 前言 一 前期疑惑 二 解答 1 关于systick是阻塞的吗 2 非阻塞 三 软件编写 总结 前言 这边记录systick相关知识点 一 前期疑惑 在学习systick志气啊 其实对于systick还是一脸
  • 从没有中断引脚并且在测量准备好之前需要一些时间的传感器读取数据的最佳方法

    我正在尝试将压力传感器 MS5803 14BA 与我的板 NUCLEO STM32L073RZ 连接 根据 第 3 页 压力传感器需要几毫秒才能准备好读取测量值 对于我的项目 我对需要大约 10 毫秒来转换原始数据的最高分辨率感兴趣 不幸的
  • 通过JTAG恢复STM32 MCU磨掉的标记

    我有一块可能带有 STM32 MCU 的板 我想为该板制作定制固件 因为库存板有很多问题 不幸的是 电路板制造商很友善地磨掉了所有标记 有没有办法通过 jtag 获取设备 系列 ID 并将其交叉引用到型号 我能找到的一切都是关于获取芯片的唯
  • 在 Contiki 程序中使用 malloc

    考虑以下 Contiki 程序 include

随机推荐

  • 如何打印堆栈

    一 打印堆栈可以方便问题定位 xff0c 找到具体的函数调用流程 二 打印堆栈的方法 2 1 用户态 include lt stdio h gt include lt stdlib h gt include lt stddef h gt i
  • 内存飞踩问题的几点思考

    1 程序编译 xff0c 链接后生成二进制可执行程序 二进制可执行文件以elf格式实现排列 可以通过readelf S xxxx查看具体section的划分 xff0c 粗略划分如下图所示 在这些section中 xff0c 代码段是只读的
  • CFS调度算法

    1 CFS调度算法 xff0c 顾名思义就是完全公平调度策略 比方说 xff0c 调度延迟时间是10ms xff0c 存在两个进程A和B xff0c 那么两个进程分别占用CPU的时间是5ms 然而 xff0c 阶级总是存在的 xff0c 毕
  • ARM处理器的异常模式

    1 ARM处理器有各种异常模式 xff0c 用于应对ARM出现的不同状态 出现异常时 xff0c 会随即进入相关的异常向量 xff0c 同时CPSR的寄存器也会设置成具体的模式 例 xff1a 当出现中断时 xff0c 不管是哪种中断 xf
  • 内核态和用户态相关的内存泄漏

    应用程序通过系统调用进入内核态代码 假如内核态代码存在内存泄漏 xff0c 此内存泄漏属于内核态还是用户态 xff1f 查看内核态和用户态的统计信息
  • 为什么在telnet登入界面下没有日志输出?

    1 每个进程的输入输出导向目标都可以在进程号下的fd软链接上查看 如 569号进程的输出目标是 dev console xff0c 即串口 其中0是标准输入 xff0c 1是标准输出 xff0c 2是标准错误输出 2 因此我们只需要查看te
  • 【无标题】

    1 将虚拟地址传入到内核态 xff0c 借助内核态中mm struct结构体的pgd页表基地址成员 xff0c 经过查页表的方式最终获取到物理地址 这种方法虽然很直观 xff0c 但是一会内核态 xff0c 一会用户态 xff0c 操作起来
  • C#串口=>发送和接收

    作用 xff1a 串口发送命令后 xff0c 等待下位机应答帧 代码 xff1a 一旦读取到数据就立即返回给上层 public string TXandRX byte buffer string data 发送 RS485专用 start
  • kprobe功能的代码实现

    1 可以借助 sys kernel debug tracing目录下的文件 xff0c linux提供了kprobes功能 xff0c 抓取内核函数中的入参和返回值 kprobes xff0c 强大的调试工具 sydyh43的博客 CSDN
  • 上位机使用C++通过ADS协议与倍福PLC通信例程-通过变量名方式读写浮点数

    前言 建议初学者先看这一章节内容 xff0c 里面包括一些基础的环境配置和项目建立流程 xff0c 以后开发项目这些流程是通用的 xff0c 务必掌握并熟练 链接 上位机使用C 43 43 通过ADS协议与倍福PLC通信例程 布尔变量的读取
  • 弄清USART串口的使能位(UE、TCIE、RXNEIE)和标志位(TC、RXNE)

    下面通过485半双工的通信过程 xff0c 记录USART串口的几个使能位 标志位 说明 xff1a USART IT TC 和 USART IT RXNE是一个常量 xff0c 并不代表 xff08 TC RXNE 这两位 define
  • 机器人视觉检测+跟踪:行人跟随过程中对目标提取特征+匹配

    今天上午也是没有很大的成效 xff0c 一直到下午睡醒 xff08 论好的睡眠的重要性 xff09 xff0c 在一篇帖子中看到一种新的写法 xff0c opencv3将IplImage转换为Mat格式的写法 xff0c 在我们的代码中采用
  • ubuntu firefox打不开网页

    检查ubuntu右上角联网开关是否打开 xff1a 需要勾选Enable Networking 如果能ping通其它主机地址 xff0c 浏览器却上不了网 xff0c 很有可能是dns域名解析的问题 查看域名配置文件 xff1a cat e
  • Java如何利用JNI调用C++(简略介绍及步骤)

    Java如何利用JNI调用C 43 43 xff08 简略介绍及步骤 xff09 文章目录 Java如何利用JNI调用C 43 43 xff08 简略介绍及步骤 xff09 一 原理介绍二 详细步骤步骤一 xff1a 编写Java类步骤二
  • HttpParser解析节点遇到的不解问题

    HttpParser遇到table时 xff0c 解析时 xff0c 直接抽取th或者td xff0c thead和tbody解析或出现异常 比如 lt table gt lt thead gt lt tr gt 相关内容 lt tr gt
  • CMakeLists 理解

    CMakeLists 理解 最近发现其实之前对CMakeLists 理解不是很全面 xff0c 零零散散在网上看到的一些教程 xff0c 其实都是为了解决某个命令的问题 xff0c 要不然就是对一些命令的翻译理解 xff0c 实际上是很劝退
  • sip协议之注册说明

    注册是SIP协议中重要的功能 xff0c 所谓注册 xff0c 就是用户A客户端将自己的联系地址告知服务器 xff0c 以便后续有其它用户呼叫用户A时 xff0c 服务器能够将呼叫转接到用户A SIP协议中的联系地址是指由账号 IP POR
  • 9v输入7.4v电路充电IC

    9v输入7 4v电路充电IC 两节串联的锂电池 xff0c 一般电压是7 4V xff0c 最高电压到8 4V xff0c 最低放电到6V左右 如果需要6V 8 4V降压到5V的DC DC降压芯片 xff0c 一般是用FS2953 如果需要
  • Java 和 C++ 语法之间的区别

    main 方法 Java java 的函数必须写在类里 class HelloWorld public static void main String args System out println 34 Hello World 34 复制
  • STM32串口中断接收不定长报文并解析

    文章目录 功能实现背景介绍HAL库的中断接收函数状态机的运用 功能实现背景介绍 本项目中 xff0c 需要使用STM32的USART6串口与FPGA板 xff08 下位机 xff09 通信 xff0c 需要发送和接收数据 xff0c 有报文