下位机接收数据代码(以STM32单片机为例)与上位机发送数据C#代码分享
1、下位机代码:
/**
* @brief 接收的数据处理
* @param void
* @return -1:没有找到一个正确的命令.
*/
int8_t receiving_process(void)
{
uint8_t frame_data[128]; // 要能放下最长的帧
uint16_t frame_len = 0; // 帧长度
uint8_t cmd_type = CMD_NONE; // 命令类型
while(1)
{
cmd_type = protocol_frame_parse(frame_data, &frame_len);
switch (cmd_type)
{
case CMD_NONE:
{
return -1;
}
case SET_P_I_D_CMD:
{
uint32_t temp0 = COMPOUND_32BIT(&frame_data[13]);
uint32_t temp1 = COMPOUND_32BIT(&frame_data[17]);
uint32_t temp2 = COMPOUND_32BIT(&frame_data[21]);
float p_temp, i_temp, d_temp;
p_temp = *(float *)&temp0;
i_temp = *(float *)&temp1;
d_temp = *(float *)&temp2;
set_p_i_d(p_temp, i_temp, d_temp); // 设置 P I D
}
break;
case SET_TARGET_CMD:
{
int actual_temp = COMPOUND_32BIT(&frame_data[13]); // 得到数据
set_pid_target(actual_temp); // 设置目标值
}
break;
case START_CMD:
{
set_motor_enable(); // 启动电机
}
break;
case STOP_CMD:
{
set_motor_disable(); // 停止电机
}
break;
case RESET_CMD:
{
HAL_NVIC_SystemReset(); // 复位系统
}
break;
case SET_PERIOD_CMD:
{
uint32_t temp = COMPOUND_32BIT(&frame_data[13]); // 周期数
SET_BASIC_TIM_PERIOD(temp); // 设置定时器周期1~1000ms
}
break;
default:
return -1;
}
}
}
这段代码是一个接收数据并进行处理的函数。函数名为receiving_process,返回类型为int8_t,参数为空。函数的作用是接收数据并根据接收到的命令类型进行相应的处理。如果没有找到正确的命令,函数返回-1。
在函数内部,定义了一些变量用于存储接收到的数据和命令类型。frame_data是一个长度为128的uint8_t数组,用于存储接收到的数据帧。frame_len是一个uint16_t类型的变量,用于记录数据帧的长度。cmd_type是一个uint8_t类型的变量,用于存储命令类型。
接下来是一个无限循环,用于不断接收并处理数据。
循环内部首先调用了一个名为protocol_frame_parse的函数,该函数用于解析数据帧并返回命令类型。解析过程将接收到的数据帧存储在frame_data中,并将数据帧的长度保存在frame_len中。解析结果保存在cmd_type中。
接下来通过switch语句对cmd_type进行判断,根据不同的命令类型进行相应的处理。
如果命令类型为CMD_NONE,表示没有找到正确的命令,返回-1。
如果命令类型为SET_P_I_D_CMD,表示接收到了设置PID参数的命令。接下来通过COMPOUND_32BIT宏将frame_data中的字节转换为32位整数,然后再通过强制类型转换将32位整数转换为float类型。将转换后的参数传递给set_p_i_d函数,用于设置PID参数。
如果命令类型为SET_TARGET_CMD,表示接收到了设置目标值的命令。通过COMPOUND_32BIT宏将frame_data中的字节转换为32位整数,然后将转换后的参数传递给set_pid_target函数,用于设置目标值。
如果命令类型为START_CMD,表示接收到了启动电机的命令。调用set_motor_enable函数,用于启动电机。
如果命令类型为STOP_CMD,表示接收到了停止电机的命令。调用set_motor_disable函数,用于停止电机。
如果命令类型为RESET_CMD,表示接收到了复位系统的命令。调用HAL_NVIC_SystemReset函数,用于复位系统。
如果命令类型为SET_PERIOD_CMD,表示接收到了设置定时器周期的命令。通过COMPOUND_32BIT宏将frame_data中的字节转换为32位整数,然后将转换后的参数传递给SET_BASIC_TIM_PERIOD函数,用于设置定时器周期。
最后,如果命令类型不在上述情况中,默认返回-1。
总结起来,这段代码是一个接收数据并进行处理的函数。函数通过解析数据帧获取命令类型,并根据命令类型进行相应的处理操作。
2、上位机代码:
using System;
using System.IO.Ports;
using System.Threading;
public class UpperComputer
{
private SerialPort serialPort;
public UpperComputer()
{
// 初始化串口
serialPort = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);
}
public void Connect()
{
try
{
serialPort.Open(); // 打开串口连接
Console.WriteLine("成功连接下位机。");
}
catch (Exception ex)
{
Console.WriteLine("连接下位机失败:" + ex.Message);
}
}
public void Disconnect()
{
serialPort.Close(); // 关闭串口连接
Console.WriteLine("已断开下位机连接。");
}
public void SendCommand(byte[] command)
{
try
{
serialPort.Write(command, 0, command.Length); // 发送命令
Console.WriteLine("发送命令成功。");
}
catch (Exception ex)
{
Console.WriteLine("发送命令失败:" + ex.Message);
}
}
public static void Main(string[] args)
{
UpperComputer upperComputer = new UpperComputer();
upperComputer.Connect();
// 示例:发送设置PID参数的命令
byte[] setPIDCommand = new byte[25];
setPIDCommand[0] = 1; // 命令类型:设置PID参数
Buffer.BlockCopy(BitConverter.GetBytes(1.23f), 0, setPIDCommand, 1, 4); // 设置P参数
Buffer.BlockCopy(BitConverter.GetBytes(4.56f), 0, setPIDCommand, 5, 4); // 设置I参数
Buffer.BlockCopy(BitConverter.GetBytes(7.89f), 0, setPIDCommand, 9, 4); // 设置D参数
upperComputer.SendCommand(setPIDCommand);
// 示例:发送设置目标值的命令
byte[] setTargetCommand = new byte[9];
setTargetCommand[0] = 2; // 命令类型:设置目标值
Buffer.BlockCopy(BitConverter.GetBytes(100), 0, setTargetCommand, 1, 4); // 设置目标值为100
upperComputer.SendCommand(setTargetCommand);
// 示例:发送启动电机的命令
byte[] startCommand = new byte[1];
startCommand[0] = 3; // 命令类型:启动电机
upperComputer.SendCommand(startCommand);
// 示例:发送停止电机的命令
byte[] stopCommand = new byte[1];
stopCommand[0] = 4; // 命令类型:停止电机
upperComputer.SendCommand(stopCommand);
// 示例:发送复位系统的命令
byte[] resetCommand = new byte[1];
resetCommand[0] = 5; // 命令类型:复位系统
upperComputer.SendCommand(resetCommand);
// 示例:发送设置定时器周期的命令
byte[] setPeriodCommand = new byte[5];
setPeriodCommand[0] = 6; // 命令类型:设置定时器周期
Buffer.BlockCopy(BitConverter.GetBytes(500), 0, setPeriodCommand, 1, 4); // 设置周期为500ms
upperComputer.SendCommand(setPeriodCommand);
upperComputer.Disconnect();
}
}
-
导入命名空间:
-
using System;
:引入System命名空间,包含了一些常用的系统类型和功能。 -
using System.IO.Ports;
:引入System.IO.Ports命名空间,提供了与串口通信相关的类和方法。 -
using System.Threading;
:引入System.Threading命名空间,提供了多线程编程相关的类和方法。
-
-
定义UpperComputer类:
-
private SerialPort serialPort;
:定义一个私有变量serialPort,用于串口通信。 -
public UpperComputer()
:构造方法,用于初始化串口。
-
-
Connect()方法:
-
serialPort.Open();
:打开串口连接。 -
Console.WriteLine("成功连接下位机。");
:在控制台输出连接成功的提示信息。
-
-
Disconnect()方法:
-
serialPort.Close();
:关闭串口连接。 -
Console.WriteLine("已断开下位机连接。");
:在控制台输出断开连接的提示信息。
-
-
SendCommand()方法:
-
serialPort.Write(command, 0, command.Length);
:发送命令给下位机。 -
Console.WriteLine("发送命令成功。");
:在控制台输出发送命令成功的提示信息。
-
-
Main()方法:
-
UpperComputer upperComputer = new UpperComputer();
:创建一个UpperComputer对象。 -
upperComputer.Connect();
:调用Connect()方法连接下位机。
-
-
示例代码:
-
发送设置PID参数的命令:
-
byte[] setPIDCommand = new byte[25];
:定义一个长度为25的byte数组,用于存储设置PID参数的命令。 -
setPIDCommand[0] = 1;
:设置命令类型为设置PID参数。 -
Buffer.BlockCopy(BitConverter.GetBytes(1.23f), 0, setPIDCommand, 1, 4);
:将浮点数1.23转换为字节数组,并复制到setPIDCommand数组的指定位置,用于设置P参数。 -
Buffer.BlockCopy(BitConverter.GetBytes(4.56f), 0, setPIDCommand, 5, 4);
:将浮点数4.56转换为字节数组,并复制到setPIDCommand数组的指定位置,用于设置I参数。 -
Buffer.BlockCopy(BitConverter.GetBytes(7.89f), 0, setPIDCommand, 9, 4);
:将浮点数7.89转换为字节数组,并复制到setPIDCommand数组的指定位置,用于设置D参数。 -
upperComputer.SendCommand(setPIDCommand);
:调用SendCommand()方法发送设置PID参数的命令。
-
-
发送设置目标值的命令:
-
byte[] setTargetCommand = new byte[9];
:定义一个长度为9的byte数组,用于存储设置目标值的命令。 -
setTargetCommand[0] = 2;
:设置命令类型为设置目标值。 -
Buffer.BlockCopy(BitConverter.GetBytes(100), 0, setTargetCommand, 1, 4);
:将整数100转换为字节数组,并复制到setTargetCommand数组的指定位置,用于设置目标值。 -
upperComputer.SendCommand(setTargetCommand);
:调用SendCommand()方法发送设置目标值的命令。
-
-
发送启动电机的命令:
-
byte[] startCommand = new byte[1];
:定义一个长度为1的byte数组,用于存储启动电机的命令。 -
startCommand[0] = 3;
:设置命令类型为启动电机。 -
upperComputer.SendCommand(startCommand);
:调用SendCommand()方法发送启动电机的命令。
-
-
发送停止电机的命令:
-
byte[] stopCommand = new byte[1];
:定义一个长度为1的byte数组,用于存储停止电机的命令。 -
stopCommand[0] = 4;
:设置命令类型为停止电机。 -
upperComputer.SendCommand(stopCommand);
:调用SendCommand()方法发送停止电机的命令。
-
-
发送复位系统的命令:
-
byte[] resetCommand = new byte[1];
:定义一个长度为1的byte数组,用于存储复位系统的命令。 -
resetCommand[0] = 5;
:设置命令类型为复位系统。 -
upperComputer.SendCommand(resetCommand);
:调用SendCommand()方法发送复位系统的命令。
-
-
发送设置定时器周期的命令:
-
byte[] setPeriodCommand = new byte[5];
:定义一个长度为5的byte数组,用于存储设置定时器周期的命令。 -
setPeriodCommand[0] = 6;
:设置命令类型为设置定时器周期。 -
Buffer.BlockCopy(BitConverter.GetBytes(500), 0, setPeriodCommand, 1, 4);
:将整数500转换为字节数组,并复制到setPeriodCommand数组的指定位置,用于设置周期。 -
upperComputer.SendCommand(setPeriodCommand);
:调用SendCommand()方法发送设置定时器周期的命令。
-
-
upperComputer.Disconnect();
:调用Disconnect()方法断开下位机连接。
-