.NET 3.5 SP1 SerialPort 类是否在传输时附加额外的 0?
更新事实
证明错误存在于加密处理器代码中,现已修复。但现在遇到了似乎可能是握手问题。
在第一次传输时,我们从设备返回一个字节,值为 0xFF(不知道为什么,与我一起工作的工程师对 RS-232 也没有太多经验)。然后,一切正常运行(只需一次向设备发送一个字节,并等待匹配的回显)。但是,设备和 .NET 应用程序一次发送的字节数都不能超过几个字节,否则它们就会锁定并拒绝发送或接收。
在工作中,我正在编写一个应用程序,该应用程序通过 RS232 与设备内部的加密处理器连接,以对设备内部的闪存模块进行重新编程。
为了放慢速度并确保所有标头都正确,我们使用 SerialPort.Write() 一次写入一个字节。然而,当我们在加密处理器上运行代码时,它会在每个字节之间读取一个额外的 NULL。当我使用两个串行端口和交叉电缆在本地计算机上测试 .NET 代码时,我在超级终端或 Putty 中捕获输出,并且当我在 Notepad++ 中查看日志时,没有额外的 NULL。
然而,更复杂的是,当我们通过超级终端手动将消息逐字节输入到加密处理器时,它仅将输入读取为单个字节,没有额外的 NULL(与 .NET 应用程序相比)。有人有过 .NET 在写入 SerialPort 时执行神秘操作的经验吗?
我们用这个初始化一个测试块:
byte[] testBytes = new byte[] { (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G', (byte)'H' };
byte[] byteArray = new byte[256];
for (int i = 0; i < 32; i++)
{
testBytes.CopyTo(byteArray, i * 8);
}
并用这个发送它:
public void StutterSend(byte[] data, long delayMs)
{
bool interactive = false;
if (delayMs < 0)
interactive = true;
for (int i = 0; i < data.Length; i++)
{
serialPort.Write(data, i, 1);
if (interactive)
{
WriteLine("Sent byte " + (i + 1) + " of " + data.Length + ". Press any key to send moar.");
Console.ReadKey();
}
else
{
double timer = DateTime.Now.TimeOfDay.TotalMilliseconds;
do { } while ((DateTime.Now.TimeOfDay.TotalMilliseconds - timer) < delayMs);
}
}
WriteLine("Done sending bytes.");
}
我们的串行端口配置了所有匹配的参数(停止位,数据位,奇偶校验,波特率,端口名称),并且我们的握手设置为无(它是这就是我们的 UART 驱动程序的工作原理)。
Update
Turns out the error was in the crypto processor code, that is fixed. But now running into what seems like it might be a handshaking issue.
On first transmission, we get a single byte back from the device with value 0xFF(don't know why, the engineer I'm working with isn't too experienced with RS-232 either). Then, things run as normal (just sending the device one byte at a time, and waiting for a matching echo). However, neither the device nor the .NET app can send more than a couple of bytes at a time before one of them locks up and refuses to send or receive.
At work I'm writing an app that interfaces over RS232 with a crypto processor inside a device to reprogram flash modules inside the device.
To just take things slow and make sure all our headers are right, we're writing one byte at a time with SerialPort.Write(). However, when we run the code on the crypto processor, it reads an extra NULL in between each byte. When I test the .NET code on my local machine with two serial ports and a crossover cable, I capture the output in HyperTerminal or Putty and there are no extra NULLs when I view the log in Notepad++.
However, to further complicate things, when we manually type messages byte-per-byte via HyperTerminal to the crypto processor, it reads the input as a single byte only, no extra NULLs (as compared to the .NET app). Anybody have any experience with .NET doing mysterious things when it writes to a SerialPort?
We're initializing a test chunk with this:
byte[] testBytes = new byte[] { (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G', (byte)'H' };
byte[] byteArray = new byte[256];
for (int i = 0; i < 32; i++)
{
testBytes.CopyTo(byteArray, i * 8);
}
And sending it with this:
public void StutterSend(byte[] data, long delayMs)
{
bool interactive = false;
if (delayMs < 0)
interactive = true;
for (int i = 0; i < data.Length; i++)
{
serialPort.Write(data, i, 1);
if (interactive)
{
WriteLine("Sent byte " + (i + 1) + " of " + data.Length + ". Press any key to send moar.");
Console.ReadKey();
}
else
{
double timer = DateTime.Now.TimeOfDay.TotalMilliseconds;
do { } while ((DateTime.Now.TimeOfDay.TotalMilliseconds - timer) < delayMs);
}
}
WriteLine("Done sending bytes.");
}
Our SerialPort is configured with all the matching parameters (stop bits, data bits, parity, baud rate, port name), and our handshake is set to None (it's just how our uart driver works).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
关于您的更新,听起来您的加密处理器还有更多问题。返回 0xff 可能是 RS232 端口的 Tx 线上出现 <= 1 位时间的意外毛刺的结果。这被 PC 解释为起始位。毛刺发生后,Tx 线返回到标记状态,现在 PC 上的 UART 具有起始位,它将“数据”位解释为全 1(标记状态的值)。标记状态也是停止位的正确值,因此您的 PC 的 UART 已收到值为 0xff 的有效字节。请注意,相对于 RS232 数据速率,毛刺可能非常快,并且仍然被解释为起始位,因此让您的工程师在正常模式/单序列触发下使用示波器查看这条线以确认这一点。
Regarding your update, it sounds like your crypto processor has some more problems. Getting a 0xff back can be the result of an unexpected glitch of <= 1 bit time on the Tx line of the RS232 port. This is interpreted as a start bit by the PC. After the glitch, the Tx line returns to the mark state and now that the UART on the PC has a start bit, it interprets the "data" bits as all ones (the value for the mark state). The mark state is also the correct value for the stop bit(s) so your PC's UART has received a valid byte with a value of 0xff. Note that the glitch can be very fast relative to the RS232 data rate and still be interpreted as a start bit so have your engineer look at this line with an oscilloscope in normal mode/single sequence trigger to confirm this.
serialPort
的Encoding
属性设置为多少? SerialPort.Write( byte[], int, int) 的文档说它通过 Encoder 对象运行数据(对于 byte[] 来说,这对我来说没有意义) )。它应该默认为ASCIIEncoding
,但似乎它可能被设置为其他值。尝试将其显式设置为ASCIIEncoding
并查看是否有帮助。我不记得当我在 .NET 中执行一些串行端口操作以与嵌入式板通信时这对我来说是否是一个问题...请注意,即使使用
ASCIIEncoding
,您也会获得一些(可能不需要的)数据转换 - 如果您尝试发送高于值 127 的内容,编码器会将其转换为“?”因为它不是有效的 ASCII 字符。我记不起我是如何获得串行端口来简单地保留我的数据的 - 我将不得不挖掘一些源代码......What is the
Encoding
property for theserialPort
set to? The docs forSerialPort.Write( byte[], int, int)
say that it runs its data through an Encoder object (which doesn't really make sense to me for abyte[]
). It's supposed to default toASCIIEncoding
, but it seems like it might be set to something else. try explicitly setting it toASCIIEncoding
and see if that helps. I can't recall if this was an issue for me back when I did some serial port stuff in .NET to talk to an embedded board...Note that even with
ASCIIEncoding
in use, you'll get some (probably unwanted) transformation of data - if you try to send something above value 127, the encoder will convert it to '?' since it's not a valid ASCII character. I can't recall off the top of my head how I got the serial port to simply leave my data alone - I'll have to dig around in some source code...如果您未指定任何值,SerialPort 会将 Parity 属性设置为 Parity.None。这意味着,如果您的接收器需要一个奇偶校验位,只要您不明确告诉 SerialPort 将奇偶校验位与传输的数据一起发送,它就永远不会得到一个。
事实上,它在超级终端上运行良好可能是因为超级终端默认使用奇偶校验位(我不太了解超级终端)。
SerialPort sets the Parity property to Parity.None if you don't specify any. This means in case your receiver expects a Partity bit, it will never get one as long as you don't tell SerialPort explicitely to send along a Parity Bit with the transmitted data.
And the fact that it went well on HyperTerminal could be that HyperTerminal uses a Parity bit by default ( I don't know HyperTerminal well).