很多C#新手在使用串口控件(MSComm)编程时可能都和小嫚儿一样疏忽,没想到可能会接收到乱码,以至于软件在使用中接收不到完整的数据,现在小嫚儿将完整的串口接收程序和大家分享,让大家避免成为象小嫚儿一样的马大哈:
//定义全局变量:
int
UnsettledDataNum=0;//未处理的数据个数
int
WorkedDataNum=0;//已处理的数据个数
int
ReceiveDataNum=0;//收到数据的个数
byte[] ReceivedData=new
byte[1024];//接收到的所有数据
private void
Form1_Load(object sender, System.EventArgs e)//串口初始化
{
MSComm.CommPort=1;//设置串口号
MSComm.RThreshold = 1;//接收缓冲区收到每一个字符都会使MSComm控件产生OnComm事件
MSComm.Settings =
"9600,O,8,1";//设置并返回数据传输速率、奇偶校验、数据比特、停止比特参数
MSComm.InputMode=MSCommLib.InputModeConstants.comInputModeBinary;//用于设置或返回传输数据的类型,此例程是通过Input属性以二进制方式检取回数据
MSComm.PortOpen =true
;//打开端口
MSComm.InBufferCount=0;//用于返回输入缓冲区内的等待读取得字节个数
}
private void MSComm_OnComm(object sender,
System.EventArgs e)//触发OnComm事件
{
switch
(MSComm.CommEvent ) //查询CommEvent属性
{
case
(short)(MSCommLib.OnCommConstants.comEvReceive): //当接收缓冲区内字符数达到RThreshold值,进入CommData()子程序
CommData
(); //接收缓冲区内数据
break;
}
}
private void CommData() //接收数据
{
int
BufferDataNumStart=0; //定义第一次查询缓冲区内数据个数
int BufferDataNumEnd=0; //定义最后一次查询缓冲区内数据个数
byte[] CommBufferData=new byte[1024];
byte[]
ComByte=new byte[8];
BufferDataNumStart=MSCommSoundBait.InBufferCount;
//将缓冲区内等待读取的字节个数赋给BufferDataNumStart
if(BufferDataNumStart==0)
return; //如果缓冲区为空,说明还没有数据传来,则返回;若不为空,进入下面的循环
MSCommSoundBait.InputLen
= 0; //读取缓冲区内全部内容
while(true)
{
System.Threading.Thread.Sleep(50); //延时,以确保数据完全接收
BufferDataNumEnd=MSCommSoundBait.InBufferCount; //再次读取缓冲区内字节个数
if(BufferDataNumStart==BufferDataNumEnd)
break; //如果BufferDataNumStart==BufferDataNumEnd,说明本帧数据已经读完,退出循环
BufferDataNumStart=BufferDataNumEnd;
//否则,将BufferDataNumEnd赋给BufferDataNumStart,并继续循环,直到完全接收
}
object
objIn;
objIn=MSComm.Input
; //这里注意MSComm.Input返回的是一个object的类型,所以必须使用显式的类型转换
CommBufferData
=(byte[])objIn; //CommBufferData为串口缓冲区内所有数据
//存取最后一次接收到的缓冲区的数据,存储部分时作为后期数据处理所用,以便于程序员分析数据。使用StreamWriter,需在添加命名控件using
System.IO;
string
sTime=DateTime.Now.ToString(); //记录当前时间
StreamWriter
strmWriter=new
StreamWriter("E:\\CommData\\ReceiveData\\CommData.txt",true);
strmWriter.Write("\r\n");
strmWriter.Write(sTime);
strmWriter.Write("\r\n");
string
StrRead="";
string
StrReadSub="";
for (int
j=0;j< BufferDataNumEnd;j++)
{
StrReadSub=(CommBufferData[j]).ToString("x");
if
(StrReadSub.Length<2)StrReadSub="0"+StrReadSub;
StrRead=StrRead+"
"+StrReadSub;
}
strmWriter.Write(StrRead.ToUpper());
strmWriter.Close();
//将上次未处理的数据和本次存储数据在ReceivedData相连,此部分是防止发送过来的数据本身就不完整,以至于数据处理不能进行完全,故保留并与新接收的数据相连
for(int
i=0;i<BufferDataNumEnd;i++)
{
ReceiveDataNum++;
UnsettledDataNum++;
ReceivedData[ReceiveDataNum-1]=CommBufferData[i];
}
//进入数据处理字程序
DealData();
}
private
void DealData() //数据处理
{
while(ReceivedData[WorkedDataNum]!=0xAA)
//判断是否是通讯头,如果是,跳出循环;否则,丢弃乱码
{
WorkedDataNum++;
UnsettledDataNum--; //目前没有处理的字节总数
if(UnsettledDataNum==0) return;
}
if(ReceivedData[WorkedDataNum+1]==0xAA
& UnsettledDataNum>=7) //第二个字节也为AA且剩下字节等于或超过7个,通讯头和剩下字节数以实际情况而定
{
DealUsefulData(); //处理有用的数据
}
return;
}
private
void DealUsefulData ()
{
//处理部分根据实际要求来做,这里只给出处理完成之后仍需注意的地方:
WorkedDataNum+=7;
UnsettledDataNum-=7;
DealData();
}
加载中,请稍候......