private void button1_Click(object sender, EventArgs e)
{
//实例化串口对象(默认:COMM1,9600,e,8,1) 
SerialPort serialPort1 = new SerialPort();
//更改参数
serialPort1.PortName = "COM1";
serialPort1.BaudRate = 19200;
serialPort1.Parity = Parity.Odd;
serialPort1.StopBits = StopBits.Two;//上述步骤可以用在实例化时调用SerialPort类的重载构造函数
//SerialPort serialPort = new SerialPort("COM1", 19200, Parity.Odd, StopBits.Two);//打开串口(打开串口后不能修改端口名,波特率等参数,修改参数要在串口关闭后修改)
serialPort1.Open();//发送数据
SendStringData(serialPort1);
//也可用字节的形式发送数据
//SendBytesData(serialPort1);//开启接收数据线程
ReceiveData(serialPort1);}//发送字符串数据
private void SendStringData(SerialPort serialPort)
{
serialPort.Write(txtSend.Text);
}/// <summary>
/// 开启接收数据线程
/// </summary>
private void ReceiveData(SerialPort serialPort)
{
//同步阻塞接收数据线程
Thread threadReceive=new Thread(new ParameterizedThreadStart(SynReceiveData));
threadReceive.Start(serialPort);//也可用异步接收数据线程
//Thread threadReceiveSub = new Thread(new ParameterizedThreadStart(AsyReceiveData));
//threadReceiveSub.Start(serialPort);}//发送二进制数据
private void SendBytesData(SerialPort serialPort)
{
byte[] bytesSend=System.Text.Encoding.Default.GetBytes(txtSend.Text );
serialPort.Write(bytesSend, 0, bytesSend.Length);
}//同步阻塞读取
private void SynReceiveData(object serialPortobj)
{
SerialPort serialPort = (SerialPort)serialPortobj;
System.Threading.Thread.Sleep(0);
serialPort.ReadTimeout = 1000;
try
{
//阻塞到读取数据或超时(这里为2秒)
byte firstByte=Convert.ToByte(serialPort.ReadByte());
int bytesRead=serialPort.BytesToRead ; 
byte[] bytesData=new byte[bytesRead+1];
bytesData[0] = firstByte;
for (int i = 1; i <=bytesRead; i++)
bytesData[i] = Convert.ToByte( serialPort.ReadByte());
txtReceive.Text = System.Text.Encoding.Default.GetString(bytesData);
}
catch(Exception e) 
{
MessageBox.Show(e.Message);
//处理超时错误
}serialPort.Close();}//异步读取
private void AsyReceiveData(object serialPortobj)
{
SerialPort serialPort = (SerialPort)serialPortobj;
System.Threading.Thread.Sleep(500);
try
{
txtReceive.Text = serialPort.ReadExisting();
}
catch (Exception e)
{
MessageBox.Show(e.Message);
//处理错误
}
serialPort.Close();
}}

解决方案 »

  1.   

    Close之后确认serialPort1.IsOpen项
      

  2.   

    多谢godgreat,为了清空缓冲区,我直接用关闭串口的方法来清空,可是关闭成功,再次启动接收就出错,怎么才能不出错?
      

  3.   

    多谢andy888666,问题是:1、我清空的是我接收数据时建立的临时数组,满足不了我程序的需求。2、我只能读空缓冲,也达不到实时要求。
    3、我的要求是,我每次下发一个命令,再读出来的应该是我的命令和其他,可是现在读出来的是:之前发的很多数之后才能接收到我需要的命令和数据。我感觉缓冲区有数据的缘故,所以就想重新关闭串口。你有什么好的方法吗?
      

  4.   

    我觉得并不是你说的 “缓冲区有数据的缘故”
    你下发一条命令 例如下位机是ARM,ARM收到马上返回一条数据给你,
    根本没有必要返回的数据中还掺杂着你下发的命令数据吧你发射的速度是不是太快了,我曾经也因为发射太快,把下位机发死了
      

  5.   

    多谢andy888666,是这样的,本来下位机定时发送,上位机定时接收没问题。
    但是现在还加一部分功能,就是:按相关按钮给下位机命令,为了验证下位机是否收到,下位机收到命令后先将上位机下发的命令返回,再处理相应操作,完了再发送其他命令。
    我希望上位机下发命令后能立即收到传回的命令。
    可是问题是:1、收到这个命令之前总是先收到很多其他数才能 收到需要的两个命令返回值。也就是不同步。2、如果我下发命令之前先清空缓冲,倒是可以立即收到返回的命令,但是这时收不到第二个命令,也就是操作 完成的命令。
      

  6.   

    我用timer定时接收。每次接收一组数,将命令放在那组数的某个位,其他是数据位。发送的时候停止接收,发完立即启动接收定时器,可是总会多收很多组数之后才出现需要的那一组,该怎么同步,让其不多收呢?
      

  7.   

    哦,才明白阿。你说的多得数就是平时timer定时取得对吧。你按一个button下发一个命令 
    例如 FFFF 那么下位机响应的数据肯定也是有协议规定的阿,例如协议头+数据包+结束标志,你必须先找到协议头然后找到结束位 完全看你的协议怎么制定了!