C# + .net下使用serialPort做串口开发 1

本文探讨了在.NET环境下使用SerialPort进行串口通信时遇到的问题及解决方案。特别是在通信不稳定或比特率较低时,如何准确地接收完整的数据帧。文章提供了一种通过定时检查输入缓冲区并适当延时的方法来确保数据的完整性。

     在.net下使用serialPort做串口通信开发,在环境状态比较好的情况下还是比较容易的。我们可是使用serialPort.write(),将组织好的byte数组写入到串口中。也可以通过serialPort的DataReceived 事件来触发读取。

    但是,如果通信情况不好,或者比特率较低的情况下,在接受的时候会出现很多情况,当触发一次Datareceived的事件,可能是收到了全部数据帧,也可能只收到了半个帧,第二次触发的时候,也许就是完整的一个帧了,这样就给写程序带来的N多问题。无法通过DataReceived事件来触发读取了。

   最后,没办法,想出一个变通的手法,因为我们可以知道serialPort中当前输入缓冲区的内容的大小,BytesToRead,我们可以在一段时间间隔内,获取这个值,如果它不改变了,说明后面没有数据了,也就是下位机发送完成。这个时间是和serialPort的波特率有关的。

  波特率的单位是 bps 就是 bit 每秒,所以换成字节的话,得除以8,在考虑上完成字节的头尾等,完成的一个字节是11bit,所以,我们就可以换算出 (波特率/11) 得到一秒可以发送的字节数,然后我们在拿 1000ms除以这个值,就可以得到 一个字节需要多少毫秒来发送: 1000/(波特率/11) 。

  理论上,我们等待这个时间,就可以获取到下一个字节了,但是考虑到实际情况,可能需要适当的延长时间,所以,我们可是适当的增加等待时间。

  我们可以使用timer来实现;

 

timer1.Interval = (1000 / (serialPort1.BaudRate / 11)) + 20;

 

int timer2Bytes = -1;
private void timer2_Tick(object sender, EventArgs e)
{
int newBytes = serialPort1.BytesToRead;
if (timer2Bytes == newBytes && newBytes != 0)
{
byte[] data = new byte[newBytes];
serialPort1.Read(data,
0, data.Length);
if (data != null)
{
textBoxResult.Text
+= BitConverter.ToString(data) + "\r\n";
Application.DoEvents();
}
timer2Bytes
= -1;

}
else
{
timer2Bytes
= newBytes;
}
}

OK,这样就基本完成了,但是依然还是有可能出现接受的帧不完整的情况,这个时候可以尝试在发送一次命令读取一次。这个好处是可以读取到通信时间,只需要在里面添加一个计时器,比如在 else下 添加 time += timer2.Interval ;  但是这个时间很不准确,不知道为什么。

最后一个比较好的方法就是:通过bytesToRead的长度来确定是否接受完成,并指定超时时限,这样的好处是,能保证接受到的就是长度符合的,否则就继续等,知道超时,可是,问题是必须事先知道,我读取的长度将会是多少,这对程序的扩展性等,都引来很多问题。纠结中。

继续研究如何比较好的实现,并精确的记录下通信时间;

转载于:https://www.cnblogs.com/lingfengchencn/archive/2010/07/01/serialPort.html

Imports System Imports System.IO.Ports Public Class Form1 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load '获取计算机有效串口 Dim ports As String() = SerialPort.GetPortNames() Dim port As String For Each port In ports ComboBox1.Items.Add(port) Next ComboBox1.Text = ComboBox1.Items(0) ComboBox2.Items.Add(1200) ComboBox2.Items.Add(4800) ComboBox2.Items.Add(9600) ComboBox2.Text = ComboBox2.Items(2) Serial_Port1() TextBox2.Text = SerialPort1.IsOpen TextBox1.Text = "串口未连接" TextBox1.ForeColor = Color.Red TextBox3.Text = "123" CheckBox1.Text = "" End Sub Private Sub Serial_Port1() SerialPort1.BaudRate = ComboBox2.Text SerialPort1.PortName = ComboBox1.Text SerialPort1.DataBits = 8 SerialPort1.StopBits = IO.Ports.StopBits.One SerialPort1.Parity = IO.Ports.Parity.None End Sub '关闭串口连接 Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click Try SerialPort1.Close() TextBox2.Text = SerialPort1.IsOpen If SerialPort1.IsOpen = False Then TextBox1.Text = "串口未连接" TextBox1.ForeColor = Color.Red TextBox4.Text = "" End If Catch ex As Exception MessageBox.Show(ex.Message) End Try End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Try SerialPort1.Open() TextBox2.Text = SerialPort1.IsOpen If SerialPort1.IsOpen = True Then TextBox1.Text = "串口已连接" TextBox1.ForeColor = Color.Green End If Catch ex As Exception MessageBox.Show(ex.Message) End Try End Sub Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click Try SerialPort1.Write(TextBox3.Text) Catch ex As Exception MessageBox.Show(ex.Message) End Try End Sub Public Sub Sp_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived Me.Invoke(New EventHandler(AddressOf Sp_DataReceiving)) End Sub Public Sub Sp_DataReceiving(ByVal sender As Object, ByVal e As EventArgs) Dim strIncoming As String Try CheckBox1.Text = Str(Val(CheckBox1.Text) + SerialPort1.BytesToRead) If SerialPort1.BytesToRead > 0 Then Threading.Thread.Sleep(100) strIncoming = SerialPort1.ReadExisting.ToString SerialPort1.DiscardInBuffer() TextBox4.Text = strIncoming End If Catch ex As Exception MessageBox.Show(ex.Message) End Try End Sub End Class
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值