首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >c#串口中缺失的数据

c#串口中缺失的数据
EN

Stack Overflow用户
提问于 2020-05-11 15:26:08
回答 2查看 360关注 0票数 0

我正在与DPS5020电源通信,以获得电压和电流。SMPS数据输出在数据包的末尾不包含任何分隔符,所以我认为它引起了问题。当我使用串行终端程序查询SMPS时,每次都得到正确的数据包,但是当我使用C#程序查询时,没有70%的数据。in数据包大小为9字节。我使用了serial_port.Read(buffer, 0, 9),但即使如此,也存在错误。这里有人能帮我吗?我的密码在下面。

主要功能

代码语言:javascript
复制
    private void ovcRead_Click(object sender, EventArgs e)
    {
        byte[] sendbyte = power2.PowerSupply_GetOVC();   // get over current value
        try
        {   serial_pow2.Write(sendbyte, 0, sendbyte.Length);
            SMPS2_timer.Enabled = true;
            textBox2.Text = "";
        }
        catch
        {   MessageBox.Show(serial_pow2.PortName + " port error");  }
    }

    private void ser_AVDD_DataRx(object sender, SerialDataReceivedEventArgs e)
    {
        //if (SMPS2_Tick == false)
        //    return;
        //SMPS2_Tick = true;

        byte[] readb = new byte[9];
        int s = serial_pow2.Read(readb, 0, 9);

        Action Receive = () =>
        {                    
            if (power2.getOutCur == true)
            {
                decimal volt, cur;
                power2.processOCP(readb, out volt, out cur);    // process over current raw data
                power2.getOutCur = false;
                if (volt != 99.99m && cur != 99.99m)
                    textBox2.Text = volt + " V,  " + cur + " A." + ";      " + readb[0].ToString("X2") + " " + readb[1].ToString("X2") + " " + readb[2].ToString("X2") + " " + readb[3].ToString("X2") + " " + readb[4].ToString("X2") + " " + readb[5].ToString("X2") + " " + readb[6].ToString("X2") + " " + readb[7].ToString("X2") + " " + readb[8].ToString("X2");
            }
        };
        this.Invoke(new Action(Receive));
        serial_pow2.DiscardInBuffer();
    }

    private void SMPS2_timer_Tick(object sender, EventArgs e)
    {
        SMPS2_timer.Enabled = false;
        SMPS2_Tick = true;
    }

类Power2函数。

代码语言:javascript
复制
   public byte[] PowerSupply_GetOVC()
    {
        UInt16 CRC_high = 0;
        UInt16 CRC_low = 0;
        int i = 0;

        getOutCur = true;
        int[] supplySet = { 0x01, 0x03, 0x00, 0x02, 0x00, 0x02 };       // get output volt, current
        byte[] sendbyte = new byte[supplySet.Length + 2];
        Modbus_CRC_Check(supplySet, out CRC_high, out CRC_low);
        for (i = 0; i < supplySet.Length; i++)
            sendbyte[i] = Convert.ToByte(supplySet[i]);
        sendbyte[i++] = Convert.ToByte(CRC_low);
        sendbyte[i++] = Convert.ToByte(CRC_high);
        return sendbyte;
    }

    public void processOCP(byte[] readb, out decimal volt, out decimal cur)
    {
        try
        {
            int t = readb[3];
            t <<= 8;
            int y = readb[4];
            int vol = (t + y);
            volt = (decimal)vol / 100;

            t = readb[5];
            t <<= 8;
            y = readb[6];
            int curr = (t + y);
            cur = (decimal)curr / 100;
        }
        catch
        {
            volt = 99.99m;
            cur = 99.99m;
        }
    }

    void Modbus_CRC_Check(int[] data_array, out UInt16 CRC_high, out UInt16 CRC_low)
    {
        UInt16 crc = 65535;

        for (int i = 0; i < data_array.Length; i++)
        {
            crc ^= (ushort)data_array[i];
            for (int j = 0; j < 8; j++)
            {
                if ((crc & 1) != 0)
                {
                    crc >>= 1;
                    crc ^= 0xA001;
                }
                else
                {
                    crc >>= 1;
                }
            }
        }            
        CRC_low = (ushort)(crc & 0x00FF);
        CRC_high = (ushort)(crc >> 8);
    }

当使用终端时,输入和输出数据如下:

代码语言:javascript
复制
input command:      01 03 00 02 00 02 65 CB
output data :       01 03 04 00 62 00 00 5B ED

当值不正确时使用C#:

代码语言:javascript
复制
input command:   01 03 00 02 00 02 65 CB
output data1:    01 03 04 00 62 00 00 5B ED
output data2:    01 03 04 00 00 00 00 00 00
output data3:    01 00 00 00 00 00 00 00 00

我尝试设置ReadTimeout值,并在串行接收事件的开头使用计时器检查,但是结果是一样的。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-05-15 03:30:04

我想我解决了。我一直怀疑程序正在接收碎片的数据。如果数据长度不是9,我将数据存储在临时缓冲区中。在下一次读取中,将最新的数据连接到串行口事件处理中的临时缓冲区。现在我得到了正确的数据。

我就是这样做的。

代码语言:javascript
复制
    private void ovcRead_Click(object sender, EventArgs e)
    {
        byte[] sendbyte = power1.PowerSupply_GetOVC();            
        try
        {   serial_pow1.Write(sendbyte, 0, sendbyte.Length);    }
        catch
        {   MessageBox.Show(serial_pow1.PortName + " port error");  }

        sendbyte = power2.PowerSupply_GetOVC();
        try
        {   serial_pow2.Write(sendbyte, 0, sendbyte.Length);
            query = true;
            textBox2.Text = "";
        }
        catch
        {   MessageBox.Show(serial_pow2.PortName + " port error");  }
    }

    byte[] readb = new byte[100];
    int cnt = 0;
    int prevlen = 0;
    int newlen = 0;

    private void ser_AVDD_DataRx(object sender, SerialDataReceivedEventArgs e)
    {          

        int bytes = serial_pow2.BytesToRead;
        byte[] readc = new byte[bytes];
        serial_pow2.Read(readc, 0, bytes);
        if (bytes < 9)
        {
            if (query == true)
            {
                readc.CopyTo(readb, 0);
                prevlen = readc.Length;
                query = false;
            }
            else
            {
                try
                {
                    readc.CopyTo(readb, prevlen);
                    newlen = prevlen + readc.Length;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(readc.Length + "/n" + ex.Message);
                }
            }
        }
        else
        {
            readc.CopyTo(readb, 0);
        }
        Action Receive = () =>
        {
            if (readc.Length == 9)
            {
                prevlen = 0;
                cnt = 0;
                decimal volt, cur;
                power2.processOCP(readc, out volt, out cur);
                power2.getOutCur = false;
                textBox2.Text = volt + " V,  " + cur + " A." + ";      " + readb[0].ToString("X2") + " " + readb[1].ToString("X2") + " " + readb[2].ToString("X2") + " " + readb[3].ToString("X2") + " " + readb[4].ToString("X2") + " " + readb[5].ToString("X2") + " " + readb[6].ToString("X2") + " " + readb[7].ToString("X2") + " " + readb[8].ToString("X2");
                //if (volt != 99.99m && cur != 99.99m)                        
            }
            else
            {
                textBox2.Text = "";
                byte[] temp = new byte[newlen];

                for (int b = 0; b < newlen; b++)
                {
                    textBox2.Text += readb[b].ToString("X2") + " ";
                }
            }
        };
        this.Invoke(new Action(Receive));            
    }
票数 0
EN

Stack Overflow用户

发布于 2020-05-14 08:55:04

这个问题可能是由serial_pow2.DiscardInBuffer()引起的。

除非您知道缓冲区中不需要数据,否则不要丢弃它。

如果您发出两个请求而只读取一个响应,serial_pow2.DiscardInBuffer()将在缓冲区中丢弃第二个响应。

由于您的代码片段是由按钮初始化的,我无法保证您如何提出请求并获得响应。

我的建议是不使用DiscardInBuffer,除非您正在初始化或关闭应用程序,否则可能会丢失数据。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61733323

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档