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自定义通信协议 的相关文章

  • FreeRtos 任务优先级和中断优先级

    首先打出这个标题是为了便于搜索 在这里赘述一下 这两者没有关系 只需要明白的是中断优先级高于任务的优先级 在单片机运行的过程中 中断来了就执行中断服务程序 在free rtos中 任务优先级设置的数值越大 任务的优先级越高 Unix任务优先

随机推荐

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

    嵌入式工程师的经典面试题目 预处理器 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