串行端口触发器DataReceived接收到一定量的字节数

时间:2013-06-24 23:29:13

标签: c# serial-port

我正在尝试编写一个程序,每当新数据进入串行端口时更新Windows窗体,但我很难理解串口的工作方式,以及如何以我想要的方式使用它。

我有一个外部设备以1Hz的频率向我的串口发送8个字节,并希望使用SerialPort类的DataReceived事件。当我调试我的代码时,根据程序在特定时间执行的操作,或多或少地随机触发事件。代码如下:

    private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        //byte[] rxbyte = new byte[1];
        byte[] rxbyte = new byte[8];
        byte currentbyte;
        port.Read(rxbyte, 0, port.BytesToRead);

        currentbyte = rxbyte[0];

        int channel = (currentbyte >> 6) & 3; //3 = binary 11, ANDS the last 2 bits
        int msb_2bit = (currentbyte >> 0) & 255; //AND compare all bits in a byte
        currentbyte = rxbyte[1];
        int val = ((msb_2bit << 8) | (currentbyte << 0));

        //Extra stuff

        SetText_tmp1(val.ToString());
    }

我想在调用Read函数之前能够在接收缓冲区中有8个字节,但我不知道如何做到这一点(之前从未使用过SerialPort类),并且只想对数据进行所有操作当我有整个8个字节。只有当缓冲区中有一定数量的字节时,是否有内置的方法来切换事件?或者是否有另一种方法只获得8个字节,但不是更多,并将剩余的字节留给下一个实例?

3 个答案:

答案 0 :(得分:2)

是的,你没有正确编码。您无法预测要接收的字节数。所以只要不完整就可以处理收到的字节。像这样:

private byte[] rxbyte = new byte[8];
private int rxcount = 0;

private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    rxcount += port.Read(rxbyte, rxcount, 8 - rxcount);
    if (rxcount < 8) return;
    rxcount = 0;
    // Process rxbyte content
    //...
}

答案 1 :(得分:0)

将ReceivedBytesThreshold属性设置为8.与port.ReceivedBytesThreshold = 8;

中一样

答案 2 :(得分:0)

处理此问题的一种有效方法是向类中添加一个计时器,该计时器每秒钟可以传输9次。完全消除串行端口事件处理程序。

在每个定时器时,代码检查串行端口是否有从串行端口接收的字节。如果有一些,那么将它们从串口中取出并将它们作为数据成员附加到类中维护的缓冲区的末尾。

当缓冲区中包含八个或更多字符时,定时器滴答逻辑将从缓冲区中取出前8个字节并使用它们来更新用户界面窗口。缓冲区中的任何剩余字节都可以移动到缓冲区的头部。

计时器刻度例程还可以保持一个计数器值,该值在每次刻度进入时递增,并且在该刻度处串行端口没有准备好数据。当此计数器达到3或4的值时,代码将数据缓冲区重置为空并将计数器重置为零。当从串行端口实际看到数据时,该计数器重置为零。这种计数器机制的目的是使数据接收缓冲区与进入的1Hz数据流同步,这样接收过程就不会与代表8字节消息开始的数据不同步。

请注意,此方法优于串口接收数据事件,因为它允许程序保持对事物的控制。我已经描述了与数据流突发同步的能力 - 这与尝试将串行端口接收数据阈值设置为8的计数无关。另一个优点是计时器刻度代码可以包括其他处理功能例如,如果在2或3秒内没有数据从串口到达,则发出超时信号。