当使用ReadFile()时,为什么我会在缓冲区的偏移处收到字符?

3

我想做什么:

我正在尝试编写一个win控制台程序,它将通过UART与我的ATMega2560板通信。现在它应该发送保存在stringToSend中的字符串到MCU,然后MCU应该将其发送回PC。从MCU发送的字符串应该保存在receivedString中,然后写入到win控制台窗口。

代码的作用:

现在它所做的是,在我将字符串发送到MCU之后,它会返回,但是在控制台上我看到了一系列意外的'╠'字符,就像这样:

你发送了:

╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠


编辑:如果BUFFER_SIZE是常量,则字符数保持一致,但它会随着BUFFER_SIZE的变化而扩展:

  • 如果BUFFER_SIZE = 124,则有132个这些字符
  • 如果BUFFER_SIZE = 1024,则有1032个这些字符
  • 如果BUFFER_SIZE = 1,则有9个这些字符

奇怪的事情(可能只有我觉得):

  • 最奇怪的是,当我使用断点并查看receivedString时,来自stringToSend的字符串不在那里,但它会出现在控制台中。
  • 当我通过Termite发送数据(通过串行通信发送数据的控制台)时,问题消失了,之后我仅收到正确的字符串,即使使用我的控制台也是如此。

问题:

  • 我是否应该在MCU中设置一些位/标志以引起这种行为?
  • 字符串格式是否有问题?
  • 我是否完全忽略了从PC / MCU发送数据之前/之后应该执行的操作?

我尝试过的:

  • 我试图在互联网上找到一些解决方案,但我找不到任何东西
  • 作为实验,我什么都没试过,因为老实说,我完全不知道问题可能是什么

我真的很感激任何帮助,甚至是重构/其他编码提示。


评论回答:

  1. 您能将值打印为十六进制并添加这些元素的数量吗?

The output:

ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc >ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc >ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc >ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc >ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc ffffffcc 53 65 6e 64 65 64 20 74 65 73 74 20 73 74 72 69 6e 67 21

Number of these characters is always BUFFER_SIZE + 8 and the character in decimal is represented as -52


解决方案:

  • 我已经在函数WriteFile()ReadFile()中添加了第四个参数,但问题不在那里(但它肯定会引起一些问题,因为文档说最后两个参数不能都为NULL)。
  • 我在文档中找到了一个地方,ReadFile()应该始终在事件发生后出现,并且函数WaitCommEvent()捕获它。事件的类型由SetCommMask(mainCom, EV_RXCHAR)设置,因此当输入缓冲区中有字符时,它就会发生(有关函数SetCommMask()的文档)。这个解决方案显示错误是由板子引起的,因为它没有发送数据,所以WaitCommEvent()将陷入无限循环等待接收数据。然而,如果不使用WaitCommEvent(),似乎发送的数据被某种内存保存并从中读取,因此即使板子没有发送它们,它们也会被打印出来(我真的不明白为什么,但请参见@thebusybee answer)。实际上,修复问题的方法只是简单地重新连接板子,每次启动Windows后(重新连接后即使使用WaitCommEvent()也可以正常工作),这让我进入了一个完全不同的问题,即Windows在引导时是否向USB端口发送一些奇怪的东西,以便与板子混淆,但这是另一个话题。它也可能是由于Windows在引导时使用不同的通信参数(如波特率等)而引起的。但这是另一个/不同的问题。

1
你的输出格式字符串中有两个 "newline":"\nYou sent: \n\n%s\n\n"。这会插入一个空行。 - the busybee
1
我注意到receivedString被声明为124个元素,但在输出格式中由相应的%s表示的槽中打印了超过124个字符。然而,我没有看到任何原因,说明ReadFile()调用会读取那么多字节。使用ReadFile()的第四个参数获取该函数自己读取了多少字节可能是值得的。 - John Bollinger
1
我认为在这种情况下这并不是必要的,但如果您使用初始化程序声明receivedString会怎样呢? char receivedString[BUFFER_SIZE] = {0}; - John Bollinger
1
看起来发生的情况是ReadFile()读取的数据进入了错误的位置——在receivedString缓冲区结束后的8个字节处。我不知道为什么会这样,但不要忽视我之前关于ReadFile()参数的评论——最后两个参数都不应该为空。WriteFile()也是如此。 - John Bollinger
1
receivedString, sizeof( stringToSend ) - 复制/粘贴错误?应该是 sizeof( receivedString )。您还没有检查读取了多少字节。我怀疑没有读取任何字节,因此您正在打印未初始化的数据。 - Raymond Chen
显示剩余17条评论
1个回答

3

ReadFile()由于您的错误调用导致最后两个参数都设置为NULL,因此不会从串行设备中读取任何字节。但是,ReadFile()没有返回FALSE

填充到receivedString中的值为0xCC(打印符号扩展为0xFFFFFFCC),被用作调试辅助工具

您PC的编译器显然在堆栈上定位变量receivedString 之前定位变量stringToSend。这些附加字节很可能是canary words

当您现在打印receivedString时,函数printf会扫描内存,直到找到终止符'\0'。这是在将stringToSend的内容扫描并复制到输出后进行的。因此,您所看到的不是由ReadFile()接收到的,而是stringToSend现有字符,恰好是您期望接收到的内容。
以下是内存情况的可视化表示:
(低地址)... receivedString 填充 stringToSend ...(高地址)
0xCC, 0xCC, ... 0xCC 0xCC, ... 0xCC 'S', 'e', ... '!', '\0'
您应该怎么做?
  1. 永远不要忽略任何返回值和输出值。在这种情况下,请检查实际读取的字节数。
  2. 始终阅读函数文档并相应使用它。通常,在Windows上尤其如此,原则“垃圾进,垃圾出”是正确的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接