如何正确读取串口传入的整数?

问题描述 投票:0回答:2

我在客户端中有这段代码(从更大的代码块简化而来)

  int key=0;
  while (1) {
    int n_read=read(fd, &key, 4);
    printf("%d\n",key);
    fflush(stdout);
    if(key==1){
        printf("in loop\n");
        }   
  }

此代码位于 ATmega2560 微控制器的服务器中

while(1){
  int key=1;
  printf("%d", key);
}

服务器中的 printf 使用此代码

void usart_putchar(char data) {
    // Wait for empty transmit buffer
    while ( !(UCSR0A & (_BV(UDRE0))) );
    // Start transmission
    UDR0 = data; 
}

// this function is called by printf as a stream handler
int usart_putchar_printf(char var, FILE *stream) {
    // translate \n to \r for br@y++ terminal
    if (var == '\n') usart_putchar('\r');
    usart_putchar(var);
    return 0;
}

我希望它“循环”打印,但这永远不会发生,当我循环打印客户端中的密钥时,它的值是 825307441 而不是值 1。

我认为这可能是因为我从串行读取字节后如何将字节一个接一个地放入整数变量中,或者也许我以错误的方式使用读取函数,但我真的不知道

c serial-port microcontroller atmega
2个回答
0
投票

您正在混合值的文本和二进制表示形式。

服务器发送以字符表示的密钥,因为您使用了

printf()
。实际上,由于值为
1
,因此仅发送一个字符:
'1'

客户端需要密钥的 4 个字节的二进制表示形式,因为您使用

read()

让我们看看您收到了什么。从串口读取的4字节值是十进制的825307441。快速放入桌面计算器并转换为十六进制显示它是0x31313131。

这4个字节是

'1'
的4个ASCII字符。如果您可以计算传输次数,您会发现服务器需要运行 4 次循环才能让客户端接收 1 个密钥。

如何解决?

您有两个选择,仅使用二进制表示或仅使用文本表示。

如果您想避免“字节序”问题,请选择文本表示。为此,将客户端代码更改为: /* fd needs to be transformed into a FILE* f. */ int key = 0; while (1) { int n_converted = fscanf(f, "%d", &key); if (n_converted == 1) { printf("%d\n", key); /* not necessary: fflush(stdout); */ if (key == 1) { printf("in loop\n"); } } else { /* error handling */ } }

并且您需要用空格分隔数字,空格至少是空白、制表符或换行符之一。扩展服务器代码:

while (1) { int key = 1; printf("%d\n", key); }



0
投票
read

。好吧,我不应该这么说,因为您可以这样做,但这与正在发送的数据不匹配。您根本没有发送

int
。您正在发送组成
int
的 ASCII 字符。这样想...如果我发送
int
44444
,我
应该
从读取中得到的是'4'的5个ascii字符。这实际上会溢出你的缓冲区,因为你的
int
的大小为 4。通过
int
打印
printf
是提供人类可读的
text
输出的方式。 有两种方法可以解决这个问题。您可以按照目前的方式执行此操作。当你读取时,你需要发送一个字节缓冲区:

char buf[25]; while (1) { int n_read=read(fd, buf, sizeof buf); int key = 0; // TODO: parse the integer out of buf with strtol or whatever printf("%d\n",key); fflush(stdout); if(key==1) { printf("in loop\n"); } }

那么另一种方法是直接发送 int 的字节,例如:

int key = 1; for (int i = 0; i < sizeof key; ++i) { usart_putchar(key[i]); }

然后,您需要在客户端解压这些字节。直接将它们读入整数可能会起作用,但前提是它们的大小相同,而我很确定它们
不是

。我建议在

两侧使用
int
类型,例如
int16_t
int32_t,以便您知道将到达多少字节。

© www.soinside.com 2019 - 2024. All rights reserved.