c#串口通信(二)--通信协议的发送及数据解析

订阅收费文章或资源:公众号“毛线杂货铺”,淘bao店铺ID:122344852,可搜索商铺“幸福的孩子yyx”或复制以下内容:
59《ZuboWnWzq1R《 https://m.tb.cn/h.5D3Od4wRAQzgQpH MF6563 我分享给你了一个超赞的内容,快来看看吧
或:
请添加图片描述

在简单的认识及使用串口通信之后,在实际应用中应该是配合硬件,和负责硬件通信的同事沟通好通信协议,来进行设备的控制及数据获取。
常用的串行通信协议有TTL电平(普通MCU芯片输出的串口电平)、RS232(工业上常用的串口标准)及RS485(串行总线标准,常用语通信距离为几十米到上千米时)等。
本文采用的是RS485,为半双工工作方式。下面是一个简单的获取设备信息的例子。
通信协议如下:

数据包格式:

包头(2byte)命令码(1byte)包长(2byte)数据/状态(Nbyte)异或校验(1byte)
发送数据/状态格式(24 bytes/每包,不足补0):
数据说明
设备编号8byte
系统时间4byte
接收设备返回的格式:
数据说明
设备编号8byte
设备电压温度8byte,浮点数
增益1byte
4G状态1byte
存储容量1byte
时间戳4byte 单位:秒
计数器4byte
控制类型1byte 0x00-停止测量,0x01-开始测量,0x02-测量类型1,0x03-测量类型2,0x04-测量类型3

发送获取数据的命令代码:

byte[] package = new byte[24];
int index=0;
package[index++] = 0x77;//帧头
package[index++] = 0xCC;
package[index++] = cmd;//命令码    
package[index++] = 0;//数据长度高字节
package[index++] = 18;//数据长度低字节
//数据
var idbytes = Encoding.ASCII.GetBytes(id);
 for (int i = 0; i < idbytes.Length; i++)
 {
     package[index++] = idbytes[i];//填充设备id
 }
 DateTime Now_Time = DateTime.Now;

 int Time_Sec = GetTimeStamp(Now_Time);

 package[index++] = (byte)(Time_Sec >> 24);
 package[index++] = (byte)(Time_Sec >> 16);
 package[index++] = (byte)(Time_Sec >> 8);
 package[index++] = (byte)(Time_Sec);
//校验码
byte tmp = 0;
var length = package.Length - 1;
for (byte i = 0; i < length; i++)
    tmp ^= package[i];
package[23] =tmp ;
serialPort.Write(package, 0, package.Length);

解析回复的数据(DataReceived事件):

Thread.Sleep(400);//延时,等待接收完数据 接收100个字节数据时间约为6ms
byte[] buffle = new byte[serialPort.BytesToRead];
serialPort.Read(buffle, 0, buffle.Length);//buffle为接收的数据
if (e.EventType != SerialData.Chars||serialPort == null)
{
    return;
}
if (!serialPort.IsOpen)//串口在关闭时不接收数据 为了防止关闭串口时卡死的问题
{
    serialPort.DiscardInBuffer();//丢弃接收缓冲区数据
    return;
}
bool isAll = false;

if (DataBuffer[0] == 0x77 && DataBuffer[1] == 0xCC)//上次未接收完
{
    var Length = DataBuffer.Length;
    DataBuffer =RS485Helper. AddBytes(DataBuffer, buffle);
    isAll = (Length == buffle.Length + bufferReadLength);
}
else//接收开始
{
    if (buffle[0] == 0x77 && buffle[1] == 0xCC)
    {
        bufferReadLength = buffle.Length;
        var length = (ushort)(buffle[3] << 8)+ (ushort)buffle[4]+6;//包长加包头包尾才是总长度
        DataBuffer = new byte[length];
        DataBuffer = RS485Helper.AddBytes(DataBuffer, buffle,false);//这个函数是将新增的byte[]添加到原有buffle后面
        isAll = (length == buffle.Length);
    }
}
if (isAll)
{
    Analyse(DataBuffer.Clone() as byte[]);
    DataBuffer = new byte[1000];
    isAccept = false;
}
private void Analyse(byte[] buffle)
{
    var gucCommand = buffle[2];
    var devId = Encoding.Default.GetString(buffle.Skip(3).Take(8).ToArray());
    object data=null;
    switch (gucCommand)
    {
    	case RS485Helper.DEV_INQUIRE_CMD:
            Deal_DevInfo(buffle);
            break;	//更新连接标志
        default: break;
    }
    if (OnComReceiveDataHandler != null)
    {
       OnComReceiveDataHandler(data, ComPortName, devId);//这里使用委托让UI界面去更新,注意现在是在子线程里面,使用
    }
}
private void Deal_DevInfo(byte[] buffle)
        {
			ushort Data_Lenght = (ushort)((buffle[3] << 8) + buffle[4]);//接收字节的长度

            string id= BitConverter.ToString(buffle, 5, 8);//仪器编号
            var power = BitConverter.ToSingle(buffle, 13).ToString("f2");//电量
            var Tem = BitConverter.ToSingle(buffle, 17).ToString("f2");//温度
            float Gain_Value = 0;
            switch (buffle[21])//增益
            {
                case 0: Gain_Value = 0.25f; break;
                case 1: Gain_Value = 0.5f; break;
            }        
            var Wireless_State = String.Format("{0:X}", buffle[22]);//4G状态  
            var Space = buffle[23].ToString();//剩余空间

            int Time_Value = (buffle[24] << 24) + (buffle[25] << 16) + (buffle[26] << 8) + buffle[27];
            var Col_Time = GetDateTime(Time_Value);//时间

            //计数器
            var Data_Count = (uint)((buffle[28] << 24) + (buffle[29] << 16) + (buffle[30] << 8) + buffle[31]);

            byte Work_Mode = buffle[32];//工作模式
            var workMode = "";
            switch (Work_Mode)
            {
                case 0: workMode = "停止"; break;
                case 1: workMode = "采集"; break;
                case 2: workMode = "模式1"; break;
                case 3: workMode = "模式2"; break;
                case 4: workMode = "模式3"; break;
                default: workMode = "停止"; break;
            }
            ...
}
C#串口通信数据解析是指在使用C#编程语言进行串口通信时,对接收到的数据进行解析和处理的过程。首先,需要设置串口通信的参数,如波特率、数据位、停止位和奇偶校验等,以确保两个通信端口的参数匹配。然后,通过串口类提供的方法和事件来实现数据的接收和解析。 在C#中,可以使用SerialPort类来进行串口通信。首先,需要实例化一个SerialPort对象,并设置好串口参数。然后,可以通过订阅DataReceived事件来接收串口数据。当有数据接收到时,该事件会触发,可以在事件处理程序中进行数据解析的操作。 在进行数据解析时,可以根据具体的通信协议数据格式进行处理。例如,可以使用字节流方式读取接收到的数据,并根据数据的长度和格式进行解析。可以根据数据包的起始标志和结束标志来提取有效数据,并进行相应的处理。还可以使用BitConverter类来将字节数组转换为相应的数据类型,以便进行后续的操作。 另外,也可以根据具体需求使用正则表达式来匹配和提取特定模式的数据。正则表达式可以用于匹配特定的字符串模式,并提取出需要的数据部分。 总之,C#串口通信数据解析是通过设置串口参数、接收串口数据,并根据具体的通信协议数据格式进行解析和处理的过程。这个过程可以根据具体需求和情况进行定制和扩展。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [C#实现串口通信解析](https://blog.csdn.net/kalvin_y_liu/article/details/126885528)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Yyuanyuxin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值