【问题标题】:to transmit and receive floating point using serial communication c++使用串行通信 C++ 发送和接收浮点数
【发布时间】:2019-12-10 00:53:52
【问题描述】:

使用 WiringPi 库在 Raspberrypi 上进行串行通信 函数 serialPutchar(int fd, unsigned char c) 和 serialGetchar (int fd) 可以很好地发送和接收整数值 但不显示浮点数

发送方

int main ()
{
int fd ;
int count ;
float val;

if ((fd = serialOpen ("/dev/ttyAMA0", 9600)) < 0)
{
fprintf (stderr, "Unable to open serial device: %s\n", strerror 
(errno)) ;
return 1 ;
}

if (wiringPiSetup () == -1)
{
fprintf (stdout, "Unable to start wiringPi: %s\n", strerror 
(errno)) ;
return 1 ;
}
for (count = 0 ; count < 256 ; ){
val=4.1;
fflush (stdout) ;
serialPutchar(fd,val);
++count ;
delay (500) ;
}
printf ("\n");
return 0;}

接收端

 int main ()
 {
 int fd ;

 if ((fd = serialOpen ("/dev/ttyUSB0", 9600)) < 0)
 {
fprintf (stderr, "Unable to open serial device: %s\n", strerror 
(errno)) ;
return 1 ;
}
if (wiringPiSetup () == -1)
{
fprintf (stdout, "Unable to start wiringPi: %s\n", strerror 
(errno)) ;
return 1 ;
}
while(true)

{

  printf ("%f", serialGetchar (fd)) ;
  fflush (stdout) ;
  printf ("\n") ;
}

return 0 ;
}

我预计输出为 4.100000,但实际输出为 0.000000

任何发送和接收浮点数的帮助将不胜感激 提前致谢

【问题讨论】:

  • 如果您想要 C++ 中的解决方案,请不要添加 C 标签。 C 和 C++ 是两种非常不同的语言,具有不同的规则、语义和结构。话虽如此,您显示的代码可能是纯 C,代码中没有任何内容需要 C++ 编译器。
  • 如果你只打印一个字符,我更喜欢putchar('\n')而不是printf("\n");结果是一样的,放前者效率更高。
  • 为什么一个字符会是4.1??
  • 您需要在发送端将浮点数转换为字节数组,然后发送,然后在接收端执行相反的过程。
  • 如果将浮点数分配给无符号字符,你认为它会发生什么?那么serialGetchar的返回类型是什么?很确定它是unsigned char。使用%f 格式说明符进行打印会调用未定义的行为。所以任何事情都可能发生......你需要先加倍(不是float)! (只是为了避开UB,传输还是不行……)

标签: c++ c raspberry-pi3 serial-communication wiringpi


【解决方案1】:

您需要做的是将浮点数分解为字节,然后一一发送/接收它们。 注意:以下代码假定发送方和接收方使用相同的字节序系统。

//Sender
float f = 4.1;
int i = 0;
for (; i < sizeof(float); ++i)
    serialPutchar(fd, ((char*)& f)[i]);


// receiver
float f;
int i = 0;
for (; i < sizeof(float); ++i)
    ((char*)& f)[i]) = serialGetchar(fd);

【讨论】:

  • 除了大小,两端也必须使用相同的二进制表示。很可能两者都使用 IEEE754,但这在任何地方都没有强制要求。
  • 请注意,一般整数的字节序不必匹配float 的字节序。然而,如果发送方/接收方是匹配的系统,则字节序和 FP 格式可以忽略不计。
【解决方案2】:

float 需要以多个字节的形式发送数据,而不仅仅是一次调用 serialPutchar() 只发送 1 个。

当通过串行通道接收多个字节时,很容易丢弃一个字节或让接收器在中途开始。我建议以某种方式对数据进行框架化处理。

示例:作为带有标记的文本发送

// Sender
char buf[30];
snprintf(buf, sizeof buf, "<%a>", some_float);
serialPutString(fd, buf);

// Receive
while (serialGerChar(fd) != '<') {
  ;
}
char buf[30*2];
for (i=0; i<sizeof buf - 1; i++) {
  buf[i] = serialGetChar(fd);
  if (buf[i] == '>') {
    break;
  }
}
buf[i] = '\0';
f = strtod(buf, &endptr);
// additional checks possible here.

健壮的代码不假设传入的数据格式正确,并检查各种问题,如不完整、过多、非数字文本。

【讨论】:

  • 使用 %a 的一个口香糖点。序列化浮点数的最佳简单方法。
猜你喜欢
  • 1970-01-01
  • 2015-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-22
  • 2017-08-20
  • 2011-06-04
  • 2023-01-27
相关资源
最近更新 更多