Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/url/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#winform解析串行端口数据_C#_.net_Winforms_Serial Port - Fatal编程技术网

C#winform解析串行端口数据

C#winform解析串行端口数据,c#,.net,winforms,serial-port,C#,.net,Winforms,Serial Port,我是一个新手,带着复制粘贴,试图从一个旧的Avery Weightronix 7820体重秤上获取数据。我把它通过RJ-232电缆连接起来,并设法从秤上得到响应。我按照本教程开始运行 一旦我让它工作,我想简化它,并基本上使用我的电脑作为一个远程显示器。我硬编码了串行连接参数,并将代码设置为每秒发送重量请求,以便在winform中显示它 后来我计划扩展它,这样我就可以得到多个项目的总重量。我计划称一件物品的重量,将重量复制到总重量,将一件新物品放在秤上,然后重复 我现在陷入了困境,因为我无法一致地

我是一个新手,带着复制粘贴,试图从一个旧的Avery Weightronix 7820体重秤上获取数据。我把它通过RJ-232电缆连接起来,并设法从秤上得到响应。我按照本教程开始运行

一旦我让它工作,我想简化它,并基本上使用我的电脑作为一个远程显示器。我硬编码了串行连接参数,并将代码设置为每秒发送重量请求,以便在winform中显示它

后来我计划扩展它,这样我就可以得到多个项目的总重量。我计划称一件物品的重量,将重量复制到总重量,将一件新物品放在秤上,然后重复

我现在陷入了困境,因为我无法一致地解析从scale返回的数据,并且因为循环锁定了UI

当我发送W
这是当前重量的请求时,一个示例响应是:

0001.10lb
00

其中
=文本结束字符(Ø3十六进制),
=换行字符(ØA十六进制),
=回车字符(ØD十六进制)

来自标尺的响应是固定长度的,但是当我进入调试模式时,在代码的前两个周期中没有收到响应。然后它会晚一点到达。当我将其输出到富文本字段时,这是可以的,但当我尝试拉出子字符串时,如果没有数据,则会出现错误

此外,UI锁定,我唯一能做的就是停止执行。从周围的阅读来看,我似乎应该实现线程,但我不确定如何重新组织代码来实现这一点

如果您能就如何解决这些问题提供任何建议,我将不胜感激

这是我的代码:

using System;
using System.Drawing;
using System.Windows.Forms;
using System.IO.Ports;

namespace ScaleView
{
  public partial class Form1 : Form
  {
    public Form1()
    {
        InitializeComponent();
    }

    private void groupBox1_Enter(object sender, EventArgs e)
    {

    }


    private void Form1_Load(object sender, EventArgs e)
    {
        //updatePorts();           //Call this function everytime the page load 
                                 //to update port names
        CheckForIllegalCrossThreadCalls = false;
    }
    

    private SerialPort ComPort = new SerialPort();  //Initialise ComPort Variable as SerialPort
    private void connect()
    {
        bool error = false;

            
        ComPort.PortName = "COM3";
        ComPort.BaudRate = int.Parse("9600");      //convert Text to Integer
        ComPort.Parity = (Parity)Enum.Parse(typeof(Parity), "Even"); //convert Text to Parity
            ComPort.DataBits = int.Parse("7");        //convert Text to Integer
            ComPort.StopBits = (StopBits)Enum.Parse(typeof(StopBits), "1");  //convert Text to stop bits

            try  //always try to use this try and catch method to open your port. 
                 //if there is an error your program will not display a message instead of freezing.
            {
                //Open Port
                ComPort.Open();
                ComPort.DataReceived += SerialPortDataReceived;  //Check for received data. When there is data in the receive buffer,
                                                                 //it will raise this event, we need to subscribe to it to know when there is data
                                                                 //MessageBox.Show(this, "Connected", MessageBoxButtons.OK);
            }
            catch (UnauthorizedAccessException) { error = true; }
            catch (System.IO.IOException) { error = true; }
            catch (ArgumentException) { error = true; }

            if (error) MessageBox.Show(this, "Could not open the COM port. Most likely it is already in use, has been removed, or is unavailable.", "COM Port unavailable", MessageBoxButtons.OK, MessageBoxIcon.Stop);

        
       
        //if the port is open, Change the Connect button to disconnect, enable the send button.
        //and disable the groupBox to prevent changing configuration of an open port.
        if (ComPort.IsOpen)
        {
            btnConnect.Text = "Disconnect";
        }
    }
    // Call this function to close the port.
    private void disconnect()
    {
        ComPort.Close();
        btnConnect.Text = "Connect";
        
    }
    //whenever the connect button is clicked, it will check if the port is already open, call the disconnect function.
    // if the port is closed, call the connect function.
    private void btnConnect_Click_1(object sender, EventArgs e)

    {
        if (ComPort.IsOpen)
        {
            disconnect();
        }
        else
        {
            connect();
            rtxtDataArea.AppendText("Connected\n");
            sendData();
        }
    }

    private void btnClear_Click(object sender, EventArgs e)
    {
        //Clear the screen
        rtxtDataArea.Clear();
    }
    // Function to send data to the serial port
    private void sendData()
    {
        bool error = false;
        while(ComPort.IsOpen)        //if text mode is selected, send data as tex
        {
            
            try
            {
                // Convert string of hex digits (in this case representing W<CR>) to a byte array
                string hextext = "57 0D";
                byte[] data = HexStringToByteArray(hextext);

                // Send the binary data out the port
                ComPort.Write(data, 0, data.Length);
                System.Threading.Thread.Sleep(3000);

                rtxtDataArea.ForeColor = Color.Blue;   //write Hex data in Blue
                string response = ComPort.ReadLine();
                int charfrom = 1;
                int charto = 9;
                //string weight = response.Substring(charfrom, charto - charfrom);
                rtxtDataArea.AppendText(response + "TEST\n");
                
            }
            catch (FormatException) { error = true; }

            // Inform the user if the hex string was not properly formatted
            catch (ArgumentException) { error = true; }

            if (error) MessageBox.Show(this, "Not properly formatted hex string: \n" + "example: E1 FF 1B", "Format Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);

        }
    }
    //Convert a string of hex digits (example: E1 FF 1B) to a byte array. 
    //The string containing the hex digits (with or without spaces)
    //Returns an array of bytes. </returns>
    private byte[] HexStringToByteArray(string s)
    {
        s = s.Replace(" ", "");
        byte[] buffer = new byte[s.Length / 2];
        for (int i = 0; i < s.Length; i += 2)
            buffer[i / 2] = (byte)Convert.ToByte(s.Substring(i, 2), 16);
        return buffer;
    }

    private void btnSend_Click(object sender, EventArgs e)
    {
        sendData();
    }
    //This event will be raised when the form is closing.
    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        if (ComPort.IsOpen) ComPort.Close();  //close the port if open when exiting the application.
    }
    //Data recived from the serial port is coming from another thread context than the UI thread.
    //Instead of reading the content directly in the SerialPortDataReceived, we need to use a delegate.
    delegate void SetTextCallback(string text);
    private void SetText(string text)
    {
        //invokeRequired required compares the thread ID of the calling thread to the thread of the creating thread.
        // if these threads are different, it returns true
        if (this.rtxtDataArea.InvokeRequired)
        {
            rtxtDataArea.ForeColor = Color.Green;    //write text data in Green colour

            SetTextCallback d = new SetTextCallback(SetText);
            this.Invoke(d, new object[] { text });
        }
        else
        {
            this.rtxtDataArea.AppendText(text);
        }
    }
    private void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        var serialPort = (SerialPort)sender;
        var data = serialPort.ReadExisting();
        SetText(data);
    }

    private void rtxtDataArea_TextChanged(object sender, EventArgs e)
    {

    }
}
}
使用系统;
使用系统图;
使用System.Windows.Forms;
使用System.IO.Ports;
命名空间ScaleView
{
公共部分类Form1:Form
{
公共表格1()
{
初始化组件();
}
私有void groupBox1_Enter(对象发送方,事件参数e)
{
}
私有void Form1\u加载(对象发送方、事件参数e)
{
//updateport();//每次加载页面时调用此函数
//更新端口名的步骤
CheckForIllegalCrossThreadCalls=false;
}
private SerialPort ComPort=new SerialPort();//将ComPort变量初始化为SerialPort
专用void connect()
{
布尔误差=假;
ComPort.PortName=“COM3”;
ComPort.BaudRate=int.Parse(“9600”);//将文本转换为整数
ComPort.Parity=(奇偶校验)Enum.Parse(typeof(奇偶校验),“偶数”);//将文本转换为奇偶校验
ComPort.DataBits=int.Parse(“7”);//将文本转换为整数
ComPort.StopBits=(StopBits)Enum.Parse(typeof(StopBits),“1”);//将文本转换为停止位
try//始终尝试使用此try-and-catch方法打开端口。
//如果出现错误,您的程序将不会显示消息而不是冻结。
{
//开放端口
ComPort.Open();
ComPort.DataReceived+=SerialPortDataReceived;//检查接收的数据。当接收缓冲区中有数据时,
//它将引发此事件,我们需要订阅它才能知道何时有数据
//MessageBox.Show(这个“已连接”,MessageBoxButtons.OK);
}
catch(UnauthorizedAccessException){error=true;}
catch(System.IO.IOException){error=true;}
catch(ArgumentException){error=true;}
if(error)MessageBox.Show(这是“无法打开COM端口。很可能它已被使用、已被删除或不可用。”,“COM端口不可用”,MessageBoxButtons.OK,MessageBoxIcon.Stop);
//如果端口打开,请将“连接”按钮更改为“断开”,然后启用“发送”按钮。
//并禁用groupBox以防止更改打开端口的配置。
if(组成等参线)
{
btnConnect.Text=“断开”;
}
}
//调用此函数以关闭端口。
私有无效断开连接()
{
ComPort.Close();
btnConnect.Text=“Connect”;
}
//无论何时单击connect按钮,它都会检查端口是否已打开,调用disconnect功能。
//如果端口已关闭,请调用connect函数。
私有void btnConnect_Click_1(对象发送方,事件参数e)
{
if(组成等参线)
{
断开连接();
}
其他的
{
connect();
rtxtDataArea.AppendText(“已连接\n”);
sendData();
}
}
私有void btnClear\u单击(对象发送者,事件参数e)
{
//清除屏幕
rtxtDataArea.Clear();
}
//函数将数据发送到串行端口
私有void sendData()
{
布尔误差=假;
while(ComPort.IsOpen)//如果选择了文本模式,则以文本形式发送数据
{
尝试
{
//将十六进制数字字符串(在本例中表示W)转换为字节数组
字符串hextext=“57 0D”;
字节[]数据=HexStringToByteArray(hextext);
//将二进制数据发送到端口
ComPort.Write(数据,0,数据长度);
系统线程线程睡眠(3000);
rtxtDataArea.ForeColor=Color.Blue;//用蓝色写入十六进制数据
字符串响应=ComPort.ReadLine();
int charfrom=1;
int charto=9;
//字符串重量=响应.子字符串(charfrom,charto-charfrom);
rtxtDataArea.AppendText(响应+测试\n);
Thread dataThread = null;
private void btnConnect_Click_1(object sender, EventArgs e) {
    if (ComPort.IsOpen) {
        disconnect();
    }
    else {
        btnConnect.Enabled = false; // user has to wait for connection to succeed or fail. Prevents clicking the button twice.
        Form form = this;

        dataThread = new Thread(() => {
            try {
                connect();

                // if you get here then connect succeeded
                form.BeginInvoke((Action) delegate {
                    btnConnect.Enabled = true; // now becomes the Disconnect button
                    rtxtDataArea.AppendText("Connected\n");
                });

                // start sending and receiving data on the thread
                sendData();
            } catch (Exception ex) {
                form.BeginInvoke((Action) delegate {
                    btnConnect.Enabled = true; // remains as the Connect button, user can try again
                    MessageBox.Show(form, ex.GetType().Name + ": " + ex.Message, "COM Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                });
            }
        });
        dataThread.IsBackground = true;
        dataThread.Start();
    }
}

delegate void SetTextCallback(string text);
private SetTextCallback callSetText = new SetTextCallback(SetText); // don't create new delegates each time
    private void SetText(string text) {
    if (this.rtxtDataArea.InvokeRequired) {
        rtxtDataArea.ForeColor = Color.Green;    //write text data in Green colour
        this.BeginInvoke(d, new object[] { text }); // use BeginInvoke instead
    }
    else {
        this.rtxtDataArea.AppendText(text);
    }
}