上位机图像处理和嵌入式模块部署(mcu项目1:实现协议)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
这种mcu的嵌入式模块理论上都是私有协议,因为上位机和下位机都是自己开发的,所以只需要自己保证上、下位机可以通讯上,没有问题就行。但是现在有一个情况,那就是如何实现这个协议。现在我们是选择了ttl作为通信的方式,下面要做的就是如何用ttl实现通信协议。
1、上、下位机分开测试
前面准备好了通信的协议,各自就可以独立开发了。上位机可以用利用虚拟com进行测试,自己写一个假的下位机。而下位机呢,则可以通过串口工具来进行测试。一般来说,下位机如果测试没有问题了,才会去找上位机进行联合调试,不然调试的效率就太低了。
对于下位机来说,只要串口工具ok了,那么上位机不管是qt,还是mfc、c# wpf,只要按照协议把数据发下来,那就应该没问题的。
2、调试的时候一般都是通过16进制调试的
通常来说,发送的协议就是8位无符号数据,不是字符串。所以这个时候调试的时候,不管是接收命令,还是发送命令,最好都是通过16进制进行调试。
3、上位机一般是主动的那一方
通常来说,上位机都是主动的那一方。不管是去读数据,还是写数据,上位机都是主动发起请求的一方。这个时候,对于下位机来说,回复好上位机的问题,给出相应的答案就可以了。
4、压力测试是一定要的
协议解析的过程有可能出现不对的地方,这是很常见的。而且,随着开发的进行,有可能添加各种不同样的协议内容。所以不管哪一种协议,我们在实现和验证的时候,一定要进行压力测试,即通过串口工具周期性发送一些命令,这些都是可以的。单挑发送、多条发送、随机发送,一般的上位机工具都会支持这样的测试。
5、使用fsm去解析协议
串口的属性,决定了我们是一个、一个去接收数据的。这个时候就要求我们,需要根据这些单个的数据来判断它是否符合协议的要求。要做到这一点,最好的方法就是用有限状态机fsm去实现。比如说,首先是什么状态,接收到一个数据,应该是什么状态,是继续维持,还是说继续走向下一个状态。一般来说,只要状态机设计好,基本上固件都是非常稳定的。
void receiveUartData(void) // receive data and parse data here
{int index = 0;if (USART_ReadIntFlag(USART_UX, USART_INT_RXBNE) == SET){g_rx_buffer[0] = USART_RxData(USART_UX); /* receive one byte data*/switch(uartState){case HEAD_STATE1: // wait 0x55if(g_rx_buffer[0] == 0x55){g_usart_rx_buf[0] = g_rx_buffer[0];g_usart_rx_sta ++;uartState = HEAD_STATE2;}else{g_usart_rx_sta = 0;}break;case HEAD_STATE2: // wait another 0x55if(g_rx_buffer[0] == 0x55){g_usart_rx_buf[1] = g_rx_buffer[0];g_usart_rx_sta ++;uartState = TAIL_STATE1;}else{g_usart_rx_sta = 0;uartState = HEAD_STATE1;}break;case TAIL_STATE1: // wait 0xaaif(g_usart_rx_sta >= 32){g_usart_rx_sta = 0;uartState = HEAD_STATE1;break;}g_usart_rx_buf[g_usart_rx_sta] = g_rx_buffer[0];g_usart_rx_sta ++;if(g_rx_buffer[0] == 0xaa){uartState = TAIL_STATE2;}break;case TAIL_STATE2: // wait another 0xaag_usart_rx_buf[g_usart_rx_sta] = g_rx_buffer[0];g_usart_rx_sta ++;if(g_rx_buffer[0] == 0xaa && useFlag == 0) /* if useFlag = 0 or not qualified data, just drop it directly*/{for(index = 0; index < g_usart_rx_sta; index++){transferBuf[index] = g_usart_rx_buf[index];}bufLen = g_usart_rx_sta;useFlag = 1;}g_usart_rx_sta = 0;uartState = HEAD_STATE1;break;default:break;}USART_ClearIntFlag(USART_UX, USART_INT_RXBNE);}
}
6、协议的处理可以放到main里面继续进行
中断部分只是负责数据的接收,具体命令的解析可以放到main函数里面继续执行。毕竟接收数据本身是在中断函数处理的,这部分花的时间越少越好。而具体的数据解析,实时性没那么高,慢一点都是没有关系的。
extern uint16_t voltage; // add by feixiaoxing
int parseData() // use app tool to test the data
{unsigned char str[32] = {0};if(useFlag == 0){return -1;}if(0 == bufLen){setFlag();return -1;}if(bufLen < 4){setFlag();return -1;}if(transferBuf[0] != 0x55 || transferBuf[1] != 0x55){setFlag();return -1;}if(transferBuf[bufLen-2] != 0xaa || transferBuf[bufLen-1] != 0xaa){setFlag();return -1;}if(bufLen != 10) // header + length + commandid + crc + tail{setFlag();return -1;}// restore flagsetFlag();// prepare datastr[ 0] = 0x55; // headerstr[ 1] = 0x55;str[ 2] = 0x00; // lengthstr[ 3] = 0x08;str[ 4] = 0x00; // command id;str[ 5] = 0x00;str[ 6] = voltage / 1000; // datastr[ 7] = voltage % 1000;str[ 8] = 0x00; // crcstr[ 9] = 0x00;str[10] = 0xaa; // tailstr[11] = 0xaa;outputData((char*)str, 12);return 0;
}
相关文章:

上位机图像处理和嵌入式模块部署(mcu项目1:实现协议)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 这种mcu的嵌入式模块理论上都是私有协议,因为上位机和下位机都是自己开发的,所以只需要自己保证上、下位机可以通讯上&…...

【NLP学习笔记】load_dataset加载数据
除了常见的load_dataset(<hf上的dataset名>)这种方式加载HF上的所有数据外,还有其他custom的选项。 加载HF上部分数据 from datasets import load_dataset c4_subset load_dataset("allenai/c4", data_files"en/c4-train.0000*-of-01024.js…...
企业如何选择好用的供应商管理系统
供应商管理系统软件(SRM)是企业用于管理供应链中各个供应商关系的重要工具。现如今竞争激烈的市场环境下,选择一款合适的SRM软件显得尤为重要。那么,如何选择一款好用的供应商管理系统呢? 企业在选择好用的供应商管理…...

震惊!运气竟能如此放大!运气的惊人作用,你了解吗?
芒格:得到你想要的东西,最保险的办法,就是让自己配得上你想要的那个东西。今天仔细想了想这句话,他其实说的是无数成功人士的心声 —— “我配得上!” 美剧《绝命毒师》有个导演叫文斯吉里根(Vince Gilliga…...
记录一次Apache Tomcat 处理返回自定义的404页面
记录工作中遇到处理访问tomcat 不存在的资源,返回自定义的404页面 删除webapps目录下的example、docs、manager、hta-manager目录,只保留 ROOT目录,应用部署在了这个目录 删除 manager、hta-manager 我没有发现有什么异常 制作404.jsp 或者 4…...
【piania 的用法】
piania 的用法 定义store建议使用箭头函数TypeScript插件扩展1、全局添加对象 定义store import { ref, computed } from vue import { defineStore } from pinia // pinia 以函数的形式暴露出去 export const useCounterStore defineStore(counter, () > {// 1、ref 相当…...

上海计算机考研炸了,这所学校慎报!上海大学计算机考研考情分析!
上海大学(Shanghai University),简称“上大”,是上海市属、国家“211工程”重点建设的综合性大学,教育部与上海市人民政府共建高校,国防科技工业局与上海市人民政府共建高校,国家“双一流”世界…...

面对全球新能源汽车合作发展创维汽车如何实现共赢
由全球新能源汽车合作组织(筹)主办、中国电动汽车百人会承办的首届全球新能源汽车合作发展论坛(GNEV2024)于6月27日,6月28日在新加坡金沙会议展览中心召开。创维汽车国际营销公司总经理齐奎源受邀参会并作出分享。 本届大会以推动全球新能源汽车产业协同发展与合作…...
安全和加密常识(1)对称加密和非对称加密以及相应算法
文章目录 对称加密(Symmetric Encryption)非对称加密(Asymmetric Encryption)使用场景和优缺点对称加密和非对称加密是信息安全领域中两种重要的加密方式,它们分别使用不同的加密算法和密钥管理方式来保护数据的机密性。下面我来简单介绍一下它们及其相应的算法。 对称加…...

afrog-漏洞扫描(挖洞)工具【了解安装使用详细】
★★免责声明★★ 文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与学习之用,读者将信息做其他用途,由Ta承担全部法律及连带责任,文章作者不承担任何法律及连带责任。 1、afrog介绍 afrog 是一款性能卓越、快速稳定、PoC可定…...

c++类模板--无法解析的外部符号
解决办法 文章目录 解决办法方法1(推荐).在主函数包含头文件时将实现模板类的函数也包含进来方法2.将模板类的实现方法写在头文件里面方法3.函数模板声明前加inline 可能错误2,类内实现友元输出重载 方法1(推荐).在主函数包含头文件时将实现模板类的函数也包含进来 …...
Postman介绍
Postman 是一款流行的 API 开发和测试工具,它提供了一个直观的用户界面,使开发者可以轻松地构建、测试和修改 HTTP 请求。Postman 不仅适用于测试人员,也广泛应用于开发人员、产品经理和API设计者中,以确保API的正确性和性能。 以…...

以智能化为舵手,引领现代计算机系统架构新航向
编者按:如今计算机系统承载的服务和算法逻辑日益复杂,理解、设计并改进计算机系统已成为核心挑战。面对系统复杂度和规模的指数级增长,以及新的大模型驱动场景下的分布式系统形态的涌现,人们亟需创新方法与技术来应对。在计算机系…...

揭秘品牌成功秘诀:品牌营销策略的核心要素大公开
品牌营销作为企业战略中至关重要的一环,其核心是建立和传播品牌的独特魅力,使其在消费者心目中占据重要位置。 一个成功的品牌营销策略能够提升品牌的知名度和影响力,带来持续的销售和忠诚客户群体。 在当今竞争激烈的市场环境中࿰…...
java如何把list转换成map
不废话,直接上代码 public static void main(String[] args) {List<UserxVO> list new ArrayList<>();for (int i 0; i < 10; i) {list.add(new UserxVO("n" i, "dd" i));}Map<String, String> map list.stream().co…...
vite typescript 配置跨域代理
打开工程目录下vite.config.ts文件 export default defineConfig({plugins: [vue(), topLevelAwait()],resolve: { alias },server:{proxy:{/api:{ //对以 /api 开头的请求跨域处理target:http://xxx.xxx.cn,//目标服务器changeOrigin: true,rewrite:(path)>{return path.…...
ArcGIS Pro SDK (七)编辑 10 捕捉
ArcGIS Pro SDK (七)编辑 10 捕捉 文章目录 ArcGIS Pro SDK (七)编辑 10 捕捉1 配置捕捉 - 打开或关闭捕捉2 配置捕捉 - 应用程序捕捉模式3 配置捕捉 - 图层捕捉可捕捉性4 配置捕捉 - 图层捕捉模式5 配置捕捉 - 组合示例6 捕捉选项…...

开始尝试从0写一个项目--后端(一)
创建文件的目录结构 利用这个界面创建 序号 名称 说明 1 SEMS maven父工程,统一管理依赖版本,聚合其他子模块 2 sems-common 子模块,存放公共类,例如:工具类、常量类、异常类等 3 sems-pojo 子模块&#x…...

STM32第十二课:ADC检测烟雾浓度(MQ2)
文章目录 需求一、MQ-2 气体传感器特点应用电路及引脚 二、实现流程1.开时钟,分频,配IO2.配置ADC的工作模式3.配置通道4.复位,AD校准5.数值的获取 需求实现总结 需求 使用ADC将MQ2模块检测到的烟雾浓度模拟量转化为数字量。 最后,…...

1975react社区问答管理系统开发mysql数据库web结构node.js编程计算机网页源码
一、源码特点 react 社区问答管理系统是一套完善的完整信息管理类型系统,结合react.js框架和node.js后端完成本系统,对理解react node编程开发语言有帮助系统采用node框架(前后端分离)),系统具有完整的源…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

【项目实战】通过多模态+LangGraph实现PPT生成助手
PPT自动生成系统 基于LangGraph的PPT自动生成系统,可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析:自动解析Markdown文档结构PPT模板分析:分析PPT模板的布局和风格智能布局决策:匹配内容与合适的PPT布局自动…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...

【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...

三分算法与DeepSeek辅助证明是单峰函数
前置 单峰函数有唯一的最大值,最大值左侧的数值严格单调递增,最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值,最小值左侧的数值严格单调递减,最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)
引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...
NPOI操作EXCEL文件 ——CAD C# 二次开发
缺点:dll.版本容易加载错误。CAD加载插件时,没有加载所有类库。插件运行过程中用到某个类库,会从CAD的安装目录找,找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库,就用插件程序加载进…...