c#串口通信,串口能连接能发送,但是不能接收数据

问题遇到的现象和发生背景

经过测试DataReceived没有触发,接线没有问题,用串口助手可以接收到数显器发送的数据。找不到代码有什么问题,希望能帮我找到问题,能够接收数据。

用代码块功能插入代码,请勿粘贴截图

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp3
{

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

    private void Form1_Load(object sender, EventArgs e)
    {
       
        //批量添加波特率列表
        string[] baud = { "9600", "56000", "57600", "115200", "128000", "230400", "256000", "460800" };
        comboBox2.Items.AddRange(baud);

        //设置默认值
        //comboBox1.Text = "COM1";
        comboBox2.Text = "9600";
        comboBox3.Text = "8";
        comboBox4.Text = "None";
        comboBox5.Text = "1";
        //获取电脑当前可用串口并添加到选项列表中
        comboBox1.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames());
        serialPort1.NewLine = "/r/n";
        serialPort1.RtsEnable = true;
        serialPort1.ReceivedBytesThreshold = 1;
        serialPort1.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(this.SerialPort1_DataReceived);
    }


   
    private void button1_Click(object sender, EventArgs e)
    {
        try
        {
            //将可能产生异常的代码放置在try块中
            //根据当前串口属性来判断是否打开
            if (serialPort1.IsOpen)
            {
                //串口已经处于打开状态
                serialPort1.Close();    //关闭串口
                button1.Text = "打开串口";
                button1.BackColor = Color.ForestGreen;
                comboBox1.Enabled = true;
                comboBox2.Enabled = true;
                comboBox3.Enabled = true;
                comboBox4.Enabled = true;
                comboBox5.Enabled = true;
                textBox_receive.Text = "";  //清空接收区
                textBox_send.Text = "";     //清空发送区
            }
            else
            {
                //串口已经处于关闭状态,则设置好串口属性后打开
                comboBox1.Enabled = false;
                comboBox2.Enabled = false;
                comboBox3.Enabled = false;
                comboBox4.Enabled = false;
                comboBox5.Enabled = false;
                serialPort1.PortName = comboBox1.Text;
                serialPort1.BaudRate = Convert.ToInt32(comboBox2.Text);
                serialPort1.DataBits = Convert.ToInt16(comboBox3.Text);

                if (comboBox4.Text.Equals("None"))
                    serialPort1.Parity = System.IO.Ports.Parity.None;
                else if (comboBox4.Text.Equals("Odd"))
                    serialPort1.Parity = System.IO.Ports.Parity.Odd;
                else if (comboBox4.Text.Equals("Even"))
                    serialPort1.Parity = System.IO.Ports.Parity.Even;
                else if (comboBox4.Text.Equals("Mark"))
                    serialPort1.Parity = System.IO.Ports.Parity.Mark;
                else if (comboBox4.Text.Equals("Space"))
                    serialPort1.Parity = System.IO.Ports.Parity.Space;

                if (comboBox5.Text.Equals("1"))
                    serialPort1.StopBits = System.IO.Ports.StopBits.One;
                else if (comboBox5.Text.Equals("1.5"))
                    serialPort1.StopBits = System.IO.Ports.StopBits.OnePointFive;
                else if (comboBox5.Text.Equals("2"))
                    serialPort1.StopBits = System.IO.Ports.StopBits.Two;

                serialPort1.Open();     //打开串口
                button1.Text = "关闭串口";
                button1.BackColor = Color.Firebrick;
                
                
            }
        }
        catch (Exception ex)
        {
            //捕获可能发生的异常并进行处理

            //捕获到异常,创建一个新的对象,之前的不可以再用
            serialPort1 = new System.IO.Ports.SerialPort();
            //刷新COM口选项
            comboBox1.Items.Clear();
            comboBox1.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames());
            //响铃并显示异常给用户
            System.Media.SystemSounds.Beep.Play();
            button1.Text = "打开串口";
            button1.BackColor = Color.ForestGreen;
            MessageBox.Show(ex.Message);
            comboBox1.Enabled = true;
            comboBox2.Enabled = true;
            comboBox3.Enabled = true;
            comboBox4.Enabled = true;
            comboBox5.Enabled = true;
        }
        

    }

    private void button2_Click(object sender, EventArgs e)
    {
        try
        {
            //首先判断串口是否开启
            if (serialPort1.IsOpen)
            {
                //串口处于开启状态,将发送区文本发送
                serialPort1.Write(textBox_send.Text);
            }
        }
        catch (Exception ex)
        {
            //捕获到异常,创建一个新的对象,之前的不可以再用
            serialPort1 = new System.IO.Ports.SerialPort();
            //刷新COM口选项
            comboBox1.Items.Clear();
            comboBox1.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames());
            //响铃并显示异常给用户
            System.Media.SystemSounds.Beep.Play();
            button1.Text = "打开串口";
            button1.BackColor = Color.ForestGreen;
            MessageBox.Show(ex.Message);
            comboBox1.Enabled = true;
            comboBox2.Enabled = true;
            comboBox3.Enabled = true;
            comboBox4.Enabled = true;
            comboBox5.Enabled = true;
        }

    }

    private void SerialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
    {
       
       
        try
        {
            //因为要访问UI资源,所以需要使用invoke方式同步ui
            this.Invoke((EventHandler)(delegate
            {
                textBox_receive.AppendText(serialPort1.ReadExisting());
            }
               )
            );

        }
        catch (Exception ex)
        {
            //响铃并显示异常给用户
            System.Media.SystemSounds.Beep.Play();
            MessageBox.Show(ex.Message);

        }
        

    }

    
}

}

运行结果及报错内容

可以发送数据至数显表,但是不能接收,无报错

我的解答思路和尝试过的方法

尝试过不使用DataReceived,用timer加readline(),但是还是没有显示数据

我想要达到的结果

希望能帮我找到问题,能够接收数据。

1.你应该在对方接一个电脑,用串口调试助手,看你这边发送的对方接到是什么,对方发送的你接到又是什么
2.发送至数显表,是有显示了吗,显示的什么
3.你确定数显表接收到数据之后会有数据反馈吗,如果对方根本没有任何数据发给你,你当然接收不到

1.拿掉所有try,早崩溃早处理。到处try还是一样
2.拿掉所有啥invoke,处理逻辑就处理逻辑。逻辑没问题了你再做别的,想验证数据是否到达,直接写Trace.Writeline 输出的IDE里
3.拿掉
serialPort1.NewLine = "/r/n";
serialPort1.RtsEnable = true;
在试试,默认情况先看看,在处理特殊情况

4.订阅Error事件,串口也有error的,尤其是你用了RtsEnable这类的握手信号检查的,无法握手了Error事件就来了。RtsEnable你要求检查信号的,信号不符合要求了他当然的用error告诉你出错了

1、首先用串口助手之类的工具,确保PDA的串口是通畅的。
2、再用串口助手测试你的程序可以正确的发送数据。
3、程序与PDA互发数据。看是否通畅。

  • 给你找了一篇非常好的博客,你可以看看是否有帮助,链接:C#实现串口通信

拿掉所有try

首先try catch 是用来捕获异常的,你的代码写的不规范。要进行断点调试,看下打开串口后能否取到数据 。其中波特率、数据位等信息要和串口调试工具保持一致。
一般一个串口只能打开一次。你要用代码调试的时候,要关闭串口调试工具

你用我的代码试试

using System;

using System.Collections.Generic;

using System.Text;

using System.IO.Ports;

using System.Globalization;

namespace SerialClass

{

    public class SerialClass

    {

        SerialPort _serialPort = null;

        //定义委托

        public delegate void SerialPortDataReceiveEventArgs(object sender, SerialDataReceivedEventArgs e, byte[] bits);

        //定义接收数据事件

        public event SerialPortDataReceiveEventArgs DataReceived;

        //定义接收错误事件

        //public event SerialErrorReceivedEventHandler Error;

        //接收事件是否有效 false表示有效

        public bool ReceiveEventFlag = false;

        #region 获取串口名

        private string protName;

        public string PortName

        {

            get { return _serialPort.PortName; }

            set

            {

                _serialPort.PortName = value;

                protName = value;

            }

        }

        #endregion

        #region 获取比特率

        private int baudRate;

        public int BaudRate

        {

            get { return _serialPort.BaudRate; }

            set

            {

                _serialPort.BaudRate = value;

                baudRate = value;

            }

        }

        #endregion

        #region 默认构造函数

        /// <summary>

        /// 默认构造函数,操作COM1,速度为9600,没有奇偶校验,8位字节,停止位为1 "COM1", 9600, Parity.None, 8, StopBits.One

        /// </summary>

        public SerialClass()

        {

            _serialPort = new SerialPort();

        }

        #endregion

        #region 构造函数

        /// <summary>

        /// 构造函数,

        /// </summary>

        /// <param name="comPortName"></param>

        public SerialClass(string comPortName)

        {

            _serialPort = new SerialPort(comPortName);

            _serialPort.BaudRate = 9600;

            _serialPort.Parity = Parity.Even;

            _serialPort.DataBits = 8;

            _serialPort.StopBits = StopBits.One;

            _serialPort.Handshake = Handshake.None;

            _serialPort.RtsEnable = true;

            _serialPort.ReadTimeout = 2000;

            setSerialPort();

        }

        #endregion

        #region 构造函数,可以自定义串口的初始化参数

        /// <summary>

        /// 构造函数,可以自定义串口的初始化参数

        /// </summary>

        /// <param name="comPortName">需要操作的COM口名称</param>

        /// <param name="baudRate">COM的速度</param>

        /// <param name="parity">奇偶校验位</param>

        /// <param name="dataBits">数据长度</param>

        /// <param name="stopBits">停止位</param>

        public SerialClass(string comPortName, int baudRate, Parity parity, int dataBits, StopBits stopBits)

        {

            _serialPort = new SerialPort(comPortName, baudRate, parity, dataBits, stopBits);

            _serialPort.RtsEnable = true;  //自动请求

            _serialPort.ReadTimeout = 3000;//超时

            setSerialPort();

        }

        #endregion

        #region 析构函数

        /// <summary>

        /// 析构函数,关闭串口

        /// </summary>

        ~SerialClass()

       {

           if (_serialPort.IsOpen)

               _serialPort.Close();

       }

        #endregion

        #region 设置串口参数

        /// <summary>

        /// 设置串口参数

        /// </summary>

        /// <param name="comPortName">需要操作的COM口名称</param>

        /// <param name="baudRate">COM的速度</param>

        /// <param name="dataBits">数据长度</param>

        /// <param name="stopBits">停止位</param>

        public void setSerialPort(string comPortName, int baudRate, int dataBits, int stopBits )

        {

            if (_serialPort.IsOpen)

                _serialPort.Close();

            _serialPort.PortName = comPortName;

            _serialPort.BaudRate = baudRate;

            _serialPort.Parity = Parity.None;

            _serialPort.DataBits = dataBits;

            _serialPort.StopBits = (StopBits)stopBits;

            _serialPort.Handshake = Handshake.None;

            _serialPort.RtsEnable = false;

            _serialPort.ReadTimeout = 3000;

            _serialPort.NewLine = "/r/n";

            setSerialPort();

        }

        #endregion

        #region 设置接收函数

        /// <summary>

        /// 设置串口资源,还需重载多个设置串口的函数

        /// </summary>

        void setSerialPort()

        {

            if (_serialPort != null)

            {

                //设置触发DataReceived事件的字节数为1

                _serialPort.ReceivedBytesThreshold = 1;

                //接收到一个字节时,也会触发DataReceived事件

                _serialPort.DataReceived += new SerialDataReceivedEventHandler(_serialPort_DataReceived);

                //接收数据出错,触发事件

                _serialPort.ErrorReceived += new SerialErrorReceivedEventHandler(_serialPort_ErrorReceived);

                //打开串口

                //openPort();

            }

        }

        #endregion

        #region 打开串口资源

        /// <summary>

        /// 打开串口资源

        /// <returns>返回bool类型</returns>

        /// </summary>

        public bool openPort()

        {

            bool ok = false;

            //如果串口是打开的,先关闭

            if (_serialPort.IsOpen)

                _serialPort.Close();

            try

            {

                //打开串口

                _serialPort.Open();

                ok = true;

            }

            catch (Exception Ex)

            {

                throw Ex;

            }

            return ok;

        }

        #endregion

        #region 关闭串口

        /// <summary>

        /// 关闭串口资源,操作完成后,一定要关闭串口

        /// </summary>

        public void closePort()

        {

            //如果串口处于打开状态,则关闭

            if (_serialPort.IsOpen)

                _serialPort.Close();

        }

        #endregion

        #region 接收串口数据事件

        /// <summary>

        /// 接收串口数据事件

        /// </summary>

        /// <param name="sender"></param>

        /// <param name="e"></param>

        void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)

        {

            //禁止接收事件时直接退出

            if (ReceiveEventFlag)

            {

                return;

            }

            try

            {

                    System.Threading.Thread.Sleep(20);

                    byte[] _data = new byte[_serialPort.BytesToRead];

                    _serialPort.Read(_data, 0, _data.Length);

                    if (_data.Length == 0) { return; }

                    if (DataReceived != null)

                    {    

                        DataReceived(sender, e, _data);

                    }

                    //_serialPort.DiscardInBuffer();  //清空接收缓冲区  

            }

            catch (Exception ex)

            {

                throw ex;

            }

        }

        #endregion

        #region 接收数据出错事件

        /// <summary>

        /// 接收数据出错事件

        /// </summary>

        /// <param name="sender"></param>

        /// <param name="e"></param>

        void _serialPort_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)

        {

        }

        #endregion

        #region 发送数据string类型

        public void SendData(string data)

        {

            //发送数据

            //禁止接收事件时直接退出

            if (ReceiveEventFlag)

            {

                return;

            }

            if (_serialPort.IsOpen)

            {

                _serialPort.Write(data);

            }

        }

        #endregion

        #region 发送数据byte类型

        /// <summary>

        /// 数据发送

        /// </summary>

        /// <param name="data">要发送的数据字节</param>

        public void SendData(byte[] data, int offset, int count)

        {

            //禁止接收事件时直接退出

            if (ReceiveEventFlag)

            {

                return;

            }

            try

            {

                if (_serialPort.IsOpen)

                {

                    //_serialPort.DiscardInBuffer();//清空接收缓冲区

                    _serialPort.Write(data, offset, count);

                }

            }

            catch (Exception ex)

            {

                throw ex;

            }

        }

        #endregion

        #region 发送命令

        /// <summary>

        /// 发送命令

        /// </summary>

        /// <param name="SendData">发送数据</param>

        /// <param name="ReceiveData">接收数据</param>

        /// <param name="Overtime">超时时间</param>

        /// <returns></returns>

        public int SendCommand(byte[] SendData, ref  byte[] ReceiveData, int Overtime)

        {

 

            if (_serialPort.IsOpen)

            {

                try

                {

                    ReceiveEventFlag = true;        //关闭接收事件

                    _serialPort.DiscardInBuffer();  //清空接收缓冲区                

                    _serialPort.Write(SendData, 0, SendData.Length);

                    int num = 0, ret = 0;

                    System.Threading.Thread.Sleep(10);

                    ReceiveEventFlag = false;      //打开事件

                    while (num++ < Overtime)

                    {

                        if (_serialPort.BytesToRead >= ReceiveData.Length)

                            break;

                        System.Threading.Thread.Sleep(10);

                    }

 

                    if (_serialPort.BytesToRead >= ReceiveData.Length)

                    {

                        ret = _serialPort.Read(ReceiveData, 0, ReceiveData.Length);

                    }

                    else

                    {

                        ret = _serialPort.Read(ReceiveData, 0, _serialPort.BytesToRead);

                    }

                    ReceiveEventFlag = false;      //打开事件

                    return ret;

                }

                catch (Exception ex)

                {

                    ReceiveEventFlag = false;

                    throw ex;

                }

            }

            return -1;

        }

        #endregion

        #region 获取串口

        /// <summary>

        /// 获取所有已连接短信猫设备的串口

        /// </summary>

        /// <returns></returns>

        public string[] serialsIsConnected()

        {

            List<string> lists = new List<string>();

            string[] seriallist = getSerials();

            foreach (string s in seriallist)

            {

            }

            return lists.ToArray();

        }

        #endregion

        #region 获取当前全部串口资源

        /// <summary>

        /// 获得当前电脑上的所有串口资源

        /// </summary>

        /// <returns></returns>

        public string[] getSerials()

        {

string[] ports = SerialPort.GetPortNames();

            Array.Sort(ports);

            return ports;

        }

        #endregion

        #region 字节型转换16

        /// <summary>

        /// 把字节型转换成十六进制字符串

        /// </summary>

        /// <param name="InBytes"></param>

        /// <returns></returns>

        public static string ByteToString(byte[] InBytes)

        {

            string StringOut = "";

            foreach (byte InByte in InBytes)

            {

                StringOut = StringOut + String.Format("{0:X2} ", InByte);

            }

            return StringOut;

        }

        #endregion

        #region 十六进制字符串转字节型

        /// <summary>

        /// 把十六进制字符串转换成字节型(方法1)

        /// </summary>

        /// <param name="InString"></param>

        /// <returns></returns>

        public static byte[] StringToByte(string InString)

        {

            string[] ByteStrings;

            ByteStrings = InString.Split(" ".ToCharArray());

            byte[] ByteOut;

            ByteOut = new byte[ByteStrings.Length];

            for (int i = 0; i <= ByteStrings.Length-1 ; i++)

            {

                //ByteOut[i] = System.Text.Encoding.ASCII.GetBytes(ByteStrings[i]);

                ByteOut[i] = Byte.Parse(ByteStrings[i], System.Globalization.NumberStyles.HexNumber);

                //ByteOut[i] =Convert.ToByte("0x" + ByteStrings[i]);

            }

            return ByteOut;

        }

        #endregion

        #region 十六进制字符串转字节型

        /// <summary>

        /// 字符串转16进制字节数组(方法2)

        /// </summary>

        /// <param name="hexString"></param>

        /// <returns></returns>

        public static byte[] strToToHexByte(string hexString)

        {

            hexString = hexString.Replace(" ", "");

            if ((hexString.Length % 2) != 0)

                hexString += " ";

            byte[] returnBytes = new byte[hexString.Length / 2];

            for (int i = 0; i < returnBytes.Length; i++)

                returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);

            return returnBytes;

        }

        #endregion

        #region 字节型转十六进制字符串

        /// <summary>

        /// 字节数组转16进制字符串

        /// </summary>

        /// <param name="bytes"></param>

        /// <returns></returns>

        public static string byteToHexStr(byte[] bytes)

        {

            string returnStr = "";

            if (bytes != null)

            {

                for (int i = 0; i < bytes.Length; i++)

                {

                    returnStr += bytes[i].ToString("X2");

                }

            }

            return returnStr;

        }

        #endregion

    }

}

 

======================================================================================

调用方法:

static SerialClass sc = new SerialClass();

static void Main(string[] Args)

{

   sc.DataReceived += new SerialClass.SerialPortDataReceiveEventArgs(sc_DataReceived);

   sc.writeData("at");

   Console.ReadLine();

   sc.closePort();

}

static void sc_DataReceived(object sender, SerialDataReceivedEventArgs e, byte[] bits)

{

   Console.WriteLine(Encoding.Default.GetString(bits));

}