精华内容
下载资源
问答
  • 串口调试助手源码

    2013-06-22 21:15:17
    串口调试助手源码,帮助你了明白串口调试助手的工作原理,参照这个源码,串口编程变成小case
  • XCOM串口调试助手

    2017-10-12 16:49:16
    XCOM串口调试助手,支持高波特率以及协议传输,稳定好用
  • 串口调试助手向STM32发送数据过多时,串口调试助手会自动返回一组乱码数据,如图。想知道原理和解决方法!!!波特率、缓冲区字节之类的参数都是设置正确的。数据在120个字节以下,不会出现次现象。求解答!!!!!...
  • UartAssist串口调试助手用户手册/使用帮助/说明文档V4.3 第一章 UartAssist简介 第二章 串口通信原理 第三章 调试助手配置选项 第四章 调试助手基本操作 第五章 脚本代码语法规则 第六章 调试助手进阶选项
  • 串口调试助手源程序 易于理解串口通信原理
  • QT制作简易串口调试助手

    千次阅读 2020-08-12 10:27:40
    文章目录QT制作简易串口调试助手0 简介1 界面制作2 逻辑实现2.1 添加与可用串口信息有关的类的准备2.2 读取可用串口并添加到控件2.3 打开串口2.4 关闭串口2.5 串口收发数据2.6 清空接收框3 打包发布3.1 切换到...

    QT制作简易串口调试助手

    0 简介

    • 本次实验涉及的QT基础: 信号和槽基本原理 常用控件使用 布局设置
    • 本次实验借鉴了网上各种资料以及查阅了相关串口类的官方文档
    • 本文只提示了最基础的功能,全面了解请自行参考各种资源
    • 本次实验源码资源在这里插入图片描述

    1 界面制作

    常用的控件及属性设置,界面布局
    在这里插入图片描述

    2 逻辑实现

    2.1 添加与可用串口信息有关的类的准备

    在这里插入图片描述

    2.2 读取可用串口并添加到控件

    QStringList serialName;
    foreach (const QSerialPortInfo& info, QSerialPortInfo::availablePorts()) {
        serialName << info.portName();
    }
    ui->serial_comboBox->addItems(serialName);
    

    在这里插入图片描述

    2.3 打开串口

    在这里插入图片描述

    //测试
    mySerialPort->setPortName(ui->serial_comboBox->currentText()); //这个容易遗忘
    mySerialPort->setBaudRate(QSerialPort::Baud4800);
    mySerialPort->setDataBits(QSerialPort::Data8);//根据MCU来选择,一般是8 这个关系到串口是否成功打开
    mySerialPort->setStopBits(QSerialPort::OneStop);
    mySerialPort->setParity(QSerialPort::NoParity);
    mySerialPort->setFlowControl(QSerialPort::NoFlowControl);
    
    if (mySerialPort->open(QIODevice::ReadWrite))//判断是否成功打开,很重要
        QMessageBox::information(this, "提示", "打开成功!");
    else
        QMessageBox::critical(this, "提示", "打开失败!");
    

    在这里插入图片描述

    2.4 关闭串口

    mySerialPort->close();
    

    2.5 串口收发数据

    1. 串口接收

      connect(mySerialPort, SIGNAL(readyRead()), this, SLOT(readyRead_slots())); //串口read的connect
      
      void Widget::readyRead_slots()
      {
          QString buf;
          buf = QString(mySerialPort->readAll());
          //buf = mySerialPort->readAll().toHex(); //16进制显示
          //ui->receive_plainTextEdit->appendPlainText(buf);
          ui->receive_plainTextEdit->insertPlainText(buf); //没有换行
          ui->receive_plainTextEdit->moveCursor(QTextCursor::End);//及时更新内容
      }
      
    2. 串口发送

      void Widget::on_send_pushButton_clicked()
      {
          mySerialPort->write(ui->send_textEdit->toPlainText().toLocal8Bit().data());
      }
      

    2.6 清空接收框

    void Widget::on_clear_pushButton_clicked()
    {
        ui->receive_plainTextEdit->clear();
    }
    

    3 打包发布

    3.1 切换到release模式并编译

    在这里插入图片描述

    3.2 完善一些信息(如改图标)

    更改图标步骤

    1. 在此目录下添加一个ico文件

      在这里插入图片描述

    2. 在pro中加入代码,并编译,发现此目录下图标改变了

      在这里插入图片描述

    3.3 封包

    1. 找到用于封包的控制台

      在这里插入图片描述

    2. 新建一个文件夹并且把相应目录下的exe文件拷贝进去

      在这里插入图片描述

    3. 使用刚刚打开好的控制台,并且进入刚刚创建的文件夹

      在这里插入图片描述

    4. 使用命令 windeployqt + 名称.exe 基本结束,此方法简单但是文件很大,其他方法可百度

      在这里插入图片描述

    展开全文
  • gsm短信模块 串口调试 助手 很容易上手 操作简单 挺好用的 和大家分享一下 自己一直在用
  • 基于WPF及C#的串口调试助手,操作简单,界面清新。基于.Net4.6.1,实现基本的串口通信功能,重要的是无广告,无毒。
  • 串口调试助手实现

    2020-03-27 17:48:33
    基于c#的串口调试助手实现 界面截图 功能 串口数据的发送,接收显示。 发送方式:发送字符,或字符对应的十六进制发送 接收显示:字符显示,或十六进制显示 发送方法:回车,发送输入的字符 默认发送新行 实现方法 ...

    基于c#的串口调试助手实现

    界面截图在这里插入图片描述
    功能

    串口数据的发送,接收显示。
    发送方式:发送字符,或字符对应的十六进制发送
    接收显示:字符显示,或十六进制显示
    发送方法:回车,发送输入的字符
    默认发送新行

    实现方法

    Visual Studio中创建windows窗体应用,添加所需控件,修改控件属性,为控件添加控件处理函数,具体实行方法:

    一。添加控件

    1.TextBox文本框

    功能:获取用户的输入数据或者显示文本,用于串口接收数据的显示,以及串口数据的发送输入框
    对于显示接收数据的文本框,只允许读取,而不允许输入,修改,

    (1.1)设置文本框为只读:
    修改Readonly属性:true,只读; false:可读可写
    例:

    textBox1.ReadOnly = true;
    

    (1.2)将数据追加到文本框
    发送或者接收的串口数据要显示在文本框,或者要定期的删除文本框显示内容,例:

    textBox1.AppendText(ret);将字符串ret追加到文本框的末尾
    textBox1.Text+=ret;将字符串ret追加到文本框的末尾
    

    2.Combobox控件
    功能:显示一个选项列表,或允许用户输入的列表框的文本框
    在本功能中,用以选择波特率,端口号,数据位的信息

    (2.1)创建只可以选择的下拉框
    修改DropDownStyle属性

    	simple:       是控件的列表部分总是可见
        DropDown:     默认值,使用户可以编辑该控件的文本框
        DropDownList: 不能编辑文本框部分,呈现下拉框的样式
    

    在我们的使用中,修改为

    comboBox1.DropDownStyle = ComboBoxStyle.DropDownList;
    

    (2.2)
    获取Combobox1控件的选择框内容:

    string str = comboBox1.Text;
    

    3.Lable控件

    主要用于显示用户不能编辑的文本,给文本框、列
    表框等添加描述信息,例如,设置label1文本:

    label1.Text = "COM";
    

    (4)buttun控件

    通过单击来执行操作,在配置完串口的选项后,点击Open按钮,对应该控件的click事件,在代码中添加配置
    通过修改buttun控件的Enabled属性,控制控件是否工作

    (5)radioButton控件

    点式控件,如果被选中,则Checked属性 返回true

    (5)Panel容器:

    用于为其他的控件提供可以识别的分组,如果不添加该控件,相同类型的控件,只能选择一个,如radioButton控件如果不用Panel容器限制,则只能选择一个,用于给控件分区

    (6)serialPort控件

    串口控件

    打开串口serialPort:

    serialPort.Open();
    

    关闭串口:

    serialPort.Close();
    

    发送数据

    serialPort.Write(byte[]int offset,int count)
    

    byte:发送数据的byte数字
    offset:开始读取的数组下表的位置
    count:读取的元素个数

    接收数据

    string str = serialPort1.ReadExisting();//读取输入缓冲区的所有字节
    
    byte   ret = (byte)serialPort1.ReadByte();  //读取输入缓冲区的一个字节
    

    判断串口是否打开

    bool serialPort.Isopen()
    

    返回值: true, 打开
    false: 关闭

    为串口添加接收事件

    serialPort1.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(portReceived) ;
    

    portReceived:
    就是对应的串口接收函数的函数名(可以自己定义函数名),该函数类似于单片机中的中断,当有数据接收时,就会触发我们所注册的函数,在该函数中添加对应的数据接收,显示处理代码。

    (7)timer控件

    功能:定时检测是否有数据发送,如果发送区有数据,且按了回车键盘,则发送数据。
    可以定期的引发事件,就如同中断一样

    timer1.Stop();      //关闭定时器
    timer1.Start();     //打开定时器
    

    interval属性:定时时间:单位:ms

    二.窗体属性

    (1)更换窗体图标 Icon 属性
    (2)隐藏窗体图标栏 FormBorderStyle 属性
    (3)设置窗体的显示位置 StartPosition 属性

    CenterParent
    窗体在其父窗体中居中
    CenterScreen
    窗体在当前显示窗体中居中,其尺寸在窗体大小中指定
    Manual
    窗体的位置由 location 属性确定
    WindowsDefaultBounds
    窗体定位在 Windows 默认位置,其边界也由 Windows 默认决定
    WindowsDefaultLocation
    窗体定位在 Windows 默认位置,其尺寸在窗体大小中指定

    (4)修改窗体的大小 size属性

    (5)设置图像背景的窗体 BackgroundImage

    三.代码实现
    设置,添加好控件之后,就可以为控件添加相应的代码块了。
    程序实现的流程:在buttun控件中读取串口配置参数,初始化打开串口,当有数据输入时,就会触发串口接收函数,在该函数中,添加对应的代码用以接受到的数据的读取与显示,数据的发送,定时器每50毫秒判断发送区是否有数据输入,如果有,则判断是否输入了回车,如果输入回车,则通过串口将数据进行发送。

    四.代码部分

    打开串口部分:

    
            private void button1_Click(object sender, EventArgs e)  //start按钮
            {
                try
                {
                    serialPort1.PortName = comboBox1.Text;
                    serialPort1.BaudRate = Convert.ToInt32(comboBox2.Text);
                    serialPort1.DataBits = Convert.ToInt32(comboBox4.Text);
                }
                catch
                {
                    MessageBox.Show("请重新配置串口,此为系统默认端口设置");
                }
    
                try
                {
                    serialPort1.Open();  //打开串口
                    button1.Enabled = false;
                    button2.Enabled = true;
                    timer1.Start();
                }
                catch
                {
                    if (serialPort1.IsOpen)
                    {
                        MessageBox.Show("串口连接错误");
                    }
                    else
                    {
                        MessageBox.Show("串口不存在,请重新连接");
    
                    }
    
                }
    
            }
    

    发送部分:

         private void timer1_Tick(object sender, EventArgs e)   //定时器处理函数,判断是否要发送数据
            {
    
                byte[] ret = new byte[1];
    
                if (serialPort1.IsOpen && textBox4.Text != "")
                {
                    string str = textBox4.Text;
                    byte[] BIT = new byte[1];
    
                    if (textBox4.Text.Substring(textBox4.Text.Length - 1, 1) == "\n")  //按下回车,发送数据
                    {
                        if (radioButton1.Checked)  //以字符方式发送
                        {
                            int i = 1;
                            BIT[0] = (byte)str[0];
                            if (radioButton5.Checked)  //判断是否发送新行
                            {
                                while (BIT[0] != '\n')  //循环发送数据,字节的方式,发送回车\r,按下回车键会发送"\r\n"
                                {
                                    serialPort1.Write(BIT, 0, 1);  //发送数组下标为0的元素
                                    BIT[0] = (byte)str[i++];
                                }
                            }
                            else  //不发送回车\r
                            {
                                while (BIT[0] != '\r') //循环发送数据,字节的方式,不发送回车\r
                                {
                                    serialPort1.Write(BIT, 0, 1);  //发送数组下标为0的元素
                                    BIT[0] = (byte)str[i++];
                                } 
    
                            }
                            textBox4.Text = "";  //清除发送区
                        }
    
                        else if (radioButton2.Checked)  //字符以对应的ASCII的16进制进行发送
                        {
                            int length = textBox4.Text.Length -2;
                            byte[] buf = new byte[2];
                            string str_test;
                            try
                            {
                                for (int i = 0; i < length; i += 3)
                                {
                                    str_test = textBox4.Text.Substring(i,2);         //字符串6c 对应  整数108
                                    buf[0] =  (byte)Convert.ToInt32(str_test, 16);//字符串形式的十六进制,转换为整形
                                    serialPort1.Write(buf, 0, 1);  //发送数组下标为0的元素
                                }
    
                                if (radioButton5.Checked)//发送回车  :\r
                                {
                                    buf[0] = 13;
                                    serialPort1.Write(buf, 0, 1);  //发送数组下标为0的元素
                                }
                            }
                            catch
                            {
                                //MessageBox.Show("sh");
                            }
                           
                            textBox4.Text = "";  //清除发送区
                        }
                      
                    }
                }
            }
    

    接收部分:

     private void portReceived(object sender,System.IO.Ports.SerialDataReceivedEventArgs e )
            {
                if (radioButton4.Checked) //判断是否以字符串的方式读取
                {
                    string ret = serialPort1.ReadExisting();//读取输入缓冲区的所有字节
                    textBox1.AppendText(ret);  //将读取到的数据追加到文本框的末尾        
                }
                else if(radioButton3.Checked)  //读取到的字符对应的ACill以16进制显示
                {
                    byte ret = (byte)serialPort1.ReadByte();  //读取输入缓冲区的一个字节  10 --对应 A
                    string str = ret.ToString("x");            //将byte对应的16进制,转换为16进制的字符串0-ff;
                    textBox1.Text += (str.Length == 1) ? "0x0" + str + " " : "0x" + str + " ";     //追加到文末
                }
            }
    
    

    完整代码块:请点击以下链接:
    https://github.com/1997LP/C-/commit/8367b256410a41178bec5620a914b9b577f1e5a7#diff-0329923df475cd6cf19e93ae2291b5dc

    展开全文
  • 通常上位机和下位机通讯可以采用不同通讯协议,可以有RS232的串口通讯或者采用RS485串行通讯。采用封装好的程序开发工具就可以实现下位机和上位机的通讯,当然可以自己编写驱动类的接口协议控制上位机和下位机的通讯...
  • 串口调试助手-ComTool

    2015-02-02 16:02:10
    可以选择串口发送并接受串口数据,可以实时修改串口的波特率等设置。 帮助串口开发的程序员进行设备调试校验工作。
  • 自己做串口调试助手

    万次阅读 多人点赞 2017-10-13 18:34:07
    一、协议介绍串口调试助手应该都比较熟悉了,主要用于和下位机通信(如单片机),使用的通信协议就是串口通讯协议。首先先介绍下这个协议。 串口通信属于异步的串行通信,有如下几个特点。1 . 物理上的连线至少三根...

    一、协议介绍

    串口调试助手应该都比较熟悉了,主要用于和下位机通信(如单片机),使用的通信协议就是串口通讯协议。首先先介绍下这个协议。
    串口通信属于异步的串行通信,有如下几个特点。

    1 . 物理上的连线至少三根,分别是tx数据发送线,rx数据接收线,GND共用的地线
    2. 0与1的约定。RS232电平,约定﹣5V至﹣25V之间的电压信号为1,﹢5V至﹢25V之间的电压信号为0 。TTL电平,约定5V的电压信号为1,0V电压信号为0 。CMOS电平,约定3.3V的电压信号为1,0V电压信号为0 。其中,CMOS电平一般用于ARM芯片中。
    3. 发送的顺序,串口是LSB->MSB
    4. 波特率,收发双方共同约定的一个数据位(0或1)在数据传输线上维持的时间。也可理解为每秒可以传输的位数。常用的波特率有2400,9600,14400,19200,115200等。
    5. 通信协议,串口通信分为起始位,数据位,校验位,停止位,时序如下图所示。
    这里写图片描述

    二、程序编写

    编程语言我使用的是C#,C#对这种桌面的图形化编程有着很好的支持,可以迅速编写一些桌面的小工具。
    IDE使用visual studio 2015。

    1.串口类的使用
    串口的库C#已经为我们编写好了 我们可以直接使用,配置如下

       serialPort1.BaudRate = Convert.ToInt32(comboBox2.Text);
       serialPort1.PortName = comboBox1.Text;
       serialPort1.StopBits = (StopBits)Convert.ToInt32(stopBox.Text);
       serialPort1.DataBits = Convert.ToInt32(dataBox.Text);
       serialPort1.Parity = (Parity)0;
       //解决中文乱码的问题
       serialPort1.Encoding = System.Text.Encoding.GetEncoding("GB2312");
       serialPort1.Open();

    设置串口通信的几个重点参数,如数据位,奇偶校验位,停止位,波特率等,同时设置
    了串口的编码为GB2312,这样就能解决中文乱码的问题。

    为了实时获取可用的端口号,可使用一个定时器,1s更新一次可用串口列表

    string[] ports = SerialPort.GetPortNames();//获得可用串口列表 
    string selectCom = comboBox1.Text;
                //更新可用串口列表
                if (comboBox1.Items.Count > 0)
                {
                    comboBox1.Items.Clear();
                }
                foreach (string port in ports)  
                {
                    comboBox1.Items.Add(port);
                    if (port.Equals(selectCom))
                    {
                        comboBox1.Text = selectCom;
                    }
                }

    配置好了后就可以添加数据接收事件,编写数据接收函数

     serialPort1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived);

    最简单的串口调试助手到此就完成了,不过我们可以再添加一些小功能。

    串口调试助手都是和底层通信,那么经常使用的就是十六进制的数据,所以我们编写字符串转16进制和16进制转字符串这两个函数。

            public static String stringToOxTool(String str)
            {
                StringBuilder sb = new StringBuilder();
                Encoding gb = Encoding.GetEncoding("GB2312");
                //按照GB2312的编码方式把字符串转换为byte型数据
                byte[] values = gb.GetBytes(str);
    
                foreach (byte item in values)
                {
                    int value = Convert.ToInt32(item);
                    //对每个数据按照16进制去格式化
                    string newstr = String.Format("{0:X}", value) + " ";
                    sb.Append(newstr);
                }
                return sb.ToString();
            }
             public static String oxToStringTool(String str)
            {
                List<byte> list = new List<byte>();
                StringBuilder sb = new StringBuilder();
                String[] data= str.Split(' ');
                Encoding gb = Encoding.GetEncoding("GB2312");
    
                foreach (String item in data)
                {
                    if (item == " ")
                    {
                        list.Add(0x20);
                    }
                    else if (item == "\r")
                    {
                        list.Add(0x0d);
                    }
                    else if (item == "\n")
                    {
                        list.Add(0x0a);
                    }
                    else
                    {
                        try
                        {
                            byte value = Convert.ToByte(item, 16);
                            list.Add(value);
                        }
                        catch
                        {
                            list.AddRange((gb.GetBytes(item)));
                        }
                    }
    
                }
                return gb.GetString(list.ToArray());
            }

    如果发送的过程是在主线程里运行的话,那么发送大文件时就会导致界面无法点击,所以数据的发送新建一个从线程,让数据在后台发送。

     Thread t = new Thread(sendDataThread);
                t.Start();
     private void sendDataThread()
    {
        String str = sendDataBox.Text;
    
        //如果数据是16进制格式的先转换为字符串格式
        if (send_0x.Checked)
        {
            str = tool.oxToStringTool(sendDataBox.Text);
        }
         /*
            按换行符去分割字符串,
            即存在多行数据分行发送
         */
        String[] data = str.Split('\n');
        for (int i = 0; i < data.Length; i++)
        {
            //如果存在\r符,则得到它的位置并删除
            int pos = data[i].LastIndexOf('\r');
            if (pos != -1)
            {
                sendData(data[i].Remove(pos));
            }
            else
            {
                sendData(data[i]);
            }
            //发送间隔
            Thread.Sleep(20);
        }
    
    }

    一些发送的配置本来打算使用xml文件,不过搜索了下发现C#自己有一个设置文件,非常好用,而且配置方便。直接新建设置文件,然后配置就能在程序里使用了

    //初始化时从设置文件中读取历史配置值
    comboBox2.Text = config.Default.portBps;  
    sendDataBox.Text = config.Default.sendDataText;
    stopBox.Text = config.Default.portStop;
    dataBox.Text = config.Default.portData;
    checkoutBox.Text = config.Default.portCheck;
    comboBox1.Items.Add(config.Default.com);
    comboBox1.Text = config.Default.com;
    
    sendPeriodValue.Text = config.Default.periodValue.ToString();
    sendNewLineBox.Checked = config.Default.sendNewLineFlag;
    send_0x.Checked = config.Default.hexSendFlag;
    hexShowBox.Checked = config.Default.hexSendFlag;
    timeTickBox.Checked = config.Default.timeTickFlag;
    checkBox2.Checked = config.Default.rxBoxBkColor;
    
    //在窗口关闭事件中把配置数据保留下来
     private void Form1_FormClosing(object sender, FormClosingEventArgs e)
      {
        //保存数据
         config.Default.Save();
      }

    三、功能介绍

    1. 16进制显示,勾选后将显示16进制的字节,如果之前接收到了数据,会自动转换.
    2. 显示界面可以黑底白字或者白底黑字
    3. 时间戳功能,当数据帧中含有”\r\n”时会自动添加当前时间[yyyy-MM-dd hh:mm:ss].
    4. 点击保存窗口可以将接收到的数据存为txt文件,编码格式为GB2312.
    5. 点击清除按钮,可以清除窗口显示的内容,并且清除发送和接收字节计数
    6. 支持16进制发送,勾选16进制发送的时候将对发送区的内容进行16进制和字符互转
    7. 发送换行勾选后,每次发送数据时会自动添加”\r\n”.
    8. 支持发送文件(txt),勾选发送新行后,会自动给文件每一行数据加上换行回车符.
    9. 支持定时发送,可以自定义发送周期
    10. 采用配置文件,记录上一次使用软件时的配置.

    界面如下,界面和功能主要都是模仿了正点原子的XCOM。
    这里写图片描述

    代码托管地址: https://github.com/yuanluw/princomputer

    展开全文
  • 该资源有两个,一是串口调试助手的源代码,可以实现数据的接收和发送;二是实现点击某个按钮发送指定数据的应用程序的源代码。代码都是含有详细的中文注释,可以直接编译通过,且内含可执行文件都是可以直接运行的。...
  • 项目要求:下位机使用单片机,不断发送一个随机数值给上位机,上位机收到数据,显示在显示框中。 实验环境:vs2013 ... 一、窗体程序制作: ...1.首先我们参照网上的串口调试助手将UI界面的大体框架完成。 2...

    项目要求:下位机使用单片机,不断发送一个随机数值给上位机,上位机收到数据,显示在显示框中。
    实验环境:vs2013
    参考文档:https://docs.microsoft.com/zh-cn/dotnet/api/system.io.ports?view=netframework-4.7.2
    下位机部分:https://blog.csdn.net/weixin_42462552/article/details/85561632



    一、窗体程序制作:

    (一)UI界面

    1.首先我们参照网上的串口调试助手将UI界面的大体框架完成。
    界面图片
    2.其中数据接收区域和发送区域的文本需要实现自动换行功能,根据网上资料,需要设置TextWrapping的属性为"Wrap"。
    3.接下来是对串口号、波特率、校验位等的一些内容设置,其中较复杂的是串口号的设置,需要根据电脑的端口实际情况来确定串口数量,不能同设置波特率属性一般,直接在程序里指定唯一值。

    string[] ports = SerialPort.GetPortNames();//获取当前计算机的串行端口名的数组。
                for(int index =0;index<ports.Length;index++)
                {
                    cb_SerialPortNumber.Items.Add(ports[index]);//添加item
                    cb_SerialPortNumber.SelectedIndex = index; //设置显示的item索引
                }
    

    在官方文档中找到获取当前计算机的串行端口名的数组的函数GetPortNames (),接着使用循环,利用comboBox的Items.Add方法将数组内的元素添加到comboBox中。

    UI界面xml代码

    <Window x:Class="SerialDebuggingAssistant.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:SerialDebuggingAssistant"
            Title="串口调试助手" Height="400" Width="600" ResizeMode="CanMinimize" Closing="Window_Closing">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="192*"/>
                <RowDefinition Height="82*"/>
                <RowDefinition Height="97*"/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="266*"/>
                <ColumnDefinition Width="327*"/>
            </Grid.ColumnDefinitions>
            <GroupBox Header="串口参数设置" BorderBrush="Black">
                <StackPanel >
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="串口号" Width="auto" Margin="5" Padding="0,6,0,0"/>
                        <ComboBox Name="cb_SerialPortNumber" Width="65" Margin="5,10,5,10"/>
                        <TextBlock Text="波特率" Width="auto" Margin="5" Padding="0,6,0,0"/>
                        <ComboBox Name="cb_BaudRate" Width="68" Margin="10,10,0,10" SelectedIndex="8">
                            <ComboBoxItem Content="600"/>
                            <ComboBoxItem Content="1200"/>
                            <ComboBoxItem Content="2400"/>
                            <ComboBoxItem Content="4800"/>
                            <ComboBoxItem Content="9600"/>
                            <ComboBoxItem Content="14400"/>
                            <ComboBoxItem Content="19200"/>
                            <ComboBoxItem Content="28800"/>
                            <ComboBoxItem Content="38400"/>
                            <ComboBoxItem Content="57600"/>
                            <ComboBoxItem Content="115200"/>
                            <ComboBoxItem Content="230400"/>
                            <ComboBoxItem Content="460800"/>
                        </ComboBox>
                    </StackPanel>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="校验位" Width="auto" Margin="5" Padding="0,6,0,0"/>
                        <ComboBox Width="65" Margin="5,10,5,10" SelectedIndex="0">
                            <ComboBoxItem Content="None"/>
                        </ComboBox>
                        <TextBlock Text="数据位" Width="auto" Margin="5" Padding="0,6,0,0"/>
                        <ComboBox Width="68" Margin="10,10,0,10" SelectedIndex="0">
                            <ComboBoxItem Content="8"/>
                        </ComboBox>
                    </StackPanel>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="停止位" Width="auto" Margin="10,10,0,10" Padding="0,3,0,0"/>
                        <ComboBox Width="65" Margin="5,10,5,10" SelectedIndex="0">
                            <ComboBoxItem Content="one"/>
                        </ComboBox>
                    </StackPanel>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Name="tb_switchStatus" Text="串口为关闭状态" Width="auto" Margin="10" Padding="0,2,0,0"/>
                        <Ellipse Name="e_status" Fill="#000000" Height="10" Stroke="Black" Margin="5,3,5,0" Width="10" />
                        <Button Name="bt_SerialSwitch" Content="打开串口" Margin="10" Padding="5,0,5,0" Click="bt_SerialSwitch_Click"/>
                       
                    </StackPanel>
                </StackPanel>
            </GroupBox>
    
    
            <GroupBox Header="接收数据设置" Grid.Row="1" BorderBrush="Black">
                <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
                    <Button Name="ClearReceiveData" Content="清空接收数据" Margin="20" Click="ClearReceiveData_Click"/>
                    <Button Name="bt_stopSend" Content="停止接收" Margin="20" Click="bt_stopSend_Click"/>
                </StackPanel>
            </GroupBox>
    
    
            <GroupBox Header="发送数据设置" Grid.Row="2" BorderBrush="Black">
                <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
                    <Button Name="bt_ClearSendData" Content="清空发送数据" Margin="20,30,20,25" Click="bt_ClearSendData_Click"/>
                    <Button Name="bt_send" Content="手动发送" Margin="20,30,20,25" Click="bt_send_Click"/>
                </StackPanel>
            </GroupBox>
            <GroupBox Header="接收数据区" Grid.Column="1" Grid.RowSpan="2" BorderBrush="Black"  Margin="5">
                <ScrollViewer VerticalScrollBarVisibility="Auto">
                    <TextBlock Name="tb_receiveData" TextWrapping="Wrap"/>
                </ScrollViewer>
            </GroupBox>
            <GroupBox Header="发送数据区" Grid.Row="2" Grid.Column="1"  BorderBrush="Black">
                <ScrollViewer VerticalScrollBarVisibility="Auto">  <!--滚动条-->
                    <TextBox Name="tb_SendData" TextWrapping="Wrap"/>
                </ScrollViewer>
            </GroupBox>
        </Grid>
    </Window>
    
    

    (二)后台逻辑代码(.cs代码部分)

    1.添加using引用

    using System.IO.Ports;
    

    2.新建串口对象

    public SerialPort _serialPort = new SerialPort ();
    

    3.设置一些简单控件的逻辑功能

    (1)“清空接收数据”和“清空发送数据”按钮的点击事件,只需要把对应区域的Text属性设为空,Text = “” 。

    		private void bt_ClearSendData_Click(object sender, RoutedEventArgs e)//清空发送区域
            {
                tb_SendData.Text = "";
            }
    
            private void ClearReceiveData_Click(object sender, RoutedEventArgs e)//清空接受数据
            {
                tb_receiveData.Text = "";
            }
    

    4.设置串口参数

    (1)如数据位、奇偶校验位、停止位和波特率等,在官方文档中说明使用PortName、BaudRate、DataBits、StopBits、Parity分别可以设置串口、波特率、数据位、停止位和校验位,其中串口、波特率是根据实际情况来设定的,数据位、停止位和校验位因为基本上在使用时不会去做更改,所以指定唯一值。

    		public void initialize()//初始化
            {
                    _serialPort.PortName = cb_SerialPortNumber.SelectedItem.ToString();//串口号
                    ComboBoxItem seletedItem = (ComboBoxItem)this.cb_BaudRate.SelectedItem;
                    _serialPort.BaudRate = Convert.ToInt32(seletedItem.Content.ToString());//波特率
                    _serialPort.DataBits = 8;//数据位
                    _serialPort.StopBits = StopBits.One;//停止位
                    _serialPort.Parity = Parity.None;//校验位
            }
    

    5.编写“打开串口”按钮的点击事件

    (1)这里主要实现的功能是打开和关闭串口,添加数据接收事件和取消数据接收事件。开关串口需要使用两个函数open()和close()。

    		private void bt_SerialSwitch_Click(object sender, RoutedEventArgs e)//串口开关
            {
                initialize();//初始化
                string strContent = this.bt_SerialSwitch.Content.ToString();
                if (strContent == "打开串口")
                {
                        _serialPort.Open();
                        _serialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);//添加数据接收事件
                        //_serialPort.DataReceived += DataReceivedHandler;
                        bt_SerialSwitch.Content = "关闭串口";
                        tb_switchStatus.Text = "串口为打开状态";
                        bt_send.IsEnabled = true;
                        bt_stopSend.IsEnabled = true;
                        e_status.Fill = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FF0000"));
                }
                else
                {
                        _serialPort.DataReceived -= DataReceivedHandler;
                        _serialPort.Close();
                        bt_SerialSwitch.Content = "打开串口";
                        tb_switchStatus.Text = "串口为关闭状态";
                        e_status.Fill = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#000000"));
                        bt_send.IsEnabled = false;
                        bt_stopSend.IsEnabled = false;
                }
            }
    

    6.添加数据接收事件

    (1)官方文档上说明需要使用SerialErrorReceivedEventHandler(注解原文:“创建SerialErrorReceivedEventHandler委托时,需要标识将处理该事件的方法。若要将事件与事件处理程序关联,请将该委托的一个实例添加到事件中”)。在文档中找到了DataReceived,具体写法是:
    SerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);后来发现可以简写 serialPort1.DataReceived += new DataReceivedHandler; 其中的DataReceivedHandler就是数据接收的具体实现方法。

    //在串口打开点击事件中添加
    _serialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);//添加数据接收事件
    

    7.数据接收

    (1)获取数据

    • 编写数据接收事件DataReceivedHandler,功能是读取下位机的数据,显示在数据接收区中。首先是使用BytesToRead获取接收缓冲区中数据的字节数,然后根据获取到的字节数来创建一个对应大小的byte数组,再使用Read函数将获取的数据放入byte数组中,然后还要对byte数组的数据转换成十六进制数,使用到了这个函数BitConverter.ToString(官方解释是“将指定的字节子数组的每个元素的数值转换为它的等效十六进制字符串表示形式”)。
      (2)更新UI界面
    • 将处理好的数据加载到Text属性上,Text += strData;不过访问UI组件必须放在主线程中运行,不然会抛异常“调用线程无法访问此对象,因为另一个线程拥有该对象”。
    • 窗体控件是由主线程执行的,因此在多线程中试图更改控件的内容比如覆盖或追加Textblock的内容,是无法在分线程中执行的,因为Textblock是由UI界面线程控制的,因此采用Dispatcher.Invoke(() =>{ ……});里面调用Textblock控件。
     		public void DataReceivedHandler(object sender,SerialDataReceivedEventArgs e)//读取下位机的数据,显示在textBlock中
            {          
                int len = this._serialPort.BytesToRead;
                byte[] buffer = new byte[len];
                this._serialPort.Read(buffer, 0, len);         
                string strData = BitConverter.ToString(buffer, 0, len);
                Dispatcher.Invoke(() =>
                {
                    this.tb_receiveData.Text += strData;
                    this.tb_receiveData.Text += "-";//字符分隔-
                });
            }
    

    8.数据发送

    (1)使用Write()方法发送数据

    • 数据发送跟数据接收的原理差不多,只不过不需要使用线程方式。首先将数据发送区域TextBox的Text属性值赋值到一个string类型的变量中,然后使用一个byte数组储存数据,因为输入的字符是十六进制数,所以这边做了个循环用Substring()切割字符串方法,每次取两位字符组成一个16进制,接着使用Write()方法发送数据。
    		private void bt_send_Click(object sender, RoutedEventArgs e)//发送按钮
            {
                string SendData = tb_SendData.Text;
                byte[] Data = new byte[20];
                for (int i = 0; i < SendData.Length / 2; i++)
                {
                        //每次取两位字符组成一个16进制
                      Data[i] = Convert.ToByte(tb_SendData.Text.Substring(i * 2, 2), 16);
                }
                this._serialPort.Write(Data, 0, Data.Length);   
            }
    

    (2)“ 停止接收数据”和“继续接收数据”

    • 这里是分别通过发送0x99和0x66指令到单片机中实现停止和继续发送数据功能,同时还使用取消和添加数据接收事件DataReceivedHandler的方式,其实这两种方式也就是主动和被动的不同罢了,第一种方式更为真实一些。
    		private void bt_stopSend_Click(object sender, RoutedEventArgs e)//停止接收数据
            {
                string strContent = this.bt_stopSend.Content.ToString();
                if (strContent == "停止接收")
                {
                    byte[] data = { 0x99 };
                    _serialPort.DataReceived -= DataReceivedHandler;
                    this._serialPort.Write(data, 0, data.Length);
                    bt_stopSend.Content = "继续接收";
                }else
                {
                    byte[] data = { 0x66 };
                    this._serialPort.Write(data, 0, data.Length);
                    _serialPort.DataReceived += DataReceivedHandler;
                    bt_stopSend.Content = "停止接收";
                }
            }
    

    9.程序关闭事件

    (1)当用户将程序关闭时,如果串口处于开启状态时,应该在关闭程序时将串口关闭。

    		private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
            {
                string strContent = this.bt_SerialSwitch.Content.ToString();
                if (strContent == "关闭串口")
                {
                    _serialPort.Close();
                }
            }
    

    10.测试时引发的异常

    (1)我们发现当串口还没被打开时,如果点击“停止接收”和“手动发送”按钮,会出现异常,导致程序无法进行,所以用了这个办法,当串口还没别打开,“停止接收”和“手动发送”按钮的IsEnabled属性就处于false状态,直到串口打开,然后才恢复true状态。
    (2)当打开串口后,点击关闭串口按钮时,也会抛异常,并且提示在初始化那一块和关闭串口事件那块,所以我们将这两个地方加了try……catch,让程序不去理他继续运行。

    三、实验结果

    (一)当程序运行,用户将串口号和波特率设置完成,点击“打开串口”按钮时,“接收数据区域”会显示从下位机传来的数据。
    (二)当点击“停止接收”按钮时,下位机停止发送数据,“接收数据区域”停止显示,按钮上的文本变成“继续接收”,当再次点击按钮时,下位机继续发送数据,“接收数据区域”继续显示数据,按钮文本变成“停止接收”。
    (三)当点击“清空接收数据”和“清空发送数据”时,对应区域的文本将会清空。
    (四)当在“发送数据区域”输入“99”,点击“手动发送”按钮时,下位机停止发送数据,“接收数据区域”停止显示。发送“66”时,下位机继续发送数据,“接收数据区域”继续显示数据。

    完整代码

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    //上面的是系统自动生成的
    using System.IO.Ports;//这是手动添加的
    namespace SerialDebuggingAssistant
    {
        /// <summary>
        /// MainWindow.xaml 的交互逻辑
        /// </summary>
        /// 
       
        public partial class MainWindow : Window
        {
            public SerialPort _serialPort = new SerialPort ();
            
            public MainWindow()
            {
                InitializeComponent();
                
                string[] ports = SerialPort.GetPortNames();//获取当前计算机的串行端口名的数组。
                for(int index =0;index<ports.Length;index++)
                {
                    cb_SerialPortNumber.Items.Add(ports[index]);//添加item
                    cb_SerialPortNumber.SelectedIndex = index; //设置显示的item索引
                }
                bt_send.IsEnabled = false;
                bt_stopSend.IsEnabled = false;
            }
            public void initialize()//初始化
            {
                //关闭串口时回抛异常
                try
                {
                    _serialPort.PortName = cb_SerialPortNumber.SelectedItem.ToString();//串口号
                    ComboBoxItem seletedItem = (ComboBoxItem)this.cb_BaudRate.SelectedItem;
                    _serialPort.BaudRate = Convert.ToInt32(seletedItem.Content.ToString());//波特率
                    _serialPort.DataBits = 8;//数据位
                    _serialPort.StopBits = StopBits.One;//停止位
                    _serialPort.Parity = Parity.None;//校验位
                }
                catch
                {
    
                }
    
            }
            private void bt_ClearSendData_Click(object sender, RoutedEventArgs e)//清空发送区域
            {
                tb_SendData.Text = "";
            }
    
            private void ClearReceiveData_Click(object sender, RoutedEventArgs e)//清空接受数据
            {
                tb_receiveData.Text = "";
            }
            
            private void bt_SerialSwitch_Click(object sender, RoutedEventArgs e)//串口开关
            {
                initialize();//初始化
                string strContent = this.bt_SerialSwitch.Content.ToString();
                if (strContent == "打开串口")
                {
                    try
                    {
                        _serialPort.Open();
                        _serialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);//添加数据接收事件
                        //_serialPort.DataReceived += DataReceivedHandler;
                        bt_SerialSwitch.Content = "关闭串口";
                        tb_switchStatus.Text = "串口为打开状态";
                        bt_send.IsEnabled = true;
                        bt_stopSend.IsEnabled = true;
                        e_status.Fill = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FF0000"));
                    }
                    catch { }
                }
                else
                {
                    try
                    {
                        _serialPort.DataReceived -= DataReceivedHandler;
                        _serialPort.Close();
                        bt_SerialSwitch.Content = "打开串口";
                        tb_switchStatus.Text = "串口为关闭状态";
                        e_status.Fill = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#000000"));
                        bt_send.IsEnabled = false;
                        bt_stopSend.IsEnabled = false;
                    }
                   catch
                    {
    
                    }
                }
            }
            public void DataReceivedHandler(object sender,SerialDataReceivedEventArgs e)//读取下位机的数据,显示在textBlock中
            {          
                int len = this._serialPort.BytesToRead;
                byte[] buffer = new byte[len];
                this._serialPort.Read(buffer, 0, len);         
                string strData = BitConverter.ToString(buffer, 0, len);
                Dispatcher.Invoke(() =>
                {
                    this.tb_receiveData.Text += strData;
                    this.tb_receiveData.Text += "-";
                });
            }
            
            private void bt_send_Click(object sender, RoutedEventArgs e)//发送按钮
            {
                string SendData = tb_SendData.Text;
                byte[] Data = new byte[20];
                for (int i = 0; i < SendData.Length / 2; i++)
                {
                        //每次取两位字符组成一个16进制
                      Data[i] = Convert.ToByte(tb_SendData.Text.Substring(i * 2, 2), 16);
                }
                this._serialPort.Write(Data, 0, Data.Length);   
            }
            private void bt_stopSend_Click(object sender, RoutedEventArgs e)//停止接收数据
            {
                string strContent = this.bt_stopSend.Content.ToString();
                if (strContent == "停止接收")
                {
                    byte[] data = { 0x99 };
                    _serialPort.DataReceived -= DataReceivedHandler;
                    this._serialPort.Write(data, 0, data.Length);
                    bt_stopSend.Content = "继续接收";
                }else
                {
                    byte[] data = { 0x66 };
                    this._serialPort.Write(data, 0, data.Length);
                    _serialPort.DataReceived += DataReceivedHandler;
                    bt_stopSend.Content = "停止接收";
                }
            }
            private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
            {
                string strContent = this.bt_SerialSwitch.Content.ToString();
                if (strContent == "关闭串口")
                {
                    _serialPort.Close();
                }
            }
        }
    }
    
    
    展开全文
  • 串口调试助手,读取、改写串口数据的工具,免安装面注册,方便使用。
  • 关于STM32 串口二、串口三串口调试助手无法显示的问题 这个问题找了好久,网上都没有找到,后来突然来了灵感,用过Arduino的同学都知道,Arduino Uno板的TX0,RX0是与电脑相连的串口,是一个人机交互的界面。如果...
  • 串口调试助手,在嵌入式开发中是很常用的。比如: 通过串口打印测试数据、调试串口WIFI(ESP8266、有人WIFI..)、调试GSM模块、GPS模块、字库更新等等。 二、效果图 三、核心代码 3.1 widget.cpp #include...
  • 串口调试助手(传送图片和文本文件)

    热门讨论 2011-03-29 15:39:05
    把图片转换成串口能识别的编码,通过串过传输图片,此外此串口调试有一般串口助手的功能开发者多百多度547170882
  • 我们知道,串口调试助手的接收窗口能够看到十六进制数和字符串,如果我要发送33这个数,直接用平常的串口字符发送函数,16进制显示的是21,而要是没有勾选“16进制显示”,那么显示的就是33在ASCII码中对应的字符...
  • 新增虚拟串口对 ... PORTEUS中增加串口控件COMPIM 在PROTEUS中增加一个串口控件,MCU使用AT89C51RD2 ...这里我们设置的属性要跟MCU的属性、串口调试助手的属性一致。 这儿我们都设置为"9600,N,8,1" 编写MCU发送程序 /*...
  • S 串口编程 详解6 串口调试助手整个程序代码 CSerialPort类的代码见 串口编程 详解2 CSerialPort类 (SerialPort.h头文件和SerialPort.ccp实现文件)http://blog.csdn.net/gdliweibing/article/details/13629129 ...
  • 基于CSerialPort修改类的串口调试助手源代码(支持中文、自动保存等)该文的补充, 其中介绍了编写过程中遇到的问题 1、下拉控件 类型设置为下拉列表,在选择的时候就不可以编辑了 2、_T("打开串口") 3、...
  • 串口调试助手是干嘛的

    千次阅读 2019-07-22 22:21:04
    简单来说其实就是用于上位机和下位机通信用的一个桥梁软件:接受单片机发送的数据显示给你看,或者人工发送数据给单片机处理。
  • 串口调试助手

    2021-05-23 17:59:40
    一个很好而小巧的串口调试助手,支持常用的300-115200bps波特率,能设置校验、数据位和停止位,能以ASCII码或十六进制接收或发送任何数据或字符(包括中文),可以任意设定自动发送周期,并能将接收数据保存成文本...
  • 基于qt4的串口调试助手开发

    千次阅读 2018-06-27 00:27:01
    本课程设计的内容是设计一个基于QT的串口调试软件,同时支持中文、英文数传输、十六进制数据传输、文件内容传输。 2. 课程设计目的 考察自己对课程的掌握程度,熟悉QT开发环境,以及自己实际的动手能力,C++编程...
  • 下面记录下串口调试助手的开发,还并不是很完善,但是基本功能还是有的。一下就不一步步记录开发过程了,贴上代码,以及重点和需要注意的地方。最终代码如下:using System; using System.Collections.Generic; ...
  •  一个很好而小巧的串口调试助手,支持常用的300-115200bps波特率,能设置校验、数据位和停止位,能以ASCII码或十六进制接收或发送 任何数据或字符(包括中文),可以任意设定自动发送周期,并能将接收数据保存成文本...
  • 目的:采集5路的电压信号,并将电压显示在oled显示屏上,同时将数据同步传输到PC机的串口调试助手中,便于对数据进行后续处理。 源代码下载链接:https://download.csdn.net/download/wang903039690/10579488 硬件...
  • //按下哪一个键就在数码管上显示数字,并且传送到串口调试助手上 #include #include "uart.h" typedef unsigned char uint8; typedef unsigned int uint16; uint8 number[]={0x0c0,0x0F9,0x0A4,0x0B0,  0x...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,307
精华内容 922
关键字:

串口调试助手原理