串口 订阅
串行接口简称串口,也称串行通信接口或串行通讯接口(通常指COM接口),是采用串行通信方式的扩展接口。串行接口 (Serial Interface)是指数据一位一位地顺序传送。其特点是通信线路简单,只要一对传输线就可以实现双向通信(可以直接利用电话线作为传输线),从而大大降低了成本,特别适用于远距离通信,但传送速度较慢。 展开全文
串行接口简称串口,也称串行通信接口或串行通讯接口(通常指COM接口),是采用串行通信方式的扩展接口。串行接口 (Serial Interface)是指数据一位一位地顺序传送。其特点是通信线路简单,只要一对传输线就可以实现双向通信(可以直接利用电话线作为传输线),从而大大降低了成本,特别适用于远距离通信,但传送速度较慢。
信息
别    称
通常指COM接口
简    称
串口
中文名
串行接口
外文名
Serial Interface
串行接口定义
串行接口 (Serial Interface) 是指数据一位一位地顺序传送,其特点是通信线路简单,只要一对传输线就可以实现双向通信(可以直接利用电话线作为传输线),从而大大降低了成本,特别适用于远距离通信,但传送速度较慢。一条信息的各位数据被逐位按顺序传送的通讯方式称为串行通讯。串行通讯的特点是:数据位的传送,按位顺序进行,最少只需一根传输线即可完成;成本低但传送速度慢。串行通讯的距离可以从几米到几千米;根据信息的传送方向,串行通讯可以进一步分为单工、半双工和全双工三种。
收起全文
精华内容
下载资源
问答
  • 串口
    千次阅读 多人点赞
    2021-07-20 21:28:14

    一、设计概述

    1. UART串口通信设计目的

    随着 FPGA/CPLD 器件在控制领域的广泛使用,开发嵌于 FPGA/CPLD 器件内部的通用异步收发器,以实现 FPGA/CPLD 开发系统与 PC 机之间的数据通信是很有实际意义的。FPGA/CPLD与单片机、ARM等器件不同,它内部并没有集成UART,因此要实现串行通信必须要独立开发UART模块。

    通用异步收发器(Universal Asynchronous Receiver/Transmitter, 简称为UART)由于具有数据通信时需要的连线少,具有相关工业标准提供的标准的接口电平规范等优点,在工业控制领域被广泛采用。近年来,FPGA器件逐渐开始广泛使用,开发基于 FPGA/CPLD 器件内部的通用异步收发器,以实现 FPGA/CPLD 开发系统与 PC 机或其它外设之间的数据通信引起了 FPGA/CPLD 领域研究人员的关注。为此,本设计基于 FPGA 器件设计了符合 RS232 标准的UART,实现开发板与计算机串口助手之间的收发,并能够自行调节波特率。

    2. UART串口通信设计目的

    通用异步收发传输器(Universal Asynchronous Receiver/Transmitter,UART)是一种异步收发传输器,其在数据发送时将并行数据转换成串行数据来传输,在数据接收时将接收到的串行数据转换成并行数据,可以实现全双工传输和接收。它包括了 RS232、RS449、RS423、RS422 和 RS485 等接口标准规范和总线标准规范。换句话说,UART是异步串行通信的总称。而 RS232、RS449、RS423、RS422 和 RS485 等,是对应各种异步串行通信口的接口标准和总

    更多相关内容
  • 安卓串口调试工具.apk

    2018-11-19 17:47:03
    串口设备包括:串口打印机、电子秤、投影机、矩阵、摄像机、等离子、单片机等等。 可以手动选择串口和选择波特率。 APP支持发送16进制指令,发送字符串。 能接收设备返回信息,采用16进制显示。 本软件专业性很...
  • C#串口介绍以及简单串口通信程序设计和实现

    千次下载 热门讨论 2017-04-26 18:20:42
    C#串口介绍以及简单串口通信程序设计实现 源代码和串口程序介绍连接:https://www.cnblogs.com/JiYF/p/6618696.html 本站积分太贵,自己变得。。直接到连接地址下载代码 周末,没事干,写个简单的串口通信工具,也...
  • 该资源有两个,一是串口调试助手的源代码,可以实现数据的接收和发送;二是实现点击某个按钮发送指定数据的应用程序的源代码。代码都是含有详细的中文注释,可以直接编译通过,且内含可执行文件都是可以直接运行的。...
  • Android串口通信:串口读写

    热门讨论 2016-01-13 17:54:02
    Android 串口通信DEMO,包括JNI CPP代码,SO库等.rar,应大家要求把所需积分改了,全部开源,绝对保证能用。
  • Android串口通信(Android Studio)

    千次下载 热门讨论 2017-12-21 15:20:53
    Android串口通信(Android Studio) serial Port 简单的demo 好久之前整的
  • VB串口通信源码210个

    千次下载 热门讨论 2013-10-15 11:32:27
    001、VB串口通讯视频教程源码41个 002、Visual Basic串口通信工程开发实例导航随书源码7个 003、Visual Basic串口通信与测控应用技术实战详解 源代码(15个全) 004、GE PLC串口通讯,VB编制,读取内存单元 005、PC机...
  • Qt串口通信

    2016-03-17 17:13:44
    解决接收数据不完整
  • 通过在网络,将本地的串口数据传输到远程计算机,远程计算机发送控制命令到本地串口,对本地串口设备进行控制,让用户在远程即可以对串口设备进行控制操作。 软件功能: ComMax在本地建立数据通道可以将本地串口...
  • 串口设备调试工具

    千次下载 热门讨论 2013-12-20 13:38:17
    4:在不断接收到大量数据时,可以暂停显示数据来查看具体数据,后台依然接收数据但不处理,无需关闭串口来查看已接收到的数据。 5:每次收到的数据都是完整的一条数据,而不是脱节的,做了延时处理。
  • C#读取RS232串口扫描枪

    热门讨论 2017-02-07 10:49:51
    C#读取RS232串口扫描枪,可以实现多线程串口扫描枪输入
  • C#串口助手源代码,有winform的,也有WPF的,一共六个打包下载。代码来自网络。
  • 串口是什么

    千次阅读 多人点赞 2022-03-04 13:10:55
    串口,原名叫做串行接口(Serial Interface)或串列埠、序列埠,别名叫COM口(串行通讯端口( cluster communication port ))。PC 机一般有两个串行口COM 1 和COM 2 。串行口不同于并行口之处在于它的数据和控制信息...

    串口,原名叫做串行接口(Serial Interface)或串列埠、序列埠,别名叫COM口(串行通讯端口( cluster communication port )PC 机一般有两个串行口COM 1 和COM 2 。串行口不同于并行口之处在于它的数据和控制信息是一位接一位地传送出去的。虽然这样速度会慢一些,但传送距离较并行口更长,因此若要进行较长距离的通信时,应使用串行口。通常COM 1 使用的是9 针D 形连接器,也称之为RS-232接口,而COM 2 有的使用的是老式的DB25针连接器,也称之为RS-422接口,不过已经很少使用。只要进行串行通讯的应该都属于串口。

    串行端口

    接口特点

    串行端口(Serial port),或称串列埠、序列埠、串口,主要用于串列式逐位元数据传输。常见的为一般电脑

    RS-232 D型9针连接器

    1 载波检测(CD)

    2 接受数据(RXD)

    3 发出数据(TXD)

    4 数据终端准备好(DTR)

    5 信号地线(SG)

    6 数据准备好(DSR)

    7 请求发送(RTS)

    清除发送(CTS)

    9 振铃指示(RI)

    RS-232 DB25针连接器(即RS-422)

    应用的RS-232(使用 25 针或 9 针连接器),工业电脑应用的半双工RS-485与全双工RS-422。

    串口叫做串行接口,也称串行通信接口,按电气标准及协议来分包括RS-232-C、RS-422、RS485、USB等。 RS-232-C、RS-422与RS-485标准只对接口的电气特性做出规定,不涉及接外挂程式、电缆或协议。USB是近几年发展起来的新型接口标准,主要应用于高速数据传输领域。

    RS-232-C

    也称标准串口,是最常用的一种串行通讯接口。它是在1970年由美国电子工业协会(EIA)联合贝尔系统、 调制解调器厂家及计算机终端生产厂家共同制定的用于串行通讯的标准。它的全名是“数据终端设备(DTE)和数据通讯设备(DCE)之间串行二进制数据交换接口技术标准”。传统的RS-232-C接口标准有22根线,采用标准25芯D型插头座。后来的PC上使用简化了的9芯D型插座。如今应用中25芯插头座已很少采用。如今的电脑一般有两个串行口:COM1和COM2,你到计算机后面能看到9针D形接口就是了。如今有很多手机数据线或者物流接收器都采用COM口与计算机相连。

    接收时序

    RS-422

    为改进RS-232通信距离短、速率低的缺点,RS-422定义了一种平衡通信接口,将传输速率提高到10Mb/s,传输距离延长到4000英尺(1219.2 米)(速率低于100kb/s时),并允许在一条平衡总线上连接最多10个接收器。RS- 422是一种单机发送、多机接收的单向、平衡传输规范,被命名为TIA/EIA-422-A标准。

    RS-485

    为扩展应用范围,EIA又于1983年在RS-422基础上制定了RS-485 标准,增加了多点、双向通信能力,即允许多个发送器连接到同一条总线上,同时增加了发送器的驱动能力和冲突保护特性,扩展了总线共模范围,后命名为 TIA/EIA-485-A标准。

    SATA接口

    SATA的全称是Serial Advanced Technology Attachment(串行高级技术附件,一种基于行业标准的串行硬件驱动器接口),是由Intel、IBM、Dell、APT、Maxtor和Seagate公司共同提出的硬盘接口规范。

    SATA即指Serial ATA,串行ATA,相对于常见的IDE接口(一种PATA接口,Parallel ATA,并行ATA)。这是一种完全不同于并行ATA的新型硬盘接口类型,由于采用串行方式传输数据而得名。SATA总线使用嵌入式时钟信号,具备了更强的纠错能力,与以往相比其最大的区别在于能对传输指令(不仅仅是数据)进行检查,如果发现错误会自动矫正,这在很大程度上提高了数据传输的可靠性。串行接口还具有结构简单、支持热插拔的优点。如今,SATA分别有SATA 1.5Gbit/s、SATA 3Gbit/s和SATA 6Gbit/s三种规范。

    USB接口

    Universal Serial Bus(通用串行总线) 简称USB,是如今电脑上应用较广泛的接口规范,由Intel、Microsoft、Compaq、IBM、NEC、Northern Telcom等几家大厂商发起的新型外设接口标准。USB接口是电脑主板上的一种四针接口,其中中间两个针传输数据两边两个针给外设供电。USB接口速度快、连接简单、不需要外接电源,最新USB3.0可达5.0Gbps;电缆最大长度5米。USB2.0电缆有4条线,2条信号线,2条电源线,可提供5伏特电源;USB3.0接口有9条线,6条(3对)信号线,3条电源线(2.0和3.0部分各有一条GND线,共用Vbus线)。USB电缆还分屏蔽和非屏蔽两种,屏蔽电缆传输距离较长,价格较贵;非屏蔽电缆传输距离短,因为易受干扰,但价格便宜;USB通过串联方式最多可串接127个设备;支持热插拔

    USB接口规范

    USB1.0

    USB1.1

    USB2.0

    USB3.0

    接口速度

    1.5Mbps/192KBps

    12Mbps/1.5MBps

    480Mbps/60MBps

    5Gbps/640MBps

    图1 10针 RJ-45接口

    小写b代表bit(位),大写B代表Byte(字节),8b=1B;在二进制系统中,1G=1024M,1M=1024K我们平常说的多少T、G、M、K分别指的是TB、GB、MB、KB。

    10针 RJ-45接口

    RJ-45接口是以太网最为常用的接口,有八条针脚,RJ45是一个常用名称,指的是由IEC (60)603-7标准化,使用由国际性的接外挂程式标准定义的8个位置(8针)的模块化插孔或者插头。而用于串行数据传输的RJ-45接口不是标准接口,它有10条针脚,如图1所示。

    区别

    传输方式

    串口形容一下就是一条车道,而并口就是有8个车道同一时刻能传送8位(一个位元组)数据。 但是并不是并口快,由于8位通道之间的互相干扰。传输时速度就受到了限制。而且当传输出错时,要同时重新传8个位的数据。串口没有干扰,传输出错后重发一位就可以了。所以要比并口快。串口硬盘就是这样被人们重视的。 从原理上讲,串行传输是按位传输方式,只利用一条信号线进行传输,例如:要传送一个字节(8位)数据,是按照该字节中从最高位逐位传输,直至最低位

    而并行传输是一次将所有一字节中8位信号一并传送出去。自然最少需要8根信号线。

    如果按每次传送的数据流量来看,并行传输要远快于串口,在电脑发展初期,由于数据传输速率不是很高,并行传输还是很快的。

    发展趋势

    并口传输的发展主要存在以下两个问题:

    1、干扰问题。

    干扰产生的根本原因是由于传输速率太快,一般达到100M以上,信号线上传递的频率将超过100MHz。想想看,调频收音机的频率也不过88~108MHz,也就是说,若用并行传输的话,是8根天线放在一起来传输信号,不发生干扰才怪。但如果加强屏蔽,减小信号线间的耦合电容,是可以继续增大传输速率的,不过这将变得不现实,因为这必然导致信号线将耗用更多金属,截面积更大。但这并不是不能解决的问题。

    2、同步问题(最主要问题)

    并行传输时,发送器是同时将8位信号电平加在信号线上,电信号虽然是以光速传输的,但仍有延迟,因此8位信号不是严格同时到达接受端,速率小时,由于每一字节在信号线上的持续时间较长,这种到达时间上的不同步并不严重,随着传输速率的增加,与8位信号到达时间的差异相比,每一字节的持续时间显得越来越短,最终导致前一字节的某几位与后一字节的几位同时到达接受端,这就造成了传输失败,而且随着信号线的加长这种现象还会越发严重,直至无法使用。——这是并口传输的致命缺点。

    串行传输由于只有一位信号在信号线上,没有位同步问题,因此传送频率可以继续提高,当前传输速率已经达到1Gb/s(1000Mb)以上,而且还在提高,而并行传输在100Mb/s左右就停滞不前了,可以预见,串行传输将会比并行传输越来越快。

    常见串口

    RS-232:D型9针串口

    RCA:常见的一种音/视频接线端子

    RS-485:

    VGA:使用模拟信号的视频输出标准,15针

    HDMI:高清晰度多媒体接口,数字化视频/音频接口

    DVI:Digital Visual Interface,中文称为“数位视讯接口”

    Lightning:苹果高速多功能I/O接口

    DOCK:苹果之前的充电数据线

    Micro USB:USB 2.0标准的一个便携版本,节省空间,高寿命和强度

     RJ45:俗称的网线接口。RJ45是布线系统中信息插座(即通信引出端)连接器的一种,连接器由插头(接头、水晶头)和插座(模块)组成,插头有8个凹槽和8个触点。计算机网络的RJ45是标准8位模块化接口的俗称

    RJ11:俗称电话线接口,和网线不同的是只有4根针脚,RJ45为8根。

    参考:

    com口_百度百科

    串行口_百度百科

    各种类型的串口说明 - 冰西瓜先生 - 博客园

    展开全文
  • Java使用开源Rxtx实现串口通讯 串口开发

    千次下载 热门讨论 2014-04-13 15:48:48
    Java使用开源Rxtx实现串口通讯 串口开发,里面包含实例,下载后按自己的要求进行修改即可(仅限对java有基础的人员)。
  • vs2013 c++串口助手源码

    热门讨论 2015-12-24 09:23:25
    vs2013 c++ mfc 开发的串口助手源码 使用mscomm控件。欢迎大家下载
  • C# 串口通讯

    千次阅读 多人点赞 2021-12-17 10:32:09
    C#--使用WPF以及虚拟串口软件进行仿真通讯。

    简介

    串口是目前最常用的通讯接口之一,常用的标准接口有RS-232和RS-485,ModbusRTU通讯协议使用的一般也是串口。

    Virtual Serial Port Driver是一款串口仿真软件,如果当前没有设备或者连接线,而又需要进行串口通讯测试,它将是你的得力助手。

    以下为官网介绍:

    Virtual COM Port Driver is a powerful technology designed specifically for those who develop, test, or debug serial port software and hardware. This solution will provide your system with as many virtual COM interfaces as you need.

    If there are not enough physical COM ports or even if you don’t have a single real serial port on your computer, this dedicated software will come to the rescue. It will help you create pairs of virtual serial interfaces communicating via a virtual null-modem connection.

    You can use Virtual Serial Port Driver as a standalone solution or integrate its advanced functionality into your own product.

    本文将使用Virtual Serial Port Driver软件虚拟两个串口,并用C#实现串口通讯。

    本文代码已上传至GitHub,项目地址如下:

    https://github.com/XMNHCAS/SerialPortWPFDemo


    软件下载

    Virtual Serial Port Driver官网下载(如需汉化版,可以自行百度)

    UartAssist串口调试助手(免安装免注册,提供了各种校验算法、生成报文等功能)

    创建虚拟串口

    打开Virtual Serial Port Driver,设定需要创建的端口号,点击添加按钮就可以创建出两个相连的虚拟串行端口,如下图所示:

     此时打开UartAssist串口调试助手,可以看到刚刚已经创建出来的虚拟串口。


    搭建界面 

    首先创建一个WPF项目,接着按照个人喜好设计界面,可参考下图:

    XAML如下:

    <!--左右布局-->
        <Grid Margin="10">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="40*"/>
                <ColumnDefinition Width="60*"/>
            </Grid.ColumnDefinitions>
            
            <!--控制面板-->
            <GroupBox Header="控制面板" Grid.Column="0" Margin="10" Padding="10" >
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition/>
                        <RowDefinition/>
                        <RowDefinition/>
                        <RowDefinition/>
                        <RowDefinition/>
                        <RowDefinition/>
                        <RowDefinition/>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="40*"/>
                        <ColumnDefinition Width="70*"/>
                    </Grid.ColumnDefinitions>
                    <TextBlock Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" Text="可用串口:"  />
                    <ComboBox Grid.Row="0" Grid.Column="1" x:Name="cbxSerialPortList" ItemsSource="{Binding}" 
                              Margin="5" VerticalAlignment="Center" />
    
                    <TextBlock  Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" Text="连接状态:"/>
                    <TextBlock x:Name="tbxStatus"  Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" 
                               Margin="5,0,0,0"  Text="未连接" FontWeight="Bold"/>
    
                    <TextBlock  Grid.Row="2" Grid.Column="0" VerticalAlignment="Center" Text="波特率:"/>
                    <ComboBox Grid.Row="2" Grid.Column="1" x:Name="cbxBaudRate" ItemsSource="{Binding}" 
                              Margin="5" VerticalAlignment="Center" />
    
                    <TextBlock Grid.Row="3" Grid.Column="0" VerticalAlignment="Center" Text="奇偶校验:"/>
                    <ComboBox Grid.Row="3" Grid.Column="1" x:Name="cbxParity" ItemsSource="{Binding}" 
                              Margin="5" VerticalAlignment="Center" />
    
                    <TextBlock Grid.Row="4" Grid.Column="0" VerticalAlignment="Center" Text="数据位:"/>
                    <ComboBox Grid.Row="4" Grid.Column="1" x:Name="cbxDataBits" ItemsSource="{Binding}" 
                              Margin="5" VerticalAlignment="Center" />
    
                    <TextBlock Grid.Row="5" Grid.Column="0" VerticalAlignment="Center" Text="停止位:"/>
                    <ComboBox Grid.Row="5" Grid.Column="1" x:Name="cbxStopBits" ItemsSource="{Binding}" 
                              Margin="5" VerticalAlignment="Center" />
                    <Button x:Name="btnSwitch" Grid.Row="6" Grid.Column="1" Content="打开串口" 
                            Margin="5" Click="btnSwitch_Click"/>
                </Grid>
            </GroupBox>
    
            <!--消息面板-->
            <Grid Grid.Column="1" Margin="10">
                <Grid.RowDefinitions>
                    <RowDefinition Height="45*"/>
                    <RowDefinition Height="55*"/>
                </Grid.RowDefinitions>
    
                <!--发送消息-->
                <GroupBox Grid.Row="0" Header="发送消息" Margin="0,10,0,0" Padding="5">
                    <StackPanel VerticalAlignment="Center">
                        <Grid VerticalAlignment="Center" Margin="0,0,0,5">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition/>
                                <ColumnDefinition/>
                                <ColumnDefinition/>
                                <ColumnDefinition/>
                            </Grid.ColumnDefinitions>
                            <TextBlock Text="消息格式:" Grid.Column="0" VerticalAlignment="Center"/>
                            <ComboBox x:Name="cbxSendStatus" Grid.Column="1" ItemsSource="{Binding}"
                                      SelectionChanged="cbxSendStatus_SelectionChanged" Margin="0,0,5,0" />
                            <Button x:Name="btnClearSendText" Grid.Column="2" Content="清空" Margin="0,0,5,0" 
                                    Click="btnClearSendText_Click"/>
                            <Button x:Name="btnSend" Grid.Column="3" Content="发送" Click="btnSend_Click"/>
                        </Grid>
                        <RichTextBox x:Name="rbxSendMsg" Height="40" Margin="0,0,0,5"/>
                    </StackPanel>
                </GroupBox>
    
                <!--接收消息-->
                <GroupBox Grid.Row="1" Header="接收消息" Margin="0,10,0,0" Padding="5">
                    <StackPanel VerticalAlignment="Center">
                        <RichTextBox x:Name="rbxReceiveMsg" Height="100"/>
                    </StackPanel>
                </GroupBox>
            </Grid>
        </Grid>

    SerialPort使用示例

    SerialPort是C#提供的串行端口资源,位于System.IO.Ports,使用时需要引入此命名空间。通过此类可以很轻松地搭建串口通讯。

    使用示例如下:

            //串口实例
            SerialPort serialPort = new SerialPort();
    
            /// <summary>
            /// 串口参数
            /// </summary>
            public void SetSerialPort()
            {
                //获取当前计算机所有的串行端口名
                string[] serialProtArray = SerialPort.GetPortNames();
    
                //端口名,如COM1
                serialPort.PortName = "COM1";
    
                //波特率
                serialPort.BaudRate = 9600;
    
                //奇偶校验
                serialPort.Parity = Parity.None;
    
                //数据位
                serialPort.DataBits = 8;
    
                //停止位
                serialPort.StopBits = StopBits.One;
    
                //串口接收数据事件
                serialPort.DataReceived += ReceiveDataMethod;
            }
    
            /// <summary>
            /// 打开串口
            /// </summary>
            public void Open()
            {
                //打开串口
                serialPort.Open();
            }
    
            /// <summary>
            /// 关闭串口
            /// </summary>
            public void Close()
            {
                serialPort.Close();
            }
    
            /// <summary>
            /// 发送数据
            /// </summary>
            /// <param name="data">要发送的数据</param>
            public void SendDataMethod(byte[] data)
            {
                //获取串口状态,true为已打开,false为未打开
                bool isOpen = serialPort.IsOpen;
    
                if (!isOpen)
                {
                    Open();
                }
    
                //发送字节数组
                //参数1:包含要写入端口的数据的字节数组。
                //参数2:参数中从零开始的字节偏移量,从此处开始将字节复制到端口。
                //参数3:要写入的字节数。 
                serialPort.Write(data, 0, data.Length);
            }
    
            /// <summary>
            /// 发送数据
            /// </summary>
            /// <param name="data">要发送的数据</param>
            public void SendDataMethod(string data)
            {
                //获取串口状态,true为已打开,false为未打开
                bool isOpen = serialPort.IsOpen;
    
                if (!isOpen)
                {
                    Open();
                }
    
                //直接发送字符串
                serialPort.Write(data);
            }
    
            /// <summary>
            /// 串口接收到数据触发此方法进行数据读取
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void ReceiveDataMethod(object sender, SerialDataReceivedEventArgs e)
            {
                //读取串口缓冲区的字节数据
                byte[] result = new byte[serialPort.BytesToRead];
                serialPort.Read(result, 0, serialPort.BytesToRead);
            }

    具体实现示例

    设置窗体:

            /// <summary>
            /// 窗体构造函数
            /// </summary>
            public MainWindow()
            {
                InitializeComponent();
    
                //获取串口列表
                cbxSerialPortList.DataContext = SerialPort.GetPortNames();
                //设置可选波特率
                cbxBaudRate.DataContext = new object[] { 9600, 19200 };
                //设置可选奇偶校验
                cbxParity.DataContext = new object[] { "None", "Odd", "Even", "Mark", "Space" };
                //设置可选数据位
                cbxDataBits.DataContext = new object[] { 5, 6, 7, 8 };
                //设置可选停止位
                cbxStopBits.DataContext = new object[] { 1, 1.5, 2 };
                //设置发送模式
                cbxSendStatus.DataContext = new object[] { "文本", "字节" };
    
                //设置默认选中项
                cbxSerialPortList.SelectedIndex = 0;
                cbxBaudRate.SelectedIndex = 0;
                cbxParity.SelectedIndex = 0;
                cbxDataBits.SelectedIndex = 3;
                cbxStopBits.SelectedIndex = 0;
                cbxSendStatus.SelectedIndex = 0;
    
                rbxReceiveMsg.Document.Blocks.Clear();
                btnSend.IsEnabled = false;
    
                //注册串口接收到数据事件的回调函数
                serialPort.DataReceived += GetReceiveMsg;
            }

    串口开关事件:

     /// <summary>
            /// 打开或关闭串口
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnSwitch_Click(object sender, RoutedEventArgs e)
            {
                if (!serialPort.IsOpen)
                {
                    //设定参数
                    serialPort.PortName = cbxSerialPortList.SelectedItem.ToString();
                    serialPort.BaudRate = (int)cbxBaudRate.SelectedItem;
                    serialPort.Parity = GetSelectedParity();
                    serialPort.DataBits = (int)cbxDataBits.SelectedItem;
                    serialPort.StopBits = GetSelectedStopBits();
    
                    try
                    {
                        //打开串口
                        serialPort.Open();
                    }
                    catch (Exception)
                    {
                        MessageBox.Show("无法打开此串口,请检查是否被占用");
                        return;
                    }
    
                    //切换文本
                    tbxStatus.Text = "已连接";
                    btnSwitch.Content = "关闭串口";
    
                    //切换可用状态
                    cbxSerialPortList.IsEnabled = false;
                    cbxBaudRate.IsEnabled = false;
                    cbxParity.IsEnabled = false;
                    cbxDataBits.IsEnabled = false;
                    cbxStopBits.IsEnabled = false;
    
                    btnSend.IsEnabled = true;
                }
                else
                {
                    if (serialPort != null)
                    {
                        //关闭串口
                        serialPort.Close();
                    }
    
                    //切换文本
                    tbxStatus.Text = "未连接";
                    btnSwitch.Content = "打开串口";
    
                    //切换可用状态
                    cbxSerialPortList.IsEnabled = true;
                    cbxBaudRate.IsEnabled = true;
                    cbxParity.IsEnabled = true;
                    cbxDataBits.IsEnabled = true;
                    cbxStopBits.IsEnabled = true;
    
                    btnSend.IsEnabled = false;
                }
            }

    向串口发送数据:

            /// <summary>
            /// 发送数据
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnSend_Click(object sender, RoutedEventArgs e)
            {
                //获取RichTextBox上的文本
                string str = new TextRange(rbxSendMsg.Document.ContentStart, rbxSendMsg.Document.ContentEnd).Text;
                if (string.IsNullOrEmpty(str.Replace("\r\n", "")))
                {
                    MessageBox.Show("未输入消息");
                    return;
                }
    
                //判断读写模式
                if (sendText)
                {
                    //发送字符串
                    serialPort.Write(str);
                }
                else
                {
                    str = str.Replace(" ", "").Replace("\r\n", "");
    
                    //将输入的16进制字符串两两分割为字符串集合
                    var strArr = Regex.Matches(str, ".{2}").Cast<Match>().Select(m => m.Value);
    
                    //需要发送的字节数组
                    byte[] data = new byte[strArr.Count()];
                    
                    //循环索引
                    int temp = 0;
    
                    //将字符串集合转换为字节数组
                    foreach (string item in strArr)
                    {
                        data[temp] = Convert.ToByte(item, 16);
                        temp++;
                    }
    
                    //发送字节
                    serialPort.Write(data, 0, data.Length);
                }
    
                MessageBox.Show("发送成功");
            }

    读取接收到的数据:

            /// <summary>
            /// 获取接收到的数据
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void GetReceiveMsg(object sender, SerialDataReceivedEventArgs e)
            {
                //读取串口缓冲区的字节数据
                byte[] result = new byte[serialPort.BytesToRead];
                serialPort.Read(result, 0, serialPort.BytesToRead);
    
                string str = $"{DateTime.Now}\n";
    
                //判断读写模式
                //将接收到的字节数组转换为指定的消息格式
                if (sendText)
                {
                    str += $"{Encoding.UTF8.GetString(result)}";
                }
                else
                {
                    for (int i = 0; i < result.Length; i++)
                    {
                        str += $"{result[i].ToString("X2")} ";
                    }
                }
    
                //在窗体中显示接收到的消息
                SetRecMsgRbx(str.Trim());
            }

    需要注意串口接收到数据的时候触发的事件并不是主线程里面执行的,而是另开了一个新的线程,如果需要访问主线程并将数据在WPF窗口中显示,则需要通过委托的方式进行跨线程操作,如下所示:

            /// <summary>
            /// 为显示接收消息的富文本框添加文本
            /// </summary>
            /// <param name="str"></param>
            private void SetRecMsgRbx(string str)
            {
                rbxReceiveMsg.Dispatcher.BeginInvoke(new Action(() =>
                {
                    Run run = new Run(str);
                    Paragraph p = new Paragraph();
                    p.Inlines.Add(run);
                    rbxReceiveMsg.Document.Blocks.Add(p);
                }));
            }

    完整示例

    using System;
    using System.Collections.Generic;
    using System.IO.Ports;
    using System.Linq;
    using System.Text;
    using System.Text.RegularExpressions;
    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.Markup;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace SerialPortWPF
    {
        /// <summary>
        /// MainWindow.xaml 的交互逻辑
        /// </summary>
        public partial class MainWindow : Window
        {
            //串口实例
            SerialPort serialPort = new SerialPort();
    
            //是否发送文本
            bool sendText = true;
    
            /// <summary>
            /// 窗体构造函数
            /// </summary>
            public MainWindow()
            {
                InitializeComponent();
    
                //获取串口列表
                cbxSerialPortList.DataContext = SerialPort.GetPortNames();
                //设置可选波特率
                cbxBaudRate.DataContext = new object[] { 9600, 19200 };
                //设置可选奇偶校验
                cbxParity.DataContext = new object[] { "None", "Odd", "Even", "Mark", "Space" };
                //设置可选数据位
                cbxDataBits.DataContext = new object[] { 5, 6, 7, 8 };
                //设置可选停止位
                cbxStopBits.DataContext = new object[] { 1, 1.5, 2 };
                //设置发送模式
                cbxSendStatus.DataContext = new object[] { "文本", "字节" };
    
                //设置默认选中项
                cbxSerialPortList.SelectedIndex = 0;
                cbxBaudRate.SelectedIndex = 0;
                cbxParity.SelectedIndex = 0;
                cbxDataBits.SelectedIndex = 3;
                cbxStopBits.SelectedIndex = 0;
                cbxSendStatus.SelectedIndex = 0;
    
                rbxReceiveMsg.Document.Blocks.Clear();
                btnSend.IsEnabled = false;
    
                //注册串口接收到数据事件的回调函数
                serialPort.DataReceived += GetReceiveMsg;
            }
    
            /// <summary>
            /// 打开或关闭串口
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnSwitch_Click(object sender, RoutedEventArgs e)
            {
                if (!serialPort.IsOpen)
                {
                    //设定参数
                    serialPort.PortName = cbxSerialPortList.SelectedItem.ToString();
                    serialPort.BaudRate = (int)cbxBaudRate.SelectedItem;
                    serialPort.Parity = GetSelectedParity();
                    serialPort.DataBits = (int)cbxDataBits.SelectedItem;
                    serialPort.StopBits = GetSelectedStopBits();
    
                    try
                    {
                        //打开串口
                        serialPort.Open();
                    }
                    catch (Exception)
                    {
                        MessageBox.Show("无法打开此串口,请检查是否被占用");
                        return;
                    }
    
                    //切换文本
                    tbxStatus.Text = "已连接";
                    btnSwitch.Content = "关闭串口";
    
                    //切换可用状态
                    cbxSerialPortList.IsEnabled = false;
                    cbxBaudRate.IsEnabled = false;
                    cbxParity.IsEnabled = false;
                    cbxDataBits.IsEnabled = false;
                    cbxStopBits.IsEnabled = false;
    
                    btnSend.IsEnabled = true;
                }
                else
                {
                    if (serialPort != null)
                    {
                        //关闭串口
                        serialPort.Close();
                    }
    
                    //切换文本
                    tbxStatus.Text = "未连接";
                    btnSwitch.Content = "打开串口";
    
                    //切换可用状态
                    cbxSerialPortList.IsEnabled = true;
                    cbxBaudRate.IsEnabled = true;
                    cbxParity.IsEnabled = true;
                    cbxDataBits.IsEnabled = true;
                    cbxStopBits.IsEnabled = true;
    
                    btnSend.IsEnabled = false;
                }
            }
    
            /// <summary>
            /// 切换读写模式
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void cbxSendStatus_SelectionChanged(object sender, SelectionChangedEventArgs e)
            {
                sendText = cbxSendStatus.SelectedItem.ToString() == "文本" ? true : false;
            }
    
            /// <summary>
            /// 发送数据
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnSend_Click(object sender, RoutedEventArgs e)
            {
                //获取RichTextBox上的文本
                string str = new TextRange(rbxSendMsg.Document.ContentStart, rbxSendMsg.Document.ContentEnd).Text;
                if (string.IsNullOrEmpty(str.Replace("\r\n", "")))
                {
                    MessageBox.Show("未输入消息");
                    return;
                }
    
                //判断读写模式
                if (sendText)
                {
                    //发送字符串
                    serialPort.Write(str);
                }
                else
                {
                    str = str.Replace(" ", "").Replace("\r\n", "");
    
                    //将输入的16进制字符串两两分割为字符串集合
                    var strArr = Regex.Matches(str, ".{2}").Cast<Match>().Select(m => m.Value);
    
                    //需要发送的字节数组
                    byte[] data = new byte[strArr.Count()];
                    
                    //循环索引
                    int temp = 0;
    
                    //将字符串集合转换为字节数组
                    foreach (string item in strArr)
                    {
                        data[temp] = Convert.ToByte(item, 16);
                        temp++;
                    }
    
                    //发送字节
                    serialPort.Write(data, 0, data.Length);
                }
    
                MessageBox.Show("发送成功");
            }
    
            /// <summary>
            /// 清空发送框的文本
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnClearSendText_Click(object sender, RoutedEventArgs e)
            {
                rbxSendMsg.Document.Blocks.Clear();
            }
    
            /// <summary>
            /// 获取接收到的数据
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void GetReceiveMsg(object sender, SerialDataReceivedEventArgs e)
            {
                //读取串口缓冲区的字节数据
                byte[] result = new byte[serialPort.BytesToRead];
                serialPort.Read(result, 0, serialPort.BytesToRead);
    
                string str = $"{DateTime.Now}:\n";
    
                //判断读写模式
                //将接收到的字节数组转换为指定的消息格式
                if (sendText)
                {
                    str += $"{Encoding.UTF8.GetString(result)}";
                }
                else
                {
                    for (int i = 0; i < result.Length; i++)
                    {
                        str += $"{result[i].ToString("X2")} ";
                    }
                }
    
                //在窗体中显示接收到的消息
                SetRecMsgRbx(str.Trim());
            }
    
            /// <summary>
            /// 为显示接收消息的富文本框添加文本
            /// </summary>
            /// <param name="str"></param>
            private void SetRecMsgRbx(string str)
            {
                rbxReceiveMsg.Dispatcher.BeginInvoke(new Action(() =>
                {
                    Run run = new Run(str);
                    Paragraph p = new Paragraph();
                    p.Inlines.Add(run);
                    rbxReceiveMsg.Document.Blocks.Add(p);
                }));
            }
    
            /// <summary>
            /// 获取窗体选中的奇偶校验
            /// </summary>
            /// <returns></returns>
            private Parity GetSelectedParity()
            {
                switch (cbxParity.SelectedItem.ToString())
                {
                    case "Odd":
                        return Parity.Odd;
                    case "Even":
                        return Parity.Even;
                    case "Mark":
                        return Parity.Mark;
                    case "Space":
                        return Parity.Space;
                    case "None":
                    default:
                        return Parity.None;
                }
            }
    
            /// <summary>
            /// 获取窗体选中的停止位
            /// </summary>
            /// <returns></returns>
            private StopBits GetSelectedStopBits()
            {
                switch (Convert.ToDouble(cbxStopBits.SelectedItem))
                {
                    case 1:
                        return StopBits.One;
                    case 1.5:
                        return StopBits.OnePointFive;
                    case 2:
                        return StopBits.Two;
                    default:
                        return StopBits.One;
                }
            }
        }
    }
    

    效果测试

    文本收发: 

    字节收发: 


    结尾

    在C#中实现串口通讯是比较简单的,但是用到真实的设备通讯的时候,往往会涉及到一些报文格式的问题,而报文比较麻烦的就是计算校验码,这里提供常用的两种常用的校验算法:BCC异或校验、CRC16循环冗余校验。

    BCC:

    public static byte[] BCC(byte[] data)
    {
        int temp = 0;
        for (int index = 0; index < data.Length; index++)
        {
            temp = temp ^ data[index];
        }
    
        byte[] result = new byte[1];
    
        result[0] = Convert.ToByte(temp);
    
        return result;
    }

    CRC16:

    public static byte[] CRC16(string code)
    {
        var strArr = Regex.Matches(code, ".{2}").Cast<Match>().Select(m => m.Value);
        byte[] pDataBytes = new byte[strArr.Count()];
        int temp = 0;
        foreach (var item in strArr)
        {
            pDataBytes[temp] = Convert.ToByte(item, 16);
            temp++;
        }
        ushort crc = 0xffff;
        ushort polynom = 0xA001;
    
        for (int i = 0; i < pDataBytes.Length; i++)
        {
            crc ^= pDataBytes[i];
            for (int j = 0; j < 8; j++)
            {
                if ((crc & 0x01) == 0x01)
                {
                    crc >>= 1;
                    crc ^= polynom;
                }
                else
                {
                    crc >>= 1;
                }
            }
        }
    
        return BitConverter.GetBytes(crc);
    }
    展开全文
  • 内有简要调试方法,如有问题可以联系qq 287068830, 提供简单指导,软件包中只有apk软件, 已测试ok, 源码还未找到,adt,串口工具请自行度娘
  • QT实现串口通信

    千次阅读 多人点赞 2022-03-11 19:39:01
    要实现串口通信,需要知道串口通信需要的信息 主要参数有:波特率、校验位、数据位、停止位、控制流 主要操作有:串口的打开和关闭、刷新设备串口、接发数据、开关显示灯等。 实现效果如图: 最后附赠完整源码...

    要实现串口通信,需要知道串口通信需要的信息

    主要参数有:波特率、校验位、数据位、停止位、控制流

    主要操作有:串口的打开和关闭、刷新设备串口、接发数据、开关显示灯等。

    实现效果如图:

    界面设计如下:

    每个控件类名如下:

     

     

     LED灯是QLable控件,设置它的长宽都是24px,然后鼠标右击,选择“样式表”,在样式表中添加代码。

     

     

    最后附赠完整源码。

    第一步:在头文件中引入 QtSerialPort 类的两个头文件(必须引入)

    // 引入串口通信的两个头文件(第一步)
    #include <QtSerialPort/QSerialPort>         // 提供访问串口的功能
    #include <QtSerialPort/QSerialPortInfo>     // 提供系统中存在的串口信息

    第二步:在工程文件中添加以下代码

    # 引入串口工程类型(第二步)
    QT       += serialport

    第三步:在头文件中定义全局的串口对象

    QSerialPort     *serial;                            // 定义全局的串口对象(第三步)

    第四步:参数设置,在头文件中定义初始化参数的函数和参数变量名,在.cpp文件中实现函数

    public:
    void        SerialPortInit();                      // 串口初始化(参数配置)
    
    private:
    // 参数配置
        QStringList     baudList;                           //波特率
        QStringList     parityList;                         //校验位
        QStringList     dataBitsList;                       //数据位
        QStringList     stopBitsList;                       //停止位
        QStringList     flowControlList;                    //控制流
    // 串口初始化(参数配置)
    void MainWindow::SerialPortInit()
    {
        serial = new QSerialPort;                       //申请内存,并设置父对象
    
        // 获取计算机中有效的端口号,然后将端口号的名称给端口选择控件
        foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
        {
            serial->setPort(info);                      // 在对象中设置串口
            if(serial->open(QIODevice::ReadWrite))      // 以读写方式打开串口
            {
                ui->PortBox->addItem(info.portName());  // 添加计算机中的端口
                serial->close();                        // 关闭
            } else
            {
                qDebug() << "串口打开失败,请重试";
            }
        }
    
        // 参数配置
        // 波特率,波特率默认选择57600 ,禁止用户点击
        ui->BaudBox->addItem("57600");
        serial->setBaudRate(QSerialPort::Baud57600);
        ui->BaudBox->setDisabled(true);
    
        // 校验,校验默认选择无
        ui->ParityBox->addItem("无");
        serial->setParity(QSerialPort::NoParity);
    
        // 数据位,数据位默认选择8位
        ui->BitBox->addItem("8");
        serial->setDataBits(QSerialPort::Data8);
    
        // 停止位,停止位默认选择1位
        ui->StopBox->addItem("1");
        serial->setStopBits(QSerialPort::OneStop);
    
        // 控制流,默认选择无
        ui->ControlBox->addItem("无");
        serial->setFlowControl(QSerialPort::NoFlowControl);
    
        // 刷新串口
        RefreshSerialPort(0);
    
        // 信号
    connect(serial,&QSerialPort::readyRead,this,&MainWindow::DataReceived);      // 接收数据
    connect(ui->SendWordOrder,&QPushButton::clicked,this,&MainWindow::DataSend); // 发送数据
    connect(ui->SendButton,&QPushButton::clicked,this,&MainWindow::DataSend);    // 发送数据
    connect(ui->SendEditBtn1,&QPushButton::clicked,this,&MainWindow::DataSend);  // 发送数据
    connect(ui->SendEditBtn2,&QPushButton::clicked,this,&MainWindow::DataSend);  // 发送数据
    connect(ui->SendEditBtn3,&QPushButton::clicked,this,&MainWindow::DataSend);  // 发送数据
    }

    第五步:刷新串口,及时更新可用的串口

    // 刷新串口
    void MainWindow::RefreshSerialPort(int index)
    {
        QStringList portNameList;                                        // 存储所有串口名
        if(index != 0)
        {
            serial->setPortName(ui->PortBox->currentText());             //设置串口号
        }
        else
        {
            ui->PortBox->clear();                                        //关闭串口号
            ui->PortBox->addItem("刷新");                                //添加刷新
            foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts()) //添加新串口
            {
                portNameList.append(info.portName());
            }
            ui->PortBox->addItems(portNameList);
            ui->PortBox->setCurrentIndex(1);                             // 当前串口号为COM1
            serial->setPortName(ui->PortBox->currentText());             //设置串口号
       }
    }

    第六步:发送数据和接收数据

    // 接收数据,使用read () / readLine () / readAll ()
    void MainWindow::DataReceived()
    {
        char BUF[512] = {0};                                       // 存储转换类型后的数据
        QByteArray data = serial->readAll();                      // 读取数据
    
        if(!data.isEmpty())                                 // 接收到数据
        {
            QString str = ui->DataReceived->toPlainText();  // 返回纯文本
            str += tr(data);                         // 数据是一行一行传送的,要保存所有数据
            ui->DataReceived->clear();                      // 清空之前的数据
            ui->DataReceived->append(str);                  // 将数据放入控件中
            qDebug() << "str info: " << ui->DataReceived->toPlainText();
    
             // 清除之前的数据,防止追加,因为每次获取的数据不一样
            int index = str.indexOf("\r\n");                // 找到,返回索引值,找不到,返回-1
            if(index != -1)
            {
                snprintf(BUF,500,"%s", str.left(index + 2).toUtf8().data()); // QString转为char * 类型
                qDebug() << "BUF info: " << BUF;        // 数据类型转换成功
                str.remove(0,index + 2); 
    
                // 处理获取到的数据,将其放入对应的控件中
                // .....
                                 
            }
        }
    }
    
    // 发送数据,write ()
    void MainWindow::DataSend()
    {
        serial->write(ui->DataSend->toPlainText().toLatin1());      // 串口发送数据
    }

    第七步:打开串口和关闭串口,当打开串口后,显示绿灯;关闭串口后,显示红灯

    // 串口开关
    void MainWindow::on_OpenSerialButton_clicked()
    {
        if(serial->isOpen())                                  // 如果串口打开了,先给他关闭
        {
            serial->clear();
            serial->close();
            // 关闭状态,按钮显示“打开串口”
            ui->OpenSerialButton->setText("打开串口");
            // 关闭状态,允许用户操作
            ui->BaudBox->setDisabled(false);
            ui->ParityBox->setDisabled(false);
            ui->BitBox->setDisabled(false);
            ui->StopBox->setDisabled(false);
            ui->ControlBox->setDisabled(false);
            // 禁止操作“发送字符操作”
            ui->SendWordOrder->setDisabled(true);
            ui->SendButton->setDisabled(true);
            // 关闭状态,颜色为绿色
            ui->OpenSerialButton->setStyleSheet("color: green;");
            // 关闭,显示灯为红色
            LED(true);
            // 清空数据
            ui->DataReceived->clear();
            ui->DataSend->clear();
        }
        else                                             // 如果串口关闭了,先给他打开
        {
            //当前选择的串口名字
            serial->setPortName(ui->PortBox->currentText());
            //用ReadWrite 的模式尝试打开串口,无法收发数据时,发出警告
            if(!serial->open(QIODevice::ReadWrite))
            {
                QMessageBox::warning(this,tr("提示"),tr("串口打开失败!"),QMessageBox::Ok);
                return;
             }
            // 打开状态,按钮显示“关闭串口”
            ui->OpenSerialButton->setText("关闭串口");
            // 打开状态,禁止用户操作
            ui->BaudBox->setDisabled(true);
            ui->ParityBox->setDisabled(true);
            ui->BitBox->setDisabled(true);
            ui->StopBox->setDisabled(true);
            ui->ControlBox->setDisabled(true);
            // 允许操作“发送字符操作”
            ui->SendWordOrder->setDisabled(false);
            ui->SendButton->setDisabled(false);
            // 打开状态,颜色为红色
            ui->OpenSerialButton->setStyleSheet("color: red;");
            // 打开,显示灯为绿色
            LED(false);
        }
    }
    
    // 开关显示灯
    void  MainWindow::LED(bool changeColor)
    {
        if(changeColor == false)
        {
            // 显示绿色
            ui->LED->setStyleSheet("background-color: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5, stop:0 rgba(0, 229, 0, 255), stop:1 rgba(255, 255, 255, 255));border-radius:12px;");
        }
        else
        {
            // 显示红色
            ui->LED->setStyleSheet("background-color: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5, stop:0 rgba(255, 0, 0, 255), stop:1 rgba(255, 255, 255, 255));border-radius:12px;");
        }
    }

    第八步:相关槽函数

    // 控件中添加 #
    void MainWindow::on_SendButton_clicked()
    {
        on_ClearButton_clicked();
        ui->DataSend->append("#");
    }
    // 清空控件
    void MainWindow::on_ClearButton_clicked()
    {
        ui->DataSend->setText("");
    }
    // 清空接收到的数据
    void MainWindow::on_ClearShowButton_clicked()
    {
        ui->DataReceived->setText("");
    }
    // 点击发送后,获取串口信息并展示在接受控件中
    void MainWindow::on_SendEditBtn1_clicked()
    {
        on_ClearButton_clicked();
        QString EditText = ui->Edit1->text();               //获取发送框内容
        ui->DataSend->setText(EditText);                     //将文本内容放在发送栏中
    }
    
    void MainWindow::on_SendEditBtn2_clicked()
    {
        on_ClearButton_clicked();
        QString EditText = ui->Edit2->text();               //获取发送框内容
    
        // qDebug() << "Edit1 text: " << EditText;
    
        ui->DataSend->append(EditText);                     //将文本内容放在发送栏中
    }
    
    void MainWindow::on_SendEditBtn3_clicked()
    {
        on_ClearButton_clicked();
        QString EditText = ui->Edit3->text();               //获取发送框内容
    
        // qDebug() << "Edit1 text: " << EditText;
    
        ui->DataSend->append(EditText);                     //将文本内容放在发送栏中
    }
    
    
    
    void MainWindow::on_SendWordOrder_clicked()
    {
        on_SendButton_clicked();
    }
    

    源码:

    工程文件.pro文件源码:

    QT       += core gui
    # 引入串口工程类型(第二步)
    QT       += serialport
    
    greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
    
    CONFIG += c++11
    
    # The following define makes your compiler emit warnings if you use
    # any Qt feature that has been marked deprecated (the exact warnings
    # depend on your compiler). Please consult the documentation of the
    # deprecated API in order to know how to port your code away from it.
    DEFINES += QT_DEPRECATED_WARNINGS
    
    # You can also make your code fail to compile if it uses deprecated APIs.
    # In order to do so, uncomment the following line.
    # You can also select to disable deprecated APIs only up to a certain version of Qt.
    #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
    
    SOURCES += \
        main.cpp \
        mainwindow.cpp
    
    HEADERS += \
        mainwindow.h
    
    FORMS += \
        mainwindow.ui
    
    # Default rules for deployment.
    qnx: target.path = /tmp/$${TARGET}/bin
    else: unix:!android: target.path = /opt/$${TARGET}/bin
    !isEmpty(target.path): INSTALLS += target
    

    头文件源码:

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    // 引入串口通信的两个头文件(第一步)
    #include <QtSerialPort/QSerialPort>         // 提供访问串口的功能
    #include <QtSerialPort/QSerialPortInfo>     // 提供系统中存在的串口信息
    
    QT_BEGIN_NAMESPACE
    namespace Ui { class MainWindow; }
    QT_END_NAMESPACE
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    
        // 串口功能
        void        SerialPortInit();                      // 串口初始化(参数配置)
        void        RefreshSerialPort(int index);          // 刷新串口
    
    public slots:
        // 串口槽函数
        void        DataReceived();                        // 接收数据
    private slots:
        // 串口槽函数
        void        DataSend();                            // 发送数据
    
        void        on_OpenSerialButton_clicked();         // 串口开关
    
        void        on_SendButton_clicked();               // 控件中添加 #
    
        void        on_ClearButton_clicked();              // 清空控件中的所有 #
    
        void        on_ClearShowButton_clicked();          // 清空接收到的数据
    
        void        LED(bool changeColor);                 // 开关显示灯
    
        // 点击发送,接收数据
        void        on_SendEditBtn1_clicked();
    
        void        on_SendEditBtn2_clicked();
    
        void        on_SendEditBtn3_clicked();
    
    
        void on_SendWordOrder_clicked();
    
    private:
        Ui::MainWindow *ui;
    
        // 串口变量
        QSerialPort     *serial;                            // 定义全局的串口对象(第三步)
        // 参数配置
        QStringList     baudList;                           //波特率
        QStringList     parityList;                         //校验位
        QStringList     dataBitsList;                       //数据位
        QStringList     stopBitsList;                       //停止位
        QStringList     flowControlList;                    //控制流
    };
    #endif // MAINWINDOW_H
    

    .cpp文件源码:

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include <QDebug>
    #include <QMessageBox>
    
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        SerialPortInit();
    }
    
    // 串口初始化(参数配置)
    void MainWindow::SerialPortInit()
    {
        serial = new QSerialPort;                       //申请内存,并设置父对象
    
        // 获取计算机中有效的端口号,然后将端口号的名称给端口选择控件
        foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
        {
            serial->setPort(info);                      // 在对象中设置串口
            if(serial->open(QIODevice::ReadWrite))      // 以读写方式打开串口
            {
                ui->PortBox->addItem(info.portName());  // 添加计算机中的端口
                serial->close();                        // 关闭
            } else
            {
                qDebug() << "串口打开失败,请重试";
            }
        }
    
        // 参数配置
        // 波特率,波特率默认选择57600 ,禁止用户点击
        ui->BaudBox->addItem("57600");
        serial->setBaudRate(QSerialPort::Baud57600);
        ui->BaudBox->setDisabled(true);
    
        // 校验,校验默认选择无
        ui->ParityBox->addItem("无");
        serial->setParity(QSerialPort::NoParity);
    
        // 数据位,数据位默认选择8位
        ui->BitBox->addItem("8");
        serial->setDataBits(QSerialPort::Data8);
    
        // 停止位,停止位默认选择1位
        ui->StopBox->addItem("1");
        serial->setStopBits(QSerialPort::OneStop);
    
        // 控制流,默认选择无
        ui->ControlBox->addItem("无");
        serial->setFlowControl(QSerialPort::NoFlowControl);
    
        // 刷新串口
        RefreshSerialPort(0);
    
        // 信号
        connect(serial,&QSerialPort::readyRead,this,&MainWindow::DataReceived);         // 接收数据
        connect(ui->SendWordOrder,&QPushButton::clicked,this,&MainWindow::DataSend);    // 发送数据
        connect(ui->SendButton,&QPushButton::clicked,this,&MainWindow::DataSend);       // 发送数据
        connect(ui->SendEditBtn1,&QPushButton::clicked,this,&MainWindow::DataSend);    // 发送数据
        connect(ui->SendEditBtn2,&QPushButton::clicked,this,&MainWindow::DataSend);    // 发送数据
        connect(ui->SendEditBtn3,&QPushButton::clicked,this,&MainWindow::DataSend);    // 发送数据
    
    }
    // 刷新串口
    void MainWindow::RefreshSerialPort(int index)
    {
        QStringList portNameList;                                        // 存储所有串口名
        if(index != 0)
        {
            serial->setPortName(ui->PortBox->currentText());             //设置串口号
        }
        else
        {
            ui->PortBox->clear();                                        //关闭串口号
            ui->PortBox->addItem("刷新");                                //添加刷新
            foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts()) //添加新串口
            {
                portNameList.append(info.portName());
            }
           
            ui->PortBox->addItems(portNameList);
            ui->PortBox->setCurrentIndex(1);                             // 当前串口号为COM1
            serial->setPortName(ui->PortBox->currentText());             //设置串口号
       }
    }
    
    // 接收数据,使用read () / readLine () / readAll ()
    void MainWindow::DataReceived()
    {
        char BUF[512] = {0};                                       // 存储转换类型后的数据
        QByteArray data = serial->readAll();                      // 读取数据
    
        if(!data.isEmpty())                                 // 接收到数据
        {
            QString str = ui->DataReceived->toPlainText();  // 返回纯文本
            str += tr(data);                                // 数据是一行一行传送的,要保存所有数据
            ui->DataReceived->clear();                      // 清空之前的数据
            ui->DataReceived->append(str);                  // 将数据放入控件中
            qDebug() << "str info: " << ui->DataReceived->toPlainText();
    
             // 清除之前的数据,防止追加,因为每次获取的数据不一样
            int index = str.indexOf("\r\n");                // 找到,返回索引值,找不到,返回-1
            if(index != -1)
            {
                snprintf(BUF,500,"%s", str.left(index + 2).toUtf8().data()); // QString转为char * 类型
                qDebug() << "BUF info: " << BUF;
                str.remove(0,index + 2);
    
                // 处理获取到的数据,将其放入对应的控件中
                // ....
            }
        }
    }
    // 发送数据,write ()
    void MainWindow::DataSend()
    {
        serial->write(ui->DataSend->toPlainText().toLatin1());      // 串口发送数据
    }
    
    // 开关显示灯
    void  MainWindow::LED(bool changeColor)
    {
        if(changeColor == false)
        {
            // 显示绿色
            ui->LED->setStyleSheet("background-color: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5, stop:0 rgba(0, 229, 0, 255), stop:1 rgba(255, 255, 255, 255));border-radius:12px;");
        }
        else
        {
            // 显示红色
            ui->LED->setStyleSheet("background-color: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5, stop:0 rgba(255, 0, 0, 255), stop:1 rgba(255, 255, 255, 255));border-radius:12px;");
        }
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    // 串口开关
    void MainWindow::on_OpenSerialButton_clicked()
    {
        if(serial->isOpen())                                        // 如果串口打开了,先给他关闭
        {
            serial->clear();
            serial->close();
            // 关闭状态,按钮显示“打开串口”
            ui->OpenSerialButton->setText("打开串口");
            // 关闭状态,允许用户操作
            ui->BaudBox->setDisabled(false);
            ui->ParityBox->setDisabled(false);
            ui->BitBox->setDisabled(false);
            ui->StopBox->setDisabled(false);
            ui->ControlBox->setDisabled(false);
            // 禁止操作“发送字符操作”
            ui->SendWordOrder->setDisabled(true);
            ui->SendButton->setDisabled(true);
            // 关闭状态,颜色为绿色
            ui->OpenSerialButton->setStyleSheet("color: green;");
            // 关闭,显示灯为红色
            LED(true);
            // 清空数据
            ui->DataReceived->clear();
            ui->DataSend->clear();
        }
        else                                                        // 如果串口关闭了,先给他打开
        {
            //当前选择的串口名字
            serial->setPortName(ui->PortBox->currentText());
            //用ReadWrite 的模式尝试打开串口,无法收发数据时,发出警告
            if(!serial->open(QIODevice::ReadWrite))
            {
                QMessageBox::warning(this,tr("提示"),tr("串口打开失败!"),QMessageBox::Ok);
                return;
             }
            // 打开状态,按钮显示“关闭串口”
            ui->OpenSerialButton->setText("关闭串口");
            // 打开状态,禁止用户操作
            ui->BaudBox->setDisabled(true);
            ui->ParityBox->setDisabled(true);
            ui->BitBox->setDisabled(true);
            ui->StopBox->setDisabled(true);
            ui->ControlBox->setDisabled(true);
            // 允许操作“发送字符操作”
            ui->SendWordOrder->setDisabled(false);
            ui->SendButton->setDisabled(false);
            // 打开状态,颜色为红色
            ui->OpenSerialButton->setStyleSheet("color: red;");
            // 打开,显示灯为绿色
            LED(false);
        }
    }
    // 控件中添加 #
    void MainWindow::on_SendButton_clicked()
    {
        on_ClearButton_clicked();
        ui->DataSend->append("#");
    }
    // 清空控件
    void MainWindow::on_ClearButton_clicked()
    {
        ui->DataSend->setText("");
    }
    // 清空接收到的数据
    void MainWindow::on_ClearShowButton_clicked()
    {
        ui->DataReceived->setText("");
    }
    // 点击发送后,获取串口信息并展示在接受控件中
    void MainWindow::on_SendEditBtn1_clicked()
    {
        on_ClearButton_clicked();
        QString EditText = ui->Edit1->text();               //获取发送框内容
        ui->DataSend->setText(EditText);                     //将文本内容放在发送栏中
    }
    
    void MainWindow::on_SendEditBtn2_clicked()
    {
        on_ClearButton_clicked();
        QString EditText = ui->Edit2->text();               //获取发送框内容
    
        // qDebug() << "Edit1 text: " << EditText;
    
        ui->DataSend->append(EditText);                     //将文本内容放在发送栏中
    }
    
    void MainWindow::on_SendEditBtn3_clicked()
    {
        on_ClearButton_clicked();
        QString EditText = ui->Edit3->text();               //获取发送框内容
    
        // qDebug() << "Edit1 text: " << EditText;
    
        ui->DataSend->append(EditText);                     //将文本内容放在发送栏中
    }
    
    
    void MainWindow::on_SendWordOrder_clicked()
    {
        on_SendButton_clicked();
    }
    

    运行后效果:

    展开全文
  • 串口调试器串口调试助手sscom32.exe 之英文版和繁体版 串口调试英文中文版
  • 串口通信详解

    万次阅读 多人点赞 2020-09-08 21:33:44
    一般开发板都会引出SOC上串口引脚直接输出的TTL电平的接口,用的是插针式插座,每个串口引出的都有3根通信线(TX、RX、GND),可以用这些插座直接连接外部的TTL电平的串口设备。 (2)收发双方事先规定好通信参数...
  • stm32之串口使用和串口中断

    千次阅读 2021-03-21 00:55:50
    串口通讯(Serial Communication)是一种设备间非常常用的串行通讯方式,因为它简单便捷,因此大部分电子设备都支持该通讯方式,其通讯协议可分层为协议层和物理层。物理层规定通信协议中具有机械、电子功能的特性,...
  • LabVIEW串口通信

    万次阅读 2022-05-03 15:50:46
    在LabVIEW中串口通信使用范围非常广泛,例如,通过串口使用ModBus协议驱动仪器、串口驱动PLC设备等。在LabVIEW中有专业的VI(VISA)可以驱动串口进行数据读、写操作,在函数面板 → 仪器I/O → 串口子面板中。
  • C++串口通信

    千次阅读 2022-03-29 15:14:56
    一、串口通信的基本原理 串口的本质功能是作为 CPU 和串行设备间的编码转换器。当数据从 CPU 经过串行端口发送出去时,字节数据转换为串行的位(bit);在接收数据时,串行的位被转换为字节数据。应用程序要使用串口...
  • QT当中的串口通信你了解多少,平时接触的代码中的串口通信是不是让你手足无措,波特率、奇偶效验位、停止位、数据位怎么收发?射频识别的工作原理和代码编写,本章必须拿下
  • Labview串口通信程序

    2018-09-04 21:06:44
    用Labview写了两个基本的串口通信程序,一个是简单的读串口程序,另一个是读写串口程序,对于学习有极大的帮助。
  • USB转多串口/单串口方案

    千次阅读 2022-01-26 10:41:58
    在日常开发或产品设计时,会遇到不少使用串口通讯或者调试的情况,一个串口时使用USB转单路串口则可优雅解决,但若是多个串口时则可能需要占据多个USB口,颇为麻烦,所以探索了单路USB转单/多路串口的方案提供给大家...
  • 3 不必关闭串口,即可直接进行更改初始化设置内容(串口号、波特率、数据位、停止位、校验位),可按更改后的信息自动将串口重新打开 4 可统计接收字节和发送字节的个数 5 接收数据可按16进制数据和非16进制数据进行...
  • C#使用SerialPort和API串口的例子

    千次下载 热门讨论 2014-12-12 11:52:34
    一个集成了SerialPort和API方式实现串口通信的例子.注意线程操作UI的部分图方便使用了不安全的代码,建议改为委托
  • 虚拟串口(虚拟 COM 端口),应该很多人都知道,也就是一种模拟物理串行接口的 软件 。... 以前的电脑,基本标配都包含一个串口。...虚拟串口软件推荐:强大的虚拟串口软件 串口调试助手软件有很多,随便选一个自己
  • STM32串口接收一帧数据的写法,数据包括帧头,功能帧,数据帧,校验位!

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 383,858
精华内容 153,543
关键字:

串口

友情链接: AB+Mask+Pattern.zip