C#与STM32自定义通信协议

功能

  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;
	}
}

猜你喜欢

转载自blog.csdn.net/qq_37120496/article/details/115167716
今日推荐