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

news2024/11/25 0:46:42

先在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转int
                    ComboBoxItem comboBoxItem = (ComboBoxItem)this.ComboBox_baud.SelectedItem;
                    serialPort.BaudRate = Convert.ToInt32(comboBoxItem.Content.ToString());

                    //数据位,string转int
                    comboBoxItem = (ComboBoxItem)this.ComboBox_DataBit.SelectedItem;
                    serialPort.DataBits = Convert.ToInt32(comboBoxItem.Content.ToString());

                    //停止位,这玩意是个enum,不能直接转出int32
                    comboBoxItem = (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的相关内容是Handshake
                    Int32 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.coloradmin.cn/o/585008.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【MYSQL】通过存储过程调用事务方法

假设有表test_1&#xff1a; BEGINDECLARE err int DEFAULT 0;declare continue handler for sqlexception set err1;#当sqlexception handler捕捉到异常时&#xff0c;设置err1START TRANSACTION;#开始事务update test_1 set value 50 where id 58;IF (err0) THENcommit;#增…

打包ios-App之使用Appuploader

appuploader教程 一.申请个人开放者账号&#xff1a;https://idmsa.apple.com 网站内申请即可 注意&#xff1a;申请付费开发者账号需要付费688&#xff0c;付费之后就直接申请证书即可 未付费 二.申请ios测试证书&#xff08;p12&#xff09; 1.打开Appuploader&#xff0c;用…

建行对接微信支付

1、获取配置信息&#xff0c;基础代码设置 1.1 建行支付、退款需要商户提供以下信息&#xff1a; 商户代码支付使用商户柜台代码支付使用分行代码支付使用公钥外联平台使用、支付使用操作员号外联平台使用操作员号交易密码外联平台使用证书外联平台使用证书密码外联平台使用 …

python-import request失败

mac电脑 vscode。 &#xff01;&#xff01;&#xff01;踩坑&#xff0c;搞了2天 烦了哦 1&#xff1a;python安装&#xff1a; 下载地址&#xff1a;https://cdn.npmmirror.com/binaries/python/3.12.0/python-3.12.0a7-macos11.pkg 2: python配置PATH terminal指令打which …

JVM学习(十二):执行引擎

目录 一、执行引擎概述 二、执行引擎的工作过程 三、Java代码编译和执行 3.1 过程概述 3.1 javac前端编译 3.2 Java字节码的执行 3.3 编译和解释概述 3.4 高级语言理解与执行过程&#xff08;机器码、指令、汇编&#xff09; 3.4.1 机器码 3.4.2 指令 3.4.3 指…

Apache的配置、应用和优化(遥不可及)

文章目录 一、构建虚拟web主机二、配置虚拟主机1.基于域名&#xff08;1&#xff09;为虚拟主机提供域名解析&#xff08;2&#xff09;为虚拟主机准备网页文档&#xff08;3&#xff09;添加虚拟主机配置&#xff08;5&#xff09;启用上一步的子配置文件&#xff08;6&#x…

Python来写一个童话故事

Python来写一个童话故事 主题&#xff1a;冒险&#xff0c; 风格&#xff1a;惊险&#xff0c; 人物&#xff1a;男孩&#xff0c; 地点&#xff1a;海底。 循环遍历鱼列表中的每一条鱼 for fish in fishes:# 获取男孩和鱼的坐标和距离boy_x, boy_y boy.position()fish_x, …

亿发生产管理信息化系统,生产制造型企业信息化建设

在不断发展的先进制造格局中&#xff0c;传统生产管理模式的固化限制了企业规模化生产能力。为适应这个充满活力的时代需求&#xff0c;实现战略目标&#xff0c;企业必须借助信息技术的力量加强生产过程管理&#xff0c;踏上企业生产信息化的征程。亿发生产管理信息化系统&…

Python3数据分析与挖掘建模(4)集中趋势与离中趋势、数据分布与抽样

分析理论是统计学和数据分析中的重要概念&#xff0c;它们用于描述和理解数据的集中趋势、离中趋势、数据分布以及抽样理论。下面是对这些概念的简要说明&#xff1a; 集中趋势&#xff1a; 均值、中位数与分位数、众数离中趋势&#xff1a;标准差、方差数据分布&#xff1a;偏…

[Nacos] Nacos Server与Nacos Client间的UDP通信 (十)

文章目录 1.Nacos Server与Nacos Client间的UDP通信1.1 Nacos Server向Nacos Client进行UDP推送1.2 Nacos Client接收Nacos Server的UDP推送 1.Nacos Server与Nacos Client间的UDP通信 Nacos Server向Nacos Client进行UDP推送Nacos Client接收Nacos Server的UDP推送 1.1 Naco…

黑客常用工具合集

首先恭喜你发现了宝藏。 本文章集成了全网优秀的开源攻防武器项目&#xff0c;包含&#xff1a; 信息收集工具&#xff08;自动化利用工具、资产发现工具、目录扫描工具、子域名收集工具、指纹识别工具、端口扫描工具、各种插件....etc...&#xff09;漏洞利用工具&#xff0…

枚举_源码_分析

枚举源码分析 前言 这是所有Java语言枚举类型的公共基类。关于枚举的更多信息&#xff0c;包括编译器合成的隐式声明方法的描述&#xff0c;可以在Java的第8.9节中找到™ 语言规范。 请注意&#xff0c;当使用枚举类型作为集合的类型或映射中键的类型时&#xff0c;可以使用专…

[NOIP2004 普及组] FBI 树 队列解法

[NOIP2004 普及组] FBI 树 题目描述: 我们可以把由 0 和 1 组成的字符串分为三类&#xff1a;全 0 串称为 B 串&#xff0c;全 1 串称为 I 串&#xff0c;既含 0 又含 1 的串则称为 F 串。 FBI 树是一种二叉树&#xff0c;它的结点类型也包括 F 结点&#xff0c;B 结点和 I …

RocketMQ实现一个简单的秒杀接口

预设场景&#xff1a; “秒杀”这一词多半出现在购物方面&#xff0c;但是又不单单只是购物&#xff0c;比如12306购票和学校抢课&#xff08;大学生的痛苦&#xff09;也可以看成一个秒杀。秒杀应该是一个“三高”&#xff0c;这个三高不是指高血脂&#xff0c;高血压和高血糖…

数据中间件 - MyCat2 配置文件说明

数据中间件 - MyCat2 配置文件说明 本章内容基于 MyCat2 版本. 会对 Mycat 中的配置文件作用,以及结合 Mycat 的一些概念进行介绍,比起一上来就盲目的开始操作,然后遇到各种问题,先从全局进行了解对提高效率是有帮助的. MyCat 的配置文件都存放在 conf 路径下. server.jso…

学习Node.js的9大理由以及日常开发中的14个高级特性和代码示例分享

目录 为什么要学Nodejs 1. 高级事件处理&#xff1a;事件驱动机制 2. 非阻塞I/O 3. 异步编程 4. 模块系统 5. 流式数据处理 6. 跨平台支持 7. 高性能网络编程 8. 调试工具 9. 第三方模块 10. 升级 V8 引擎至 10.7 11. 函数式编程 12. 高级路由 13. 试验 Node wat…

国内免费可用的ChatGPT网页版

ChatGPT 一、ChatGPT是个啥&#xff1f;二、16个国内免费的ChatGPT网站。三、ChatGPT使用方式 一、ChatGPT是个啥&#xff1f; chat&#xff1a;表示“聊天”。 GPT&#xff1a;则是Generative、Pre-trained、Transformer的缩写&#xff0c;表示“预训练语言模型”&#xff0…

【Unity100个实用小技巧】同一个Canvas下的UI顺序通过代码如何修改

☀️博客主页&#xff1a;CSDN博客主页&#x1f4a8;本文由 萌萌的小木屋 原创&#xff0c;首发于 CSDN&#x1f4a2;&#x1f525;学习专栏推荐&#xff1a;面试汇总❗️游戏框架专栏推荐&#xff1a;游戏实用框架专栏⛅️点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd;&#…

三维场景重建经典论文详解

来源&#xff1a;投稿 作者&#xff1a;小灰灰 编辑&#xff1a;学姐 论文标题&#xff1a; 《REAL-TIME INDOOR SCENE RECONSTRUCTION WITH RGBD AND INERTIA INPUT》 论文链接: https://arxiv.org/pdf/2008.00490.pdf https://github.com/CWanli/RecoNet 数据集&#xff1a;P…

停车系统多位多车算法

1、算法代码 下面代码是伪Java代码&#xff0c;看得懂就行。 //查询当前车牌号对应的车主的其他的车牌号的入场纪录&#xff0c;根据时间倒叙排列。 List<Record> comeRecords mapper.selectFromDB; //车主所有的在场车辆数量-车主拥有车位数量 等于需要计费的车辆数量…