この章は、シリアル ポート デバッグ アシスタントと構造体の送受信の補足として機能します。主にカスタム プロトコルで負の数、浮動小数点数などを送受信するために使用されます (以前に使用した浮動小数点数は直接文字列の送受信に使用されます。文字列から分析するために、ここでは主に 16 進数を使用して、その送受信原理と使用操作を分析します。
仮想シリアルポートデバッグアシスタント
一般に、コンピュータの外部デバイスはさまざまなポートを介してコンピュータに接続できます。一般的なものには、USB、VGA、DVI などが含まれます。産業分野やソフトウェア開発分野では、コンピュータと機器間の接続を完了するために、シンプル、低コスト、迅速な方法を使用する必要があることがよくあります。その場合、シリアルポートは非常に良い選択です
開発段階では、デバイスの準備がまだ整っていない場合がありますが、まず PC ソフトウェアを開発し、その後ソフトウェアを通じてシリアル ポートを仮想化することができます。デバイスの交換に使用されるエンティティ。学習用
1 つは COM1 を使用し、もう 1 つは COM2 を使用して通信します。
バイトとデータ変換
C#の実装
using System.Runtime.CompilerServices;
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
byte[] dataByte = new byte[120];
int count = 0;
//将double型数据存入databyte中。
double data1 = -123.125;
//C# BitConverter 类用来字节数组转换 可以转换成字节 也可以字节转换成int、double等
byte[] buf = BitConverter.GetBytes((double)data1);//单精度浮点型用 BitConverter.ToSingle
Console.WriteLine(BitConverter.ToDouble(buf));
}
}
}
cの実装
#include <stdio.h>
/*
*function:ftoc(float fvalue,unsigned char*arr)
*decription: 浮点数转化成四个字节
*input: 浮点数
*output: 4个字节的字节数组
*/
//例如12.5--0x41 48 00 00;转换完之后,arr[0]-00,arr[1]-00,arr[2]-48,arr[3]-41
void ftoc(float fvalue,unsigned char*arr)
{
unsigned char *pf;
unsigned char *px;
unsigned char i; //计数器
pf =(unsigned char *)&fvalue; /*unsigned char型指针取得浮点数的首地址*/
px = arr; /*字符数组arr准备存储浮点数的四个字节,px指针指向字节数组arr*/
for(i=0;i<4;i++)
{
*(px+i)=*(pf+i); /*使用unsigned char型指针从低地址一个字节一个字节取出*/
}
}
/*
*function:float ByteToFloat(unsigned char* byteArray)
*decription: 将字节型转化成32bits浮点型
*input: 长度为4的字节数组
*output:
*/
float ByteToFloat(unsigned char* byteArray)
{
return *((float*)byteArray); //强制类型转换 然后取值
}
int main(int argc, char *argv[])
{
int i;
unsigned char byteArray[4];
ftoc(-12.5,byteArray);//浮点数转化成四个字节
for(i=0;i<4;i++)
printf("%x ",byteArray[i]);//%x即按十六进制输出,英文字母小写,右对齐
float x=0;
x = ByteToFloat(byteArray);
printf("\n%f ",x);
return 0;
}
練習する
シリアルポートデバッグアシスタント付き
最初の 2 バイト、最後の 1 バイト、および中間データは 4 バイトで、C 言語から変換された単精度 4 バイトは、上記の C 実装で確認できます。
public static int cnt = 0;
private void serialPort1_DataReceived2(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
cnt++;
this.Invoke((EventHandler)delegate
{
uiRichTextBox1.AppendText("\r\n" + "cnt:" + cnt);
});
Thread.Sleep(40);
int len = serialPort1.BytesToRead;//一共接收到多少数据
Byte[] readBuffer = new Byte[100];
serialPort1.Read(readBuffer, 0, len);
//2+4+1 80 81 0 0 48 c1 ff 就是-12.5
//获得一帧掐头去尾的数据
for (int ptr = 0; ptr < len; ptr++)
{
if ((readBuffer[ptr] == HEAD1) && (readBuffer[ptr + 1] == HEAD2))
{
if (readBuffer[ptr + 6] == 0xff)
{
int index = ptr + 2;
byte[] fdata = new byte[4];
for (int i = 0; i < 4; i++)//这样就把尾巴给去掉了
{
fdata[i] = readBuffer[index + i];
}
this.Invoke((EventHandler)delegate
{
uiRichTextBox1.AppendText("\r\n" + "接收数据值:" + BitConverter.ToSingle(fdata,0).ToString());
});
}
}
}
}
C#は浮動小数点データを受け取ります
受信したのは 2 バイトの ushort です
//直接调用ReadDate函数,接收到的数据会自动保存入 ushort[] value1 中
//一个ushort占用两个字节,一共接收到2个ushort,共四个字节
//调用GetFloat即可实现转换
public static void ReadDate()
{
ushort startAddress = 0x0066;
ushort numberOfPoints = 2;
ushort[] value1 = master.ReadHoldingRegisters(1, startAddress, numberOfPoints);
log.SaveLog("value1字节数:"+value1.Length.ToString());
float valuefloat;
valuefloat = GetFloat(value1[0], value1[1]);
log.SaveLog("流量" + valuefloat);
}
public static float GetFloat(ushort P1, ushort P2)
{
int intSign, intSignRest, intExponent, intExponentRest;
float faResult, faDigit;
intSign = P1 / 32768;
intSignRest = P1 % 32768;
intExponent = intSignRest / 128;
intExponentRest = intSignRest % 128;
faDigit = (float)(intExponentRest * 65536 + P2) / 8388608;
faResult = (float)Math.Pow(-1, intSign) * (float)Math.Pow(2, intExponent - 127) * (faDigit + 1);
return faResult;
}