功能
- 可通过C#上位机与STM32下位机之间进行通信
- 可以保证接收的数据的正确性
一、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
{
///
/// 串口工具类
///
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
);
}
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); //发送一个字节数据
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;itx_byte;i++) //循环异或
{
temp=temp^hmi_Struct->tx_buf;
}
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;irx_buf[1]+2;i++)
{
temp = temp^hmi_Struct->rx_buf;
}
//判断检验码是否正确
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;
}
}
功能
- 可通过C#上位机与STM32下位机之间进行通信
- 可以保证接收的数据的正确性
一、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
{
///
/// 串口工具类
///
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
);
}
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); //发送一个字节数据
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;itx_byte;i++) //循环异或
{
temp=temp^hmi_Struct->tx_buf;
}
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;irx_buf[1]+2;i++)
{
temp = temp^hmi_Struct->rx_buf;
}
//判断检验码是否正确
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;
}
}
举报