serialPort类数据采集代码。

窗口数据发送和接受的类 新建 PortControl

 

using  System;
using  System.IO.Ports;
using  System.Windows.Forms;

namespace  SPC
{
    
/// <summary>
    
/// 串口控制  
    
/// </summary>

    public class PortControl

    
{
        
/// <summary>
        
/// 定义一个串口类
        
/// </summary>

        private   SerialPort  MyPort;

        
/// <summary>
        
/// 初始化类
        
/// </summary>

        public PortControl()
        
{
            MyPort 
= new SerialPort();
            setup();
        }

        
/// <summary>
        
/// 直接使用给某个串口
        
/// </summary>
        
/// <param name="port">COM1,COM2。。。。。。</param>

        public  PortControl(string port)
        
{
            _portname 
= port;
            MyPort 
= new SerialPort(_portname);

            setup();
        }

        
private void setup()
        
{
            
            MyPort.DataReceived 
+= new SerialDataReceivedEventHandler(DataReceived);

        }


        
        
public bool  Open()
        
{
            
try
            
{
                
if (MyPort.IsOpen != true{ MyPort.Open(); };
                
return true ;
            }

            
catch
            
{
                
return false;
            }

        }

        
public void Open(string port)
        
{
            MyPort.PortName 
= _portname;
            MyPort.Open();
        }


        
public void Close()
        
{
            MyPort.Close();
        }

        
        
private string  _portname;


        
/// <summary>
        
/// 端口名称
        
/// </summary>
        
/// <example>COM1 COM2</example>

        public string  PortName
        
{
            
get return _portname; }
            
set { _portname = value; }
        }

        
public Exception LastException;

    
        
/// <summary>
        
/// 最后收到的信息
        
/// </summary>

        public string LastReceived 
        
{
            
get return hex_return; }

        }

        
public bool Received = false;//是否收到了信息。 发送完数据,如果需要车检器返回数据,该属性设置为false;
                              
//当收到消息,并解析完成后。这个设置为true;
        string hex_return = "";//收到数据后把十六进制存到这个字符串中。
        byte[] bin_return = new byte[] { };

        
double _timeout = 0.8;
        
public double TimeOut
        
{
            
get return _timeout; }
            
set { _timeout = value; }
        }


        
/// <summary>
        
/// 向端口中发送命令。
        
/// </summary>
        
/// <param name="cmdstring">"0A 46 0B 31 30 30 32 35"</param>
        
/// <example>  Send("0A 46 0B 31 30 30 32 35")</example>
        
/// <remarks>超时设置为5秒,一般来说,端口速度不会延时超过1秒。</remarks>

        
/// <summary>
        
/// 向端口中发送命令。
        
/// </summary>
        
/// <param name="cmdstring">"0A 46 0B 31 30 30 32 35"</param>
        
/// <param name="timeout">指定超时,按秒计算。端口速度一般不会迟延超过1秒。</param>
        
/// <example>  Send("0A 46 0B 31 30 30 32 35")</example>

        public string Send(string cmdstring)
        
{

          

            
byte[] buff = Funs.HexStringToBinary(cmdstring.Trim());//转换命令字符串为字节数组
            hex_return = "";//十六进制返回设置为空。
            bin_return = new byte[] { };//重新初始化返回字节数组。
            Received = false;//设置标识为没有接受到信息
            MyPort.Write(buff, 0, buff.Length);//写入串口命令。
            double tmpx = DateTime.Now.TimeOfDay.TotalSeconds;//记录下当前总计秒数
             
                
do
                
{
                    Application.DoEvents();
//释放CPU
                }
 while ((Received != true&& (DateTime.Now.TimeOfDay.TotalSeconds - tmpx < _timeout));
                
if (Received == falsereturn null; }
            
//如果接受到了数据或者已超时就不再循环。
            string rt;//初始化返回内容。
            int sum = 0;//初始化命令总数。
            for (int i = 3; i < bin_return.Length - 2; i++)
            
{
                sum 
+= bin_return[i];
            }

            
int sum1 = bin_return[bin_return.Length - 2+ bin_return[bin_return.Length - 1]*256;
            
if (
                sum 
!= sum1
                
&&
                bin_return[bin_return.Length 
- 3== 3
                )
            
{ rt = null; }
            
else
            
{
                rt 
= Funs.BinaryToHexString(bin_return);
            }

            
return rt;
        }


      


     
        
/// <summary>
        
/// 如果接受到了数据。
        
/// </summary>
        
/// <param name="sender">发送者</param>
        
/// <param name="e">时间参数</param>

        private void DataReceived(object sender, SerialDataReceivedEventArgs e)
        
{
            
//MyPort.DiscardInBuffer(); //丢弃事件发生前的数据。
            int n = MyPort.BytesToRead;//读取当前有多少数据可读。
            byte[] binary = new byte[n];//新建内容。
            MyPort.Read(binary, 0, n);//读取
            Array.Resize(ref bin_return, bin_return.Length + n);//改写数组大小
            if (bin_return.Length < 1return; }

            binary.CopyTo(bin_return, bin_return.Length 
- binary.Length );//复制数据。
            int infleng = 0;
            
//16 16 02 10 01 02 00 07 00 03 1D 00  
            if (bin_return.Length > 7)//基本信息头应该是7个字节。
            {
                
if (bin_return[0== bin_return[1&& bin_return[0]== 22 && bin_return[2== 2)
                
//如果第零字节和第一字节相等,并且第二自己为0,那么表示信息的开头 。 
                {
                    
//计算第五字节和第六字节。这两个字节表示长度。
                   infleng = bin_return[5+ bin_return[6* 256;
                }


            }

            
else if (bin_return.Length == 3)
            
{
                Received 
= true;
                
return;
            }

            
            Received 
= ((10 + infleng) == bin_return.Length);//命令基本格式包含10个字节。
            
//加上信息长度如果等于bin接收到的长度的话。说明接受完了。接受完了就设置receive为真。
            Console.WriteLine(String.Format("读取字节数:{0}:内容:{1}----{2}", n, hex_return,e.EventType));
        }

   
          

     
    }

}

 其他一些相关的函数

 

using  System;
using  Microsoft.VisualBasic;

namespace  SPC
{
    
public class Funs
    
{


       
/// <summary>
       
/// 十六进制字符串到日期时间的转换 。
       
/// </summary>
       
/// <param name="hexstring"></param>
       
/// <returns></returns>

        public static DateTime HexString2DateTime(string hexstring)
        
{                    
        



            
int nian, yue, ri, xiaoshi, fenzhong, miao;
            
//08 21 14 19 05 04    //时分秒天月年 
            string tmp = hexstring.Trim();
            xiaoshi 
= Hex2Int(Strings.Left(tmp, 3).Trim()); tmp = tmp.Remove(03);
            fenzhong 
= Hex2Int(Strings.Left(tmp, 3).Trim()); tmp = tmp.Remove(03);
            miao 
= Hex2Int(Strings.Left(tmp, 3).Trim()); tmp = tmp.Remove(03);
            ri 
= Hex2Int(Strings.Left(tmp, 3).Trim()); tmp = tmp.Remove(03);
            ri 
= (ri != 0? ri : 1;
            yue 
= Hex2Int(Strings.Left(tmp, 3).Trim()); tmp = tmp.Remove(03);
            yue 
= (yue != 0? yue : 1;
            nian 
= Hex2Int(Strings.Left(tmp, 3).Trim());
            nian 
= (nian != 0? 2000 + nian : 2000;
            
return (new DateTime(nian, yue, ri, xiaoshi, fenzhong, miao));
        

        }

        

        
/// <summary>
        
/// 把时间转换为车检器需要的字符串 。
        
/// </summary>
        
/// <param name="dt">时间</param>
        
/// <returns>格式为时分秒日月年</returns>

        public static string DateTime2HexString(DateTime dt)
        
{
            
string info = ToHex(dt.Hour) + " ";
            info 
+= ToHex(dt.Minute) + " ";
            info 
+= ToHex(dt.Second) + " ";
            info 
+= ToHex(dt.Day) + " ";
            info 
+= ToHex(dt.Month) + " ";
            info 
+= ToHex(dt.Year-2000+ " ";
            
return info.Trim();

        }

        
/// <summary>
        
/// 设置事件
        
/// </summary>
        
/// <param name="dt">时间</param>
        
/// <returns>转换为秒分时日月年</returns>

        public static string DateTime2HexString2(DateTime dt)
        
{
            
string info = ToHex(dt.Second) + " ";
            info 
+= ToHex(dt.Minute) + " ";
            info 
+= ToHex(dt.Hour) + " ";
            info 
+= ToHex(dt.Day) + " ";
            info 
+= ToHex(dt.Month) + " ";
            info 
+= ToHex(dt.Year - 2000+ " ";
            
return info.Trim();

        }


        
/// <summary>
        
/// 转换为符合本程序的十六进制格式
        
/// </summary>
        
/// <param name="var">1 2 3 等。</param>
        
/// <returns>返回十六进制字符串,如果是1-9的话,前面带零</returns>
        
/// <example>例如: 5  ="05"  12 ="0C" 无论何时,都是两位数。  </example>

        public static string ToHex(int var)
        
{
            
int cs = var;
            
string tmp = "";
            
if (cs == 0{ tmp = "00"; }
            
while (cs > 0)
            
{
                
int ys;
                cs 
= Math.DivRem(cs, 256out   ys);
                tmp 
+= string.Format(" {0}", Strings.Right("00" + Convert.ToString(ys, 16), 2).ToUpper());
            }

            
            
return tmp.Trim();
        }



        
/// <summary>
        
/// 转换为符合本程序的十六进制格式
        
/// </summary>
        
/// <param name="var">1 2 3 等。</param>
        
/// <param name="tianbu">填补</param>
        
/// <param name="lng">长度</param>
        
/// <returns>返回指定长度字符串,缺少的用 tianbu 来补齐</returns>

        public static string ToHex(int var,string tianbu,int lng)
        
{
            
string tmp = ToHex(var);
            tmp 
= Strings.Left(tmp +" "+ tianbu,lng );
            
return tmp;
        }


        
/// <summary>
        
/// 统计和
        
/// </summary>
        
/// <param name="v">被统计的变量</param>
        
/// <returns></returns>

        public static int Sum(byte[] v)
        
{
            
int s = 0;
            
foreach (int var in v)
            
{
                s 
+= var;
            }

            
return s;
        }



        
/// <summary>
        
/// 统计和
        
/// </summary>
        
/// <param name="v">被统计的变量</param>
        
/// <returns></returns>
        
/// <param name="istart">开始位置</param>

        public static int Sum(byte[] v, int istart)
        
{
            
int s = 0;
            
for (int i = istart; i < v.Length; i++)
            
{
                s 
+= v[i];
            }

            
return s;
        }


        
/// <summary>
        
/// 统计和
        
/// </summary>
        
/// <param name="v">被统计的变量</param>
        
/// <returns></returns>
        
/// <param name="istart">开始位置</param>
        
/// <param name="iend">结束位置</param>

        public static int Sum(byte[] v, int istart, int iend)
        
{
            
int s = 0;
            
for (int i = istart; i < iend; i++)
            
{
                s 
+= v[i];
            }

            
return s;
        }


        
/// <summary>
        
/// 转换16进制字符串为int
        
/// </summary>
        
/// <param name="hexstring">字符串,低字节在前,高字节在后</param>
        
/// <returns></returns>

        public static  int Hex2Int(string hexstring)
        
{

            
return Hex2Int(hexstring ,false );
        }


        
/// <summary>
        
/// 转换16进制字符串为int
        
/// </summary>
        
/// <param name="hexstring">字符串</param>
        
/// <param name="Reverse">是否反转为高字节在前,低字节在后</param> 
        
/// <returns></returns>
        
/// <remarks> 高字节在前,低字节在后</remarks>

        public static int Hex2Int(string hexstring,bool Reverse)
        
{
            
//02 00

            
byte[] b = HexStringToBinary(hexstring);
            
if (Reverse) { Array.Reverse(b); };
            
int r = b[0];
            
for (int i = 1; i < b.Length - 1; i++)
            
{
                
if (b[i] != 0)
                
{
                    r 
+= Convert.ToInt32(Math.Pow(16, b[i]));
                }

            }

            
return r;
        }












        
/// <summary>
        
/// 16进制字符串转换为二进制数组
        
/// </summary>
        
/// <param name="hexstring">字符串每个字节之间都应该有空格,大多数的串口通讯资料上面的16进制都是字节之间都是用空格来分割的。</param>
        
/// <returns>返回一个二进制字符串</returns>

        public static byte[] HexStringToBinary(string hexstring)
        
{
            
string[] tmpary = hexstring.Trim().Split(' ');
            
byte[] buff = new byte[tmpary.Length];
            
for (int i = 0; i < buff.Length; i++)
            
{
                buff[i] 
= Convert.ToByte(tmpary[i], 16);
            }

            
return buff;
        }

        
/// <summary>
        
/// 把二进制转换为十六进制字符串。
        
/// </summary>
        
/// <param name="buff">要被转换的二进制数组</param>
        
/// <returns>返回十六进制字符串,以空格隔开每个字节 。</returns>

        public static string BinaryToHexString(byte[] buff)
        
{
            
string tmpstring = "";
            
foreach (byte var in buff)
            
{

                tmpstring 
+= " " + Strings.Right("00" + Convert.ToString(var, 16), 2);
            }

            
return tmpstring.Trim().ToUpper();
        }


    }



}

命令的提取和剔除。

 

using  Microsoft.VisualBasic;

namespace  SPC
{
    
public class CommandString
    
{
        
public const string Sync2STX = "16 16 02";
        
/// <summary>
        
/// 从返回的字符串中取得信息部分。
        
/// </summary>
        
/// <param name="returnstring">返回的字符串。</param>
        
/// <param name="loc">取得地址部分的字符串。</param>
        
/// <returns>返回字符串的信息部分</returns>

        public static string GetCmdFromReturnString(string returnstring,out string loc)
        
{
            
/*
            SYNC|SYNC | STX | 地址  | 长度  |信息  |ETX |2字节校验和。
            16  | 16  |  02 | 10 01 | 02 00 |07 00  |03 |1D 00 
            解释:
            开始的16 16 02 是信息的开头;
            10 01 即为该车检的地址,
            02 00是命令的长度低字节在前,高字节在后,代表查询的命令值是两个字节;
            07 00 即为查询的命令,具体解析在后;
            03为停止位;
            最后两位是校验位,为STX之后(不包括STX)到ETX(包括)所有字节的和。
            
*/


            
string tmp = returnstring.Remove(0, Sync2STX.Length).Trim();//去掉头信息
            loc = Strings.Left(tmp, 5);//取得位置 
             tmp = tmp.Remove(05).Trim();//去掉 位置
            int lng=Funs.Hex2Int(Strings.Left(tmp,5));//取得信息长度。
            tmp = tmp.Remove(05).Trim();//去掉信息长度
            string r = Strings.Left(tmp, lng * 3).Trim();//取得信息。 
            
//校验和这里不验证了。在 PortControl 中接受的时候就验证过了。 
            return r;
        }

        
/// <summary>
        
/// 从返回的字符串中取得信息部分。
        
/// </summary>
        
/// <param name="returnstring">返回的字符串</param>
        
/// <returns>返回字符串的信息部分</returns>

        public static string GetCmdFromReturnString(string returnstring)
        
{
            
string loc;
            
string r =GetCmdFromReturnString(returnstring , out  loc);
            
return r ;
        }


        
/// <summary>
        
/// 计算完整的命令字符串
        
/// </summary>
        
/// <param name="pm0_dizhi">The pm0_dizhi.</param>
        
/// <param name="pm2_mingling">The pm2_mingling.</param>
        
/// <returns>
        
/// 返回完整的十六进制字符串,包括信息头,地址,命令,校正码等内容。可以直接发送给车检器。
        
/// </returns>

        public static string GetFullCommandString(string pm0_dizhi,string pm2_mingling )
        


            
/*
            SYNC|SYNC | STX | 地址  | 长度  |信息  |ETX |2字节校验和。
            16  | 16  |  02 | 10 01 | 02 00 |07 00  |03 |1D 00 
            解释:
            开始的16 16 02 是信息的开头;
            10 01 即为该车检的地址,
            02 00是命令的长度低字节在前,高字节在后,代表查询的命令值是两个字节;
            07 00 即为查询的命令,具体解析在后;
            03为停止位;
            最后两位是校验位,为STX之后(不包括STX)到ETX(包括)所有字节的和。
            
*/


            
//SYNC、SYNC、STX、地址、长度、信息、ETX、2字节校验和。
            string tmpstring = "16 16 02 {0} {1} {2} 03";
            
//0 地址,1 长度,2 信息 3 校验和。
            string pm1_changdu = Funs.ToHex(pm2_mingling.Split(' ').Length,"00",5);
            tmpstring
=string.Format(tmpstring,pm0_dizhi,pm1_changdu,pm2_mingling);
            
int pm3_jiaoyanhe = Funs.Sum(Funs.HexStringToBinary(tmpstring), 3);
            tmpstring 
+=" "+ Funs.ToHex ( pm3_jiaoyanhe,"00",5); 
            
return tmpstring ;
            

        }


    }

}


如何调用:

 

         获取版本号

        
公用常量

        
执行命令

     
    }

单元测试

 


       [Test]
        
public   void  GetVer()
        
{
            
string tmp = DoCommand.GetVer(_地址);
            Assert.AreEqual(
"3.3", tmp, "如果是 null ,表示车检器的端口通讯失败,如果是 -  表示车检器回应的数据不正确");
        }
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值