解决WPF软件Arduino Leonardo串口通讯收不到问题

41 篇文章 1 订阅
27 篇文章 1 订阅

简介:本来这应该是无比基础的一个设计,然而却让我折腾了两天

 

大致情况是这样的,我写了一个USB应用的工程,下位机是基于32U4的Leonardo,而我的上位机使用WPF来写,然后在一切就绪之后,我发现我的代码并不能正常的运作,点击发送却收不到数据。

首先我试着检查了线程的运作,并没有发现问题,一切都很好,因为串口部分的处理和收发代码是我从上一个工程中拷贝的。

 

然后我试着检测下位机的代码,并且加入了众多的调试语句,比如这样的

 Serial.print("Input Data: ");
 Serial.println(comdata);
 Serial.print("Input Data length: ");
 Serial.println(comdata.length());

还有这样的。为了确认是不是发的太快导致Buffer部分可能出现问题,加了很长的延迟

if (Serial.available() > 0)   
        {  
            char c = Serial.read();  
            if (c == '1')   
            {  
                delay(10);
                Serial.println("Received 1");
            } else if (c == '0')   
            {  
              delay(10);
                Serial.println("Received 0");
            }  
            delay(1000);
            Serial.println("Dat");
        }  

然而,结果是,我依然不能找到解决的方法,但是在IDE中我可以正常的收发数据,SSCOM(串口调试助手)中也能正常收发,我试着将代码烧到一块328P(UNO)上也可以正常的收发数据,因此,我认为原因并不是出自于下位机的代码如何,而是USB转串口驱动方面与C#这边兼容性的问题。

而这个问题主要就是国产Leonardo这边的问题了,因为没有烧录器没法重新烧写一遍bootloader,所以我暂时不能确定是否和这个有关系。

 

总结下目前状态:

1.代码是正确的,因为328P上可以正常运行,使用非WPF+C#开发的串口调试工具也能正常的收发

2.上位机软件的收发代码是正确的

3.数据有正常的发送到下位机,因为RX指示灯在发送数据后有闪烁

 

如果要尽快解决这一个问题,我需要先找一个类似的可以正常接收的软件,分析和我写的有什么区别。如果说WPF本身这个架构可能不兼容,我应该先找一个类似的界面架构来检查问题。

因为最接近WPF的还是winform,所以我从PUDN(程序员软件开发网)上找到了几个winform界面的串口调试软件,其中有一个能正常的使用

http://www.pudn.com/Download/item/id/3651885.html

好的,经过确定这个软件可以正常的接收我的下位机(Leonardo)所传送的数据,并且显示在文本框内

 

这会,我需要建立一个新的工程来将他的代码的核心部分移植出来并进行测试。建立了一个WPF工程后,绘制了简单的界面,保留串口所应该有的必要的部分内容。一些串口的配置,包括波特率、停止位和校验位,直接在程序中赋值。

 

将winform的界面相关代码转换为wpf,软件使用.NET 4我也在属性中将我现有工程的.NET版本更改为4.0

 

没有效果,那么我需要重新找一下原因,是不是漏了什么配置,我试着添加了while(!Serial)来使得我能够判断串口是否正常的开启,也因此,最后,我发现是配置这块的问题

 

Leonardo如果要开启串口连接,必须接受一个复位信号,而这个信号默认是不发送的!UNO等其他328P的芯片的板子则无需这个复位信号。

整个问题缘于这个部分没有配置

serialport.RtsEnable = true;

 

问题解决

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
以下是一个WPF异步线程的串口通讯的示例代码: 首先,在XAML文件中添加一个文本框和两个按钮,分别用于发送和接数据: ```xml <Window x:Class="WpfSerialComm.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Serial Communication" Height="250" Width="400"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <StackPanel Orientation="Horizontal" Grid.Row="0"> <Label Content="Port Name:" Margin="10"/> <ComboBox x:Name="cmbPortName" Width="100" Margin="5"/> <Button x:Name="btnConnect" Content="Connect" Click="btnConnect_Click" Margin="10"/> <Button x:Name="btnDisconnect" Content="Disconnect" Click="btnDisconnect_Click" Margin="10" IsEnabled="False"/> </StackPanel> <StackPanel Orientation="Horizontal" Grid.Row="1"> <Label Content="Send Data:" Margin="10"/> <TextBox x:Name="txtSendData" Width="100" Margin="5"/> <Button x:Name="btnSend" Content="Send" Click="btnSend_Click" Margin="10" IsEnabled="False"/> </StackPanel> <StackPanel Orientation="Vertical" Grid.Row="2"> <Label Content="Received Data:" Margin="10"/> <TextBox x:Name="txtReceivedData" Width="350" Height="150" Margin="10" TextWrapping="Wrap" IsReadOnly="True"/> </StackPanel> </Grid> </Window> ``` 然后,在C#代码中添加以下内容: ```csharp using System.IO.Ports; using System.Threading.Tasks; using System.Windows; namespace WpfSerialComm { public partial class MainWindow : Window { private SerialPort serialPort; public MainWindow() { InitializeComponent(); // 初始化串口 serialPort = new SerialPort(); serialPort.BaudRate = 9600; serialPort.Parity = Parity.None; serialPort.DataBits = 8; serialPort.StopBits = StopBits.One; serialPort.Handshake = Handshake.None; // 获取可用串口列表 string[] portNames = SerialPort.GetPortNames(); foreach (string portName in portNames) { cmbPortName.Items.Add(portName); } } private async void btnConnect_Click(object sender, RoutedEventArgs e) { if (cmbPortName.SelectedItem == null) { MessageBox.Show("Please select a port name!"); return; } // 连接串口 serialPort.PortName = cmbPortName.SelectedItem.ToString(); try { serialPort.Open(); } catch (System.Exception ex) { MessageBox.Show(ex.Message); return; } // 启用发送按钮 btnSend.IsEnabled = true; // 启用断开按钮 btnDisconnect.IsEnabled = true; // 禁用连接按钮 btnConnect.IsEnabled = false; // 开始异步读取数据 await Task.Run(() => ReadData()); } private void btnDisconnect_Click(object sender, RoutedEventArgs e) { // 断开串口 serialPort.Close(); // 禁用发送按钮 btnSend.IsEnabled = false; // 禁用断开按钮 btnDisconnect.IsEnabled = false; // 启用连接按钮 btnConnect.IsEnabled = true; } private void btnSend_Click(object sender, RoutedEventArgs e) { // 发送数据 string sendData = txtSendData.Text; serialPort.Write(sendData); // 清空发送数据文本框 txtSendData.Text = ""; } private void ReadData() { while (serialPort.IsOpen) { try { // 读取数据 string receivedData = serialPort.ReadLine(); // 在UI线程中更新文本框 Dispatcher.Invoke(() => { txtReceivedData.AppendText(receivedData); txtReceivedData.ScrollToEnd(); }); } catch (System.Exception ex) { MessageBox.Show(ex.Message); } } } } } ``` 在上面的代码中,我们首先在构造函数中初始化了串口,并获取了可用串口列表,将其添加到ComboBox控件中。在连接按钮的Click事件处理程序中,我们首先检查是否选择了串口名称,然后打开串口,启用发送和断开按钮,禁用连接按钮,并开始异步读取数据。在断开按钮的Click事件处理程序中,我们关闭串口,禁用发送和断开按钮,启用连接按钮。在发送按钮的Click事件处理程序中,我们从发送数据的文本框中获取要发送的数据,向串口写入数据,然后清空发送数据的文本框。在ReadData方法中,我们使用while循环不断读取串口缓冲区中的数据,然后在UI线程中更新接数据的文本框。 注意,我们使用了异步线程来读取数据,这样可以避免在UI线程中阻塞导致界面卡顿。同时,我们使用了Dispatcher.Invoke方法来在UI线程中更新文本框,这样可以避免在异步线程中更新UI导致的线程安全问题。 在使用时,我们需要先选择串口名称,然后点击连接按钮连接串口。连接成功后,发送和断开按钮将启用,可以向串口发送数据或断开串口。接到的数据将自动显示在接数据的文本框中。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值