现象:(以下描述中,用vs 写的程序,简称为程序)
用串口助手给程序发数据,如果数据为全英文,则结果正确,而如果数据中含有英文,则结果有时正确,有时错误。
代码如下
{
int iThisLength = serialPort1.BytesToRead;
if (iThisLength > 0)
{
byte[] cpConfig = new byte[iThisLength];
serialPort1.Read(cpConfig, 0, iThisLength);
string sReceiveContent = Encoding.GetEncoding(“GB2312”).GetString(cpConfig);
if (sReceiveContent != "")
{
AllReceive += sReceiveContent ;
}
}
以上代码中为了处理串口事件的一个特性(发送端发送了一串数据,但是接收端有可能会分几次触发这个事件,每次都只收一部分) ,因此使用了一个全局字符串AllReceive 。
并且使用了一个timer来判断串口是否收完整了一包数据(这里,我判断数据的完整性依据:如果串口在一定时间内(如200ms)再没有收到任何内容,则认为已经收到了一个完整的包) 。
注意:就是这句导致了乱码的问题
string sReceiveContent = Encoding.GetEncoding(“GB2312”).GetString(cpConfig);
如果串口事件,在一次触发中,数据的最末端正好收到了一个完整的汉字(一个汉字使用2个字节来表示),那么没有问题。
但是如果数据的最末端正好收到了前半个汉字的编码,则经过 Encoding.GetEncoding(“GB2312”).GetString(cpConfig) 之后,就会把汉字补齐,因此就会出现问题。
解决的办法:
不能在此处做编码转换的工作,而应该是在收到完整的一包数据后,再去转换整个完整的包,这样就不会出现问题了。
有的网友提到在接收之前来句System.Threading.Thread.Sleep(1000); 就可以解决问题了,这样是可以解决问题,但是
道理上还是等完整的一包数据都存放到缓冲区后再去触发串口的接收事件,因为经过了1s的延迟,因此串口的接收事件只会触发因此,而不会像我的代码中会触发多次了。
当然,付出的代价就是,延迟了1s的时间,这在很多场合是不可接受的。