老实讲,自从用上了c#之后,就再也没有心思去折腾delphi了,从开发速度来讲,c#要用的顺手的多,最起码两点:不用在开头写函数声明,局部变量也不用在函数头声明。抛弃这些东西,强大的LIST链表用的是相当的爽。
前些年觉得,技术进步太快,你只需要专注你自己的东西就ok了,现在看来倒是未必了。开发语言是一种工具,人家用的是大炮了,你还在用手枪,迟早就是躲不开被淘汰的命运。
抛弃存量,寻找增量,是在互联网时代存活下去的定律。编程语言在进化,人也在进化。
com口的通信,要不就用windows自带的API去写,然后用多线程进行异步分装,这个可以参考:
在c#中,我们终于发现事情变得非常简单,用serialport控件就行了,在窗口上,拉上这个控件,然后写上DataReceived事件就行了,具体可以参考微软的例子:
using System; using System.IO.Ports; class PortDataReceived { public static void Main() { SerialPort mySerialPort = new SerialPort("COM1"); mySerialPort.BaudRate = 9600; mySerialPort.Parity = Parity.None; mySerialPort.StopBits = StopBits.One; mySerialPort.DataBits = 8; mySerialPort.Handshake = Handshake.None; mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler); mySerialPort.Open(); Console.WriteLine("Press any key to continue..."); Console.WriteLine(); Console.ReadKey(); mySerialPort.Close(); } private static void DataReceivedHandler( object sender, SerialDataReceivedEventArgs e) { SerialPort sp = (SerialPort)sender; string indata = sp.ReadExisting(); Console.WriteLine("Data Received:"); Console.Write(indata); } }
上面的例子是控制台程序的,如果我们做的是winform呢?在DataReceived事件中直接将数据输入到文本框是行不通的,因为UI是一个独立的线程,要跨线程操作,需要用到委托:
public delegate void MyInvoke(string str); private void AddReceiveText(string str) { if (tbReceive.InvokeRequired) { MyInvoke _myInvoke = new MyInvoke(AddReceiveText); this.Invoke(_myInvoke, new object[] { str }); } else { if (this.tbReceive.Text != "") { this.tbReceive.Text = this.tbReceive.Text + "\r\n" + str; } else { this.tbReceive.Text = str; } } }
从这里就可以看得出来,微软封装的serialport异步类,依旧是使用多线程来封装的,至于原理么,大概应该和前文我写的那篇文章差不多。
编码问题
原来困扰我们的ASCII和Unicode编码的问题,在c#时代因为Encoding类的出现变得十分简单,直接用相关的函数直接转码就可以了。
VS默认的编码格式是unicode的,也就是双字节的,而ASCII依旧是单字节的。在串口通讯中,大部分时候都是用ASCII编码格式来传输数据的,因此发送内容就应该这么写:
byte[] btSend = Encoding.ASCII.GetBytes(tbSend.Text);
serialPort.Write(btSend, 0, btSend.Length);
很轻松把Unicode编码的文本转化为了ASCII编码的字节数组!
当然,收到数据怎么办呢?那还不简单,再转一次呗:
Encoding.ASCII.GetString(bytes)
在LIS的串口通信中,大部分时候用的还是ASCII编码,比如发送ACK信号:
public void SendACK()
{
if (this.IsOpen)
{
byte[] btACK = new byte[1];
btACK[0] = 6;
this.Write(btACK, 0, btACK.Length);
}
}
至于ACK为什么是6,你去查ASCII码表就知道了。
有些时候,我们需要用com口来传输文本数据,比如中文,这个时候你用ASCII去读取发现还是全部都是?????,为啥啊?因为还有一种格式叫做GB2313.
Encoding chs = Encoding.GetEncoding(“gb2312”);
用这种格式去读取中文,就不会乱码了。
接下来会写一个LIS串口通信协议的分析程序,慢慢来吧。
如无特别说明,本博客文章皆为原创。转载请说明,来自吵吵博客。
原文链接:http://chaochaoblog.com/archives/2948
吵吵微信朋友圈,请付款实名加入:
其实我想说的是:c#是什么呀