STM32
直播中

宜家

8年用户 1122经验值
私信 关注
[问答]

怎样通过C#上位机与STM32下位机之间进行通信呢

怎样通过C#上位机与STM32下位机之间进行通信呢?这种方式有何优点?

回帖(1)

高川

2021-12-8 15:17:44
功能


  • 可通过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;
        }
}
举报

更多回帖

×
20
完善资料,
赚取积分