C#Avalonia串口通讯Linux部署测试

一、效果展示

虚拟两串口

C#Avalonia串口通讯Linux部署测试

打包程序

C#Avalonia串口通讯Linux部署测试

配虚拟机串口

C#Avalonia串口通讯Linux部署测试

C#Avalonia串口通讯Linux部署测试

C#Avalonia串口通讯Linux部署测试

虚拟机开机

C#Avalonia串口通讯Linux部署测试

运行程序

C#Avalonia串口通讯Linux部署测试

发现找不到串口,需要设置权限

C#Avalonia串口通讯Linux部署测试

Linux串口访问权限设置:

–要查询Linux系统中的当前用户可以使用whoami命令。

whoami

–将当前用户加入dialout组。 命令:

sudo usermod -aG dialout debian

sudo adduser debian dialout

–查询所有串口

ls /dev/tty*

–发送串口消息

echo hello > /dev/ttyS0

–检查串口读写权限

ls -l /dev/ttyS0

–接收串口消息

cat /dev/ttyS0

串口权限正常了

C#Avalonia串口通讯Linux部署测试

windows串口发送消息

C#Avalonia串口通讯Linux部署测试

Linux串口接收消息

C#Avalonia串口通讯Linux部署测试

二、VS2022开发

.net8环境

C#Avalonia串口通讯Linux部署测试

NuGet 安装 Avalonia

C#Avalonia串口通讯Linux部署测试

界面编写

C#Avalonia串口通讯Linux部署测试

三、代码展示

MainWindow.axaml

<Window xmlns="https://github.com/avaloniaui"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="using:BaoYuanSerial.ViewModels"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:Lan="clr-namespace:BaoYuanSerial.Util"
xmlns:i="using:Avalonia.Xaml.Interactivity"
xmlns:ia="using:Avalonia.Xaml.Interactions.Core"
        mc:Ignorable="d" d:DesignWidth="900" d:DesignHeight="500"
        x:Class="BaoYuanSerial.Views.MainWindow"
WindowStartupLocation="CenterScreen"
Width="900" Height="700"
MinWidth="900" MinHeight="700"
        Icon="/Assets/yinyang_64.png"
        Title="AvaloniaSerial"
		>


    <Design.DataContext>
        <vm:MainWindowViewModel/>
    </Design.DataContext>
<Window.Styles>
<Style Selector="ComboBoxItem">
<Setter Property="FontSize" Value="15"/>
</Style>
</Window.Styles>


<Grid RowDefinitions="30,32,*,25" >
<Menu Background="LightGray">
<MenuItem Header="{Lan:Localize menuTool}" Margin="5,5,0,0">
<MenuItem Header="{Lan:Localize menuToolBox}" Name="ToolBoxMenu" />
<MenuItem Header="{Lan:Localize menuAscii}" Name="AsciiCodeMenu" />
		        <Separator/>
<MenuItem Name="OptionsMenu" Header="{Lan:Localize menuOptions}" />
</MenuItem>
<MenuItem Header="{Lan:Localize menuHelp}" Margin="5,5,0,0">
<MenuItem Header="{Lan:Localize menuDoc}" />
<Separator/>
<MenuItem Name="AboutMenu" Header="{Lan:Localize menuAbout}" />
</MenuItem>
<MenuItem Header="{Lan:Localize menuLanguage}" Name="LanguageMenu" Margin="5,5,0,0">
<MenuItem Name="ChineseMenu" Header="{Lan:Localize menuCh}" />
<Separator/>
<MenuItem Name="EnglishMenu" Header="{Lan:Localize menuEn}" Margin="5,5,0,0" />
</MenuItem>
<MenuItem Header="{Lan:Localize menuDonate}" Name="DonateMenu" Margin="5,5,0,0">
</MenuItem>


</Menu>
<Grid Grid.Row="1" ColumnDefinitions="32,32,32,32,32,32,32,100,*">
<Button Grid.Column="0" ToolTip.Tip="{Lan:Localize mvTipSaveLog}" 
HorizontalAlignment="Stretch" VerticalContentAlignment="Stretch"
Command="{Binding OnLogCommand}"
Background="{Binding LogBtnBackColor}"
					>
<Image Source="/Assets/save.png"/>
</Button>
<Button Grid.Column="1" ToolTip.Tip="{Lan:Localize mvTipStart}"
HorizontalAlignment="Stretch" VerticalContentAlignment="Stretch"
Command="{Binding OnStartCommand}" IsEnabled="{Binding IsStartCan}"				    
					>
<Image Source="/Assets/start.png"/>
</Button>
<Button Grid.Column="2" ToolTip.Tip="{Lan:Localize mvTipPause}"
HorizontalAlignment="Stretch" VerticalContentAlignment="Stretch"
Command="{Binding OnPauseCommand}" IsEnabled="{Binding IsPauseCan}"
Background="{Binding PauseBtnBackColor}"
					>
<Image Source="/Assets/pause.png"/>
</Button>
<Button Grid.Column="3" ToolTip.Tip="{Lan:Localize mvTipStop}"
HorizontalAlignment="Stretch" VerticalContentAlignment="Stretch"
Command="{Binding OnStopCommand}" IsEnabled="{Binding IsStopCan}"
					>
<Image Source="/Assets/stop.png"/>
</Button>
<Button Grid.Column="4" ToolTip.Tip="{Lan:Localize mvTipClear}"
HorizontalAlignment="Stretch" VerticalContentAlignment="Stretch"
Command="{Binding OnClearCommand}"
					>
<Image Source="/Assets/clear.png"/>
</Button>
<Button Grid.Column="5" ToolTip.Tip="{Lan:Localize mvTipHideLeft}"
HorizontalAlignment="Stretch" VerticalContentAlignment="Stretch"
Name="btnHideLeft"
					>
<Image Source="/Assets/hide-left.png"/>
</Button>
<Button Name="tlbtnOptions" Grid.Column="6" ToolTip.Tip="{Lan:Localize mvTipOption}"
HorizontalAlignment="Stretch" VerticalContentAlignment="Stretch"
HorizontalContentAlignment="Stretch" >
<Image Source="/Assets/options.png"/>
</Button>
<ComboBox  Grid.Column="7" SelectionChanged="OnLanguageChanged" IsVisible="False">
<ComboBoxItem>English</ComboBoxItem>
<ComboBoxItem>Chinese</ComboBoxItem>
</ComboBox>
</Grid>
<SplitView Grid.Row="2" IsPaneOpen="True"
           DisplayMode="Inline" Name="viewSplit"
           OpenPaneLength="300">
<SplitView.Pane>
<Grid RowDefinitions="9*,9*,6*">
<Grid RowDefinitions="*,*,*,*,*,*,*" ColumnDefinitions="*,3*">
<TextBlock Grid.Row="0" Grid.ColumnSpan="2" VerticalAlignment="Center"
							   Text="{Lan:Localize mwSPS}" Margin="5,0"/>
<Border Grid.Row="1" Grid.RowSpan="6" Grid.ColumnSpan="2"
BorderThickness="1" BorderBrush="Black" Margin="5,0,5,-5"
CornerRadius="2"/>
<TextBlock Grid.Row="1" Text="{Lan:Localize mwPort}" TextAlignment="Right"
								   VerticalAlignment="Center" Margin="5,2,0,0"/>
<ComboBox Grid.Row="1" Grid.Column="1" HorizontalAlignment="Stretch" 
								  VerticalAlignment="Center" Margin="5,2,10,0" 
								  Items="{Binding SerialPortList}" SelectedIndex="{Binding PortNameIndex}"


								  />
<TextBlock Grid.Row="2" Text="{Lan:Localize mwBaudRate}" TextAlignment="Right"
								   VerticalAlignment="Center" Margin="5,0,0,0"/>
<ComboBox Grid.Row="2" Grid.Column="1" HorizontalAlignment="Stretch"
								  VerticalAlignment="Center" Margin="5,2,10,0"
								  Items="{Binding BaudRateList}" SelectedIndex="{Binding BaudRateIndex}"/>
<TextBlock Grid.Row="3" Text="{Lan:Localize mwDataBits}" TextAlignment="Right"
								   VerticalAlignment="Center" Margin="5,0,0,0"/>
<ComboBox Grid.Row="3" Grid.Column="1" HorizontalAlignment="Stretch"
								  VerticalAlignment="Center" Margin="5,2,10,0"
							      Items="{Binding DataBitsList}"
								  SelectedIndex="{Binding DataBitsIndex}"
								  />
<TextBlock Grid.Row="4" Text="{Lan:Localize mwParity}" TextAlignment="Right"
								   VerticalAlignment="Center" Margin="5,0,0,0"/>
<ComboBox Grid.Row="4" Grid.Column="1" HorizontalAlignment="Stretch"
								  VerticalAlignment="Center" Margin="5,2,10,0"
								  SelectedIndex="{Binding Parity}">
<ComboBoxItem Content="None"/>
<ComboBoxItem Content="Odd"/>
<ComboBoxItem Content="Even"/>
<ComboBoxItem Content="Mark"/>
<ComboBoxItem Content="Space"/>
</ComboBox>
<TextBlock Grid.Row="5" Text="{Lan:Localize mwStopBits}" TextAlignment="Right"
								   VerticalAlignment="Center" Margin="5,0,0,0"/>
<ComboBox Grid.Row="5" Grid.Column="1" HorizontalAlignment="Stretch"
								  VerticalAlignment="Center" Margin="5,2,10,0"
								  SelectedIndex="{Binding StopBits}"
								  >
<ComboBoxItem Content="1"/>
<ComboBoxItem Content="1.5"/>
<ComboBoxItem Content="2"/>
</ComboBox>
<TextBlock Grid.Row="6" Text="{Lan:Localize mwFlowType}" TextAlignment="Right"
								   VerticalAlignment="Center" Margin="5,0,0,0"/>
<ComboBox Grid.Row="6" Grid.Column="1" HorizontalAlignment="Stretch"
								  VerticalAlignment="Center" Margin="5,2,10,0"
								  SelectedIndex="{Binding FlowType}"								  
								  >
<ComboBoxItem Content="None"/>
<ComboBoxItem Content="RTS/CTS"/>
<ComboBoxItem Content="DTR/CTS"/>
</ComboBox>
</Grid>
<Grid Grid.Row="1" RowDefinitions="3*,0.2*,2*,*,*,*" ColumnDefinitions="*,*">
<TextBlock Grid.Row="0" Grid.ColumnSpan="2" VerticalAlignment="Bottom"
							   Text="{Lan:Localize mwReceiveSet}" Margin="5,0"/>
<Border Grid.Row="1" Grid.RowSpan="5" Grid.ColumnSpan="2"
BorderThickness="1" BorderBrush="Black" Margin="5,0,5,0"
CornerRadius="2"/>
<RadioButton Grid.Row="2" Grid.Column="0" GroupName="Receive"
									 Content="ASCII" Margin="10,5" 
									 IsChecked="{Binding ReceivePara.IsText}"/>
<RadioButton Grid.Row="2" Grid.Column="1" GroupName="Receive"
									 Content="Hex" Margin="10,5" 
									 IsChecked="{Binding ReceivePara.IsHex}"/>
<CheckBox Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2"
									 Content="{Lan:Localize mwAutoFL}" Margin="10,5" 
								  IsChecked="{Binding ReceivePara.AutoFeed}"/>
<CheckBox Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="2"
									 Content="{Lan:Localize mwDisSend}" Margin="10,5" 
								  IsChecked="{Binding ReceivePara.DisplaySend}"/>
<CheckBox Grid.Row="5" Grid.Column="0" Grid.ColumnSpan="2"
									 Content="{Lan:Localize mwDisTime}" Margin="10,5" 
								  IsChecked="{Binding ReceivePara.DisplayTime}"/>


</Grid>
<Grid Grid.Row="2" RowDefinitions="*,0.2*,2*,1.5*" ColumnDefinitions="*,1.5*,40">
<TextBlock Grid.Row="0" Grid.ColumnSpan="2" VerticalAlignment="Bottom"
							   Text="{Lan:Localize mwSendSet}" Margin="5,0"/>						
<Border Grid.Row="1" Grid.RowSpan="5" Grid.ColumnSpan="3"
BorderThickness="1" BorderBrush="Black" Margin="5,0,5,5"
CornerRadius="2"/>
<RadioButton Grid.Row="2" Grid.Column="0" GroupName="Send"
									 Content="ASCII" Margin="10,5" 
									 IsChecked="{Binding SendPara.IsText}"
									 />
<RadioButton Grid.Row="2" Grid.Column="1" GroupName="Send"
									 Content="Hex" Margin="10,5" 
									 IsChecked="{Binding SendPara.IsHex}"/>
<CheckBox Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2"
									 Content="{Lan:Localize mwLoop}" Margin="10,0,0,10"
									 VerticalAlignment="Stretch" 
								    Name="chbLoop"  >


</CheckBox>
<NumericUpDown Grid.Row="3" Grid.Column="1" VerticalAlignment="Stretch" 
									   Margin="10,0,0,10" Padding="5"
									   Value="{Binding SendPara.LoopInterval}"
									   VerticalContentAlignment="Center"
									   />
<TextBlock Grid.Row="3" Grid.Column="2"
Text="ms" VerticalAlignment="Center" Margin="5,5,5,10" />
</Grid>
</Grid>
</SplitView.Pane>


<Grid RowDefinitions="*,70,40" ColumnDefinitions="*,100">


<TextBox Grid.Row="0" Grid.ColumnSpan="2" IsReadOnly="False" Margin="0,0,5,5"
						 ScrollViewer.VerticalScrollBarVisibility="Auto" VerticalContentAlignment="Top" HorizontalContentAlignment="Left"
						 VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
						 TextWrapping="Wrap" Text="{Binding Path=ReceiveTxt}" 
						 />
<TextBox Grid.Row="1" Grid.ColumnSpan="2" Margin="0,0,5,5" 


						 ScrollViewer.VerticalScrollBarVisibility="Auto"
TextWrapping="Wrap" 
						 Text="{Binding SendTxt}"
						 />
<ComboBox Grid.Row="2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0,0,5,5"
						  SelectedIndex="{Binding SendTxtHisSelIndex}" Items="{Binding SendTxtHistory}"


						  Name="CbbHistory"
						  />
<Button Grid.Row="2" Grid.Column="1" VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" Margin="0,0,5,5"
Content="{Lan:Localize mwSend}" FontSize="15" Padding="0" 
VerticalContentAlignment="Center" HorizontalContentAlignment="Center"
Command="{Binding OnSendCommand}" 
IsEnabled="{Binding SendCmdIsEnable}"
						/>
</Grid>
</SplitView>
<Grid Grid.Row="3" ColumnDefinitions="200,200,200">
<TextBlock Grid.Column="0" Text="{Binding ComPortState}" 
					   VerticalAlignment="Bottom" Margin="5"
					   Foreground="{Binding ComPortStateColor}"
					   />
<TextBlock Grid.Column="1" Text="{Binding ReceiveBytesStr}" 
					   Foreground="{Binding ReceiveBytesColor}" 
					   VerticalAlignment="Bottom" Margin="5"/>
<TextBlock Grid.Column="2" Text="{Binding SendBytesStr}" 
					   Foreground="{Binding SendBytesColor}"
					   VerticalAlignment="Bottom" Margin="5"/>
</Grid>
</Grid>




</Window>

MainWindow.axaml.cs

using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
using BaoYuanSerial.ViewModels;
using ReactiveUI;


using System.Reactive;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading;
using Avalonia.Styling;


using MessageBox.Avalonia.DTO;
using MessageBox.Avalonia.Enums;
using BaoYuanSerial.Models;
using System;
using Avalonia.Markup.Xaml.MarkupExtensions;
using BaoYuanSerial.Util;


namespace BaoYuanSerial.Views
{
    public partial class MainWindow :Window
    {
        private readonly List<Window> _windows = new List<Window>();


        MainWindowViewModel _thisViewModel;
        CheckBox _chbLoop;


        public MainWindow()
        {
            InitializeComponent();
#if DEBUG
            this.AttachDevTools();
#endif
            //Instance = this;
            var AboutMenu = this.FindControl<MenuItem>("AboutMenu");
            AboutMenu.Command = ReactiveCommand.Create(AboutMenuClicked);
            var DonateMenu = this.FindControl<MenuItem>("DonateMenu");
            DonateMenu.Command = ReactiveCommand.Create(DonateMenuClicked);
            var OptionsMenu = this.FindControl<MenuItem>("OptionsMenu");
            OptionsMenu.Command = ReactiveCommand.Create(OptionsMenuClicked);
            var tlbtnOptions = this.FindControl<Button>("tlbtnOptions");
            tlbtnOptions.Command = ReactiveCommand.Create(OptionsMenuClicked);
            var ToolBoxMenu = this.FindControl<MenuItem>("ToolBoxMenu");
            ToolBoxMenu.Command = ReactiveCommand.Create(ToolBoxMenuClicked);
            var AsciiCodeMenu = this.FindControl<MenuItem>("AsciiCodeMenu");
            AsciiCodeMenu.Command = ReactiveCommand.Create(AsciiCodeMenuClicked);
            var ChineseMenu = this.FindControl<MenuItem>("ChineseMenu");
            ChineseMenu.Command = ReactiveCommand.Create(ChineseMenuClicked);
            var EnglishMenu = this.FindControl<MenuItem>("EnglishMenu");
            EnglishMenu.Command = ReactiveCommand.Create(EnglishMenuClicked);
            Button btnHideLeft = this.FindControl<Button>("btnHideLeft");
            btnHideLeft.Click += btnHideLeft_Click;
            ComboBox CbbHistory = this.FindControl<ComboBox>("CbbHistory");
            CbbHistory.SelectionChanged += SendHistoryComb_Changed;
            _chbLoop = this.FindControl<CheckBox>("chbLoop");            
            _chbLoop.Checked += LoopChbox_Checked;  //当checkbox未选中转为选中时触发。
            _chbLoop.Unchecked += LoopChbox_UnChecked;  //当checkbox选中转为未选中时触发
            GlobalPara.GetLocSet();
            Localizer.Instance.LoadLanguage(GlobalPara.LocSet.Language);


        }


        private void InitializeComponent()
        {
            AvaloniaXamlLoader.Load(this);
        }




        public void LoopChbox_Checked(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
        {
            _thisViewModel = (MainWindowViewModel)this.DataContext;
            if (_thisViewModel != null)
            {
                if (_thisViewModel._serialPort == null || _thisViewModel.SendTxt.Trim() == "")
                {
                    var msBoxStandardWindow = MessageBox.Avalonia.MessageBoxManager
                    .GetMessageBoxStandardWindow(new MessageBoxStandardParams
                    {
                        ButtonDefinitions = ButtonEnum.Ok,
                        ContentTitle = "Tips",
                        ContentMessage = "Please Open ComPort First Or SendText is not Empty",
                        Icon = MessageBox.Avalonia.Enums.Icon.Info,
                        FontFamily = "Microsoft YaHei,Simsun",
                        WindowStartupLocation = Avalonia.Controls.WindowStartupLocation.CenterScreen,
#if Ubuntu
                    Style =MessageBox.Avalonia.Enums.Style.UbuntuLinux
#elif MSWindow
                    Style = MessageBox.Avalonia.Enums.Style.Windows
#endif
                });
                    msBoxStandardWindow.Show();
                    _chbLoop.IsChecked = false;
                    return;
                }               
                _thisViewModel.SendCmdIsEnable = false;
                _thisViewModel.SendPara.IsLoop = true;
                Task.Factory.StartNew(async() => {
                    while(_thisViewModel.SendPara.IsLoop)
                    {
                        await _thisViewModel.SendCmdLoop();
                    }                       
                });
            }
        }


        public void LoopChbox_UnChecked(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
        {
            _thisViewModel = (MainWindowViewModel)this.DataContext;
            if (_thisViewModel != null)
            {
                _thisViewModel.SendCmdIsEnable = true;
                _thisViewModel.SendPara.IsLoop = false;
            }
        }


        private void btnHideLeft_Click(object obj, Avalonia.Interactivity.RoutedEventArgs e)
        {
            SplitView splitView = this.FindControl<SplitView>("viewSplit");
            splitView.IsPaneOpen = !splitView.IsPaneOpen;
        }
        private void SendHistoryComb_Changed(object obj, SelectionChangedEventArgs e)
        {
            _thisViewModel = (MainWindowViewModel)this.DataContext;
            if(_thisViewModel != null)
            {
                _thisViewModel.SendTxt= _thisViewModel.SendTxtHistory[_thisViewModel.SendTxtHisSelIndex];
            }
        }


        protected override void OnClosing(CancelEventArgs e)
        {
            foreach (var window in _windows)
            {
                window.Close();
            }
        }
        private void AboutMenuClicked()
        {
            var window = new AboutWindow
            {
                DataContext = new AboutViewModel(),
                Topmost = true,
                CanResize = false


            };
            window.ShowDialog(this);
            window.Activate();


            _windows.Add(window);
        }
        private void DonateMenuClicked()
        {
            var window = new DonateWindow
            {                
                Topmost = true,
                CanResize = false
            };
            window.ShowDialog(this);
            window.Activate();


            _windows.Add(window);
        }
        private void OptionsMenuClicked()
        {
            var window = new OptionsWindow
            {
                DataContext = new OptionsViewModel(),
                Topmost = true,
                CanResize = false
            };
            window.Show();
            window.Activate();


            _windows.Add(window);
        }


        private void ToolBoxMenuClicked()
        {
            var window = new ToolBoxWindow
            {
                DataContext=new ToolBoxViewModel(),
                Topmost = true,
                CanResize = false
            };
            window.ShowDialog(this);
            window.Activate();


            _windows.Add(window);
        }


        private void AsciiCodeMenuClicked()
        {
            var window = new AsciiCodeWindow
            {
                Topmost = true,
                CanResize = false
            };
            window.ShowDialog(this);
            window.Activate();


            _windows.Add(window);
        }


        private void ChineseMenuClicked()
        {
            Localizer.Instance.LoadLanguage("zh-CN");
             try
            {
                GlobalPara.SaveCurLanguage("zh-CN");
            }
            catch
            {
            }


        }
        private void EnglishMenuClicked()
        {
            Localizer.Instance.LoadLanguage("en-US");
            try
            {
                GlobalPara.SaveCurLanguage("en-US");
            }
            catch
            {
            }
        }
        private void OnLanguageChanged(object sender, SelectionChangedEventArgs args)
        {
            //var cb = sender as ComboBox;
            //var language = cb.SelectedIndex == 0 ? "en-US" : "zh-CN";
            //Localizer.Instance.LoadLanguage(language);
        }
    }
}

以上Linux系统部署串口通讯就完成,快去试试吧。

Linux系统安装SQL Server数据库

.NET6接口WebApi部署到Linux系统上

C# VOL.NET6项目使用宝塔部署到Linux系统完整篇

C# AvaloniaUI实现跨平台多语言串口通讯

C# WinForm实现跨平台串口通讯

C#WPF实现串口通讯

Visual Studio 2022安装Avalonia

C#Avalonia串口通讯Linux部署测试 (qq.com)

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容