在Linux上用C读写串口

我正在尝试 ,因此我需要使用C / C ++处理串行通信。我正在使用

(Ubuntu)。

基本上,我已连接到正在侦听传入命令的设备。我需要发送这些命令并阅读设备的响应。命令和响应都是 。

使用GtkTerm一切正常,但是,当我切换到C编程时,遇到了问题。

这是我的代码:

#include <stdio.h>      // standard input / output functions

#include <stdlib.h>

#include <string.h> // string function definitions

#include <unistd.h> // UNIX standard function definitions

#include <fcntl.h> // File control definitions

#include <errno.h> // Error number definitions

#include <termios.h> // POSIX terminal control definitions

/* Open File Descriptor */

int USB = open( "/dev/ttyUSB0", O_RDWR| O_NONBLOCK | O_NDELAY );

/* Error Handling */

if ( USB < 0 )

{

cout << "Error " << errno << " opening " << "/dev/ttyUSB0" << ": " << strerror (errno) << endl;

}

/* *** Configure Port *** */

struct termios tty;

memset (&tty, 0, sizeof tty);

/* Error Handling */

if ( tcgetattr ( USB, &tty ) != 0 )

{

cout << "Error " << errno << " from tcgetattr: " << strerror(errno) << endl;

}

/* Set Baud Rate */

cfsetospeed (&tty, B9600);

cfsetispeed (&tty, B9600);

/* Setting other Port Stuff */

tty.c_cflag &= ~PARENB; // Make 8n1

tty.c_cflag &= ~CSTOPB;

tty.c_cflag &= ~CSIZE;

tty.c_cflag |= CS8;

tty.c_cflag &= ~CRTSCTS; // no flow control

tty.c_lflag = 0; // no signaling chars, no echo, no canonical processing

tty.c_oflag = 0; // no remapping, no delays

tty.c_cc[VMIN] = 0; // read doesn't block

tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout

tty.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines

tty.c_iflag &= ~(IXON | IXOFF | IXANY);// turn off s/w flow ctrl

tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make raw

tty.c_oflag &= ~OPOST; // make raw

/* Flush Port, then applies attributes */

tcflush( USB, TCIFLUSH );

if ( tcsetattr ( USB, TCSANOW, &tty ) != 0)

{

cout << "Error " << errno << " from tcsetattr" << endl;

}

/* *** WRITE *** */

unsigned char cmd[] = {'I', 'N', 'I', 'T', ' ', '\r', '\0'};

int n_written = write( USB, cmd, sizeof(cmd) -1 );

/* Allocate memory for read buffer */

char buf [256];

memset (&buf, '\0', sizeof buf);

/* *** READ *** */

int n = read( USB, &buf , sizeof buf );

/* Error Handling */

if (n < 0)

{

cout << "Error reading: " << strerror(errno) << endl;

}

/* Print what I read... */

cout << "Read: " << buf << endl;

close(USB);

发生的结果是read()返回0(根本不读取任何字节)或阻塞直到超时(VTIME)。我假设发生这种情况是因为write()没有发送任何东西。在这种情况下,设备将不会接收命令,并且我将无法接收响应。实际上,在我的程序被阻止读取时关闭设备实际上成功地获得了响应(设备在关闭时发送了一些信息)。

奇怪的是,添加这个

cout << "I've written: " << n_written << "bytes" << endl;

write()致电后,我收到:

I've written 6 bytes

这正是我所期望的。只有我的程序无法正常工作,就像 在端口上 内容一样。

我已经尝试了不同的方法和解决方案,还涉及了数据类型(我尝试使用std :: string,例如cmd = "INIT \r"or const

char),但是没有任何实际效果。

有人可以告诉我我错了吗?

先感谢您。

以前使用此代码的版本

unsigned char cmd[] = "INIT \n"

还有cmd[] = "INIT \r\n"。我更改了它,因为我的设备的命令sintax报告为

<command><SPACE><CR>

我也尝试过避免O_NONBLOCK读取时出现标志,但是后来我一直阻塞直到永远。我尝试使用,select()但是什么也没有发生。只是尝试一下,我创建了一个等待循环,直到数据可用为止,但是我的代码从未退出循环。顺便说一句,等待还是usleep()我需要避免的事情。报告的只是我的代码的一部分。

(特别是OROCOS)中工作,所以我真的不想要类似睡眠的功能。

回答:

我已经解决了我的问题,所以我在这里发布了正确的代码,以防有人需要类似的东西。

int USB = open( "/dev/ttyUSB0", O_RDWR| O_NOCTTY );

struct termios tty;

struct termios tty_old;

memset (&tty, 0, sizeof tty);

/* Error Handling */

if ( tcgetattr ( USB, &tty ) != 0 ) {

std::cout << "Error " << errno << " from tcgetattr: " << strerror(errno) << std::endl;

}

/* Save old tty parameters */

tty_old = tty;

/* Set Baud Rate */

cfsetospeed (&tty, (speed_t)B9600);

cfsetispeed (&tty, (speed_t)B9600);

/* Setting other Port Stuff */

tty.c_cflag &= ~PARENB; // Make 8n1

tty.c_cflag &= ~CSTOPB;

tty.c_cflag &= ~CSIZE;

tty.c_cflag |= CS8;

tty.c_cflag &= ~CRTSCTS; // no flow control

tty.c_cc[VMIN] = 1; // read doesn't block

tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout

tty.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines

/* Make raw */

cfmakeraw(&tty);

/* Flush Port, then applies attributes */

tcflush( USB, TCIFLUSH );

if ( tcsetattr ( USB, TCSANOW, &tty ) != 0) {

std::cout << "Error " << errno << " from tcsetattr" << std::endl;

}

unsigned char cmd[] = "INIT \r";

int n_written = 0,

spot = 0;

do {

n_written = write( USB, &cmd[spot], 1 );

spot += n_written;

} while (cmd[spot-1] != '\r' && n_written > 0);

绝对没有必要每个字节写一个字节,也可以正常int n_written = write( USB, cmd, sizeof(cmd) -1)工作。

最后, :

int n = 0,

spot = 0;

char buf = '\0';

/* Whole response*/

char response[1024];

memset(response, '\0', sizeof response);

do {

n = read( USB, &buf, 1 );

sprintf( &response[spot], "%c", buf );

spot += n;

} while( buf != '\r' && n > 0);

if (n < 0) {

std::cout << "Error reading: " << strerror(errno) << std::endl;

}

else if (n == 0) {

std::cout << "Read nothing!" << std::endl;

}

else {

std::cout << "Response: " << response << std::endl;

}

这个为我工作。谢谢你们!

以上是 在Linux上用C读写串口 的全部内容, 来源链接: utcz.com/qa/435497.html

回到顶部