【问题标题】:Binary data from a serial port in linux using c使用c从Linux中的串行端口获取二进制数据
【发布时间】:2012-09-10 20:53:54
【问题描述】:

我正在使用 Linux 从 Phidg​​et sbc 上的串行端口读取二进制数据,以从 PC 上运行的应用程序获取命令。我在 VB 中编写了一个测试程序,将数据读入字节数组并将其转换为十进制以使用它,但无法弄清楚如何在 c 中执行此操作。我在互联网上所做的研究无法得出任何结论。

从 PC 发送的命令是 0x0F。

为了检查我是否获得了正确的数据,我读取了数据并将其发回。这是我回来的。返回的数据添加了一个回车符。

十六进制显示 0F00 0000 0D

‘\’显示\0F\00\00\00\r

正常显示只是显示一个奇怪的字符。

这告诉我有数据可以使用,但无法提取值 0F 或 15。

如何转换传入的数据以使用它?

我尝试使用 strtol 转换接收到的数据,但它返回 0。我还尝试将端口设置为 raw,但没有任何区别。

unsigned char buffer1[1];
int ReadPort1()
{
int result;

result = read(file1, &buffer1,1);

if(result > 0)
{
    WritePort1(buffer1);
    sprintf(tempstr, "Port1 data %s %d", buffer1, result);
    DisplayText(2,tempstr);
}
return result;
}

端口打开/设置

void OpenPort1()
{
//file1 = open("/dev/ttyUSB1", O_RDWR | O_NOCTTY | O_NONBLOCK);
     file1 = open("/dev/ttyUSB1", O_RDWR | O_NOCTTY | O_NODELAY);

if(file1 < 0)
    printf("Error opening serial port1.\n");
else
{
    SetPort(file1, 115200, 8, 1, 0, 1);
    port1open = 1;
}
}


void SetPort(int fd, int Baud_Rate, int Data_Bits, int Stop_Bits, int Parity, int raw)
{
    long BAUD;                      // derived baud rate from command line
    long DATABITS;
    long STOPBITS;
    long PARITYON;
    long PARITY;

struct termios newtio;

  switch (Baud_Rate)
  {
    case 115200:
        BAUD = B115200;
        break;
     case 38400:
        BAUD = B38400;
        break;
     case 19200:
        BAUD  = B19200;
        break;
     case 9600:
        BAUD  = B9600;
        break;
  }  //end of switch baud_rate
  switch (Data_Bits)
  {
     case 8:
     default:
        DATABITS = CS8;
        break;
     case 7:
        DATABITS = CS7;
        break;
     case 6:
        DATABITS = CS6;
        break;
     case 5:
        DATABITS = CS5;
        break;
  }  //end of switch data_bits
  switch (Stop_Bits)
  {
     case 1:
     default:
        STOPBITS = 0;
        break;
     case 2:
        STOPBITS = CSTOPB;
        break;
  }  //end of switch stop bits
  switch (Parity)
  {
     case 0:
     default:                       //none
        PARITYON = 0;
        PARITY = 0;
        break;
     case 1:                        //odd
        PARITYON = PARENB;
        PARITY = PARODD;
        break;
     case 2:                        //even
        PARITYON = PARENB;
        PARITY = 0;
        break;
  }  //end of switch parity

  newtio.c_cflag = BAUD | DATABITS | STOPBITS | PARITYON | PARITY | CLOCAL | CREAD;   
  newtio.c_iflag = IGNPAR;

  if(raw == 1)
  {
        newtio.c_oflag &= ~OPOST;
        newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); 
  }
  else
  {
        newtio.c_lflag = 0;       //ICANON;
        newtio.c_oflag = 0;
  }

  newtio.c_cc[VMIN]=1;
  newtio.c_cc[VTIME]=0;
  tcflush(fd, TCIFLUSH);
  tcsetattr(fd,TCSANOW,&newtio);
}

【问题讨论】:

  • 不是read(file1, buffer1, sizeof(buffer1))吗?
  • 我得到与 read(file1, buffer1, sizeof(buffer1)) 相同的结果
  • 不要使用%s来显示字符。 %s 用于显示以零结尾的字符数组(字符串)。要将您 read() 的一个字符显示为 buffer1[0],请使用 count0 建议的 %x。
  • 如果在 printf 上指定字符串长度,则可以输出为 %s。例如。 printf("%.8s", buffer1);
  • 我遇到了类似的问题,但就我而言,当我尝试读取 0x0D 时,读取函数正在回复 0x0A...所以,谢谢!

标签: c linux binary


【解决方案1】:

您是否正在寻找数据的十六进制表示?

  sprintf(tempstr, "Port1 data %s %x", buffer1, buffer1[0]);

【讨论】:

  • 以十六进制打印缓冲区的地址,而不是内容。
  • buffer1 的内容解释为以零结尾的字符串(通过使用%s)仍然很危险,因为不能保证它是这样的字符串。因此,如果sprintf() 没有找到0,它可能会去读取不允许的内存地址并最终导致分段违规(更不用说崩溃)。
  • 这个答案的重点是十六进制表示,无需临床剖析每一个小错误。
  • 你的权利,绝对的。这就是为什么更难理解您为什么建议使用%s(明确设计用于以零结尾的字符串)来显示数据的原因。
  • sprintf(tempstr, "Port1 data %x", buffer1[0]);工作。谢谢
猜你喜欢
  • 2011-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-30
  • 1970-01-01
  • 2013-04-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多