我的 linux C 程序无法通过 USB 串口从 Arduino 接收数据
my linux C program cannot receive data from Arduino through USB Serial
我的 Linux C 应用程序无法从 Arduino 接收字节
大家好,我打算使用 Arduino Mega 2560 作为 AT89S52(8051 微处理器家族)的编程器。 Arduino开发板通过USB串口线连接PC。
起初我需要在我的 Ubuntu 中编写一个程序来与 Arduino 板进行通信。我的程序可以正确打开连接并向 Arduino 写入字节(我通过转动 led on/off 进行测试),但问题是 Linux 程序无法从 Arduino 接收数据。
我已经搜索了很多教程和论坛,但仍然无法解决问题,所以我post在这里提问,希望有人能帮助我。
下面是我用来打开与设备连接的函数
AT89S_EID usbserial_open ( char* dev_name,
UsbSerialDevice* dev_ptr,
int baudrate,
int config ) {
speed_t io_baudrate = B9600;
if (dev_name == NULL || dev_ptr == NULL)
{
return AT89S_EID_ARG_NULL;
}
if (baudrate != US_BAUDRATE_9600
&& baudrate != US_BAUDRATE_19200
&& baudrate != US_BAUDRATE_115200)
{
return AT89S_EID_SERIAL_BAUDRATE_INVALID;
}
if (config != US_CONFIG_8N1
&& config != US_CONFIG_7E1
&& config != US_CONFIG_7O1)
{
return AT89S_EID_SERIAL_CONFIG_INVALID;
}
// store device name
strcpy(dev_ptr->name, dev_name);
// open device
dev_ptr->fd = open (dev_ptr->name,
O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
if (dev_ptr->fd < 0)
{
return AT89S_EID_SERIAL_OPEN;
}
// get current termios settings
if (tcgetattr(dev_ptr->fd, &dev_ptr->tios) < 0)
{
return AT89S_EID_SERIAL_GET_ATTR;
}
// set input/output baudrdate
if (baudrate == US_BAUDRATE_9600)
io_baudrate = B9600;
else if (baudrate == US_BAUDRATE_19200)
io_baudrate = B19200;
else if (baudrate == US_BAUDRATE_115200)
io_baudrate = B115200;
if (cfsetispeed(&dev_ptr->tios, io_baudrate) != 0
|| cfsetospeed(&dev_ptr->tios, io_baudrate) != 0)
{
return AT89S_EID_SERIAL_SET_IOSPEED;
}
// enable receiver, ignore status line
dev_ptr->tios.c_cflag |= (CREAD | CLOCAL);
// set config
if (config == US_CONFIG_8N1)
{
dev_ptr->tios.c_cflag &= ~PARENB;
dev_ptr->tios.c_cflag &= ~CSTOPB;
dev_ptr->tios.c_cflag &= ~CSIZE;
dev_ptr->tios.c_cflag |= CS8;
}
else if (config == US_CONFIG_7E1)
{
dev_ptr->tios.c_cflag |= PARENB;
dev_ptr->tios.c_cflag &= ~PARODD;
dev_ptr->tios.c_cflag &= ~CSTOPB;
dev_ptr->tios.c_cflag &= ~CSIZE;
dev_ptr->tios.c_cflag |= CS7;
}
else if (config == US_CONFIG_7O1)
{
dev_ptr->tios.c_cflag |= PARENB;
dev_ptr->tios.c_cflag |= PARODD;
dev_ptr->tios.c_cflag &= ~CSTOPB;
dev_ptr->tios.c_cflag &= ~CSIZE;
dev_ptr->tios.c_cflag |= CS7;
}
// no HW flow control
dev_ptr->tios.c_cflag &= ~CRTSCTS;
// no input processing (raw input)
dev_ptr->tios.c_iflag &= ~(IXON | IXOFF | IXANY);
// other input settings
dev_ptr->tios.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG);
// no output processing (raw output)
dev_ptr->tios.c_oflag &= ~OPOST;
// control character settings
dev_ptr->tios.c_cc[VMIN] = 1; // wait for 1 minimum chacacter received
dev_ptr->tios.c_cc[VTIME] = 0; // no timeout when waiting for charater
// commit new settings
if (tcsetattr(dev_ptr->fd, TCSANOW, &dev_ptr->tios) < 0)
{
return AT89S_EID_SERIAL_SET_ATTR;
}
// wait for device reset & sync up
usleep(1500 * 1000);
return AT89S_EID_OK;
} /* usbserial_open */
这是接收函数:
AT89S_EID usbserial_recv ( UsbSerialDevice* dev_ptr,
unsigned char* data_ptr,
int data_len ) {
int read_byte = 0;
char b[1];
if (dev_ptr == NULL
|| data_ptr == NULL)
{
return AT89S_EID_ARG_NULL;
}
// block reading
fcntl(dev_ptr->fd, F_SETFL, 0);
// start receiving data
while (read_byte < data_len)
{
if (read(dev_ptr->fd, b, 1) > 0)
{
data_ptr[read_byte++] = *b;
}
else
{
if (errno == EAGAIN)
continue;
else if (errno == ETIMEDOUT)
break;
else
return AT89S_EID_SERIAL_RECV;
}
}
return AT89S_EID_OK;
} /* usbserial_recv */
很抱歉post输入了一个长代码:)
我已经搜索了很多教程和论坛,但仍然无法解决问题。我相信 Arduino 代码工作正常,因为我使用了一些其他工具来测试它(例如:minicom)
我解决了我的问题。只需在打开与设备的连接时添加刷新功能,一切都可以正常工作。
tcflush(fd, TCIOFLUSH);
我的 Linux C 应用程序无法从 Arduino 接收字节
大家好,我打算使用 Arduino Mega 2560 作为 AT89S52(8051 微处理器家族)的编程器。 Arduino开发板通过USB串口线连接PC。
起初我需要在我的 Ubuntu 中编写一个程序来与 Arduino 板进行通信。我的程序可以正确打开连接并向 Arduino 写入字节(我通过转动 led on/off 进行测试),但问题是 Linux 程序无法从 Arduino 接收数据。 我已经搜索了很多教程和论坛,但仍然无法解决问题,所以我post在这里提问,希望有人能帮助我。
下面是我用来打开与设备连接的函数
AT89S_EID usbserial_open ( char* dev_name, UsbSerialDevice* dev_ptr, int baudrate, int config ) { speed_t io_baudrate = B9600; if (dev_name == NULL || dev_ptr == NULL) { return AT89S_EID_ARG_NULL; } if (baudrate != US_BAUDRATE_9600 && baudrate != US_BAUDRATE_19200 && baudrate != US_BAUDRATE_115200) { return AT89S_EID_SERIAL_BAUDRATE_INVALID; } if (config != US_CONFIG_8N1 && config != US_CONFIG_7E1 && config != US_CONFIG_7O1) { return AT89S_EID_SERIAL_CONFIG_INVALID; } // store device name strcpy(dev_ptr->name, dev_name); // open device dev_ptr->fd = open (dev_ptr->name, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK); if (dev_ptr->fd < 0) { return AT89S_EID_SERIAL_OPEN; } // get current termios settings if (tcgetattr(dev_ptr->fd, &dev_ptr->tios) < 0) { return AT89S_EID_SERIAL_GET_ATTR; } // set input/output baudrdate if (baudrate == US_BAUDRATE_9600) io_baudrate = B9600; else if (baudrate == US_BAUDRATE_19200) io_baudrate = B19200; else if (baudrate == US_BAUDRATE_115200) io_baudrate = B115200; if (cfsetispeed(&dev_ptr->tios, io_baudrate) != 0 || cfsetospeed(&dev_ptr->tios, io_baudrate) != 0) { return AT89S_EID_SERIAL_SET_IOSPEED; } // enable receiver, ignore status line dev_ptr->tios.c_cflag |= (CREAD | CLOCAL); // set config if (config == US_CONFIG_8N1) { dev_ptr->tios.c_cflag &= ~PARENB; dev_ptr->tios.c_cflag &= ~CSTOPB; dev_ptr->tios.c_cflag &= ~CSIZE; dev_ptr->tios.c_cflag |= CS8; } else if (config == US_CONFIG_7E1) { dev_ptr->tios.c_cflag |= PARENB; dev_ptr->tios.c_cflag &= ~PARODD; dev_ptr->tios.c_cflag &= ~CSTOPB; dev_ptr->tios.c_cflag &= ~CSIZE; dev_ptr->tios.c_cflag |= CS7; } else if (config == US_CONFIG_7O1) { dev_ptr->tios.c_cflag |= PARENB; dev_ptr->tios.c_cflag |= PARODD; dev_ptr->tios.c_cflag &= ~CSTOPB; dev_ptr->tios.c_cflag &= ~CSIZE; dev_ptr->tios.c_cflag |= CS7; } // no HW flow control dev_ptr->tios.c_cflag &= ~CRTSCTS; // no input processing (raw input) dev_ptr->tios.c_iflag &= ~(IXON | IXOFF | IXANY); // other input settings dev_ptr->tios.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG); // no output processing (raw output) dev_ptr->tios.c_oflag &= ~OPOST; // control character settings dev_ptr->tios.c_cc[VMIN] = 1; // wait for 1 minimum chacacter received dev_ptr->tios.c_cc[VTIME] = 0; // no timeout when waiting for charater // commit new settings if (tcsetattr(dev_ptr->fd, TCSANOW, &dev_ptr->tios) < 0) { return AT89S_EID_SERIAL_SET_ATTR; } // wait for device reset & sync up usleep(1500 * 1000); return AT89S_EID_OK; } /* usbserial_open */
这是接收函数:
AT89S_EID usbserial_recv ( UsbSerialDevice* dev_ptr, unsigned char* data_ptr, int data_len ) { int read_byte = 0; char b[1]; if (dev_ptr == NULL || data_ptr == NULL) { return AT89S_EID_ARG_NULL; } // block reading fcntl(dev_ptr->fd, F_SETFL, 0); // start receiving data while (read_byte < data_len) { if (read(dev_ptr->fd, b, 1) > 0) { data_ptr[read_byte++] = *b; } else { if (errno == EAGAIN) continue; else if (errno == ETIMEDOUT) break; else return AT89S_EID_SERIAL_RECV; } } return AT89S_EID_OK; } /* usbserial_recv */
很抱歉post输入了一个长代码:)
我已经搜索了很多教程和论坛,但仍然无法解决问题。我相信 Arduino 代码工作正常,因为我使用了一些其他工具来测试它(例如:minicom)
我解决了我的问题。只需在打开与设备的连接时添加刷新功能,一切都可以正常工作。
tcflush(fd, TCIOFLUSH);