毕业设计中,用到串口与无人机通信,所以就用到了SerialPort这个类,这个类在设置属性时,

用到最主要的属性应该是COM口和波特率,由于本人不熟悉硬件,不便多说,但经验告诉我是这样的,

还有数据位,停止位,奇偶检验位等,和我合作的同学告诉我,只要给飞控版发指令那么自动会返回

数据,但一开始总是触发不了返回数据事件注册的函数,网上查资料说要设置

port.ReceivedBytesThreshold = 1;这个数据,大概意思是缓存区里有一个字节就去触发指定的

函数,还是不行。后来调换各种数据格式,最后换成byte数组,以最原始的格式定义

byte[] buffer = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };

发送就行了。

资料表明,SerialPort会自动开启一个线程去执行数据回传注册的函数的,

这里由于可能操作到主线程下的控件,所以这里介绍一一下Invoke,

1.Invoke大概意思就是找到定义所属控件的线程去执行相关操作,C#里是

不允许跨线程调用的,(在拥有此控件的基础句柄的线程上执行指定的委托)

当然如果不想麻烦也可以写这样一句话

Control.CheckForIllegalCrossThreadCalls = false;

不检查跨线程的逻辑错误。

2.BeginInvoke:(在创建控件的基础句柄所在线程上异步执行指定的委托)

Invoke的异步版本 (Invoke是同步完成的)。

3.RequireInvoke 可用通过RequireInvoke属性来检测是否需要使用Invoke或则是BeginInvoke去执行相关的操作:

(获取一个值,该值指示调用方在对控件进行方法调用时是否必须调用Invoke方法,因为调用方位于创建控件所在的线程以外)

4.EndInvoke 如果异步执行的委托(BeginInvoke)有返回值,可以通过EndInvoke去获取:(检索由传递的IAsyncResult表示的异步操作返回值)

因为是异步的,所以是另外一个线程去执行,主线程就不可能去等待执行的结果。等待有返回值时会自动得到。

5.代码解析

Serialport port=new SerialPort();//创建Serialport实例
  List<string> comList = new List<string>();
            for (int i = 1; i < 9; i++)  //查找可用的COM放入combox中
            {
                port.PortName = "COM" + i;
                try
                {
                    port.Open();
                    comList.Add("COM" + i);
                    port.Close();
                }
                catch (Exception)
                {


                }
            } 

portCbx.DataSource = comList;//以数据源的方式给combox赋值,会把索引为0的数据当作默认选中的值。
//直接用port.Items.Add()方法则不会默认选中值,需要设置SelectedIndex才能达到相同的想过
port.DataReceived
+= new SerialDataReceivedEventHandler(this.receiveData);//注册接收数据的方法

port.ErrorReceived += Port_ErrorReceived;//注册错误事件的处理方法

int r=port.Read(buffer,0,buffer.Length);//读取接收到的数据,返回的值是接收到数据的个数,

buffer.Take(r).ToArray();//拿到真实接收到的数据,