[LINUX] Probléme de récup de donnée sur ttyS

anbakkali Messages postés 4 Statut Membre -  
anbakkali Messages postés 4 Statut Membre -
Bonjour,
Bonjour,
j'ai un gros problème que je n'arrive tjrs pas à résoudre !
Je dois récupérer des données provenant d'un montage électronique sur une carte équipée d'un noyau LINUX (FOX Board).

Donc pour ce faire j'ai un code en C que j'exécute sur la carte et qui permet d'ouvrir une connexion série (virtuelle) à travers une connexion Bluetooth (rfcomm0) pour envoyer les donnée de mon montage à la carte FOX Board.

Ce code en effet marche très bien, mes données arrivent, mais seulement, elles n'arrivent pas comme il faut:
j'envoie des trames de 19 bytes dans un certain ordre bien déterminé, le problème c'est que pratiquement une trame sur 10 n'arrive pas dans l'ordre et certaines trames arrivent avec un byte ou deux qui manquent !!!!
J'ai testé l'envoi de ces données sur un PC avec Hyperterminal et Docklight, mes trames arrivent correctement !

Donc le problème vient de mon code C que j'exécute sur la carte (FOX Board), je met le code plus bas si quelqu'un à une solution à mon problème ça m'aidera bcp, d'autant plus je doit finaliser ce projet ds quelque jours !

MERCI POUR VOTRE AIDE

Exemple de Données correcte:
----------------------------
Chaque trame commence par 02 EA et se termine par 03 comme ci dessous (les xx représentent des valeurs qui peuvent changer)
02 EA xx xx xx xx 00 00 00 00 00 00 00 00 00 00 00 00 03

02 EA 3E 00 49 E1 00 00 00 00 00 00 00 00 00 00 00 00 03 
02 EA 3C E1 39 E1 00 00 00 00 00 00 00 00 00 00 00 00 03 
02 EA 3D 00 40 E1 00 00 00 00 00 00 00 00 00 00 00 00 03 
02 EA 40 02 56 E2 00 00 00 00 00 00 00 00 00 00 00 00 03 
02 EA 40 82 5A E2 00 00 00 00 00 00 00 00 00 00 00 00 03 
02 EA 40 00 5B E2 00 00 00 00 00 00 00 00 00 00 00 00 03 
02 EA 41 AC 62 E1 00 00 00 00 00 00 00 00 00 00 00 00 03 
...


Exemple de Données incorrecte:
-----------------------------
02 EA 58 00 84 E1 00 00 00 00 00 00 00 00 00 00 00 00 03 
02 00 00 00 00 00 00 00 00 03 EA 55 00 66 E1 00 00 00 00 
02 EA 53 00 4C E1 00 00 00 00 00 00 00 00 00 00 00 00 03 
02 EA 4E 01 CA E1 00 00 00 00 00 00 00 00 00 00 00 00 03 
02 EA 50 02 1D E1 00 00 00 00 00 00 00 00 00 00 00 00 03 
02 00 00 00 00 00 00 00 03 EA 5E 01 E1 00 00 00 00 00 02 
EA 60 01 64 E1 00 00 00 00 00 00 00 00 00 00 00 00 03 02
EA 00 01 1D E1 00 00 00 00 00 00 00 00 00 00 00 00 03 02 
EA 00 01 2B E1 00 03 02 EA 00 01 94 E1 00 00 00 00 00 00 
00 00 00 00 00 00 03 02 EA 00 01 CA 00 00 00 00 00 00 00 
00 00 00 00 03 02 EA 00 01 62 E1 00 00 00 00 00 00 00 00 
00 00 00 00 E1 00 00 00 00 00 00 00 00 00 00 00 00 03 02 
EA 00 02 1D E1 00 00 00 00 00 00 00 00 00 00 00 00 03 02 
EA 00 41 E1 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 03 02 EA 00 03 02 EA 00 41 64 E1 00 
...


CODE C pour l'ouverture de la communication serie sur la carte LINUX:

#include <stdio.h>     
#include <string.h>    
#include <unistd.h>    
#include <fcntl.h>     
#include <errno.h>     
#include <termios.h>   
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdarg.h>
#include <signal.h>

#define TAILLE_MAX 1000 	// Tableau de taille 1000 pour la lecture du nom de fichier

/****************************************************/
/*  CONFIGURATION POUR ÉTABLIR LA CONNEXION SÉRIE   */ 
/****************************************************/

struct termios stdin_saved_attributes;
struct termios tty_saved_attributes;
int tty_fd;
int tty_open(char* tty_dev) {
struct termios new_attributes;


  tty_fd = open(tty_dev,O_RDWR| O_NOCTTY | O_NONBLOCK);
	
  if (tty_fd<0) {
  	return -1;
  } else {
		tcgetattr(tty_fd,&tty_saved_attributes);
		tcgetattr(tty_fd,&new_attributes);

	new_attributes.c_cflag |= CREAD;		 	// Enable receiver
  	new_attributes.c_cflag |= B9600;		 	// Set baud rate
  	new_attributes.c_cflag |= CS8;			 	// 8 data bit
  	new_attributes.c_iflag |= IGNPAR;		 	// Ignore framing errors and parity errors. 
  	new_attributes.c_lflag &= ~(ICANON); 		// DISABLE canonical mode. 
  												// Disables the special characters EOF, EOL, EOL2, 
  												// ERASE, KILL, LNEXT, REPRINT, STATUS, and WERASE, and buffers by lines.
  	new_attributes.c_lflag &= ~(ECHO);			// DISABLE this: Echo input characters.
  	new_attributes.c_lflag &= ~(ECHOE);			// DISABLE this: If ICANON is also set, the ERASE character erases the preceding input 
  												// character, and WERASE erases the preceding word.
  	new_attributes.c_lflag &= ~(ISIG);			// DISABLE this: When any of the characters INTR, QUIT, SUSP, 
  												// or DSUSP are received, generate the corresponding signal.
 	new_attributes.c_cc[VMIN]=1;				// Minimum number of characters for non-canonical read.
	new_attributes.c_cc[VTIME]=0;				// Timeout in deciseconds for non-canonical read.
    tcsetattr(tty_fd, TCSANOW, &new_attributes);
	}
  return tty_fd;
}

// Serial version of printf
void tty_printf(char *format, ...) {
  va_list argptr;
  char buffer[200];
  va_start(argptr,format);
  vsprintf(buffer,format,argptr);
  va_end(argptr);
  write(tty_fd,buffer,strlen(buffer));
}

void termination_handler (int signum) {
	tcsetattr(STDIN_FILENO,TCSANOW,&stdin_saved_attributes);
	if (tty_fd>0) tcsetattr (tty_fd,TCSANOW,&tty_saved_attributes);

	close(tty_fd);
	printf("Exit\n");
	exit(0);
}

int stdin_init(void) {
  struct termios tattr;
  // Make sure stdin is a terminal
	if (!isatty (STDIN_FILENO)) {
		fprintf (stderr,"stdin is not a terminal\n");
	  return -1;
	}
	// Save the terminal attributes so we can restore them later.
	tcgetattr (STDIN_FILENO, &stdin_saved_attributes);

  // Set the funny terminal modes. 
  tcgetattr (STDIN_FILENO, &tattr);
  tattr.c_lflag &= ~(ICANON | ECHO); /* Clear ICANON and ECHO. */
  tattr.c_cc[VMIN] = 0;
  tattr.c_cc[VTIME] = 0;
  tcsetattr (STDIN_FILENO, TCSAFLUSH, &tattr);
  return 0;
}


/*********************************************************/
/*  ROUTINE POUR RÉCUPÉRER LES DONNÉES ET LES AFFICHER   */ 
/*********************************************************/

int main(int argc, char *argv[]) {
  int rxChar;
  char i;
  i=0;
  FILE* fichiersave = NULL;
  FILE* fichiernom = NULL;
  char chaine[TAILLE_MAX] = ""; 	// Chaîne vide de taille TAILLE_MAX
	
  printf("Acme Serial Test (press ctrl-c to exit)\n");
  if (tty_open(argv[1])<0) {
  	fprintf (stderr,"tty open error %s\n", strerror(errno));
	  exit(EXIT_FAILURE);
  } 
	
  if (stdin_init()<0) {
  	printf("stdin init error %s\n", strerror(errno));
//  exit(EXIT_FAILURE);
  } 

  if (signal (SIGINT, termination_handler) == SIG_IGN) signal (SIGINT, SIG_IGN);
  if (signal (SIGHUP, termination_handler) == SIG_IGN) signal (SIGHUP, SIG_IGN);
  if (signal (SIGTERM, termination_handler) == SIG_IGN) signal (SIGTERM, SIG_IGN);
  
  fichiernom = fopen("/mnt/flash/noms/nom.save", "r");
  if (fichiernom != NULL)
	{
		fgets(chaine, TAILLE_MAX, fichiernom); 	// On lit maximum TAILLE_MAX caractères du fichiernom, on stocke le tout dans "chaine"
		printf("%s", chaine); 					// On affiche la chaîne
	 	fclose(fichiernom);
	}
	fichiersave = fopen(("%s",chaine), "a");
	
  while (1) 
	{
	
		if (read(tty_fd,&rxChar,1)>0) 
		{	
			printf("%02X ",rxChar);
			if (fichiersave != NULL)
			{
				// On écrit dans le fichier
				fprintf(fichiersave, "%02X ",rxChar);
				i++;
			}
			if (i==19)
			{
				printf("\n");
				i=0;
			}
		}
	}
		fclose(fichiersave);
		return EXIT_SUCCESS;
}


MERCI
A voir également:

3 réponses

dubcek Messages postés 19031 Date d'inscription   Statut Contributeur Dernière intervention   5 641
 
hello
essayer à très basse vitesse
new_attributes.c_cflag |= B50; /* ou B110 */
0
anbakkali Messages postés 4 Statut Membre
 
Bonjour, le problème c'est que les données viennent d'un sonomètre, et chaque trame représente une mesure, le sonomètre sera utilisé dans un milieu routier, mes mesures doivent être très précises, je doit prélever une histoire de +/- 100 mesures par seconde que je traiterai par après.
Je ne sait pas c'est le faite de diminuer le baud-rate, influencerai mes exigences (100 mesures /s).
En tt cas, je vais tester la solution !

Mais sinon, j'ai lu un peu sur les forums et j'ai vu qu'il y a certaine personne qu'on le même genre de problème que moi, https://openclassrooms.com/forum/sujet/comment-eviter-des-problemes-avec-scanf-94623
Le problème peut venir du buffer de stdin, mais seulement, mes données n'arrivent à partir de stdin, mais d'une connexion série, donc je ne sait pas le tty_fd de if (read(tty_fd,&rxChar,1)>0) peut être considérer comme un stdin.
while (1) 
	{	
		if (read(tty_fd,&rxChar,1)>0) 
		{	
			printf("%02X ",rxChar);
			if (fichiersave != NULL)
			{
				// On écrit dans le fichier
				fprintf(fichiersave, "%02X ",rxChar);
				i++;
			}
			if (i==19)
			{
				printf("\n");
				i=0;
			}
		}
	}


Merci à toi
0
dubcek Messages postés 19031 Date d'inscription   Statut Contributeur Dernière intervention   5 641
 
le but de diminuer la vitesse est de tester si il n'y a pas un problème de handshake, du genre xon/xoff
0
anbakkali Messages postés 4 Statut Membre
 
Salut,
j'ai testé mais ça na rien donné :-(

0