FTDI kullanarak bir USB Portu üzerinden veri gönderiyorum/almak için veriyorum, bu yüzden C/C++ kullanarak seri iletişimi kullanmam gerekiyor. Linux (Ubuntu) üzerinde çalışıyorum. Temel olarak, gelen komutları dinleyen bir aygıta bağlandım. Bu komutları göndermem ve cihazın cevabını okumam gerek. Her iki komut ve yanıt ASCII karakterleri'dur.Linux C Seri Port Okuma/Yazma
GtkTerm kullanarak her şey iyi çalışıyor, ancak C programlamaya geçtiğimde sorunla karşılaşıyorum. Zaman aşımı (VTIME
) kadar
#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);
ne olur read()
döner 0 (byte hiç okuma) olmasıdır veya blok:
İşte benim kod. Bunun olduğunu varsayıyorum, çünkü write()
hiçbir şey göndermiyor. Bu durumda, cihaz komut almazdı ve yanıt alamıyorum. Aslında, programımı bloke ederken cihazımı kapatırken aslında yanıt almayı başardı (cihaz kapanırken bir şey gönderir).
Garip bir şey olduğunu bu
cout << "I've written: " << n_written << "bytes" << endl;
sağ write()
çağrısından sonra, Aldığım ekleyerek:
I've written 6 bytes
. Sadece benim programım gerektiği gibi çalışmıyor, gibi cihazım aslında portta yazdığım şeyi alamıyor.
Veri türleri ile ilgili farklı şeyler ve çözüm denedim (örneğin, cmd = "INIT \r"
veya const char
gibi std :: string'i kullanarak denedim) ama gerçekten işe yaramadı.
Birisi bana nerede yanlış olduğumu söyleyebilir mi?
Önceden teşekkür ederiz.
DÜZENLEME: Bu kodun Önceden sürüm
unsigned char cmd[] = "INIT \n"
ve ayrıca cmd[] = "INIT \r\n"
<command><SPACE><CR>
olarak bildirildiği için değiştirdim.
Ayrıca okumada O_NONBLOCK
bayrağından kaçınmayı denedim, ancak daha sonra sadece sonsuza dek bloke ediyorum. select()
kullanmayı denedim ama hiçbir şey olmuyor. Sadece bir deneme için, veriler uygun olana kadar bir bekleme döngüsü oluşturdum, fakat kodum asla döngüden çıkmıyor. Btw, beklemek veya usleep()
kaçınmak gereken bir şey. Bildirilen bir tanesi sadece kodumun bir alıntıdır. Tam kodun, gerçek zamanlı bir ortamda çalışmak üzere (özellikle OROCOS) çalışması gerekiyor, bu yüzden gerçekten uyku benzeri bir işlev istemiyorum.
Sizin satırınız response.append (&buf); 'benim için derleme yapmıyor. Ne yapmıyorsa (buf! = '\ R' && n> 0);' Bu yazım hataları mı yoksa bir şey mi eksik? – josaphatv
int n_written = write (USB, cmd, sizeof (cmd) -1) 'i gerçekten önermek için büyük önbellekler için işe yaramaz. Bu durumda, yukarıda gördüğünüz gibi bir döngüye ihtiyacınız olacaktır, ancak n_written ile = Yazma (USB, cmd + nokta, command_length - spot) Ayrıca, her karakteri ayrı ayrı kontrol etmek yerine, döngüyü sonlandırmak için uzunluğu kullanmanız gerekir: – Fritz
'cfmakeraw()' zaten bir grup özniteliği ayarlar. şu satırlara gerek yoktur: , tty.c_cflag & = ~ CSIZE; tty.c_cflag | = CS8; tty.c_cflag & = ~ PARENB; – rumpel