不从串口读取数据 [英] not reading data from serial port

查看:92
本文介绍了不从串口读取数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
using System.Timers;



namespace serialcomm
    
{ 
    public partial class Form1 : Form
    {
        SerialPort ComPort = new SerialPort();
        private Queue<byte> recievedData = new Queue<byte>();
        
        
        public Form1()
        { 
            InitializeComponent();
        }

        private void ports_Click(object sender, EventArgs e)
        { 
             
            
    string[] ArrayComPortsNames = null;
    int index = -1;
    string ComPortName = null;

    ArrayComPortsNames = SerialPort.GetPortNames();
    do
    {
        index += 1;
        comboBox1.Items.Add(ArrayComPortsNames[index]);
    }

    while (!((ArrayComPortsNames[index] == ComPortName)
                  || (index == ArrayComPortsNames.GetUpperBound(0))));
    Array.Sort(ArrayComPortsNames);

    //want to get first out
    if (index == ArrayComPortsNames.GetUpperBound(0))
    {
        ComPortName = ArrayComPortsNames[0];
    }
    comboBox1.Text = ArrayComPortsNames[0];
            // baud rate values

    cboBaudRate.Items.Add(300);
    cboBaudRate.Items.Add(600);
    cboBaudRate.Items.Add(1200);
    cboBaudRate.Items.Add(2400);
    cboBaudRate.Items.Add(9600);
    cboBaudRate.Items.Add(14400);
    cboBaudRate.Items.Add(19200);
    cboBaudRate.Items.Add(38400);
    cboBaudRate.Items.Add(57600);
    cboBaudRate.Items.Add(115200);
    cboBaudRate.Items.ToString();
    //get first item print in text
    cboBaudRate.Text = cboBaudRate.Items[0].ToString();
            // handshaking bits
    cboHandShaking.Items.Add("None");
    cboHandShaking.Items.Add("XOnXOff");
    cboHandShaking.Items.Add("RequestToSend");
    cboHandShaking.Items.Add("RequestToSendXOnXOff");
    cboHandShaking.Items.ToString();
    cboHandShaking.Text=cboHandShaking.Items[0].ToString();
            
           // data bits
            cboDataBits.Items.Add("7"); 
            cboDataBits.Items.Add("8");
            cboDataBits.Items.ToString();
            cboDataBits.Text = cboDataBits.Items[0].ToString();
            // stop bits
            cboStopBits.Items.Add("One");
            cboStopBits.Items.Add("OnePointFive");
            cboStopBits.Items.Add("Two");
            //get the first item print in the text
            cboStopBits.Text = cboStopBits.Items[0].ToString();

            //Parity 
            cboParity.Items.Add("None");
            cboParity.Items.Add("Even");
            cboParity.Items.Add("Mark");
            cboParity.Items.Add("Odd");
            cboParity.Items.Add("Space");
            cboParity.Text = cboParity.Items[0].ToString();
               
        }

       
        
        private void button1_Click(object sender, EventArgs e)
        { 
           

    if (button1.Text == "Closed")
    {
        button1.Text = "Open";
        ComPort.PortName = Convert.ToString(comboBox1.Text);
        ComPort.BaudRate = Convert.ToInt32(cboBaudRate.Text);
        ComPort.DataBits = Convert.ToInt32(cboDataBits.Text);
        ComPort.StopBits = (StopBits)Enum.Parse(typeof(StopBits), cboStopBits.Text);
        ComPort.Handshake = (Handshake)Enum.Parse(typeof(Handshake), cboHandShaking.Text);
        ComPort.Parity = (Parity)Enum.Parse(typeof(Parity), cboParity.Text);
        
        ComPort.Open();
        button1.BackColor = Color.Green;
    }
    else if (button1.Text == "Open")
    {
        button1.Text= "Closed";
        ComPort.Close();
        button1.BackColor = Color.Red;
    }
        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {

        }



        public class CommTimer
        {
            public System.Timers.Timer tmrComm = new System.Timers.Timer();
            public bool timedout = false;
            public  CommTimer()
            {
                timedout = false;
                tmrComm.AutoReset = false;
                tmrComm.Enabled = false;
                tmrComm.Interval = 1000; //default to 1 second
                tmrComm.Elapsed += new ElapsedEventHandler(OnTimedCommEvent);
            }

            public void OnTimedCommEvent(object source, ElapsedEventArgs e)
            {
                timedout = true;
                tmrComm.Stop();
            }

            public void Start(double timeoutperiod)
            {
                tmrComm.Interval = timeoutperiod;             //time to time out in milliseconds
                tmrComm.Stop();
                timedout = false;
                tmrComm.Start();
            }


        }



      

        private void button2_Click(object sender, EventArgs e)
        {
            string str = textBox1.Text;
            byte[] raw = new byte[textBox1.TextLength/2];
            for (int i = 0; i < raw.Length; i++)
            {
                raw[i] = Convert.ToByte(str.Substring(i * 2, 2), 16);



            }
           ComPort.Write(raw,0,raw.Length);
           ComPort.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);

           
        }

        private void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
             CommTimer tmrComm = new CommTimer();
            tmrComm.Start(4000);
             while ((ComPort.BytesToRead == 0) && (tmrComm.timedout == false))
            {
                Application.DoEvents();
            }

             int dataLength = ComPort.BytesToRead;
             byte[] data = new byte[dataLength / 2];
             string str = ComPort.ReadExisting();

             for (int i = 0; i < dataLength; i++)
             {
                 data[i] = Convert.ToByte(str.Substring(i * 2, 2), 16);
                 if (dataLength > 0)
                 {
                     textBox2.Text = Convert.ToString(data);
                 }

                tmrComm.tmrComm.Dispose();
                ComPort.DiscardInBuffer();
                ComPort.DiscardOutBuffer();
                ComPort.Close();

            }
        }
                        

        private void textBox2_TextChanged(object sender, EventArgs e)
        {

        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }
                                  
  }

}

推荐答案

我们无能为力 - 我们无法访问您的系统或您的代码尝试与之通信的硬件。



这可能不是你的工作代码,因为缩进遍布整个地方,通常只有当你有编译错误并且Visual Studio无法解决你想要编写的内容时才会发生这种情况。如果是,尝试按CTRL + K CTRL + D重新格式化整个文档并更正缩进(它使代码更具可读性)。



所以它是取决于你:使用调试器跟随代码并找出现在和未发生的事情。



但是你不能做的事情之一是DataRecieved事件中的文本框等访问控件 - 它始终位于不同的线程上,因此如果访问UI元素,它将始终导致交叉线程问题。你必须调用它们。
There isn't really anything we can do - we don't have any access to your system or the hardware your code is trying to communicate with.

And that probably isn't your "working" code because the indentation is all over the place, which normally only happens when you have compilation errors and Visual Studio can't work out what you are trying to write. If it is, try pressing CTRL+K CTRL+D to reformat the whole document and correct the indentation (it makes the code a lot more readable).

So it's up to you: use the debugger to "follow" the code and work out what is and isn't happening.

But one of the things you can't do is access controls such as text boxes in the DataRecieved event - it is always on a different thread, so it will always cause cross thread problems if you access UI elements. You have got to Invoke them.


在计时器事件中读取内容的整个想法都很糟糕。更确切地说,它不起作用。不是在任何时刻读取端口,而是从RS-232电缆的另一端写入数据。当您尝试读取数据,并且数据未放入缓冲区时,它没问题。此调用的行为类似于阻塞调用,因此您的读取线程将进入等待状态,直到它被唤醒,通过获取缓冲区中的数据或其他原因(超时) ,线程堕胎/终止)。



因此,请执行以下操作:将所有串行通信放在一个单独的线程中,以及负责通信的所有逻辑。要在UI上通知事件,请使用我在过去的答案中解释的UI线程调用机制.w窗口> ^]。



这个想法是:您不能从非UI线程调用与UI相关的任何内容。相反,您需要使用方法调用 BeginInvoke System.Windows.Threading.Dispatcher (对于Forms或WPF)或 System.Windows.Forms.Control (仅限表格)。



您将在我过去的答案中找到有关工作原理和代码示例的详细说明:

Control.Invoke()与Control.BeginInvoke() [ ^ ],

Treeview扫描仪出现问题和MD5 [ ^ ]。



另请参阅有关线程的更多参考资料:

如何让vydown事件在vb.net中的不同线程上运行 [ ^ ],

[ ^ ]。



< dd> -SA
The whole idea to read something in the timer event is bad. More exactly, it's not working. The ports is read not by any moments of time, but then data is written from the other end of your RS-232 cable. When you try to read data, and the data is not put in the buffer, it's fine. This call behaves like a blocking call, so your reading threads gets to the wait state, until it get awaken, by getting data in a buffer, or some other reason (timeout, thread abortion/termination).

Therefore, do this: put all your serial communication in a separate thread, along with all the logic responsible for the communication. For notification of the event on the UI, use the UI thread invocation mechanism explained in my past answers referenced below.w Window">^].

The idea is: you cannot call anything related to UI from non-UI thread. Instead, you need to use the method Invoke or BeginInvoke of System.Windows.Threading.Dispatcher (for both Forms or WPF) or System.Windows.Forms.Control (Forms only).

You will find detailed explanation of how it works and code samples in my past answers:
Control.Invoke() vs. Control.BeginInvoke()[^],
Problem with Treeview Scanner And MD5[^].

See also more references on threading:
How to get a keydown event to operate on a different thread in vb.net[^],
Control events not firing after enable disable + multithreading[^].

—SA


嗯,你回答了我的问题关于你做了什么来诊断这个 - 程序在哪里停止或挂起或任何东西?老实说,我把你的大部分代码都还给了



设置串口

发送(无论命令设备需要什么)

读取结果



并跳过超时的东西,直到你知道你可以以任何方式与设备通信 - 更好的是,找到一个通用的串口程序,也许像hyperterm等,当你可以用它来与设备通信时,你可以开始复制程序中的设置,命令等,并建立功能 - 否则你甚至不知道你是否有硬件问题例如
well, you havnt answered my question about what have you've done to diagnose this - where does the program stop or hang or anything ? honestly, I'd pare most of your code back to

setup serial port
send (whatever command device needs)
read result

and skip the timeout stuff, until you know you can talk to the device in any fashion - even better, find a generalised serial port program, maybe like hyperterm or such, and when you can use that to talk to the device, then you can start replicating the settings, commands etc in your program, and building up functionality - else you don't even know if you have hardware issues for example


这篇关于不从串口读取数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆