VS2019 WPF制作OTA上位机(三)串口打开

news/2024/11/25 4:19:46/

先在UI上添加控件
首先,改变一下原来的方法, 原来的三个控件是没有布局的,添加一下布局。
布局用简单的行布局,也就是说从,上到下,分成一行一行的,如下图
在这里插入图片描述
将上一篇文章的代码修改

<Window x:Class="Test.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:Test"mc:Ignorable="d"Title="MainWindow" Height="450" Width="950"><Grid><Grid.RowDefinitions><RowDefinition Height="60"></RowDefinition><RowDefinition Height="60"></RowDefinition><RowDefinition Height="170"></RowDefinition><RowDefinition Height="130"></RowDefinition></Grid.RowDefinitions><Grid Grid.Row="0"><Label Height="1" Background="Black" VerticalAlignment="Top"></Label><Label Height="40" Width="85" Content="bin文件路径:" VerticalContentAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Left"></Label><TextBox Name="TextBox_BinFilePath" Height="40" Width="600" VerticalContentAlignment="Center" HorizontalContentAlignment="Left" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="100,0,0,0"></TextBox><Button Name="Button_GetBinFilePath" Content="浏览bin路径" Height="40" Width="70" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,100,0" Click="Button_GetBinFilePath_Click"></Button><Label Height="1" Background="Black" VerticalAlignment="Bottom"></Label></Grid><Grid Grid.Row="1"><Label Height="40" Width="50" Content="端口号" VerticalContentAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Left"></Label><ComboBox Name="ComboBox_SerialPortNumber" Height="40" Width="80" VerticalContentAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="50,0,0,0"></ComboBox><Button Content="刷新端口" Name="Button_Refresh" Click="Button_Refresh_Click" Height="40" Width="90" VerticalAlignment="Center" HorizontalAlignment="Left" VerticalContentAlignment="Center" Margin="140,0,0,0"></Button><Label Height="40" Width="50" Content="波特率" VerticalContentAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,0,410,0"></Label><ComboBox SelectedIndex="0" Name="ComboBox_baud" Height="40" Width="80" VerticalContentAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,0,280,0"><ComboBoxItem Content="115200"></ComboBoxItem><ComboBoxItem Content="57600"></ComboBoxItem><ComboBoxItem Content="9600"></ComboBoxItem></ComboBox><Label Height="40" Width="50" Content="校验位" VerticalContentAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,0,140,0"></Label><ComboBox SelectedIndex="0" Name="ComboBox_Parity" Height="40" Width="70" VerticalContentAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,0,20,0"><ComboBoxItem Content="None"></ComboBoxItem><ComboBoxItem Content="Odd"></ComboBoxItem><ComboBoxItem Content="Even"></ComboBoxItem><ComboBoxItem Content="Space"></ComboBoxItem><ComboBoxItem Content="Mark"></ComboBoxItem></ComboBox><Label Height="40" Width="50" Content="数据位" VerticalContentAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="110,0,0,0"></Label><ComboBox SelectedIndex="0" Name="ComboBox_DataBit" Height="40" Width="40" VerticalContentAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="200,0,0,0"><ComboBoxItem Content="8"></ComboBoxItem><ComboBoxItem Content="7"></ComboBoxItem><ComboBoxItem Content="6"></ComboBoxItem><ComboBoxItem Content="5"></ComboBoxItem></ComboBox><Label Height="40" Width="50" Content="停止位" VerticalContentAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="300,0,0,0"></Label><ComboBox SelectedIndex="0" Name="ComboBox_StopBit" Height="40" Width="50" VerticalContentAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="400,0,0,0"><ComboBoxItem Content="1"></ComboBoxItem><ComboBoxItem Content="1.5"></ComboBoxItem><ComboBoxItem Content="2"></ComboBoxItem></ComboBox><Label Height="40" Width="50" Content="流控制" VerticalContentAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,190,0"></Label><ComboBox SelectedIndex="0" Name="ComboBox_FlowControl" Height="40" Width="90" VerticalContentAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,100,0"><ComboBoxItem Content="None"></ComboBoxItem><ComboBoxItem Content="Hardware"></ComboBoxItem><ComboBoxItem Content="Software"></ComboBoxItem><ComboBoxItem Content="Custom"></ComboBoxItem></ComboBox><Button Content="打开串口" Name="Button_OpenCloseSerial" Click="Button_OpenCloseSerial_Click" Height="40" Width="70" VerticalAlignment="Center" HorizontalAlignment="Right" VerticalContentAlignment="Center" Margin="0,0,10,0"></Button><Label Height="1" Background="Black" VerticalAlignment="Bottom"></Label></Grid></Grid>
</Window>

首先在布局中手动添加了边界线,虽然不好看但便于观察(直男审美,如果真正用到项目还需要美工给出UI的总体图和素材)

<Label Height="1" Background="Black" VerticalAlignment="Bottom"></Label>

其次是控件ComboBox,下拉列表框,按微软的说法:组合了 ListBox 和 TextBox 的功能。 用户可以像使用 TextBox 一样输入新值,也可以选择现有值,就像使用 ListBox 一样。微软官网ComboBox说明:https://learn.microsoft.com/zh-cn/dotnet/api/system.windows.controls.combobox?view=windowsdesktop-7.0

第一个ComboBox是端口号,也就是COMx,设备管理器中可以看到的
在这里插入图片描述
这个需要我们在后台去获取,即点击刷新端口按钮,然后显示到控件上,所以给了控件的ame=“ComboBox_SerialPortNumber”。

其他的不需要后台更改,所以直接在UI上把所有的选项ComboBoxItem都列出来,例如:

<ComboBoxItem Content="115200"></ComboBoxItem>
<ComboBoxItem Content="57600"></ComboBoxItem>
<ComboBoxItem Content="9600"></ComboBoxItem>

这里还可以添加其他的波特率,我只用过这三种所以只写了三个。

每一个ComboBox的默认值由SelectedIndex="0"来决定。

到此,前台UI的代码本阶段写完,开始写后台的代码了。

首先添加引用 using System.IO.Ports;

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 Microsoft.Win32;
using System.IO;
using System.IO.Ports;

这个在vs2019后经常会报错,找不到,需要我们添加。项目–>管理NuGet程序包(N)…
在这里插入图片描述

选择浏览,在搜索栏输入serialport,找到作者是Microsoft的,选中它,右边点击安装

在这里插入图片描述

弹出一个窗口,意思是给我们的项目添加System.IO.Ports,点击确定即可

在这里插入图片描述

先new SerialPort

    public partial class MainWindow : Window{//读取bin文件的数据private byte[] g_read_data;//串口public SerialPort serialPort = new SerialPort();public MainWindow(){InitializeComponent();}

然后开始写获取端口号的button里面的代码

        private void Button_Refresh_Click(object sender, RoutedEventArgs e){//先清空所有选项ComboBox_SerialPortNumber.Items.Clear();//获取所有端口号string[] ports = SerialPort.GetPortNames();for (int i = 0; i < ports.Length; i++){//将所有获取的端口号添加到下拉列表里ComboBox_SerialPortNumber.Items.Add(ports[i]);}//如果不只有COM1,那么默认选除了COM1外的第一个if (1 != ports.Length){ComboBox_SerialPortNumber.SelectedIndex = 1;}else{ComboBox_SerialPortNumber.SelectedIndex = 0;}}

点击启动试试看,一开始端口号是空的

在这里插入图片描述

点击刷新端口,COM3出现了,刷新之前要记得插入USB转串口工具哦

在这里插入图片描述

如果觉得一开始端口号是空的不好,那么可以在public MainWindow()里面添加Button_Refresh_Click里面的代码,把这些代码封装成一个函数

        private void GetSerialPorts(){//先清空所有选项ComboBox_SerialPortNumber.Items.Clear();//获取所有端口号string[] ports = SerialPort.GetPortNames();for (int i = 0; i < ports.Length; i++){//将所有获取的端口号添加到下拉列表里ComboBox_SerialPortNumber.Items.Add(ports[i]);}//如果不只有COM1,那么默认选除了COM1外的第一个if (1 != ports.Length){ComboBox_SerialPortNumber.SelectedIndex = 1;}else{ComboBox_SerialPortNumber.SelectedIndex = 0;}}
        public MainWindow(){InitializeComponent();GetSerialPorts();}private void Button_Refresh_Click(object sender, RoutedEventArgs e){GetSerialPorts();}

如此打开程序后,端口号就不是空的了。

接下来写打开串口的button

        private void Button_OpenCloseSerial_Click(object sender, RoutedEventArgs e){if (ComboBox_SerialPortNumber.Items.IsEmpty){MessageBox.Show("端口号是空的!");return;}//获取button上的文字内容string bt_str = this.Button_OpenCloseSerial.Content.ToString();if ("打开串口" == bt_str){try{//串口号serialPort.PortName = ComboBox_SerialPortNumber.SelectedItem.ToString();//波特率,string转intComboBoxItem comboBoxItem = (ComboBoxItem)this.ComboBox_baud.SelectedItem;serialPort.BaudRate = Convert.ToInt32(comboBoxItem.Content.ToString());//数据位,string转intcomboBoxItem = (ComboBoxItem)this.ComboBox_DataBit.SelectedItem;serialPort.DataBits = Convert.ToInt32(comboBoxItem.Content.ToString());//停止位,这玩意是个enum,不能直接转出int32comboBoxItem = (ComboBoxItem)this.ComboBox_StopBit.SelectedItem;Double stopbits = Convert.ToDouble(comboBoxItem.Content.ToString());switch (stopbits){case 1:serialPort.StopBits = StopBits.One;break;case 1.5:serialPort.StopBits = StopBits.OnePointFive;break;case 2:serialPort.StopBits = StopBits.Two;break;default:serialPort.StopBits = StopBits.One;break;}//校验位Int32 parity = ComboBox_Parity.SelectedIndex;switch (parity){case 0:serialPort.Parity = Parity.None;break;case 1:serialPort.Parity = Parity.Odd;break;case 2:serialPort.Parity = Parity.Even;break;case 3:serialPort.Parity = Parity.Mark;break;case 4:serialPort.Parity = Parity.Space;break;default:serialPort.Parity = Parity.None;break;}//SerialPort里flow control的相关内容是HandshakeInt32 handshake = ComboBox_FlowControl.SelectedIndex;switch (handshake){case 0:serialPort.Handshake = Handshake.None;break;case 1:serialPort.Handshake = Handshake.XOnXOff;break;case 2:serialPort.Handshake = Handshake.RequestToSend;break;case 3:serialPort.Handshake = Handshake.RequestToSendXOnXOff;break;default:serialPort.Handshake = Handshake.None;break;}serialPort.Open();//serialPort.DataReceived += new SerialDataReceivedEventHandler(SerialDataReceivedHandler);//serialPort.DataReceived += SerialDataReceivedHandler;Button_OpenCloseSerial.Content = "关闭串口";}catch{MessageBox.Show("打开串口失败!");}}else{try{//serialPort.DataReceived -= SerialDataReceivedHandler;serialPort.Close();Button_OpenCloseSerial.Content = "打开串口";}catch{MessageBox.Show("关闭串口失败!");}}}

运行点击打开串口,没有报错,文字也变成了关闭串口。

在serialPort.Open()打断点,添加serialPort到监视,可以看到端口、波特率等相关的值都是对的
在这里插入图片描述

SerialPort类的所有属性和方法可以在官网查看
https://learn.microsoft.com/zh-cn/dotnet/api/system.io.ports.serialport?view=dotnet-plat-ext-7.0

章节到此结束,下一个就要处理串口的数据收发了


http://www.ppmy.cn/news/103680.html

相关文章

自定义线程池

自定义线程池原理 线程池中分为核心线程和临时线程&#xff1b;首先创建核心线程使用&#xff0c;创建之后一直存在线程池&#xff0c;核心线程被占用并且队列任务已满&#xff0c;才会创建临时线程&#xff1b;临时线程使用超过自定义临时线程最大数时会触发自定义的任务拒绝策…

Jenkins是什么?以及Jenkins有哪些具体的应用呢?

Jenkins是一个流行的开源持续集成和持续交付&#xff08;CI/CD&#xff09;工具&#xff0c;它可以自动化构建、测试和部署软件项目。以下是Jenkins的一些具体应用场景&#xff1a; 1. 自动化构建和集成&#xff1a;Jenkins可以与代码版本控制系统&#xff08;如Git、SVN&#…

《微服务实战》 第二十六章 Java锁的分类

前言 本章节介绍Java中的几种常见的锁&#xff1a;公平锁和非公平锁、可重入锁、独享锁/共享锁、互斥锁/读写锁、乐观锁/悲观锁、分段锁、偏向锁/轻量级锁/重量级锁、自旋锁。 1、公平锁和非公平锁 公平锁是指多个线程按照申请锁的顺序来获取锁。 非公平锁是指多个线程获取锁…

部署微信小程序-shopro

部署微信小程序 开始之前 注意不要运行模式下的代码提交小程序审核&#xff0c;第一包体积太大&#xff0c;第二性能太差请下载 小程序开发工具正式小程序无法正常使用&#xff0c;而开发版正常&#xff0c;请确保域名都添加到小程序后台&#xff0c;并且配置好了 IP 白名单&a…

Vue中的$nextTick有什么作用?

Vue中的$nextTick有什么作用&#xff1f; 官方定义 在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法&#xff0c;获取更新后的 DOM 什么意思呢&#xff1f; 我们可以理解成&#xff0c;Vue 在更新 DOM 时是异步执行的。当数据发生变化&#xff0…

在华为眼里,ICT行业今年还有啥搞头?

大家好&#xff0c;我是老杨。 不知道你们有没有研究年报的习惯&#xff0c;一些超大厂是会每年发布年报的&#xff0c;而从年报里&#xff0c;你能看出很多行业趋势出来。 以最热门的华为举例&#xff1a; 每年&#xff0c;华为都会发布全年财报&#xff0c;对自己今年的整…

Toolkit.getDefaultToolkit()获得的java.awt.Toolkit是不是同一个? 是否为单例设计模式?答案是**是**

Toolkit.getDefaultToolkit()获得的java.awt.Toolkit是不是同一个? 是否为单例设计模式? 答案是是 反复调用Toolkit.getDefaultToolkit()获得的 java.awt.Toolkit 是同一个 import java.awt.Toolkit;public class GetDefaultToolkit是不是获得单例Toolkit {static public …

STM32F4_指针(单片机)

目录 前言 1. 计算机存储机制 2. 定义指针 2.1 指针操作 2.2 数组与指针 前言 指针(Pointer)是C语言的一个重要知识点&#xff0c;其使用灵活、功能强大&#xff0c;是C语言的灵魂。指针与底层硬件联系密切&#xff0c;使用指针可操作数据的地址&#xff0c;实现数据的间…