Tôi đang cố gắng để gửi/nhận dữ liệu qua cổng USB bằng FTDI, vì vậy tôi cần xử lý giao tiếp nối tiếp bằng C/C++. Tôi đang làm việc trên Linux (Ubuntu).Đọc thêm/viết số
Về cơ bản, tôi được kết nối với thiết bị đang nghe lệnh đến. Tôi cần gửi các lệnh đó và đọc phản hồi của thiết bị. Cả hai lệnh và phản hồi là ký tự ASCII.
Mọi thứ hoạt động tốt bằng GtkTerm nhưng khi tôi chuyển sang lập trình C, tôi gặp sự cố.
Dưới đây là mã của tôi:
#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);
gì xảy ra là read()
trả về 0 (không byte đọc ở tất cả) hoặc chặn cho đến khi thời gian chờ (VTIME
). Tôi giả định điều này xảy ra bởi vì write()
không gửi bất cứ điều gì. Trong trường hợp đó, thiết bị sẽ không nhận được lệnh và tôi không thể nhận phản hồi. Trong thực tế, tắt thiết bị trong khi chương trình của tôi bị chặn khi đọc thực sự được thu hút trong việc nhận phản hồi (thiết bị sẽ gửi thứ gì đó trong khi tắt).
Lạ một điều là rằng việc thêm này
cout << "I've written: " << n_written << "bytes" << endl;
ngay sau khi write()
cuộc gọi, tôi nhận được:
I've written 6 bytes
đó là chính xác những gì tôi mong đợi. Chỉ chương trình của tôi không hoạt động như mong muốn, như thiết bị của tôi không thể nhận được những gì tôi thực sự đang viết trên cổng.
Tôi đã thử những thứ và giải pháp khác nhau, cũng liên quan đến kiểu dữ liệu (tôi đã thử sử dụng std :: string, chẳng hạn như cmd = "INIT \r"
hoặc const char
) nhưng không có gì thực sự hiệu quả.
Ai đó có thể cho tôi biết tôi đang ở đâu sai?
Cảm ơn bạn trước.
EDIT: Trước đó phiên bản của mã này sử dụng
unsigned char cmd[] = "INIT \n"
và cũng cmd[] = "INIT \r\n"
. Tôi đã thay đổi nó vì lệnh sintax cho thiết bị của tôi được báo cáo là
<command><SPACE><CR>
.
Tôi cũng đã cố gắng tránh cờ O_NONBLOCK
để đọc, nhưng sau đó tôi chỉ chặn cho đến mãi mãi. Tôi đã thử sử dụng select()
nhưng không có gì xảy ra. Chỉ cần cho một thử, tôi đã tạo ra một vòng lặp chờ đợi cho đến khi dữ liệu có sẵn, nhưng mã của tôi không bao giờ thoát khỏi vòng lặp. Btw, chờ đợi hoặc usleep()
là điều tôi cần tránh. Báo cáo một trong những chỉ là một đoạn trích của mã của tôi. Mã hoàn chỉnh cần làm việc trong môi trường thời gian thực (cụ thể là OROCOS) vì vậy tôi không thực sự muốn chức năng giống như giấc ngủ.
Dòng của bạn 'response.append (&buf);' không biên dịch cho tôi. Không có 'while (buf! = '\ R' && n> 0);'. Là những lỗi chính tả hay tôi thiếu một cái gì đó? – josaphatv
Mã bạn gợi ý cho việc gửi 'int n_written = write (USB, cmd, sizeof (cmd) -1)' không thực sự làm việc cho các bộ đệm lớn. Trong trường hợp đó, bạn cần một vòng lặp giống như bạn đã trình bày ở trên, nhưng với 'n_written = write (USB, cmd + spot, command_length - spot) 'Ngoài ra bạn phải sử dụng độ dài để chấm dứt vòng lặp, thay vì kiểm tra từng ký tự riêng lẻ – Fritz
' cfmakeraw() 'đã thiết lập một loạt các thuộc tính. không cần những dòng này: 'tty.c_cflag & = ~ CSIZE; tty.c_cflag | = CS8; tty.c_cflag & = ~ PARENB;' – rumpel