大家好,我是新来的,我听过很多关于这个网站的消息,它真的很有帮助。希望你能帮到我!
我有一个非常简单的程序,它的唯一目的是从串口读取并在C#的控制台窗口上打印2000次。
我只是在一个微控制器上转动一个可变电阻器
以下是代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
namespace Testing_serial_v3._0
{
class Program
{
static void Main(string[] args)
{
string buff;
SerialPort port = new SerialPort("COM4", 9600, Parity.None, 8, StopBits.One);
port.Open();
for (int i = 0; i < 2000; i++)
{
buff = port.ReadLine();
Console.WriteLine(buff);
//Console.ReadLine();
}
}
}
}
但是这段代码中发生了一件有趣的事情。当控制台读取线被注释时,如上面的代码所示,当我转动可变电阻器的旋钮时,端口的值会发生变化。所以这意味着它运作良好。 另一方面,如果我使readline发生,以便在每个值后我必须按一个键,端口读取当前值,即使我更改旋钮并再次按Enter键,值将保持第一个,就好像它没有重置一点都没有?
您是否必须包含任何其他命令行以便端口重置?
希望您了解我的问题以及您需要了解的任何其他问题请不要犹豫,我确实需要尽快解决这个问题。 非常感谢和问候
答案 0 :(得分:2)
通过端口传输的数据是一个流 - 当您阅读时,您正在逐渐使用该流。你没有看到“最近的价值”,你看到“流中的下一个值”。添加读取行时,会添加延迟,这意味着存在大量积压的数据。这不是“它保持不变”......只是你还没有读到最后(以及更近期的值)。
在许多情况下,最好通过异步回调处理网络IO,以便从流中读取值不会与人类数据输入等延迟相关联。但这可能涉及一些线程知识。
答案 1 :(得分:1)
您正在从微控制器向串口发送数千个数据(例如延迟1ms),这使得串口的缓冲区填充了相同的值!如果你按回车键逐一阅读,你正在阅读第一个收到的......
我认为如果您想通过“Enter”键在计算机中读取数据,您应该通过按钮从微控制器发送日期!这意味着您通过电阻设置值,按下按钮,微型发送“One Byte”到计算机。按下计算机上的enter键,让计算机从串口读取“One Byte”!
还要对代码进行一些修改:
static void Main(string[] args)
{
int buff; // string to int
SerialPort port = new SerialPort("COM4", 9600, Parity.None, 8, StopBits.One);
port.Open();
for (int i = 0; i < 2000; i++)
{
Console.ReadLine(); // wait for the Enter key
buff = port.ReadByte(); // read a byte
Console.WriteLine(buff);
}
}
我希望这对你有用! :)
答案 2 :(得分:1)
你也可以使用一个Task在一个单独的线程中读取它并在那里观察它,就像@Marc Gravel提到的那样。您只需等到任务完成或按Enter键手动取消它。另一个将任务卸载到另一个线程的例子。
以下是一个例子:
using System;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ReadStreamAsyncTask
{
internal class Program
{
private static CancellationToken _cancelTaskSignal;
private static byte[] _serialPortBytes;
private static MemoryStream _streamOfBytesFromPort;
private static CancellationTokenSource _cancelTaskSignalSource;
private static void Main()
{
_serialPortBytes = Encoding.ASCII.GetBytes("Mimic a bunch of bytes from the serial port");
_streamOfBytesFromPort = new MemoryStream(_serialPortBytes);
_streamOfBytesFromPort.Position = 0;
_cancelTaskSignalSource = new CancellationTokenSource();
_cancelTaskSignal = _cancelTaskSignalSource.Token; // Used to request cancel the task if needed.
var readFromSerialPort = Task.Factory.StartNew(ReadStream, _cancelTaskSignal);
readFromSerialPort.Wait(3000); // wait until task is complete(or errors) OR 3 seconds
Console.WriteLine("Press enter to cancel the task");
_cancelTaskSignalSource.Cancel();
Console.ReadLine();
}
private static void ReadStream()
{
// start your loop here to read from the port and print to console
Console.WriteLine("Port read task started");
int bytesToReadCount = Buffer.ByteLength(_serialPortBytes);
var localBuffer = new byte[bytesToReadCount];
int bytesRead = 0;
bool finishedReading = false;
try
{
while (!finishedReading)
{
_cancelTaskSignal.ThrowIfCancellationRequested();
bytesRead += _streamOfBytesFromPort.Read(localBuffer, 0, bytesToReadCount);
finishedReading = (bytesRead - bytesToReadCount == 0);
}
}
catch (TaskCanceledException)
{
Console.WriteLine("You cancelled the task");
}
Console.WriteLine(Encoding.ASCII.GetString(localBuffer));
Console.WriteLine("Done reading stream");
}
}
}