Je suis confronté à un problème très étrange, que je n'ai pas pu résoudre. Je veux lire (juste lire) les données collectées et envoyées par un micro-contrôleur via USB comme port série (FTDI) sur Mac Os X en utilisant C++. La taille d'une séquence de données complète est toujours exactement de 10 octets. Cependant, j'utilisais le code suivant pour lire les données:Problème de lecture du port série C++: ioctl (FIONREAD) définit-il une valeur incorrecte?
Bibliothèques importées:
#include <iostream>
#include <fstream>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/ioctl.h>
code:
void init(){
serial = open(port.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK); // 0_RDONLY ?
struct termios options;
//set opt to 115200-8n1
cfsetspeed(&options, B115200);
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
tcsetattr(serial, TCSANOW, &options);
if (serial < 0){
//Error
}else{
//run loop
}
}
void serial_loop(){
long bytes_read;
int bytes_available;
unsigned char msg[10];
while(1){
do{
usleep(1000);
ioctl(serial, FIONREAD, &bytes_available);
}while(bytes_available < 10); //wait for the sequence to complete
bytes_read = read(serial, msg, 10);
//do some parsing here
}
}
Ce code a travaillé il y a quelques jours, mais maintenant il est plus. Les données atteignent parfaitement l'ordinateur en fonction de la commande Terminal -> screen. J'ai vérifié le port-nom de fichier qui est toujours correct et le port est également ouvert avec succès. J'ai limité mon problème à la commande ioctl FIONREAD qui n'écrit pas le bon numéro dans le fichier bytes_available-var (plus). Ça a marché, et je crois que je n'ai rien changé dans le code.
Voyez-vous des problèmes qui pourraient causer ce problème? Y a-t-il des passages dangereux dans mon code? Merci pour votre aide, je suis vraiment coincé ici ...
EDIT: Grâce aux commentaires, j'ai pu le faire fonctionner à nouveau. Voici le code actuel:
int serial;
void init(){
serial = open(port.c_str(), O_RDWR | O_NOCTTY); //removed 0_NONBLOCK
struct termios options;
//set opt to 115200-8n1
cfsetspeed(&options, B115200);
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); //Non-canonical
options.c_cc[VMIN] = 1; //block read until at least 1 byte was recieved
options.c_lflag = 0;
tcsetattr(serial, TCSANOW, &options);
if (serial < 0){
//Error
}else{
//run loop
}
}
void serial_loop(){
int datalength = 10;
long bytes_read = 0;
int bytes_in_msg = 0;
unsigned char buf[datalength];
unsigned char msg[datalength];
do{
bytes_read = read(serial, buf, datalength-bytes_in_msg);
usleep(1000);
if (bytes_read>0){
memcpy(&msg[bytes_in_msg], &buf, bytes_read);
}
bytes_in_msg += bytes_read;
}while(bytes_in_msg < datalength);
//do some parsing here
}
}
Cela fonctionne, mais y a-t-il quelque chose qui pourrait poser problème?
Nous vous remercions de votre soutien!
Il semble que vous ayez un problème de mise à la terre dans votre appareil. Essayez de le vérifier – vadikrobot
Non, le périphérique fonctionne toujours, et si j'utilise la commande d'écran (commandline) ou CoolTerm je peux lire les données sans erreurs. Est-il possible de réinitialiser tous les paramètres du port? – archimedes
* "Ce code a fonctionné il y a quelques jours mais maintenant il ne l'est plus." * - Cela indique généralement une initialisation incorrecte ou incomplète. Votre initialisation termios ne configure que le débit et la taille des caractères, et tout le reste est laissé au hasard. Voir [Réglage correct des modes de terminal] (http://www.chemie.fu-berlin.de/chemnet/use/info/libc/libc_12.html # SEC237) et [Guide de programmation série pour les systèmes d'exploitation POSIX] (http://www.cmrr.umn.edu/~strupp/serial.html) – sawdust