简体   繁体   English

如何通过串行终端检索数据而不破坏其在嵌入式 GNU ARM 中的基本价值?

[英]How can I retrieve data through a serial terminal without corrupting its fundamental value in GNU ARM embedded?

I'm wondering if anyone can help me spot the problem here...我想知道是否有人可以帮我在这里发现问题...

In my C++ embedded program for an STM32L, I'm trying to retrieve a binary data file stored on an SD card over a serial connection via a CLI (or terminal, or whatever will work).在我用于 STM32L 的 C++ 嵌入式程序中,我试图通过 CLI(或终端,或任何可行的方法)通过串行连接检索存储在 SD 卡上的二进制数据文件。 So far, I can read the data file just fine using the FatFs f_read function.到目前为止,我可以使用 FatFs f_read 函数很好地读取数据文件。 It's contents are being stored in the f_read buffer, which I can verify in debug mode.它的内容存储在 f_read 缓冲区中,我可以在调试模式下验证。

However, the problem is that the RTOS I'm using requires outgoing data to be in the const char* form, so I'm forced to somehow get the elements into that type.但是,问题是我使用的 RTOS 要求传出数据为 const char* 形式,因此我不得不以某种方式将元素放入该类型。 So far I've been doing this by casting, however, depending on which type I use as a an f_read buffer, this either causes nothing to be printed or changes the its fundamental hex value when it's transferred over the serial connection to the CLI on my CPU.到目前为止,我一直通过强制转换来完成此操作,但是,根据我用作 f_read 缓冲区的类型,这要么不会导致打印任何内容,要么在通过串行连接传输到 CLI 时更改其基本十六进制值我的 CPU。

Here's the operative part of my code.这是我的代码的操作部分。 In this instance I'm storing the buffer data as uint16_t, but I've tried many other types (char, BYTE, char*), none of which manage to get the data to the other side without being corrupted.在这种情况下,我将缓冲区数据存储为 uint16_t,但我尝试了许多其他类型(char、BYTE、char*),但没有一种能够在不损坏的情况下将数据传输到另一端。

FRESULT res;
FIL fsrc;
uint16_t buffer[512];
uint16_t bw = 0;

res = f_open(&fsrc, "zurn.dat", FA_READ | FA_OPEN_ALWAYS);  

res = f_read(&fsrc, buffer, sizeof buffer, &bw);                                      

//just printing the first few elements to see if it works
for(int i=0; i<10; i++){
     CLI_printMessage(ZString((const char*)buffer[i])); 
}

f_close(&fsrc);                                               

I must emphasize that its the fundamental hex values that I'm trying to transfer.我必须强调它是我试图转移的基本十六进制值。 A user has already kindly showed me how to get the ASCII representation of the hex values to go through (which I may have to resort to in the end), however, it'd be more useful for me if there's a way to get maintain the hex values themselves rather.一个用户已经好心地向我展示了如何获得十六进制值的 ASCII 表示(最后我可能不得不求助于它),但是,如果有办法维护它对我来说会更有用十六进制值本身。

To further clarify, as an example: the first few characters of the data file look like this in ASCII: Èì‰Jà©í, and this in Hex: ecc8 8903 e04a a9ad.为了进一步澄清,举个例子:数据文件的前几个字符在 ASCII 中看起来像这样:Èì‰Jà©í,在十六进制中是这样:ecc8 8903 e04a a9ad。 This is what I need on the other side, rather than this in ASCII: ecc8 8903 e04a a9ad, which is this in hex: 6563 6338 2038 3930 3320 6530 3461 2061 3961 64.这是我在另一边需要的,而不是 ASCII:ecc8 8903 e04a a9ad,这是十六进制的:6563 6338 2038 3930 3320 6530 3461 2061 3961 64。

Some further thoughts: I realize the problem is likely with the casting.一些进一步的想法:我意识到问题可能出在演员身上。 For starters, it gives me the warning "cast to pointer from integer of different size [-Wint-to-pointer-cast]".对于初学者,它给了我警告“从不同大小的整数[-Wint-to-pointer-cast]转换为指针”。 I understand this is because in C++ pointers default to 16 bits, hence the uint16_t type for my buffer.我理解这是因为在 C++ 中,指针默认为 16 位,因此缓冲区的 uint16_t 类型。

I've also tried copying the data stored in the buffer to another variable, and casting that.我还尝试将存储在缓冲区中的数据复制到另一个变量,然后进行转换。 In most circumstances, this shows the proper hex values at the debug level, but with lots of ASCII junk attached to it, of which I have no explanation for.在大多数情况下,这在调试级别显示了正确的十六进制值,但是附加了很多 ASCII 垃圾,对此我没有解释。 I've also tried reducing my buffer array size to a mere 8 elements, still no difference.我还尝试将我的缓冲区数组大小减少到仅 8 个元素,但仍然没有区别。

The answer may also be specific to my RTOS, which has many special types made for it that I don't fully understand, though its mostly based on FreeRTOS.答案也可能特定于我的 RTOS,它有许多我不完全理解的特殊类型,尽管它主要基于 FreeRTOS。 If you haven't noticed I'm not a very experienced programmer...如果你没有注意到我不是一个非常有经验的程序员......

Also, I'm using the Eclipse IDE and the GNU Arm Build Tools.此外,我正在使用 Eclipse IDE 和 GNU Arm Build Tools。

Casting will not solve the issue and perhaps you have illustrated why casting is bad.铸造不能解决问题,也许你已经说明了为什么铸造不好。


You need a function like something like this,你需要一个像这样的函数,

/* four 'nibbles' (nibble = 4 bits = one hex) is 16 bits. */
void int16ToString(char *buf[4], uint16_t val)
{
   static const char *lookup = "0123456789ABCDEF";
   buf[3] = lookup[val & 0xf]; /* write backwards or you need a copy of val */
   val = val >> 4;
   buf[2] = lookup[val & 0xf];
   val = val >> 4;
   buf[1] = lookup[val & 0xf];
   val = val >> 4;
   buf[0] = lookup[val & 0xf];
}

There are various functions in the C library, etc which do similar things. C 库等中有各种功能可以做类似的事情。 Obviously the routine needs a buffer of 4 bytes and it is not null terminated by the routine.显然,例程需要一个 4 字节的缓冲区,并且它不是由例程终止的。 It is just to demonstrate what needs to happen.这只是为了展示需要发生的事情。 sprintf , snprint , etc will be useful to look at as well as itoa , etc. sprintfsnprint等将有助于查看以及itoa等。


Why do you need a function like that?为什么需要这样的功能? Because there are two sides to the conversation and they can (and probably do interpret things differently ).因为对话有两个方面,他们可以(并且可能会以不同的方式解释事物)。 Generally you can transfer the lower ascii characters without effect.一般情况下,您可以传输较低的ascii 字符而不会产生任何影响。 For example 'XON' is a flow control character that can be embedded in a data stream.例如,'XON' 是一个可以嵌入数据流中的流控制字符。

If you are to transmit the binary data via the CLI you need to 'clean it' and then you need code on the other side of the CLI uart to undo that.如果您要通过 CLI 传输二进制数据,您需要“清理它”,然后您需要 CLI uart 另一侧的代码来撤消该操作。 You can just send hex and then convert back to binary.您可以只发送十六进制,然后再转换回二进制。 There are more efficient ways to do this such as zmodem and base64 if the data is large or the link (CLI uart) is not reliable.如果数据很大或链接(CLI uart)不可靠,还有更有效的方法可以做到这一点,例如zmodembase64 A simple itoa() with ahexdump conversion on another host will transfer the binary which is suitable for a debugging transfer.在另一台主机上使用十六进制转储转换的简单itoa()将传输适合调试传输的二进制文件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何重建GNU Arm嵌入式工具链的newlib和newlib-nano - How to rebuild newlib and newlib-nano of GNU Arm Embedded Toolchain 如何通过串行端口发送请求从目录中检索数据? - How to retrieve a data from a directory by sending a request through the serial port? 如何在不破坏数据的情况下将缓冲区投射到结构? - How would one cast a buffer to a struct without corrupting the data? 如何在我的串行监视器中添加带有传感器值的日期 - how can i add a date with the value of sensor in my serial monitor 如何将数据从网页发送到串行端口? - How can I send data from a web page to a serial port? 如何在不破坏连接的情况下发送和接收高达SO_SNDTIMEO和SO_RCVTIMEO的数据? - How to send and receive data up to SO_SNDTIMEO and SO_RCVTIMEO without corrupting connection? 如何以向量的向量作为其值来遍历 map? - How can you iterate through a map with a vector of vectors as its value? GNU ARM Embedded Toolchain 和普通 gcc/g++ 与裸机 ARM 架构之间的区别 - Difference between the GNU ARM Embedded Toolchain and normal gcc/g++ with bare metal ARM architecture 如何在Windows中编译Gnu C - How can I compile Gnu C in windows 如何加载图像并遍历其像素? - How can I load an image and iterate through its pixels?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM