C#与STM32自定义通信协议

2023-05-16

功能

  1. 可通过C#上位机与STM32下位机之间进行通信
  2. 可以保证接收的数据的正确性

一、C#作为上位机实现代码

using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MNTC_HMI.utils
{
   /// <summary>
   /// 串口工具类
   /// </summary>
   class SerialportHelper
   {
       #region 变量
       const byte HEADER = 0xA5;           //帧头
       const byte FOOTER = 0x5A;           //帧尾
       Byte[] rx_buf = new Byte[255];      //接收缓冲数组		
       Byte[] tx_buf = new Byte[255];      //发送缓冲数组		
       byte rx_byte = 0;                   //接收有效数据长度															
       byte tx_byte = 0;                   //接收有效数据长度	 
       #endregion

       #region 串口工具类相关函数
       /******************************************************************************************************************
        * name        : public void HMI_WriteBuf(byte data)
        * Function    : 向缓冲区发送缓冲区中写入一个字节数据
        * Parameters  : data :待写入的数据
        * Returns     : NULL
        * Author      : 那些你很冒险的梦
        * Check       :
        * Date        : 2021-3-21
       ******************************************************************************************************************/
       public void HMI_WriteBuf(byte data)
       {
           tx_buf[tx_byte] = data;                     //赋值
           tx_byte++;                                  //有效数据个数加1
       }

       /******************************************************************************************************************
        * name        : public byte HMI_Check( )
        * Function    : 根据有效数据生成校验码
        * Parameters  : void
        * Returns     : NULL
        * Author      : 那些你很冒险的梦
        * Check       :
        * Date        : 2021-3-21
        ******************************************************************************************************************/
       public byte HMI_Check( )
       {
           byte temp = tx_byte;
           for (int i = 0; i < tx_byte; i++)               //循环取异或
           {
               temp = (byte)(temp ^ tx_buf[i]);
           }
           return temp;
       }

       /******************************************************************************************************************
        * name        : public void HMI_SendCode(SerialPort serialPort)
        * Function    : 将缓冲区中的数据发送出去
        * Parameters  : serialPort:选择使用的串口
        * Returns     : NULL
        * Author      : 那些你很冒险的梦
        * Check       :
        * Date        : 2021-3-21
        ******************************************************************************************************************/
       public void HMI_SendCode(SerialPort serialPort)
       {
           Byte[] temp_buf = new Byte[255];                //创建临时数组
           temp_buf[0] = HEADER;                           //添加帧头
           temp_buf[1] = tx_byte;                          //添加有效数据的长度
           for (int j = 0; j < tx_byte; j++)
           {
               temp_buf[j + 2] = tx_buf[j];
           }
           temp_buf[tx_byte + 2] = HMI_Check();            //检验位
           temp_buf[tx_byte + 3] = FOOTER;                 //添加帧尾
           serialPort.Write(temp_buf, 0, tx_byte + 4);     //将数据发送出去
       }
       #endregion
   }
}

二、STM32下位机实现代码

bsp_hmi.h

#ifndef __BSP_HMI_H
#define __BSP_HMI_H

/******************************* 引入头文件 start *********************************/
#include "stm32f4xx.h"
/******************************** 引入头文件 end **********************************/


/********************************* 宏定义 start ***********************************/
#define HMI_RX_BUF_LEN		255								//接收缓冲数组最大长度
#define HMI_TX_BUF_LEN		255     						//发送缓冲数组最大长度
#define HEAD  				0xA5  							//帧头1												
#define FOOTER 			    0X5A    						//帧尾1
/********************************** 宏定义 end ************************************/

/********************************* 结构体 start ***********************************/
typedef struct _DW_Struct
{
	USART_TypeDef*	com;	                				//串口号												
	unsigned char 	rx_buf[HMI_RX_BUF_LEN];					//接收缓冲数组		
	unsigned char 	tx_buf[HMI_TX_BUF_LEN];					//发送缓冲数组		
	int rx_byte;	                        				//接收有效数据长度															
	int tx_byte;				            				//发送有效数据长度																										
}HMI_Struct;
/*********************************** 结构体 end *************************************/

/********************************* 函数声明  start **********************************/
void HMI_WriteBuf(HMI_Struct *hmi_Struct,int data);   		//向发送缓冲区写入一个数组
void HMI_Write2Buf(HMI_Struct *hmi_Struct,int data);		//向发送缓冲区写入两个数组
void HMI_SendCode(HMI_Struct* hmi_Struct);					//将缓冲区中的数据处理后发送出去
void HMI_Decode(HMI_Struct* hmi_Struct,uint8_t isFinish);	//处理接收缓冲区中的数组
/********************************** 函数声明  end ***********************************/

#endif /*__BSP_HMI*/

bsp_hmi.h

#include "bsp_hmi.h"
#include "led.h" 
#include "delay.h"
#include "bsp_motor.h"
#include "usart.h"	

extern uint8_t motor1_flag;		//产生脉冲标志位    1:表示产生脉冲    0表示不产生脉冲
extern uint8_t motor2_flag;		//产生脉冲标志位    1:表示产生脉冲    0表示不产生脉冲

extern int speed1;
extern uint8_t isFinish;
/**************************************************************************************
  * name        : void HMI_WriteBuf(HMI_Struct *hmi_Struct,int data)
  * Function    : 向发送缓冲区写入一个字节
  * Parameters  : hmi_Struct:发送与接收结构体   data:写入的数据
  * Returns     : NULL
  * Author      : 那些你很冒险的梦
  * Check       :
  * Date        : 2021/3/20
**************************************************************************************/
void HMI_WriteBuf(HMI_Struct *hmi_Struct,int data)
{
	hmi_Struct->tx_buf[hmi_Struct->tx_byte]= data;			//赋值			
	hmi_Struct->tx_byte++;									//有效值加1
}

/**************************************************************************************
  * name        : void HMI_Write2Buf(HMI_Struct *hmi_Struct,int data)
  * Function    : 向发送缓冲区写入两个字节
  * Parameters  : hmi_Struct:发送与接收结构体   data:写入的数据
  * Returns     : NULL
  * Author      : 那些你很冒险的梦
  * Check       :
  * Date        : 2021/3/20
**************************************************************************************/
void HMI_Write2Buf(HMI_Struct *hmi_Struct,int data)
{
	hmi_Struct->tx_buf[hmi_Struct->tx_byte]= (data & 0xFF00)>>8;	//高八位赋值							
	hmi_Struct->tx_byte++;											//有效值加1
	hmi_Struct->tx_buf[hmi_Struct->tx_byte]= (data & 0xFF);			//第八位赋值							
	hmi_Struct->tx_byte++;											//有效值加1
}

/**************************************************************************************
  * name        : void USART_SendBuf(USART_TypeDef *com, uint16_t *buf, int buf_len)
  * Function    : 将数组中的数据发送出去
  * Parameters  : com:使用的串口号   buf:发送数组的名称		buf_len:有效数据的长度
  * Returns     : NULL
  * Author      : 那些你很冒险的梦
  * Check       :
  * Date        : 2021/3/20
**************************************************************************************/
void USART_SendBuf(USART_TypeDef *com, uint16_t *buf, int buf_len)
{																									
	for(int i=0; i < buf_len; i++)
	{
		USART_SendData(com, buf[i]);								//发送一个字节数据										
		while(USART_GetFlagStatus(com,USART_FLAG_TXE)==RESET);		//等待发送完成	
	}
}


/**************************************************************************************
  * name        : uint16_t HMI_Check(HMI_Struct* hmi_Struct)
  * Function    : 生成校验码 --异或检验
  * Parameters  : hmi_Struct:发送与接收结构体
  * Returns     : NULL
  * Author      : 那些你很冒险的梦
  * Check       :
  * Date        : 2021/3/20
**************************************************************************************/
uint16_t HMI_Check(HMI_Struct* hmi_Struct)
{
	uint16_t temp=hmi_Struct->tx_byte;
	for(int i=0;i<hmi_Struct->tx_byte;i++)			//循环异或
	{
		temp=temp^hmi_Struct->tx_buf[i];
		
	}
	return temp;
}

/**************************************************************************************
  * name        : void HMI_SendCode(HMI_Struct* hmi_Struct)
  * Function    : 将数据处理之后发送出去
  * Parameters  : hmi_Struct:发送与接收结构体
  * Returns     : NULL
  * Author      : 那些你很冒险的梦
  * Check       :
  * Date        : 2021/3/20
**************************************************************************************/
void HMI_SendCode(HMI_Struct* hmi_Struct)
{																										
	uint16_t temp_buf[HMI_TX_BUF_LEN];									//定义临时数组
	temp_buf[0]= HEAD;													//添加帧头
	temp_buf[1]= hmi_Struct->tx_byte;									//有效数据为的个数
	for(int j=0; j < hmi_Struct->tx_byte ; j++)							//将数组中的数据赋值到临时数组
	{
		temp_buf[j+2]= hmi_Struct->tx_buf[j];
	}
	temp_buf[hmi_Struct->tx_byte+2]=HMI_Check(hmi_Struct);				//检验位
	temp_buf[hmi_Struct->tx_byte+3]=FOOTER;								//添加帧尾
	USART_SendBuf(hmi_Struct->com, temp_buf , hmi_Struct->tx_byte+4);	//发送数据			
}

/**************************************************************************************
  * name        : void HMI_Decode(HMI_Struct* hmi_Struct,uint8_t* isFinish)
  * Function    : 将接收到数据发送出去
  * Parameters  : hmi_Struct:发送与接收结构体   isFinish:接收完成标志位地址
  * Returns     : NULL
  * Author      : 那些你很冒险的梦
  * Check       :
  * Date        : 2021/3/20
**************************************************************************************/
void HMI_Decode(HMI_Struct* hmi_Struct,uint8_t isFinish1)
{
	if(isFinish1==1)
	{
		if(hmi_Struct->rx_buf[0]==0XA5 && hmi_Struct->rx_buf[hmi_Struct->rx_byte-1]==0X5A)			//帧头 帧尾是否正确
		{
			//计算校验码
			int temp = hmi_Struct->rx_buf[1];
		
			for(int i=2;i<hmi_Struct->rx_buf[1]+2;i++)
			{
				temp = temp^hmi_Struct->rx_buf[i];
			}
			//判断检验码是否正确
			if(temp==hmi_Struct->rx_buf[hmi_Struct->rx_byte-2])
			{
				//对数据进行处理 ---速度
				if(hmi_Struct->rx_buf[2]==0x00)
				{
					motor1_flag = 0;
				}else{	
					motor1_flag = 1;
					speed1 = hmi_Struct->rx_buf[2];
				}
				//对数据进行处理 ---方向
				switch(hmi_Struct->rx_buf[3])
				{
					case 0x01:	//正向
						motor_dir(0);
						LED0_TOGGLE;
						break;
					case 0x02:	//反向
						motor_dir(1);
						LED0_TOGGLE;
						break;
					defalt:
						LED0_TOGGLE;
						break;
				}
			}
		}
		hmi_Struct->rx_byte=0;
		isFinish = 0;
	}
}

欢迎一起讨论技术问题,求关注!

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

C#与STM32自定义通信协议 的相关文章

  • 初始化 ST-Link 设备时出错 - 无法连接到设备

    我目前正在使用 ST Link 调试器对我的 STM32F3 Discovery 板进行编程 我使用的IDE是Atollic TrueStudio 5 5 2 现在我面临一个非常奇怪的问题 那就是我不断收到消息 初始化 ST Link 设备
  • 在 MCU 内部 FLASH 中从一个固件跳转到另一个固件

    我目前正在开发针对 STM32F030C8 的引导加载程序固件应用程序 我在分散文件中指定引导加载程序应用程序将占用主内存位置 0x08000000 到 0x08002FFF 扇区 0 到扇区 2 我还编写了一个主固件应用程序 存储在0x0
  • 优化 ARM Cortex M3 代码

    我有一个 C 函数 它尝试将帧缓冲区复制到 FSMC RAM 这些函数将游戏循环的帧速率降低至 10FPS 我想知道如何分析反汇编的函数 我应该计算每个指令周期吗 我想知道CPU把时间花在哪里 在哪个部分 我确信该算法也是一个问题 因为它的
  • 134-基于stm32单片机矿井瓦斯天然气浓度温湿度检测自动通风系统Proteus仿真+源程序...

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

    先吐槽一下 rt thread studio出现BUG真多 好多时间都是在找BUG 但里面用好多控件还是挺好用的 真是又爱又恨 所以一般使用功能不多的话还是用keil多一点 创建5 02版本工程之后直接进行编译 直接会报下面这个错误 资源
  • 物联网网关

    物联网网关是 连接物联网设备和互联网的重要桥梁 它负责将物联网设备采集到的数据进行处理 存储和转发 使其能够与云端或其它设备进行通信 物联网网关的作用是实现物联网设备与云端的无缝连接和数据交互 物联网网关功能 数据采集 物联网网关可以从物联
  • SHT10温湿度传感器——STM32驱动

    实验效果 硬件外观 接线 3 3V供电 IIC通讯 代码获取 查看下方 END
  • 解决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测试 再慢慢使用
  • 1.69寸SPI接口240*280TFT液晶显示模块使用中碰到的问题

    1 69寸SPI接口240 280TFT液晶显示模块使用中碰到的问题说明并记录一下 在网上买了1 69寸液晶显示模块 使用spi接口 分辨率240 280 给的参考程序是GPIO模拟的SPI接口 打算先移植到FreeRtos测试 再慢慢使用
  • STM32的HAL中实现单按、长按和双按功能

    我正在尝试实现单击 双击和长按功能来执行不同的功能 到目前为止 我已经理解了单击和长按的逻辑 但我不知道如何检测双击 至于代码 我使用计数器实现了单击和长按 但代码仅停留在第一个 if 条件上 bool single press false
  • 毕设开题分享 单片机智能教室系统(智能照明+人数统计)

    1 简介 Hi 大家好 今天向大家介绍一个学长做的单片机项目 单片机智能教室系统 智能照明 人数统计 大家可用于 课程设计 或 毕业设计 项目分享 https gitee com feifei1122 simulation project
  • Freertos低功耗管理

    空闲任务中的低功耗Tickless处理 在整个系统运行得过程中 其中大部分时间都是在执行空闲任务的 空闲任务之所以执行 因为在系统中的其他任务处于阻塞或者被挂起时才会执行 因此可以将空闲任务的执行时间转换成低功耗模式 在其他任务解除阻塞而准
  • STM32F4XX的12位ADC采集数值超过4096&右对齐模式设置失败

    文章目录 一 前言 二 问题1 数值超过4096 三 问题1的排错过程 四 问题2 右对齐模式设置失败 五 问题2的解决方法 5 1 将ADC ExternalTrigConv设置为0 5 2 使用ADC StructInit 函数 一 前
  • Arm:objcopy 如何知道 elf 中的哪些部分要包含在二进制或 ihex 中?

    我正在开发一个项目 其中涉及解析arm elf 文件并从中提取部分 显然 elf 文件中有很多部分没有加载到闪存中 但我想知道 objcopy 到底如何知道要在二进制文件中包含哪些部分以直接闪存到闪存中 以arm elf文件的以下reade
  • 特殊寄存器

    特殊寄存器 文章目录 前言 一 背景 二 2 1 2 2 总结 前言 前期疑问 STM32特殊寄存器到底是什么 特殊寄存器怎么查看和调试代码 本文目标 记录和理解特殊寄存器 一 背景 最近在看ucosIII文章是 里面提到特殊寄存器 这就进
  • systick定时器

    systick定时器 文章目录 前言 一 前期疑惑 二 解答 1 关于systick是阻塞的吗 2 非阻塞 三 软件编写 总结 前言 这边记录systick相关知识点 一 前期疑惑 在学习systick志气啊 其实对于systick还是一脸
  • STM32 Nucleo 上的上升沿中断多次触发

    我正在使用 STM32 NUCLEO F401RE 微控制器板 我有一个扬声器 经过编程 当向上 向下推操纵杆时 可以按设定的量改变频率 我的问题是 有时 通常 当向上 向下推动操纵杆时 频率会增加 减少多次 这意味着 ISR 正在执行多次
  • STM32F0、ST-link v2、OpenOCD 0.9.0:打开失败

    我在用着发射台 http www ti com ww en launchpad about htmlgcc arm none eabi 4 9 2015q2 为 STM32F0 进行编译 现在我想使用该集合中的 arm none eabi
  • 哪些变量类型/大小在 STM32 微控制器上是原子的?

    以下是 STM32 微控制器上的数据类型 http www keil com support man docs armcc armcc chr1359125009502 htm http www keil com support man d

随机推荐

  • 嵌入式工程师的经典面试题目

    嵌入式工程师的经典面试题目 预处理器 xff08 Preprocessor xff09 1 用预处理指令 define 声明一个常数 xff0c 用以表明1年中有多少秒 xff08 忽略闰年问题 xff09 define SECONDS P
  • rabbitmq版本升级

    目录 一 背景 二 部署新的mq 三 元数据备份和还原 四 消息数据备份和还原 五 注意 一 背景 因原来rabbitmq版本存在漏洞需升级至最新版本 原来是使用软件包部署 xff0c 升级我采用使用docker compose部署 xff
  • __attribute__

    前言 本文介绍 attribute 的使用方法 attribute 介绍 要了解Linux Kernel代码的分段信息 xff0c 需要了解一下gcc的 attribute 的编绎属性 xff0c attribute 主要用于改变所声明或定
  • 卡尔曼滤波(2):一个简单的例子

    为了说明离散性卡尔曼滤波器的用法 xff0c 我将用一个最简单的例子来进行说明 假设我们现在对一个房间内的温度进行测试 xff0c 房间内温度初值为25 c xff0c 每过一个时间周期 xff0c 温度x都将在上一个周期温度的基础上变动
  • 使用websocket连接Activemq,让前端接收MQTT消息

    使用websocket连接Activemq xff0c 让前端接收MQTT消息 Activemq简介准备工作简单示例 Activemq简介 Apache ActiveMQ is the most popular open source mu
  • Unix时间戳,GPS时间戳 ,UTC时间 , 本地时间

    本地时间 xff1a 计算机显示的时间 本地时间 61 UTC 时间 43 时区 xff08 北京时间是东八区 xff0c 也就是 43 8小时 xff09 unix 时间戳 xff1a UTC时间都是从 xff08 1970年01月01日
  • 详解PID控制算法 位置式和增量式区别 附代码详解

    1PID控制算法 什么是PID PID 控制器以各种形式使用超过了 1 世纪 xff0c 广泛应用在机械设备 气动设备 和电子设备 在工业应用中PID及其衍生算法是应用最广泛的算法之一 xff0c 是当之无愧的万能算法 PID 实指 比例
  • 虚拟机中打开Gazebo闪退的解决办法

    问题 xff1a 在vmware虚拟机中打开Gazebo闪退 原因 xff1a 开启了3D加速 xff0c 但分配的显存太小 xff0c 不足1G无法满足Gazebo的最低要求 解决办法如下 xff1a 1 关闭虚拟机 xff0c 在虚拟机
  • mysql插入千万条随机数据

    因为想测试sql在千万级数据下的优化 xff0c 准备在自己的阿里云数据库插入一千万条数据 xff0c 在网上搜了全是些乱七八糟的 xff0c 于是就自己动手 xff0c 同时也希望和大家分享 xff0c 不足之处还请各位指教 一 建表 1
  • linux C/C++ socket编程

    文章目录 前言linux socket api介绍简单客户端例子简单的服务端上述程序的问题epoll 前言 我们都知道socket编程实际上是使用tcp或者udp协议进行消息传输 xff0c 所以我们要更为的了解tcp udp协议 tcp三
  • 实现loading加载效果带百分比进度

    html lt div class 61 34 d loading 34 id 61 34 loading 34 gt lt div class 61 34 d loadVpic 34 gt lt div class 61 34 d opc
  • 什么是事件流?

    一 事件流的定义 页面触发一个事件时 xff0c 会按照一定的顺序来响应事件 xff0c 事件的响应过程为事件流 就我个人理解就是网页对点击事件的排序顺序就是事件流 二 事件流的分类 1 冒泡型的事件流 xff08 任何一款浏览器都支持 x
  • prometheus 学习(1)

    prometheus 配置文档 github地址 https github com prometheus prometheus blob master docs configuration configuration md 标签学习 glo
  • ROS订阅最新的消息及queue_size和buff_size的理解

    机器人应用中难免会遇到运算起来很费时间的操作 xff0c 比如图像的特征提取 点云的匹配等等 有时候 xff0c 不可避免地 xff0c 我们需要在ROS的Subscriber的Callback回调函数中进行这些费时的操作 Subscrib
  • NUC980第一篇:开发环境的搭建以及官方源码编译

    序言 之前参加了一个rtthread举办的活动 xff0c 拿到了一个新塘的NK IOT的板子 于是 xff0c 打算研究一下 xff0c 跑一跑linux 官方buildroot编译 下载地址 xff1a https gitee com
  • Linux系统安装Anaconda

    本文软件信息 xff1a 系统 xff1a RHEL8软件 xff1a Anaconda3 2022 10 Linux x86 64 sh Linux安装Anaconda的步骤都一样 xff0c 没啥差别 下载Anaconda的安装包 在官
  • apt-get vs aptitude

    apt get T 软件包管理工具 参数 h 帮助文件 q 输出到日志 无进展指示 qq 不输出信息 xff0c 错误除外 d 仅下载 不安装或解压归档文件 s 不实际安装 模拟执行命令 y 在需要确认的场景中回应 yes f 尝试修正系统
  • SPIN、VIBE 等 3D Human Pose Estimation 方法中的弱透视投影 (Weak Perspective Projection)

    弱透视投影 Weak Perspective Projection 弱透视投影假设焦距与物距足够大 xff0c 此时物体在 z z z 轴 光轴 上的变化可以忽略 SPIN VIBE 等 3D Human Pose Estimation 方
  • Nvidia Jetson Xavier NX系统从emmc到内存卡

    1 一块EMMC版本的JETSON XAVIER NX xff0c 搭配冬虫电子NCB00载板 由于板载的emmc只有16G xff0c 载板上支持SD卡 xff0c 在载板上插一个128G的内存卡来扩充以下容量 2 使用NVIDIA的SD
  • C#与STM32自定义通信协议

    功能 可通过C 上位机与STM32下位机之间进行通信可以保证接收的数据的正确性 一 C 作为上位机实现代码 using System using System Collections Generic using System IO Port