C# ---- 串口数据YSI实例

原文:C# ---- 串口数据YSI实例

C#----串口数据接收发送中,发送接收数据已经可以模拟了。

 

本次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;
        }
    }

 

综上:串口数据发送接收是比较简单的,难点在于数据类型转换。

需要怎么转换成字节发送出去,再如何接收字节转换成所需数据。

上一篇:AI伦理:机器人伴侣可以代替人类伴侣?


下一篇:可举起为自身1000倍重物体的人造肌肉面世,离超强人形机器人又近了一步