串口通信

1. NuGet安装System.IO.Ports

在这里插入图片描述

2. 界面布局XAML

<Window x:Class="BlocksTools.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:BlocksTools"
        mc:Ignorable="d"
        Title="串口工具" Height="450" Width="800">
    <Grid>
        <TabControl>
            <TabItem>
                <TabItem.Header>
                    <StackPanel>
                        <Label>串口设置</Label>
                    </StackPanel>
                </TabItem.Header>
                <StackPanel Orientation="Horizontal">
                    <GroupBox Header="串口" Width="200">
                        <StackPanel>
                            <StackPanel Orientation="Horizontal">
                                <Label Margin="3" Height="25" Width="50">端口号</Label>
                                <ComboBox x:Name="comboBoxCOM" Margin="3" Height="20" Width="130" DragDrop.Drop="comboBoxCOM_Drop"/>
                            </StackPanel>
                            <StackPanel Orientation="Horizontal">
                                <Label Margin="3" Height="25" Width="50">波特率</Label>
                                <ComboBox x:Name="comboBoxBaudRate" Margin="3" Height="20" Width="130" SelectedIndex="0" >
                                    <ComboBoxItem>9600</ComboBoxItem>
                                    <ComboBoxItem>19200</ComboBoxItem>
                                    <ComboBoxItem>38400</ComboBoxItem>
                                    <ComboBoxItem>115200</ComboBoxItem>
                                    <ComboBoxItem>1000000</ComboBoxItem>
                                </ComboBox>
                            </StackPanel>
                            <StackPanel Orientation="Horizontal">
                                <Label Margin="3" Height="25" Width="50">数据位</Label>
                                <ComboBox x:Name="comboBoxDataBit" Margin="3" Height="20" Width="130" SelectedIndex="3">
                                    <ComboBoxItem>5</ComboBoxItem>
                                    <ComboBoxItem>6</ComboBoxItem>
                                    <ComboBoxItem>7</ComboBoxItem>
                                    <ComboBoxItem>8</ComboBoxItem>
                                </ComboBox>
                            </StackPanel>
                            <StackPanel Orientation="Horizontal">
                                <Label Margin="3" Height="25" Width="50">停止位</Label>
                                <ComboBox x:Name="comboBoxStopBit" Margin="3" Height="20" Width="130" SelectedIndex="0">
                                    <ComboBoxItem>1位</ComboBoxItem>
                                    <ComboBoxItem>1.5位</ComboBoxItem>
                                    <ComboBoxItem>2位</ComboBoxItem>
                                </ComboBox>
                            </StackPanel>
                            <StackPanel Orientation="Horizontal">
                                <Label Margin="3" Height="25" Width="50">校验位</Label>
                                <ComboBox x:Name="comboBoxSdd" Margin="3" Height="20" Width="130" SelectedIndex="0">
                                    <ComboBoxItem>无校验</ComboBoxItem>
                                    <ComboBoxItem>奇校验</ComboBoxItem>
                                    <ComboBoxItem>偶校验</ComboBoxItem>
                                    <ComboBoxItem>1 校验</ComboBoxItem>
                                    <ComboBoxItem>0 校验</ComboBoxItem>
                                </ComboBox>
                            </StackPanel>
                            <StackPanel Orientation="Horizontal">
                                <Label Margin="3" Height="25" Width="50">流控位</Label>
                                <ComboBox x:Name="comboBoxlik" Margin="3" Height="20" Width="130" SelectedIndex="0" >
                                    <ComboBoxItem>无流控</ComboBoxItem>
                                    <ComboBoxItem>RTS/CTS</ComboBoxItem>
                                    <ComboBoxItem>XON/XOFF</ComboBoxItem>
                                </ComboBox>
                            </StackPanel>
                            <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
                                <Button x:Name="btnOpenCloseCom" Margin="3" Width="80" Height="25" Click="btnOpenCloseCom_Click">打开串口</Button>
                                <Button x:Name="btnClearRecv" Margin="3" Width="80" Height="25" Click="btnClearRecv_Click">清空接收</Button>
                            </StackPanel>
                        </StackPanel>
                    </GroupBox>
                    <GroupBox Header="接收数据" MinWidth="590" MaxWidth="1000" Width="515">
                        <ScrollViewer>
                            <ScrollViewer.Content>
                                <TextBlock x:Name="textBlockRecv" MinWidth="300"></TextBlock>
                            </ScrollViewer.Content>
                        </ScrollViewer>

                    </GroupBox>
                </StackPanel>
            </TabItem>
            <TabItem>
                <TabItem.Header>
                    <StackPanel>
                        <Label>数据显示</Label>
                    </StackPanel>
                </TabItem.Header>
            </TabItem>
        </TabControl>
    </Grid>
</Window>

3. C#代码

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO.Ports;
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;

namespace BlocksTools
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        SerialPort mSerialPort = new SerialPort();
        private StringBuilder lineBuilder = new StringBuilder();    // 用于存放串口接收数据        

        public MainWindow()
        {
            InitializeComponent();

            // 获取所有可用串口端口,并添加到comboBoxCOM
            string[] ports = System.IO.Ports.SerialPort.GetPortNames();
            comboBoxCOM.ItemsSource = ports;
            comboBoxCOM.SelectedIndex = 0;  // 默认选择索引                      
        }

        /// <summary>
        /// 串口数据接收函数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            System.Threading.Thread.Sleep(1); // 等待1S保证串口发送的一帧数据全部接收完成

            // 读取数据
            byte[] data = new byte[mSerialPort.BytesToRead];
            mSerialPort.Read(data, 0, data.Length);

            string str = Encoding.UTF8.GetString(data); // 字符串转码UTF-8格式
            lineBuilder.Append(str);

            this.Dispatcher.Invoke(new Action(() =>
            {
                string str2 = lineBuilder.ToString();
                textBlockRecv.Text = str2;  // 显示串口数据内容

                // 解析串口数据:
                // $$ADC:[228,246,247,253,828,348,262,260,316,275,297,320,291,343,837,]ADC$$ 

                int index_start = str2.IndexOf("$$ADC:[", StringComparison.Ordinal);
                int index_end = str2.IndexOf("]ADC$$", StringComparison.Ordinal);

                if ((index_start >= 0) && (index_end >= 0))
                {                 
                    string str3 = str2.Substring(index_start + "$$ADC:[".Length, index_end - index_start);  // 截取"$$ADC:["之后的数据
                    string[] array = str3.Split(new char[] { ',' }); // 以","分割数据,并存储到数组
                    double adc1 = Convert.ToDouble(array[0]);   // 字符串转数值

                }
            }));
        }

        /// <summary>
        /// 打开关闭串口
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnOpenCloseCom_Click(object sender, RoutedEventArgs e)
        {

            if (mSerialPort.IsOpen)
            {
                mSerialPort.Close();
                btnOpenCloseCom.Content = "打开串口";
                Console.WriteLine("关闭串口成功");
                Debug.WriteLine("关闭串口成功");
                comboBoxBaudRate.IsEnabled = true;
                comboBoxCOM.IsEnabled = true;
                comboBoxDataBit.IsEnabled = true;
                comboBoxStopBit.IsEnabled = true;
                comboBoxSdd.IsEnabled = true;
                comboBoxlik.IsEnabled = true;
            }
            else
            {
                mSerialPort.PortName = comboBoxCOM.SelectedItem.ToString();
                mSerialPort.BaudRate = 1000000; // 波特率
                mSerialPort.DataBits = 8;   // 数据位
                mSerialPort.StopBits = StopBits.One;    // 停止位
                mSerialPort.Parity = Parity.None;   // 校验位
                mSerialPort.Handshake = Handshake.None;
                //mSerialPort.ReadTimeout = 1500; // 读超时
                //mSerialPort.Encoding = Encoding.UTF8; // 编码方式
                //mSerialPort.RtsEnable = true;

                mSerialPort.DataReceived += SerialPort_DataReceived;

                switch (comboBoxBaudRate.SelectedIndex)
                {
                    case 0:
                        Console.WriteLine("baudrate: 9600");
                        mSerialPort.BaudRate = 9600;
                        break;
                    case 1:
                        mSerialPort.BaudRate = 19200;
                        Console.WriteLine("baudrate: 19200");
                        break;
                    case 2:
                        mSerialPort.BaudRate = 38400;
                        Console.WriteLine("baudrate: 38400");
                        break;
                    case 3:
                        Console.WriteLine("baudrate: 115200");
                        mSerialPort.BaudRate = 115200;
                        break;
                    case 4:
                        Console.WriteLine("baudrate: 1000000");
                        mSerialPort.BaudRate = 1000000;
                        break;
                    default:
                        Console.WriteLine("default baudrate!");
                        mSerialPort.BaudRate = 9600;
                        break;
                }
            
                // mSerialPort.Write("Hello world"); // 写字符串口
                // mSerialPort.Write(new byte[] { 0xA0, 0xB0, 0xC0}, 0, 3); // 写入3个字节数据

                //Debug.WriteLine("Hello world");
                //MessageBox.Show("端口名:" + mSerialPort.PortName);

                try
                {
                    mSerialPort.Open();
                    btnOpenCloseCom.Content = "关闭串口";                  
                    Console.WriteLine("打开串口成功");
                    Debug.WriteLine("打开串口成功");

                    comboBoxBaudRate.IsEnabled = false;
                    comboBoxCOM.IsEnabled = false;
                    comboBoxDataBit.IsEnabled = false;
                    comboBoxStopBit.IsEnabled = false;
                    comboBoxSdd.IsEnabled = false;
                    comboBoxlik.IsEnabled = false;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }

        /// <summary>
        /// 清空串口接收数据
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnClearRecv_Click(object sender, RoutedEventArgs e)
        { 
            lineBuilder.Clear();
            textBlockRecv.Text = lineBuilder.ToString();  
        }

        /// <summary>
        /// 串口端口选择
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void comboBoxCOM_Drop(object sender, DragEventArgs e)
        {
            string[] ports = System.IO.Ports.SerialPort.GetPortNames();
            comboBoxCOM.ItemsSource = ports;
            comboBoxCOM.SelectedIndex = 0;
        }
    }
}

4. 运行效果

在这里插入图片描述

源码下载

源码下载

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐