毕业设计中,用到串口与无人机通信,所以就用到了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();//拿到真实接收到的数据,