STM32F通过UART发送UINT16_T

发布于 2025-01-29 13:19:17 字数 623 浏览 5 评论 0原文

我试图使用此代码发送UINT16_T数据,

uint16_t ADCValue;
uint8_t lowerMessage;
uint8_t upperMessage;
uint8_t message[2];

while (1)
{
      ADCValue = 2375;
      lowerMessage = (uint8_t)ADCValue;
      upperMessage = (uint8_t)(ADCValue >> 8);
      message[0]= lowerMessage;
      message[1]= upperMessage;
      HAL_UART_Transmit(&huart1,message, 8, 1000);
      //HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_9);
      HAL_Delay(2000);  
}

我将16位整数拆分为8位整数发送。但是,当我尝试发送此消息时,我会收到这个 - > 接收到数据。 我该怎么办来发送这些数据?

im trying to send uint16_t data with this code

uint16_t ADCValue;
uint8_t lowerMessage;
uint8_t upperMessage;
uint8_t message[2];

while (1)
{
      ADCValue = 2375;
      lowerMessage = (uint8_t)ADCValue;
      upperMessage = (uint8_t)(ADCValue >> 8);
      message[0]= lowerMessage;
      message[1]= upperMessage;
      HAL_UART_Transmit(&huart1,message, 8, 1000);
      //HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_9);
      HAL_Delay(2000);  
}

i split the 16 bit integer to 8 bit integers to send. But when i try the send this i recieve this -> Received Data.
What should i do to send this data?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

翻身的咸鱼 2025-02-05 13:19:17

在调用hal_uart_transmit的调用中,您将8作为大小。这就是您要发送的字节中的大小。而且您的数组仅具有两个两个字节(即sizeof Message等于2)。

在接收大小上,您当然应该阅读两个字节。并将它们视为原始字节,没有任何特定的含义。您绝对不应该尝试将其打印为字符串,因为它不是。取而代之的是,您应该将数组的单个字节和在发件人程序中所做的操作的逆转,以重建原始uint16_t值。

In the call to HAL_UART_Transmit you pass 8 as the size. That's the size in bytes you want to send. And your array only have two bytes (i.e. sizeof message is equal to 2).

And on the receiving size, you should of course read two bytes. And treat them as raw bytes without any specific meaning. You should definitely not try to print it as a string, because it isn't. Instead you should take the individual bytes of the array and to the reverse of what you're doing in the sender program, to reconstruct the original uint16_t value.

眼角的笑意。 2025-02-05 13:19:17
while (1)
{
      ADCValue = ReadADC();
      /* .... */
      HAL_UART_Transmit(&huart1,(uint8_t *)&ADCValue, sizeof(ADCValue), 1000);
      /* .... */
}

在接收方侧(假设大多数系统使用它现在使用它)

HAL_UART_Receive(&huart1,(uint8_t *)&ADCValue, sizeof(ADCValue), 1000);

HAL库是一个很糟糕的方法(而不是void *他们期望uint8_t *)和演员是沉默警告。相信您所做的“信息”魔术是避免此警告。

还要检查返回值是否错误。

while (1)
{
      ADCValue = ReadADC();
      /* .... */
      HAL_UART_Transmit(&huart1,(uint8_t *)&ADCValue, sizeof(ADCValue), 1000);
      /* .... */
}

On the receiver side (assuming the same endianness - most systems use it nowadays)

HAL_UART_Receive(&huart1,(uint8_t *)&ADCValue, sizeof(ADCValue), 1000);

HAL library is written quite a bad way (instead of void * they expect uint8_t *) and the cast is to silence the warning. A believe that the 'message' magic you did was to avoid this warning.

Also check the return value for errors.

浪漫人生路 2025-02-05 13:19:17

正如其他人提到的那样,您的消息大小错误,应该是“ 2”(字节数,SizeOf()的使用更灵活)。

我还将详细说明您为什么看到垃圾的原因:当您发送一个字节时,例如“ 97”,在接收方中,您会看到字母“ a”。因为那是97(十六进制0x61)编码的内容。您不是发送小数数字作为字符,而是发送0B01010101(或任何单独的位),并且您的接收器选择将其解释为char-通常是所需的行为。

因此,收到的数据很可能是正确的,但是您仍然会在屏幕上看到垃圾,因为它被视为char。 char 97只是一个字母a。您可以通过手动感测97/0x61并查看接收器上实际到达的东西进行实验。

在这里您可以找到带有每个编号的char carl carl carl a的ascii表。这是其中的表:

”在此处输入图像描述“

“在此处输入图像描述”

首先有小数值,然后是十六进制值,然后是其作为char的含义。例如,请注意0xff(12月255日)以符号表示。如果您在某些十六进制编辑器中打开二进制文件,则可以在整个地方看到。这只是字节,所有1个被视为字符。


这个问题有多种解决方案。

解决方案编号1:您将整个16位整数变成其小数位数的字符串。在发送某些内容之前,您将35000的AdcValue转换为字符串“ 35000”,然后将所有这些作为字符发送。

重要说明:字符“ 1”与uint8_t1。字符1是0x31(12月49日)的二进制值1。因此,如果您通过UART发送0x31,则接收器将显示“ 1”。您需要实际将数字的每个数字转换为相应的字符。

这种方法的优点:接收器获得格式化的数据,您要做的就是将其投放给整数,然后您就完成了。您将在终端中看到实际的“ 35000”。
缺点:实际上,您需要根据数字的长度将小数号转换为各个长度的字符串,这是一个不愉快的操作,它具有MCU的处理能力,并且您通常会有更多的字节来传输该小数的每个字符数字。发送2个字节比发送“ 35000”的5个字节字符要短。您可以在Internet上找到它的解决方案 - 从35000转换为“ 35000”。

方法2:您将转换传递给整数到接收器。像您现在一样,将数据作为RAW字节发送,但在接收器上将其解释。

优点:您像问题一样从MCU发送2个字节。接收者正确解释它们是责任。每个变速箱都严格为2个字节,因此您可以更好地计时整个过程。另外,如果您的接收器是PC,则具有与微控制器相比的无限计算能力。

缺点:在终端中,您实际上会看到垃圾,除非您的终端支持将传入的数据视为字符,否则您应该检查设置。您需要实现转换以在接收器上进行整数,并在您的应用程序中自己打印出来,终端可能也可能无法做到这一点。

建议:也许是出于测试目的,您首先实现方法1,以便您可以在终端快速看到ADC的实际价值。当您在终端中看到并正确发送内容时,可以将Intereger删除以从发射器串起转换零件,然后发送原始字节并在接收器侧转换它们。


一旦修复了传输长度,您发送的数据很可能是正确的,只是终端将这些字节解释为字符。

As mentioned by others, you have wrong message size, it should be "2" there (number of bytes, sizeof() is even more flexible to use).

I will also elaborate one why you see garbage: when you send a byte with, say, number "97", on the receiving side you will see letter "a". Because that's what number 97 (hex 0x61) encodes. You're not sending decimal digits as characters, you're sending 0b01010101 (or whatever individual bits are), and your receiver chooses to interpret it as a char - which is often the desired behavior.

So the data received may very well be correct, but you will still see garbage on the screen, because it's treated as a char. And char 97 is just a letter a. You can experiment with it by manually sensing 97/0x61 and seeing what actually arrives on the receiver.

Here you can find the ASCII table with what char every number encodes. Here is the table from there:

enter image description here

enter image description here

There is a decimal value first, then hex value, then its meaning as a char. For example, notice that 0xFF (dec 255) shows as a symbol ÿ. If you ever open binary file in some hex editor, you will see ÿ all over the place. That's just bytes with all 1s treated as characters.


There are various solutions to this problem.

Solution number 1: you turn your entire 16-bit integer into a string of its decimal digits. Before you send something, you convert, for example, ADCValue of 35000 into string '35000' and send all these as chars.

Important note: character "1" is not the same as uint8_t 1. Character 1 is a binary value of 0x31 (dec 49), as per table above. So if you send 0x31 via uart, the receiver will show "1". You need to actually convert every digit of the number into corresponding character.

Advantages of this approach: the receiver gets formatted data, all you need to do is to cast it to integer, and you're done. You will see actual "35000" in the terminal.
Disadvantages: you actually need to turn a decimal number into a string of various lengths depending on length of the number, which is an unpleasant operation that takes processing power of MCU, and you will often have more bytes to transfer for every character of the decimal digit. Sending 2 bytes is shorter than sending 5 byte characters of '35000'. You can find solutions to it on the internet - conversion from 35000 to '35000'.

Approach 2: you pass conversion to integer to the receiver. Send data as raw bytes as you do now, but interpret it on the receiver.

Advantages: you send 2 bytes from MCU just like you do in the question. It's the responsibility of the receiver to interpret them correctly. Every transmission will be strictly 2 bytes, so you can time the whole thing better. Also, if your receiver is a PC, it has infinite computational power for conversion comparing to the microcontroller.

Disadvantages: in the terminal you will actually see garbage, unless your terminal supports treating incoming data not as chars, you should check settings. You need to implement conversion to integer on a receiver and print it out yourself in your application, terminal may or may not be able to do that.

Advice: maybe for test purposes you first implement approach 1, so that you can quickly see in the terminal what actual value of ADC was. When you see in the terminal it measures and sends the stuff correctly, you can delete the intereger to string conversion part from the transmitter and send raw bytes and convert them on the receiver side.


Once you fix length of transmission, it is very likely that the data you're sending is correct, it's just the terminal that interprets those bytes as chars.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文