C# ---- 串口數據YSI實例
本次YSI實例過程中 主要是:類型轉換問題 、計算校驗碼
一、不同設備不同的規則,本次實例代碼如下:
復制代碼
string serialNumber = sn;//Packet Command Payload
int i1 = 0x11;//Packet Length Byte
int i2 = 0xA5;//Packet Sync Byt[]
string[] strarr = new string[32];//命令字符串
strarr[0] = Convert.ToString(i1, 16);//轉化固定字符
strarr[1] = Convert.ToString(i2, 16);//轉化固定字符
char[] arr = serialNumber.ToCharArray();//字符數組
int[] ii = new int[16];//整形數組,為了計算校驗碼
ii[0] = i1;//轉化固定字符
ii[1] = i2;//轉化固定字符
for (int i = 0; i < arr.Length; i++)
{
strarr[2 + i] = Convert.ToString(arr[i], 16);
ii[2 + i] = (int)arr[i];
}
//計算校驗碼
int checksum = 0;
for (int i = 0; i < ii.Length; i++)
{
checksum += ii[i];
if (checksum > 256)
checksum = checksum - 256;
}
strarr[16] = Convert.ToString(checksum, 16);
復制代碼
上述,一是采用強制類型轉換 char 類型為 16進制int,然後計算校驗碼;二是將char轉換為16進制形式的string。
這樣最後就得出需要發送的字符串數組。
二、發送字符串數據並且接收數據,代碼如下:
復制代碼
//計算傳輸字符串
string[] sendstr = Sendstr(sdstr);
//發送字節數組
byte[] wbb = new byte[64];
//轉換成16進制字節
for (int i = 0; i < sendstr.Length; i++)
{
wbb[i] = Convert.ToByte(sendstr[i], 16);
}
//接收字節數組
byte[] rdb = new byte[64];
//打開新的串行端口連接
sp.Open();
//丟棄來自串行驅動程序的接受緩沖區的數據
sp.DiscardInBuffer();
//丟棄來自串行驅動程序的傳輸緩沖區的數據
sp.DiscardOutBuffer();
//使用緩沖區的數據將指定數量的字節寫入串行端口
sp.Write(wbb, 0, wbb.Length);
//當前線程掛起500毫秒
System.Threading.Thread.Sleep(500);
//讀取數據超時
sp.ReadTimeout = 1000;
//讀取接收數據
sp.Read(rdb, 0, rdb.Length);
復制代碼
上述,一是需要轉換為字節發送,設備要求16進制字節;二是發送數據後,可以掛起線程500毫秒,避免數據沖突的問題。
這樣返回字節數組rdb。
三、接收後的字節數組,需要轉換解析,代碼如下:
//讀取記錄轉換為字符串
string[] rdstr = new string[100];
for (int i = 0; i < rdb.Length; i++)
{
rdstr[i] = rdb[i].ToString("X2");
}
上述,先轉換為16進制字符串。
四、最終需要收集的數據是浮點型數據
網上搜到一個string 與浮點類型相互轉換的類,可以直接使用,代碼如下:
復制代碼
class stConvertFloat
{
public static string FloatToStandard(double f, int style)
{
char[] Num = new char[32];//32為二進制結果加1結束符
if (f < 0) //f為負數 ,符號位Num[0]賦1
{
Num[0] = '1';
f = f * (-1); //轉換為整數
}
else
Num[0] = '0';
//求指數
int exponent = 0;
if (f >= 1)//指數符號為正情況,即fabs(f)>=1
{
while (f >= 2)
{
exponent++;
f = f / 2;
}
}
else//負指數情況
{
while (f < 1)
{
exponent++;
f = f * 2;
}
exponent = (128 - exponent) + 128;//(128-exponent)為補碼,+128是指數符號位置1
}
exponent += 127;//指數轉換為階碼
int i;
for (i = 8; i >= 1; i--)//將指數轉換為二進制數
{
if (exponent % 2 == 0)
Num[i] = '0';
else
Num[i] = '1';
exponent /= 2;
}
f = f - 1;//小數轉換為標准格式
//求小數部分
double s = 1;
for (i = 9; i < 32; i++)
{
s /= 2;
if (f >= s)
{
//MessageBox.Show(Convert.ToString(s));
f = f - s;
Num[i] = '1';
}
else
Num[i] = '0';
}
if (style == 2)//二進制輸出
{
string tt = new string(Num);
return tt;
}
else //二進制轉換為十六進制
{
char sum;
int j = 0;
for (i = 0; i < 32; i = i + 4, j++)
{
sum = Convert.ToChar((Num[i] - '0') * 8 + (Num[i + 1] - '0') * 4 + (Num[i + 2] - '0') * 2 + (Num[i + 3] - '0'));
if (sum > 9)
Num[j] = Convert.ToChar((sum - 10) + 'a');
else
Num[j] = Convert.ToChar(sum + '0');
}
string tt = new string(Num);
tt = tt.Substring(0, 8);
return tt;
}
}
public static double StandardToFloat(string FNum, int style)
{
char[] Num = new char[32];
char[] Hex = new char[8];
int i, j, value;
if (style == 2)//二進制
{
for (i = 0; i < 32; i++)
Num[i] = FNum[i];
}
else//十六進制轉換為二進制
{
for (i = 0; i < 8; i++)
{
Hex[i] = FNum[i];
if (Hex[i] >= '0' && Hex[i] <= '9')
value = Hex[i] - '0';
else
{
Hex[i] = Convert.ToChar(Hex[i] | 0x20); //統一轉換為小寫
value = Hex[i] - 'a' + 10;
}
for (j = 3; j >= 0; j--)
{
Num[i * 4 + j] = Convert.ToChar((value % 2) + '0');
value /= 2;
}
}
}
double f = 1;//f為最終浮點數結果,標准浮點格式隱含小數點前的1
double s = 1;//s為小數各個位代表的權值
for (i = 9; i < 32; i++)//轉換小數部分
{
s /= 2;
if (Num[i] == '1')
{
f += s;
//MessageBox.Show(Convert.ToString(s));
}
}
int exponent = 0;//指數部分
int d = 1;//d代表指數部分各位的權值
for (i = 8; i >= 1; i--)//此時計算的是階碼
{
if (Num[i] == '1')
exponent += d;
d *= 2;
}
if (exponent >= 127)
exponent -= 127;//將階碼轉換為指數
else
{
exponent += 256;//補上指數變階碼溢出的最高位
exponent -= 127;//階碼變指數,指數為補碼
exponent = 128 - (exponent - 128);//(exponent-128)去符號位,在講補碼變為指數絕對值
exponent = exponent * (-1);//最終指數部分
}
if (Num[0] == '1')//浮點數符號位為1,說明為負數
f = f * (-1);
f = f * Math.Pow(2, exponent);//將小數部分和浮點部分組合
return f;
}
}