细说STM32单片机USART中断收发RTC实时时间并改善其鲁棒性的方法
目录
一、工程目的
1、 目标
2、通讯协议及应对错误指令的处理目标
二、工程设置
三、程序改进
四、下载与调试
1、合规的指令
2、 proBuffer[0]不是#
3、proBuffer[4]不是;
4、指令长度小于5
5、指令长度大于5
6、proBuffer[2]或proBuffer[3]不是数字
7、';'位于proBuffer[2]或proBuffer[3]位置
在本文作者的文章(参考文章):细说STM32单片机USART中断实现收发控制的方法_stm32 uart 中断接收-CSDN博客 https://wenchm.blog.csdn.net/article/details/143189217 中作者曾经建立了一个Cube IDE工程,利用STM32单片机的USART2串口中断程序,实现单片机接收由串口助手发送来的指令,根据指令更新RTC时间,再通过USART2串口向串口助手发送RTC时间。
参考文章的缺点是,程序简单,没有考虑到干扰指令的影响。程序的鲁棒性很差,除了必须严格按照表格中的协议输入指令外,程序对于不知情、不甚了解协议得错误输入没有鉴别和应急处理的措施。
本文中,作者对不同情况下输入的错误指令,在程序中提供了对应的应急处理方法和错误信息提示。提高了程序的鲁棒性和可用性。
一、工程目的
1、 目标
除参考文章中提到的设计目的之外,重点解决程序设计的鲁棒性:对不同的指令输入的应急处理能力、消息提示。
2、通讯协议及应对错误指令的处理目标
通讯协议(同参考文件)及不同情景下的对错误指令的应急处理方案,对照表如下:
上位机发送的指令字符串 | 指令功能 | 操作说明 |
#H13; | 设置小时,将RTC时间的小时修改为13 | |
#M32; | 设置分钟,将RTC时间的分钟修改为32 | |
#S05; | 设置秒,将RTC时间的秒修改为5 | |
#U01; | 恢复上传时间数据 | |
#U00; | 停止上传时间数据 | |
&H13; | proBuffer[0]不是# | |
#H13! | proBuffer[4]不是; | |
#HER;#H6R;#HE6; | proBuffer[2]或proBuffer[3]不是数字 | |
#Y13; | proBuffer[1]不是H、M、S、U | |
#H9; | 指令长度小于5 | 第一次输入,串口助手没有相应,因为, 串口接收中断没有接收到足够的5个 字节数据,没有产生中断。第二次输入, 助手显示#H9;#,执行相应的应急处理 程序,清空缓存,重启串口。 |
#H192; | 指令长度大于5 | 第一次输入。串口助手显示#H192,因 为proBuffer[4]不是;执行相应的处理程序 |
#H19;2 | 指令长度大于5 | 第一次输入。串口助手显示#H19;程 序正常处理,下一中断,助手显示2**** ,因为proBuffer[0]不是#,执行相应 的应急处理程序,清空缓存,重启串口。 |
#H30; | 小时的数值范围不属于[0,24] | |
#M70; | 分钟的数值范围不属于[0,60] | |
#S70; | 秒的数值范围不属于[0,60] |
二、工程设置
与参考文章相同。
三、程序改进
受影响的程序只有usart.c,且只需修改其中的函数void updateRTCTime()。
/*根据串口接受来的指令字符串,更新修改RTC时间*/
void updateRTCTime()
{unsigned char hello1[]="Invalid command\n";unsigned char hello2[]="Invalid data\n";/* -0x30 操作用于将ASCII码表示的字符(假设是数字'0'~'9')转换为其对应的整数 */uint8_t timeSection = proBuffer[1]; //类型字符uint8_t tmp10 = proBuffer[2]-0x30; //十位uint8_t tmp1 = proBuffer[3]-0x30; //个位uint8_t val= 10*tmp10+tmp1;// Identify the start_bit is '#',the end_bit is ';'or not,
// Regardless of whether the input characters are less than 5 or more than 5, they will all be processed by this program in the end.
// No matter how you clear the buffer, the data received next time will not be complete.
// This situation will never improve until the serial port is restarted.if (rxBuffer[0] != '#' || rxBuffer[4] != ';'){HAL_UART_Transmit(&huart2,hello1,sizeof(hello1),200);memset(rxBuffer, '\0', sizeof(rxBuffer));memset(proBuffer, '\0', sizeof(proBuffer));HAL_UART_Init(&huart2); //重启串口rxCompleted = RESET;HAL_UART_Receive_IT(&huart2, rxBuffer, RX_CMD_LEN);return;}// Identify the data_bit is digits or notif (isalpha(proBuffer[2]) || isalpha(proBuffer[3])){HAL_UART_Transmit(&huart2,hello2,sizeof(hello2),200);memset(proBuffer, '\0', sizeof(proBuffer));return;}//update RTCtimeRTC_TimeTypeDef sTime;RTC_DateTypeDef sDate;if (HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN) == HAL_OK){//调用HAL_RTC_GetTime()之后必须调用HAL_RTC_GetDate()以解锁数据,才能连续更新Date and TimeHAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN);switch (timeSection){case 'H': // 修改小时{if(val <= 24)sTime.Hours = val;else{HAL_UART_Transmit(&huart2,hello2,sizeof(hello2),200);memset(proBuffer, '\0', sizeof(proBuffer));return;}}break;case 'M': // 修改分钟{if(val <= 60)sTime.Minutes = val;else{HAL_UART_Transmit(&huart2,hello2,sizeof(hello2),200);memset(proBuffer, '\0', sizeof(proBuffer));return;}}break;case 'S': // 修改秒{if(val <= 60)sTime.Seconds = val;else{HAL_UART_Transmit(&huart2,hello2,sizeof(hello2),200);memset(proBuffer, '\0', sizeof(proBuffer));return;}}break;case 'U':{if( tmp1 == 0){isUploadTime = 0;//pausereturn;}elseisUploadTime = 1; //resume}break;default: // 不是 'H', 'M' , 'S','U'则返回{HAL_UART_Transmit(&huart2,hello1,sizeof(hello1),200);memset(proBuffer, '\0', sizeof(proBuffer));}return;}HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN); //设置RTC时间影响到下一次唤醒}
}
四、下载与调试
本文的重点在于调试。测试各种情况下新设计的程序的鲁棒性:对各种错误的输入的应急处理能力和信息提示。
1、合规的指令
2、 proBuffer[0]不是#
指令不符合格式,显示指令错误。
3、proBuffer[4]不是;
指令不符合格式,显示指令错误。
4、指令长度小于5
指令长度小于5时,第一次输入后,看不到相应,再次输入后,显示错误的指令字符(只显示前5个字节),执行应急处理程序,清除缓存,重置串口初始化。
如果不重置串口初始化,无论怎么输入,程序接收到的数据总是陷入混乱的状态。
5、指令长度大于5
指令长度小于5时,显示指令错误。当proBuffer[4]=;时,如果前面的数据符合格式,那么执行数据更新;再次 输入指令后,显示指令错误,并执行相应的应急处理程序,清空缓存,重置串口。
6、proBuffer[2]或proBuffer[3]不是数字
显示数据错误。
7、';'位于proBuffer[2]或proBuffer[3]位置
显示指令错误。
其它没有测试到的错误指令输入的情形,感兴趣的网友亲测吧。
本方法,只限于大写字母,没有提供区分大小写字母的算法,感兴趣的网友可以自己去完善。
相关文章:

细说STM32单片机USART中断收发RTC实时时间并改善其鲁棒性的方法
目录 一、工程目的 1、 目标 2、通讯协议及应对错误指令的处理目标 二、工程设置 三、程序改进 四、下载与调试 1、合规的指令 2、 proBuffer[0]不是# 3、proBuffer[4]不是; 4、指令长度小于5 5、指令长度大于5 6、proBuffer[2]或proBuffer[3]不是数字 7、;位于p…...

无人机场景 - 目标检测数据集 - 夜间车辆检测数据集下载「包含VOC、COCO、YOLO三种格式」
数据集介绍:无人机场景夜间车辆检测数据集,真实场景高质量图片数据,涉及场景丰富,比如夜间无人机场景城市道路行驶车辆图片、夜间无人机场景城市道边停车车辆图片、夜间无人机场景停车场车辆图片、夜间无人机场景小区车辆图片、夜…...
Dubbo 构建高效分布式服务架构
一、引言 随着软件系统的复杂性不断增加,传统的单体架构已经难以满足大规模业务的需求。分布式系统架构通过将系统拆分成多个独立的服务,实现了更好的可扩展性、可维护性和高可用性。在分布式系统中,服务之间的通信和协调是一个关键问题&…...

Unity XR Interaction Toolkit 开发教程(1):OpenXR 与 XRI 概述【3.0 以上版本】
文章目录 📕Unity XR 开发架构🔍底层插件(对接硬件)🔍高层 SDK(面向应用交互层) 📕OpenXR📕XR Interaction Toolkit🔍特点🔍XRI 能够实现的交互类…...

自扶正救生艇,保障水上救援的安全卫士_鼎跃安全
在应急事件中,自扶正救生艇能够发挥关键的救援和保障作用,确保救援人员和被困人员的生命安全,尤其在极端天气或突发水上事故中展现出明显优势。 在救援过程中如果遭遇翻船,救生艇能够迅速恢复正常姿态,确保救援人员不会…...

《Qwen2-VL》论文精读【下】:发表于2024年10月 Qwen2-VL 迅速崛起 | 性能与GPT-4o和Claude3.5相当
1 前言 《Qwen2-VL》论文精读【上】:发表于2024年10月 Qwen2-VL 迅速崛起 | 性能与GPT-4o和Claude3.5相当 上回详细分析了Qwen2-VL的论文摘要、引言、实验,下面继续精读Qwen2-VL的方法部分。 文章目录 1 前言2 方法2.1 Model Architecture2.2 改进措施2…...
WebSocket消息帧的组成结构
WebSocket消息帧是WebSocket协议中的一个基本单位,它定义了数据在客户端和服务器之间传递的格式。每个数据帧包含了不同类型的数据和各种控制信息。以下是WebSocket消息帧的组成结构: WebSocket 帧结构 FIN、RSV1、RSV2、RSV3 和 opcode(第一…...
如何利用低代码开源框架实现高效开发?
随着数字化转型步伐的加快,越来越多的企业开始关注提高软件开发效率的方法。低代码平台因其能够大幅减少编码量而受到欢迎,而开源框架则因其灵活性和社区支持成为开发者的首选。如何利用低代码开源框架实现高效开发,成为许多企业和开发者面临…...

使用 RabbitMQ 有什么好处?
大家好,我是锋哥。今天分享关于【使用 RabbitMQ 有什么好处?】面试题。希望对大家有帮助; 使用 RabbitMQ 有什么好处? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 RabbitMQ 是一种流行的开源消息代理,广…...

机器学习周报(RNN的梯度消失和LSTM缓解梯度消失公式推导)
文章目录 摘要Abstract 1 RNN的梯度消失问题2 LSTM缓解梯度消失总结 摘要 在深度学习领域,循环神经网络(Recurrent Neural Network, RNN)被广泛应用于处理序列数据,特别是在自然语言处理、时间序列预测等任务中。然而,…...

一篇文章理解前端中的 File 和 Blob
概述: js处理文件、二进制数据和数据转换的时候,提供了一些API和对象,例如:File、Blob、FileReader、ArraryBuffer、Base64、Object URL 和 DataURL。现在主要介绍File和Blob这两个对象。 1.Blob介绍 在js中,Blob&am…...

串口屏控制的自动滑轨(未完工)
序言 疫情期间自己制作了一个自动滑轨,基于无线遥控的,但是整体太大了,非常不方便携带,所以重新设计了一个新的,以2020铝型材做导轨的滑轨,目前2020做滑轨已经很成熟了,配件也都非常便宜&#x…...

DFA算法实现敏感词过滤
DFA算法实现敏感词过滤 需求:检测一段文本中是否含有敏感词。 比如检测一段文本中是否含有:“滚蛋”,“滚蛋吧你”,“有病”, 可使用的方法有: 遍历敏感词,判断文本中是否含有这个敏感词。 …...
Python自动化运维:技能掌握与快速入门指南
#编程小白如何成为大神?大学生的最佳入门攻略# 在当今快速发展的IT行业中,Python自动化运维已经成为了一个不可或缺的技能。本文将为您详细介绍Python自动化运维所需的技能,并提供快速入门的资源,帮助您迅速掌握这一领域。 必备…...

在linux系统中安装pygtftk软件
1.下载和安装 网址: https://dputhier.github.io/pygtftk/index.html ## 手动安装 git clone http://gitgithub.com:dputhier/pygtftk.git pygtftk cd pygtftk # Check your Python version (>3.8,<3.9) pip install -r requirements.txt python setup.py in…...

decodeURIComponentSafe转义%问题记录URI malformed
decodeURIComponentSafe转义%问题记录 问题背景 当我们解析包涵 % 字符的字符串时,会出现错误如下 Uncaught URIError: URI malformed 解决方案: function decodeURIComponentSafe(s) {if (!s) {return s;}return decodeURIComponent(s.replace(/%(?…...

自由学习记录(18)
动画事件的碰撞器触发 Physics 类的常用方法 RaycastHit hit; if (Physics.Raycast(origin, direction, out hit, maxDistance)) {Debug.Log("Hit: " hit.collider.name); } Physics.Raycast:从指定点向某个方向发射射线,检测是否与碰撞体…...
vue3-ref 和 reactive
文章目录 vue3 中 ref 和 reactivereactive 与 ref 不同之处ref 处理复杂类型ref在dom中的应用 vue3 中 ref 和 reactive ref原理 基本原理 ref是Vue 3中用于创建响应式数据的一个函数。它的基本原理是通过Object.defineProperty()(在JavaScript的规范中用于定义对…...
Apache Calcite - 查询优化之自定义优化规则
RelOptRule简介 为了自定义优化规则,我们需要继承RelOptRule类。org.apache.calcite.plan.RelOptRule 是 Apache Calcite 中的一个抽象类,用于定义优化规则。优化规则是用于匹配查询计划中的特定模式,并将其转换为更优化的形式的逻辑。通过继…...
大型语言模型(LLM)的小型化研究进展
2024年,大型语言模型(LLM)的小型化研究取得了显著进展,主要采用以下几种方法实现: 模型融合:通过将多个模型或检查点合并为一个单一模型,减少资源消耗并提升整体性能。例如,《WARM: …...

测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...

云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...

排序算法总结(C++)
目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指:同样大小的样本 **(同样大小的数据)**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...

AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别
【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而,传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案,能够实现大范围覆盖并远程采集数据。尽管具备这些优势…...

【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...