我是初学者,对这方面的知识不太了解,希望高手指点。用不用多线程呀?为什么我的总是出问题,不是发送不了,就是给COM8发送数据,COM3也能收到,不知道是怎么回事,我的代码如下,希望高手指点。或者给一段多个串口同时通信的代码,让小弟参考一下,不胜感激![code=C#]namespace NETTEST
{
    public partial class Form_Main : Form
    {
        SerialPort spcom = new SerialPort();
        SerialPort spcom2 = new SerialPort();
        delegate void HandleInterfaceUpdateDelegate(string text); //委托        
        HandleInterfaceUpdateDelegate interfaceUpdateHandle;       
        HandleInterfaceUpdateDelegate interfaceUpdateHandle2; 
        public Form_Main()
        {
            InitializeComponent();
        }        private void Form1_Load(object sender, EventArgs e)
        {
            comboBox1.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames());
            comboBox6.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames());
            comboBox1.Text = comboBox1.Items[0].ToString();
            comboBox2.Text = comboBox2.Items[0].ToString();
            comboBox3.Text = comboBox3.Items[0].ToString();
            comboBox4.Text = comboBox4.Items[0].ToString();
            comboBox5.Text = comboBox5.Items[0].ToString();
            comboBox6.Text = comboBox6.Items[0].ToString();
            comboBox7.Text = comboBox7.Items[0].ToString();
            comboBox8.Text = comboBox8.Items[0].ToString();
            comboBox9.Text = comboBox9.Items[0].ToString();
            comboBox10.Text = comboBox10.Items[0].ToString();
        }           public void spcom_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {           byte[] readBuffer = new byte[spcom.ReadBufferSize];
            spcom.Read(readBuffer, 0, readBuffer.Length);
           this.Invoke(interfaceUpdateHandle, new string[] { Encoding.ASCII.GetString (readBuffer)      }
         }
        public void spcom2_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
             byte[] readBuffer = new byte[spcom2.ReadBufferSize];
            spcom2.Read(readBuffer, 0, readBuffer.Length);
        this.Invoke(interfaceUpdateHandle2, new string[] { Encoding.ASCII.GetString(readBuffer) });
        }        //字节数组转换为十六进制
        private string ByteArrayToHexString(byte[] data)
        {
            StringBuilder sb = new StringBuilder(data.Length * 3);
            foreach (byte b in data)
            sb.Append(Convert.ToString(b, 16).PadLeft(2, '0').PadRight(3, ' '));
            return sb.ToString().ToUpper();
        }
        //字符串转换为十六进制
        private string StringToHexString(string str)
        {
            StringBuilder sb = new StringBuilder(str.Length * 3);
            foreach (char b in str)
            sb.Append(Convert.ToString(b, 16).PadLeft(2, '0').PadRight(3, ' '));
            return sb.ToString().ToUpper();
        }
        private void UpdateTextBox1(string text)
        {
            txtrev1.Text += text;
        }
        private void UpdateTextBox2(string text)
        {
            txtrev2.Text += text;
        }        //发送字符串数据 
        private void SendStringData(SerialPort serialPort)
        {
            try
            {
                SerialPort  i = serialPort;
                //if (!spcom.IsOpen)
                //{ spcom.Open(); }
                string str = txtsend.Text.Trim();
                //serialPort.WriteLine(CharToIntStr(str));// .Write //txtsend.Text.ToString().Trim()
                // byte[] data= Convert .ToByte (str);
                serialPort.WriteLine(StringToHexString(str));
                serialPort.Write(txtsend.Text);
                //spcom2.WriteLine(CharToIntStr(str));// .Write //txtsend.Text.ToString().Trim()
                //// byte[] data= Convert .ToByte (str);
                //spcom2.WriteLine(StringToHexString(str));
                //spcom2.Write(txtsend.Text);
            }
            catch(Exception ex)
            {
                MessageBox.Show("没有找到串口,请先打开串口", "警告"+ex.Message );
            }
           
        }        //发送二进制数据 
        private void SendBytesData(SerialPort serialPort)
        {
            byte[] bytesSend = Encoding.Default.GetBytes(txtsend.Text);
            spcom.Write(bytesSend, 0, bytesSend.Length);
        }      private void txtrev_TextChanged(object sender, EventArgs e)
        {
            txtrev1.SelectionStart = txtrev1.Text.Length;
            txtrev1.SelectionLength = 0;
            txtrev1.ScrollToCaret();
        }        private void button1_Click(object sender, EventArgs e)
        {
           SerialPortInitial();
           SerialPortInitial2();
           try
           {
             if (!spcom.IsOpen) spcom.Open();
             if (!spcom2.IsOpen) spcom2.Open();
           }
           catch (Exception ex)
           {
               MessageBox.Show("没有找到串口,请检查后再试……", "警告" + ex.Message);
           }             interfaceUpdateHandle = new HandleInterfaceUpdateDelegate(UpdateTextBox1);
            spcom.DataReceived += new SerialDataReceivedEventHandler(spcom_DataReceived);
            spcom.ReceivedBytesThreshold = 1;
            interfaceUpdateHandle2 = new HandleInterfaceUpdateDelegate(UpdateTextBox2);
            spcom2.DataReceived += new SerialDataReceivedEventHandler(spcom2_DataReceived);
            spcom2.ReceivedBytesThreshold = 1;        }
        private void button3_Click(object sender, EventArgs e)
        {
             try
            {
                  SendStringData(spcom);
                SendStringData(spcom2);
             }
            catch (Exception ex)
            {
                MessageBox.Show("没有找到串口,请检查后再试……", "警告" + ex.Message);
            } 
            
          } 
      

解决方案 »

  1.   

      private void SerialPortInitial()
            {
                try
                {
                 int BTL = 9600;
                    string com = "COM1";
                      if (comboBox1.Text.ToString().Trim() == "") MessageBox.Show("请选择COM口!");
                    else com = comboBox1.Text.ToString().Trim();
                    if (comboBox2.Text.ToString().Trim() == "") MessageBox.Show("请设置波特率!");
                    else BTL = Convert.ToInt32(comboBox2.Text.ToString().Trim());
                    spcom.PortName = com;
                    spcom.BaudRate = BTL;
                    if (comboBox3.Text.ToString().Trim() == "") MessageBox.Show("请设置校验方式!");
                    else
                    {
                        switch (comboBox3.Text.ToString().Trim())
                        {
                            case "奇校验": spcom.Parity = Parity.Even; break;
                            case "偶校验": spcom.Parity = Parity.Odd; break;
                            case "无校验": spcom.Parity = Parity.None; break;
                            case "保留为0": spcom.Parity = Parity.Space; break;
                            case "保留为1": spcom.Parity = Parity.Mark; break;
                            default: break;                    }
                    }                if (comboBox4.Text.ToString().Trim() == "") MessageBox.Show("请设置停止位!");
                    else
                    {
                        switch (comboBox4.Text.ToString().Trim())
                        {
                            case "1": spcom.StopBits = StopBits.One; break;
                            case "2": spcom.StopBits = StopBits.Two; break;
                            case "1.5": spcom.StopBits = StopBits.OnePointFive; break;
                            default: break;
                        }
                    }
                    if (comboBox5.Text.ToString().Trim() == "") MessageBox.Show("请设置数据位!");
                    else
                    {
                        switch (comboBox5.Text.ToString().Trim())
                        {
                            case "8": spcom.DataBits = 8; break;
                            case "7": spcom.DataBits = 7; break;
                            case "6": spcom.DataBits = 6; break;
                            default: break;
                        }
                    }
                  }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message ,"系统提示");
                }
            }
            private void SerialPortInitial2()
            {
                try
                {
                    int BTL = 115200;
                    string com = "COM1";
                    if (comboBox6.Text.ToString().Trim() == "") MessageBox.Show("请选择COM口!");
                    else com = comboBox6.Text.ToString().Trim();
                    if (comboBox7.Text.ToString().Trim() == "") MessageBox.Show("请设置波特率!");
                    else BTL = Convert.ToInt32(comboBox7.Text.ToString().Trim());
                    spcom2.PortName = com;
                    spcom2.BaudRate = BTL;
                    if (comboBox8.Text.ToString().Trim() == "") MessageBox.Show("请设置校验方式!");
                    else
                    {
                        switch (comboBox8.Text.ToString().Trim())
                        {
                            case "奇校验": spcom2.Parity = Parity.Even; break;
                            case "偶校验": spcom2.Parity = Parity.Odd; break;
                            case "无校验": spcom2.Parity = Parity.None; break;
                            case "保留为0": spcom2.Parity = Parity.Space; break;
                            case "保留为1": spcom2.Parity = Parity.Mark; break;
                            default: break;
                        }
                    }                if (comboBox9.Text.ToString().Trim() == "") MessageBox.Show("请设置停止位!");
                    else
                    {
                        switch (comboBox9.Text.ToString().Trim())
                        {
                            case "1": spcom2.StopBits = StopBits.One; break;
                            case "2": spcom2.StopBits = StopBits.Two; break;
                            case "1.5": spcom2.StopBits = StopBits.OnePointFive; break;
                            default: break;
                        }
                    }
                    if (comboBox10.Text.ToString().Trim() == "") MessageBox.Show("请设置数据位!");
                    else
                    {
                        switch (comboBox10.Text.ToString().Trim())
                        {
                            case "8": spcom2.DataBits = 8; break;
                            case "7": spcom2.DataBits = 7; break;
                            case "6": spcom2.DataBits = 6; break;
                            default: break;
                        }
                    }
                  }
                
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message ,"系统提示");
                }
            }        private void button2_Click(object sender, EventArgs e)
            {
                spcom.Close();
                spcom2.Close();
            }
            private void comboBox1_DropDown(object sender, EventArgs e)
            {
                comboBox1.Items.Clear();
                comboBox1.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames());//自动搜索本机的COM口
            }        private void comboBox6_DropDown(object sender, EventArgs e)
            {
                comboBox6.Items.Clear();
                comboBox6.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames());//自动搜索本机的COM口
            } 
             }
    }[/code]
    我的目的是让这个程序能与多个单片机同时通信,目前只是学习串口编程,最基本的功能都不能实现。发送数据时已发送就卡住了,谢谢每一位走过路过的朋友!
      

  2.   

    不用多开线程了,DataReceived 事件绑定的方法本身会在一个新的线程中执行的.
    你把this.Invoke改成this.BeginInvoke 异步执行
      

  3.   

    您好,如果把this.Invoke改成this.BeginInvoke 异步执行之后,多个串口即SerialPort对象,
    可不可以公用这几行代码呀?
    interfaceUpdateHandle = new HandleInterfaceUpdateDelegate(UpdateTextBox1);
    spcom.DataReceived += new SerialDataReceivedEventHandler(spcom_DataReceived);
    spcom.ReceivedBytesThreshold = 1;
    能帮我开一下我的程序代码吗?是哪里有问题呀?我点发送调用了两次SendStringData方法,分别发送到两个不同的textbox里面但是总是只有一个能收的。
    分不多,不好意思,如果有空帮我分析一下吧,谢谢
      

  4.   

    你如果想使用同一个串口COM1来与多个单片机进行通信,那要注意SendStringData(spcom);
    在spcom发送完数据后,并且你确定spcom的数据接收完后,你要关闭COM1,这个时候才能使用spcom2,去开启COM1,然后SendStringData(spcom2);去发送数据和接收数据。两者不要混用。interfaceUpdateHandle = new HandleInterfaceUpdateDelegate(UpdateTextBox1);
    spcom.DataReceived += new SerialDataReceivedEventHandler(spcom_DataReceived);
    spcom.ReceivedBytesThreshold = 1;
    这个不要共用,当你使用不同的COM端口,这个部分就可以同时工作
      

  5.   

    楼上不错。网上也COM通信的例子,你可以找个看看
      

  6.   

    那我要是同时与多个单片机通信是不是要用多个SerialPort,多个spcom_DataReceived(如spcom1_DataReceived、spcom2_DataReceived.。。),多HandleInterfaceUpdateDelegate对象呀?
      

  7.   

    让你多个是有好处的,当你的电脑上有3个COM口时,你可以同时与个单片机进行通信,如果你要共用,那你同时只能有一个处于通信中,一个使用完后才能让下一个使用.
      

  8.   

     public void spcom2_DataReceived(object sender, SerialDataReceivedEventArgs e)
     {
    try
       {
        byte[] readBuffer = new byte[spcom2.ReadBufferSize];
        spcom2.Read(readBuffer, 0, readBuffer.Length);
        this.BeginInvoke(interfaceUpdateHandle2, new string[] { Encoding.ASCII.GetString(readBuffer) });
      }
     catch (Exception ex)
      {
          MessageBox.Show(ex.Message +"系统提示");
        }}但是为什么我的程序能接收ASCII码的数据,不能接收二进制数据呀?我要是想接收16进制的应该怎么写?还有
    interfaceUpdateHandle2 = new HandleInterfaceUpdateDelegate(UpdateTextBox2);
    spcom2.DataReceived += new SerialDataReceivedEventHandler(spcom2_DataReceived);
     spcom2.ReceivedBytesThreshold = 1;
    这里当缓存中收到数据时 是怎么调用UpdateTextBox2方法的呀?谢谢指点
      

  9.   

        byte[] readBuffer = new byte[spcom2.BytesToRead];
        spcom2.Read(readBuffer, 0, readBuffer.Length);
        this.BeginInvoke(interfaceUpdateHandle2, new string[] { Encoding.ASCII.GetString(readBuffer) });
    只能接收ASCII码的数据,其它格式的需要你自己接收到后进行转换。因为spcom2_DataReceived方法是在一个新的线程中执行的,所以需要使用委托,用this.BeginInvoke去调用UpdateTextBox2方法
      

  10.   

    谢谢朋友的一步步指导,终于接近问题的中心了,呵呵。我要接受的是单片机发过来的16进制的数据,从缓存buffer里面可以看到,但是我怎么转换之后显示呢? 
    private string ByteArrayToHexString(byte[] data)
            {
                StringBuilder sb = new StringBuilder(data.Length * 3);
                foreach (byte b in data)
                sb.Append(Convert.ToString(b, 16).PadLeft(2, '0').PadRight(3, ' '));
                return sb.ToString().ToUpper();
            }
    我用这个方法将它转换之后,赋值给String read;然后用read代替this.BeginInvoke(interfaceUpdateHandle2, new string[] { Encoding.ASCII.GetString(readBuffer) });
    中的new string[] { Encoding.ASCII.GetString(readBuffer) }可以显示,但是总是假死,有时候就是真死了,不响应了,能帮我分析一下怎么样才能让我的程序正常运行,谢谢高手
      

  11.   

                learn  
      

  12.   

    十分感谢xingyuebuyu,其它朋友也可以指点指点呀。多谢每一位过客
      

  13.   

    byte[] readBuffer = new byte[spcom2.BytesToRead];
      spcom2.Read(readBuffer, 0, readBuffer.Length);
      this.BeginInvoke(interfaceUpdateHandle2, new string[] { ByteArrayToHexString(readBuffer) });你怎么改的,贴下你改后的代码.
      

  14.   

    如果使用多个串口同时通讯的话还是要多个SerialPort,而且最好不要在一个事件里同时操作多个SerialPort,如果有一个SerialPort卡死就无法操作其他SerialPort了,还是分别控制比较好,比如多口的下载程序就应该一个SerialPort对应一个button。可以使用SerialPort.readbyte()读取二进制数据吧
      

  15.   

    考虑是不是可以开多个程序,每个程序serialport.name设成不同端口
      

  16.   

    你好,我用SerialPort控件时
     delegate void HandleInterfaceUpdateDelegate(string text); //委托   
      HandleInterfaceUpdateDelegate interfaceUpdateHandle;   
      interfaceUpdateHandle = new HandleInterfaceUpdateDelegate(UpdateTextBox1);
      spcom.DataReceived += new SerialDataReceivedEventHandler(spcom_DataReceived);
      spcom.ReceivedBytesThreshold = 40;
    如上使用委托,当我要接收的数据包长度是变化的时候怎么办?我这里的spcom.ReceivedBytesThreshold参数值怎么设置呀?高手请指点
      

  17.   

    可用serialPort.ReadLine()读出所有数据包