WPF使用TouchSocket实现Tcp client

news2024/9/28 9:23:43

文章目录

  • 前言
  • 1、页面展示
  • 2、主页面UI代码
  • 2、TCP client的UI代码
  • 3、Tcp client后台代码实现
  • 4、UI与后台代码的关联

前言

在该篇的Demo中,您可以找到以下内容:
1、TouchSocket的使用;
2、CommunityToolkit.Mvvm的使用;
3、AvalonDock可拖拽停靠控件的使用;
4、Visual Studio的Dark主题页面的实现;
5、MVVM框架开发使用;
6、RichTextBox控件的使用;

Demo下载地址: WPF Demo项目代码

1、页面展示

在这里插入图片描述

2、主页面UI代码

<Window x:Class="WPF_Demo_V2.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:WPF_Demo_V2"
        mc:Ignorable="d"
        Background="#1F1F1F"
        MouseLeftButtonDown="Window_MouseLeftButtonDown"
        WindowStartupLocation="CenterScreen"
        WindowState="Normal"
        xmlns:avalon="https://github.com/Dirkster99/AvalonDock"
        Title="WPF Demo V0.0.1" Height="768" Width="1024" >
    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="./Resource/Dictionary/DarkStyle.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>

            <!--<TextBlock Text="&#xe6ab;" FontFamily="./Resource/Font/#iconfont" TextAlignment="Center" Foreground="{DynamicResource Foreground}" FontSize="30" Background="{DynamicResource WindowBrush}"/>-->

            <Menu Grid.Column="1" Background="{DynamicResource WindowBrush}" Foreground="{DynamicResource Foreground}" HorizontalAlignment="Left" VerticalAlignment="Top">
                <MenuItem Header="File" >
                    <MenuItem Header="New"/>
                    <MenuItem Header="Open" />
                </MenuItem>
                <MenuItem Header="Edit" >
                    <MenuItem Header="Undo"/>
                    <MenuItem Header="Cut"/>
                    <MenuItem Header="Copy"/>
                </MenuItem>
                <MenuItem Header="View" >
                    <MenuItem Header="Explorer"/>
                    <MenuItem Header="Open"/>
                </MenuItem>
                <MenuItem Header="Tool" >
                    <MenuItem Header="Extentions"/>
                    <MenuItem Header="Options"/>
                </MenuItem>
                <MenuItem Header="Help" >
                    <MenuItem Header="Welcome"/>
                    <MenuItem Header="Support"/>
                    <MenuItem Header="About"/>
                </MenuItem>
            </Menu>
        </Grid>

        <avalon:DockingManager Grid.Row="1">
            <avalon:DockingManager.Theme>
                <avalon:Vs2013DarkTheme/>
            </avalon:DockingManager.Theme>
            <avalon:LayoutRoot>
                <avalon:LayoutPanel Orientation="Horizontal">
                    <avalon:LayoutAnchorablePaneGroup DockWidth="150" FloatingWidth="240">
                        <avalon:LayoutAnchorablePane x:Name="panelLeft">
                            <avalon:LayoutAnchorable Title="Tool"></avalon:LayoutAnchorable>
                            <avalon:LayoutAnchorable Title="Team"></avalon:LayoutAnchorable>
                        </avalon:LayoutAnchorablePane>
                    </avalon:LayoutAnchorablePaneGroup>
                    <avalon:LayoutPanel Orientation="Vertical">
                        <avalon:LayoutDocumentPaneGroup>
                            <avalon:LayoutDocumentPane x:Name="panelTop">
                                <avalon:LayoutDocument Title="TCP Server">
                                    <Frame Source="./View/TcpServerPage.xaml"/>
                                </avalon:LayoutDocument>
                                <avalon:LayoutDocument Title="TCP Client">
                                    <Frame Source="./View/TcpClientPage.xaml"/>
                                </avalon:LayoutDocument>
                                <avalon:LayoutDocument Title="MainWindow.xaml"></avalon:LayoutDocument>
                                <avalon:LayoutDocument Title="MainWindow.xaml.cs"></avalon:LayoutDocument>
                            </avalon:LayoutDocumentPane>
                        </avalon:LayoutDocumentPaneGroup>
                        <avalon:LayoutAnchorablePaneGroup DockMinHeight="30" DockHeight="100" FloatingHeight="180">
                            <avalon:LayoutAnchorablePane x:Name="panelBottom">
                                <avalon:LayoutAnchorable Title="Output"></avalon:LayoutAnchorable>
                                <avalon:LayoutAnchorable Title="Exception"></avalon:LayoutAnchorable>
                                <avalon:LayoutAnchorable Title="Error"></avalon:LayoutAnchorable>
                            </avalon:LayoutAnchorablePane>
                        </avalon:LayoutAnchorablePaneGroup>
                    </avalon:LayoutPanel>
                    <avalon:LayoutAnchorablePaneGroup DockMinWidth="50" DockWidth="150" FloatingWidth="270">
                        <avalon:LayoutAnchorablePane x:Name="panelRight" DockWidth="240" FloatingWidth="240">
                            <avalon:LayoutAnchorable Title="Solution"></avalon:LayoutAnchorable>
                            <avalon:LayoutAnchorable Title="Property"></avalon:LayoutAnchorable>
                        </avalon:LayoutAnchorablePane>
                    </avalon:LayoutAnchorablePaneGroup>
                </avalon:LayoutPanel>
            </avalon:LayoutRoot>
        </avalon:DockingManager>

        <Border Grid.Row="2" Background="{DynamicResource SliderBackground}" Height="20">

        </Border>
    </Grid>
</Window>

2、TCP client的UI代码

<Page x:Class="WPF_Demo_V2.View.TcpClientPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:local="clr-namespace:WPF_Demo_V2.View"
      mc:Ignorable="d" 
      d:DesignHeight="450" d:DesignWidth="800"
      Title="TcpClientPage">

    <Page.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="../Resource/Dictionary/DarkStyle.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Page.Resources>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="5*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Grid Grid.Row="0">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="0.5*"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="0.5*"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Label Grid.Column="0" Margin="5" Content="服务器IP:" HorizontalContentAlignment="Right" Foreground="{DynamicResource Foreground}"/>
            <TextBox Grid.Column="1" Margin="5" Text="{Binding Ip}" Foreground="{DynamicResource Foreground}" HorizontalContentAlignment="Left" VerticalContentAlignment="Center" Background="{DynamicResource SliderBackground}"/>
            <Label Grid.Column="2"  Margin="5" Content="Port:"  HorizontalContentAlignment="Right" Foreground="{DynamicResource Foreground}" />
            <TextBox Grid.Column="3" Margin="5" Text="{Binding Port}" Foreground="{DynamicResource Foreground}" HorizontalContentAlignment="Left" VerticalContentAlignment="Center" Background="{DynamicResource SliderBackground}"/>
            <Button Grid.Column="4" Margin="40,5" BorderBrush="{DynamicResource Green}"  Content="{Binding BtnStartOrStop}" Command="{Binding StartOrStopClientCommand}" Background="{DynamicResource SliderBackground}" Foreground="{DynamicResource Foreground}"/>
        </Grid>
        <RichTextBox Grid.Row="1" x:Name="myRichTextBox" Background="{DynamicResource WindowBackground}" IsReadOnly="True" Foreground="{DynamicResource Foreground}">
            <RichTextBox.ContextMenu>
                <ContextMenu>
                    <MenuItem Header="清空" Command="{Binding ClearRichTextData}"/>
                </ContextMenu>
            </RichTextBox.ContextMenu>
            <FlowDocument>
                <Paragraph x:Name="progressPara"></Paragraph>
            </FlowDocument>
        </RichTextBox>
        <!--<TextBox  Text="{Binding ServerLog}" IsReadOnly="True" Name="txtLog" AcceptsReturn="True" TextWrapping="Wrap" Background="{DynamicResource WindowBackground}" Foreground="{DynamicResource Foreground}"/>-->
        <Grid Grid.Row="2" Margin="0,2" >
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="3.5*"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <TextBox Grid.Column="0" Text="{Binding ServerSendMsg}" x:Name="txtMsg"  AcceptsReturn="True" TextWrapping="Wrap" Background="{DynamicResource WindowBackground}" Foreground="{DynamicResource Foreground}" IsEnabled="{Binding IsEnable}"/>
            <Grid Grid.Column="1" >
                <Grid.RowDefinitions>
                    <RowDefinition />
                    <RowDefinition/>
                    <RowDefinition/>
                </Grid.RowDefinitions>
                <Button Grid.Row="0" Content="发送消息" Margin="40,5" Command="{Binding SendMsgCommand}" BorderBrush="{DynamicResource Green}" Background="{DynamicResource SliderBackground}" Foreground="{DynamicResource Foreground}" IsEnabled="{Binding SendMagIsEnable}"/>
                <StackPanel Grid.Row="1" Orientation="Horizontal">
                    <TextBox Width="60" Margin="2" Text="{Binding AutoSendTimes}" VerticalAlignment="Center" HorizontalContentAlignment="Right"  Background="{DynamicResource WindowBackground}" Foreground="{DynamicResource Foreground}" IsEnabled="{Binding IsEnable}"/>
                    <TextBlock Text="ms" VerticalAlignment="Center" Background="{DynamicResource WindowBackground}" Foreground="{DynamicResource Foreground}"/>
                    <CheckBox VerticalAlignment="Center" Style="{DynamicResource CheckBoxStyle}" Content="定时发送" Width="80"  Background="{DynamicResource WindowBackground}" Foreground="{DynamicResource Foreground}" IsChecked="{Binding AutoSendIsCheck}"/>
                </StackPanel>

            </Grid>
        </Grid>
    </Grid>
</Page>

3、Tcp client后台代码实现

using System;
using System.Collections.Generic;
using System.DirectoryServices.ActiveDirectory;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using System.Timers;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media;
using CommunityToolkit.Mvvm;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using TouchSocket.Core;
using TouchSocket.Sockets;

namespace WPF_Demo_V2.ViewModel
{
    partial class TcpClientViewModel:ObservableObject
    {
        #region 变量
        private TcpClient tcpClient;

        private System.Timers.Timer timer;
        public Action<Brush, string> UpdataRichText { get; set; }
        public Action<Brush, string, Brush, string> UpdataRichTextLine { get; set; }
        public Action<bool> ClearRichText { get; set; }

        bool isStart = false;

        bool isAuto = false;
        #endregion

        #region 构造函数
        public TcpClientViewModel()
        {
            tcpClient = new TcpClient();

        }
        #endregion

        #region 属性
        [ObservableProperty]
        //[NotifyCanExecuteChangedFor(nameof())]
        public string? ip = "192.168.2.120";//CommunityToolkit.MVVM 属性用法1 小写首字母

        [ObservableProperty]
        public string? _Port = "2300";    //CommunityToolkit.MVVM 属性用法2 下划线+大写首字母

        [ObservableProperty]
        public string _BtnStartOrStop = "连接";

        [ObservableProperty]
        public string? _ServerSendMsg;

        [ObservableProperty]
        public string? _AutoSendTimes = "1000";//100ms

        [ObservableProperty]
        public bool? _SendMagIsEnable = false;

        [ObservableProperty]
        public bool? _IsEnable = true;

        [ObservableProperty]
        private bool _AutoSendIsCheck = false;

        /// <summary>
        /// AutoSendIsCheck属性已修改触发的事件,使用partial关键字自动补全该事件,可选
        /// </summary>
        /// <param name="value"></param>
        partial void OnAutoSendIsCheckChanged(bool value)
        {
            isAuto = value;
            IsEnable = !value;
            if (isAuto) {
                timer?.Dispose();
                timer = new System.Timers.Timer { Interval = Convert.ToUInt32(AutoSendTimes), AutoReset = true, Enabled = true };
                timer.Elapsed += (s, e) => Application.Current.Dispatcher.BeginInvoke(new Action(() =>
                {
                    SendMsg();
                }));
            }
            else
            {
                if (timer != null)
                {
                    timer?.Dispose();
                }
            }
        }

        /// <summary>
        /// AutoSendIsCheck属性将要修改触发的事件,使用partial关键字自动补全该事件,可选
        /// </summary>
        /// <param name="value"></param>
        partial void OnAutoSendIsCheckChanging(bool value)
        {

        }
        #endregion

        #region 方法
        #region 开始/停止服务
        [RelayCommand]
        private void StartOrStopClient()      //CommunityToolkit.MVVM 命令command用法:Binding部分对应StartOrStopServerCommand 必须包含<MethodName>Command
        {
            if (!isStart)
            {
                BtnStartOrStop = "断开";
                isStart = true;
                if (string.IsNullOrWhiteSpace(Ip) || string.IsNullOrWhiteSpace(Port))
                {
                    MessageBox.Show("IP 和 Port 不能为空");
                    return;
                }
                try
                {
                    if (tcpClient != null)
                    {
                        tcpClient.Setup(new TouchSocket.Core.TouchSocketConfig()
                            .SetRemoteIPHost($"{Ip}:{Port}")
                            .ConfigureContainer(a => {
                                a.AddConsoleLogger();//添加一个日志注入
                            }));
                        tcpClient.Connect();//连接,连接不成功抛出异常
                        SendMagIsEnable = true;
                        tcpClient.Logger.Info("客户端成功连接");
                        tcpClient.Received = (client, e) => {
                            //从服务器收到信息
                            string mes = Encoding.UTF8.GetString(e.ByteBlock.Buffer, 0, e.ByteBlock.Len);
                            string ServerLog = $"接收到信息:{mes}";
                            DateTime dateTime = DateTime.Now;
                            string times = dateTime.ToString("yyyy-MM-dd HH:mm:ss");
                            Application.Current.Dispatcher.Invoke(() =>
                            {
                                UpdataRichTextLine.Invoke((Brush)new BrushConverter().ConvertFromString("#FFD9ECFF"), $"【{times} Client】", (Brush)new BrushConverter().ConvertFromString("#55B155"), $"{ServerLog}");
                                //UpdataRichText.Invoke((Brush)new BrushConverter().ConvertFromString("#FFD9ECFF"), $"【{times} client】:");
                                //UpdataRichText.Invoke((Brush)new BrushConverter().ConvertFromString("#55B155"), $"{ServerLog}");
                            });
                            
                            Console.WriteLine($"接收到信息:{mes}");
                            return EasyTask.CompletedTask;
                        };
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"连接服务器失败: {ex.Message}");
                    BtnStartOrStop = "连接";
                    isStart = false;
                    SendMagIsEnable = false;
                }

            }
            else
            {
                BtnStartOrStop = "连接";
                isStart = false;
                SendMagIsEnable = false;
                // 关闭Socket
                if (tcpClient != null)
                {
                    tcpClient.Close();
                }
            }
        }
        #endregion

        #region 发送信息按钮事件
        [RelayCommand]
        private void SendMsg()
        {
            if(!string.IsNullOrEmpty(ServerSendMsg))
            {
                byte[] data = Encoding.Default.GetBytes(ServerSendMsg);
                tcpClient.Send(data);
            }
        }
        #endregion

        #endregion

    }
}

4、UI与后台代码的关联

using CommunityToolkit.Mvvm.DependencyInjection;
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 WPF_Demo_V2.ViewModel;

namespace WPF_Demo_V2.View
{
    /// <summary>
    /// TcpClientPage.xaml 的交互逻辑
    /// </summary>
    public partial class TcpClientPage : Page
    {
        FlowDocument Doc = new FlowDocument();

        public TcpClientPage()
        {
            InitializeComponent();
            this.DataContext = new TcpClientViewModel() { UpdataRichText = ShowRichText, ClearRichText = ClearText, UpdataRichTextLine = ShowRichTextLine };
        }

        private void ShowRichText(Brush brush, string txt)
        {
            //this.Dispatcher.Invoke(() => {
                var p = new Paragraph(); // Paragraph 类似于 html 的 P 标签
                var r = new Run(txt); // Run 是一个 Inline 的标签
                p.Inlines.Add(r);
                p.LineHeight = 1;
                p.Foreground = brush;//设置字体颜色
                Doc.Blocks.Add(p);
                myRichTextBox.Document = Doc;
                myRichTextBox.ScrollToEnd();
            //});

        }

        private void ShowRichTextLine(Brush fbrush, string ftxt, Brush bbrush, string btxt)
        {
            //this.Dispatcher.Invoke(() => {
            var p = new Paragraph(); // Paragraph 类似于 html 的 P 标签
            var r1 = new Run(ftxt)
            {
                Foreground = fbrush
            };
            p.Inlines.Add(r1);
            var r2 = new Run(btxt)
            {
                Foreground = bbrush
            };
            p.Inlines.Add(r2);
            p.LineHeight = 1;
            Doc.Blocks.Add(p);
            myRichTextBox.Document = Doc;
            myRichTextBox.ScrollToEnd();
            //});

        }




        private void ClearText(bool obj)
        {
            if (obj)
            {
                System.Windows.Documents.FlowDocument doc = myRichTextBox.Document;
                doc.Blocks.Clear();
            }
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1949101.html

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

相关文章

IF=8.5 MIMIC-IV高阶玩法!中国用新指标SHR+机器学习拿一区top,思路太牛了

‍ MIMIC-IV 发文难&#xff1f;那是你还没遇到对的思路&#xff01;如今机器学习数据库挖掘的文章层出不穷&#xff0c;今天介绍的这篇文章是在MIMIC-IV数据库的基础上&#xff0c;用了一个新指标—应激性高血糖比&#xff08;SHR&#xff09;&#xff0c;结合机器学习构建预测…

【iOS】——Block循环引用

循环引用原因 如果在Block中使用附有_ _strong修饰符的对象类型自动变量&#xff0c;那么当Block从栈复制到堆时&#xff0c;该对象为Block所持有&#xff0c;这样容易引起循环引用。 HPPerson *person [[HPPerson alloc] init];person.block ^{NSLog("person.age--- …

Redis使用场景-热点数据缓存

什么是缓存&#xff1f; 为了把一些经常访问的数据放入缓存中已减少对数据库的访问&#xff0c;从而减少数据库的压力&#xff0c;提高程序的性能。【内存中存储】-效率快 缓存的原理 什么样的数据适合放入缓存中&#xff1f; 1.查询频率高且修改频率低 2.数据安全性低 哪些组件…

《python语言程序设计》第6章第7题财务应用程序:计算未来投资,编写函数计算制定年数以给定利率

记住这里增加循环应该是以年为单位。但是添加的数是月为单位 此处需留意其实点不是1&#xff0c;1代表1年&#xff0c;这里月所以其实是12&#xff0c;这里的单位是月&#xff0c;而不是年。 python for i in range(12,monthNum12,12) 如果你把12都换成1呢&#xff1f;&…

本地生活抽佣系统搭建:如何让系统具有竞争优势?

随着本地生活的潜力不断展现&#xff0c;本地生活服务商逐渐成为新兴职业中的一大热门&#xff0c;本地生活抽佣系统搭建的热度也一直保持着飙升的状态。 抖音生活发布的《2023年数据报告》显示&#xff0c;2023年&#xff0c;抖音生活服务平台总交易额增长256%&#xff0c;抖…

监测Nginx访问日志状态码,并做相应动作

文章目录 引言I 监测 Nginx 访问日志情况,并做相应动作1.1 前提准备1.2 访问日志 502 情况,重启 bttomcat9服务1.3 其他案例:访问日志 502 情况,重启 php-fpm 服务II 将Shell 脚本check499.sh包装成systemd服务2.1 创建systemd服务2.2 配置service2.3 开机启动2.4 其他常用…

自监督学习概述(Self-Supervised Learning,SSL)

自监督学习&#xff08;Self-Supervised Learning&#xff0c;SSL&#xff09;是一种机器学习方法&#xff0c;旨在利用未标记数据进行训练。这种方法通过从数据本身生成伪标签&#xff0c;来创建监督信号&#xff0c;使得模型能够学习有效的数据表示。自监督学习在深度学习领域…

HTTP传输下载和P2P传输下载的区别?

HTTP传输下载和P2P&#xff08;Peer-to-Peer&#xff09;传输下载在多个方面存在显著的区别&#xff0c;以下是详细的分析&#xff1a; 1. 工作原理 HTTP传输下载&#xff1a; HTTP&#xff08;Hypertext Transfer Protocol&#xff09;是一种用于在Web上进行数据通信的协议&…

PHP多功能投票系统源码小程序

&#x1f389;决策不再难&#xff01;「多功能投票小程序」一键搞定所有选择困难症✨ &#x1f914;选择困难&#xff1f;「多功能投票小程序」来救场&#xff01; 每次聚会、团队讨论还是日常小决策&#xff0c;是不是总有那么几个瞬间让你陷入“选哪个好呢&#xff1f;”的…

spine to unity-2.利用边缘框实现实时碰撞检测

主要讲spine的边缘框&#xff0c;在unity中&#xff0c;实现实时碰撞检测。其中使用的素材&#xff0c;是我为独立游戏ink制作的动画。独立游戏ink的开发日志&#xff0c;在小红薯持续更新中。spine工具包的安装&#xff0c;下载请参考spine to unity-1spine BoundingBoxFollow…

【MySQL篇】Percona XtraBackup标准化全库完整备份策略(第三篇,总共五篇)

&#x1f4ab;《博主介绍》&#xff1a;✨又是一天没白过&#xff0c;我是奈斯&#xff0c;DBA一名✨ &#x1f4ab;《擅长领域》&#xff1a;✌️擅长Oracle、MySQL、SQLserver、阿里云AnalyticDB for MySQL(分布式数据仓库)、Linux&#xff0c;也在扩展大数据方向的知识面✌️…

STM32H7的LPUART基础和唤醒示例

STM32H7的LPUART基础知识 硬件框图低功耗的高级特性低功耗串口的时钟以及波特率低功耗串口发送时序低功耗串口支持的唤醒方式 LPUART 的全称是 Low power universal synchronous asynchronous receiver transmitter&#xff0c;中文意思是低功耗通用异步收发器&#xff0c;简称…

【C语言】栈的实现(数据结构)

前言&#xff1a; 还是举一个生活中的例子&#xff0c;大家都玩过积木&#xff0c;当我们把积木叠起来的时候&#xff0c;如果要拿到最底部的积木&#xff0c;我们必须从顶端一个一个打出&#xff0c;最后才能拿到底部的积木&#xff0c;也就是后进先出&#xff08;先进后出&a…

Python - 开源库 ReportLab 库合并 CVS 和图像生成 PDF 文档

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/140281680 免责声明&#xff1a;本文来源于个人知识与公开资料&#xff0c;仅用于学术交流&#xff0c;欢迎讨论&#xff0c;不支持转载。 Report…

[Spring] MyBatis操作数据库(基础)

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏: &#x1f9ca; Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 &#x1f355; Collection与…

Elasticsearch概念及ELK安装

1、Elasticsearch是什么 它是elastic技术栈中的一部分。完整的技术栈包括&#xff1a; Elasticsearch&#xff1a;用于数据存储、计算和搜索 Logstash/Beats&#xff1a;用于数据收集 Kibana&#xff1a;用于数据可视化 整套技术栈被称为ELK&#xff0c;经常用来做日志收集…

WPF启动失败报System.Windows.Automation.Peers.AutomationPeer.Initialize()错误解决

问题描述 win10系统上WPF程序启动后就崩溃&#xff0c;通过查看崩溃日志如下&#xff1a; 应用程序: xxx.exe Framework 版本: v4.0.30319 说明: 由于未经处理的异常&#xff0c;进程终止。 异常信息: System.TypeLoadException 在 System.Windows.Automation.Peers.Automatio…

CMake 使用 OpenCV:从库中查找包含头文件

前言 在开发使用 OpenCV 的项目时&#xff0c;正确配置 CMake 是确保项目顺利构建和运行的关键。开发过程经常存在各种各样的意外和偶然, 是困难也是收获. 比如一直好好的项目, include某个头文件, 编译突然出现:No such file or directory CmakeTest/test_opencv.h:4: error:…

一套成熟的实验室信息管理系统源码,.Net 检验系统LIS源码,实现从采集、检测、报告、归档的全程跟踪管理

一套成熟的实验室信息管理系统源码。在长期的医疗信息化实践中&#xff0c;我们分析总结了大量客户实例&#xff0c;建立了以病人为中心、以业务处理为基础、以提高检验科室管理水平和工作效率为目标的产品开发思路&#xff0c;将医学检验、科室管理和财务统计等检验科室/实验室…

ControlNet on Stable Diffusion

ControlNet on Stable Diffusion 笔记来源&#xff1a; 1.Adding Conditional Control to Text-to-Image Diffusion Models 2.How to Use OpenPose & ControlNet in Stable Diffusion 3.ControlNet与DreamBooth&#xff1a;生成模型的精细控制与主体保持 4.Introduction t…