[Linux - prog en C] Lécture liaison série

Fermé
Grmi91 Messages postés 12 Date d'inscription jeudi 23 juin 2005 Statut Membre Dernière intervention 17 octobre 2017 - 5 févr. 2007 à 17:30
 Grmi'91 - 7 févr. 2007 à 17:56
Bonjour, voilà je souhaiterais lire des données que me renvoies mon robot par l'intermediaire d'un programme en C. J'arrive à écrire des trames et les envoyées sur la liaison série (le robot fait les mouvements que je lui demande). En revanche je n'arrive pas à lire ce qu'il me renvoie (si je tape le caractere '$', le robot devrait me renvoyer ses positions). Sous windows avec procomm j'y arrive, ce qui n'est pas le cas sous linux !!!

Donc voilà un morceau du programme:
/* Déclarations des variables*/
char trame[50];
char *trameRecue;
int fichier;

/*Ouverture du fichier (port COM1) en lecture/ecriture*/
if ((fichier=open("/dev/ttyS1",O_RDWR)) == -1 ) 
	{perror("open");exit(-1);}

(...)

/* Ecriture dans fichier (envoie sur liaison serie (port COM1)) */
if ((write(fichier, &trame, strlen(trame))) == -1 ) 
       {perror("write"); close (fichier); exit(-1);} 

/* Lecture dans fichier (reception sur liaison serie (port COM1)) */
if ((read (fichier, &trameRecue, 1)) == -1)
		{perror("open"); close (fichier); exit(-1);}

=>Au moment de la lecture, le programme attend un caractère, mais le problème c'est qu'apparement il reçoit rien !?

Si quelqu'un pouvais m'aider ça serais sympa. Merci
A voir également:

6 réponses

dubcek Messages postés 18718 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 22 mars 2024 5 615
7 févr. 2007 à 16:32
Cette ligne enlève le mode ICANON, c-a-d traite chaque caractere sans attendre le NL, ce que j'appelle le mode raw:

tdata.c_lflag &= ~ICANON;

ce petit programme lit un caractere à la fois jusqu'à un x.
essayez le pour comprendre.

ioctl modifie les parametres de la ligne série, comme stty au niveau du shell
4
dubcek Messages postés 18718 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 22 mars 2024 5 615
6 févr. 2007 à 14:58
Si mes souvenirs sont bons, la ligne doit être ouverte en mode RAW pour lire un charactère, sinon le read attend un NL (NewLine ou return ou Enter)

A+
0
dubcek Messages postés 18718 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 22 mars 2024 5 615
6 févr. 2007 à 16:03
Le programme sur ce site fait cela, lire un seul caractère: http://boudicca.tux.org/mhonarc/ma-linux/2001-Feb/msg00130.html
0
OK. Déjà merci pour la réponse.
Mais pour le programme déjà écrit, je le trouve pas très compréhensible !!!
Sinon comment on fait pour mettre le port en mode RAW?
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
ah ok merci
Donc me suis "inspiré" de ta ligne et je reçois maintenant quelque chose !!!!
C'est pas vraiment c'que j'attenfais mais c'est toujours ça.
Voila mon programme en integrale si tu veux y comprendre un peu mieux :

fichier robot.h
using namespace std;

class robot
{
	public:	
		void InitialisationLiaisonSerie ();
		void EnvoieTrame ();
		void ReceptionTrame ();
};


fichier main.cpp
#include <stdio.h>
#include "robot.h"

using namespace std;

/************* Méthode principale *************/
int main()
{
	/*definition de l'instanciation*/
	robot monRobot;
	
	/*Appel des methodes*/	
	monRobot.InitialisationLiaisonSerie();
	monRobot.EnvoieTrame();
}


fichier robot.cpp
/************************************************************************
* compilation : g++ -o robot robot.cpp main.cpp            		*
************************************************************************/

#include <stdio.h>
#include <termios.h>
#include <sys/fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

#include "robot.h"

using namespace std;

/************* Methode InitialisationLiaisonSerie *************/
void robot::InitialisationLiaisonSerie()
{
	int fichier;
	struct termios termios_p;
	char modeLie[5]="L \n";

	/* Ouverture de la liaison serie */
	if ((fichier=open("/dev/ttyS1",O_RDWR)) == -1 ) 
	     {perror("open");exit(-1);}

	/* Lecture des parametres courants */
	tcgetattr(fichier,&termios_p);
		
	/* On ignore les BREAK et les caracteres avec erreurs de parite */
	termios_p.c_iflag = IGNBRK | IGNPAR;	
	
	/* Pas de mode de sortie particulier */
	termios_p.c_oflag = 0;	
	
	/* Liaison de 9600 bps, 8 bits de donnees, pas de parité (1 bit de stop par defaut) */
	termios_p.c_cflag = B9600 | CS8;
	termios_p.c_cflag &= ~PARENB;
	
	/* Mode RAW */
	termios_p.c_lflag = ~ICANON;
	
	/* 1 caractere suffit et données immediatement disponibles */
	termios_p.c_cc[VMIN] = 0;
	termios_p.c_cc[VTIME] = 1;
	
	/* Sauvegarde des nouveaux parametres */
	tcsetattr(fichier,TCSANOW,&termios_p);	
		
	/* Envoie du mode lié pour une utilisation manuel*/
	if ((write(fichier, &modeLie, strlen(modeLie))) == -1 ) 
	     {perror("envoie trame");close (fichier); exit(-1);}
	
	/* Fermeture */
	close(fichier);
}

/************* Methode EnvoieTrame *************/
void robot::EnvoieTrame()
{
	/* Declaration des variables*/
	char trame[50];
	char trameRecue[10];
   	int longueurTrame, fichier;

	/*Ouverture du fichier (port COM1) en lecture/ecriture*/
	if ((fichier=open("/dev/ttyS1",O_RDWR)) == -1 ) 
		{perror("open");exit(-1);}
	while(1)
        {
	        /* Saisie trame */
	        printf("Entrez une trame : ");
                scanf ("%s", &trame);
   	
                longueurTrame = strlen(trame);   	
 
                /* Ajout de caracteres de fin de trame*/
   		trame[longueurTrame] = ' ';
   		trame[longueurTrame+1] = '\n';
   		trame[longueurTrame+2] = '\0';
   						
		/* Ecriture dans fichier (envoie sur liaison serie (port COM1)) */
   		if ((write(fichier, &trame, strlen(trame))) == -1 ) 
		     {perror("write"); close (fichier); exit(-1);} 
		
		/* Lecture dans fichier (reception sur liaison serie (port COM1)) */
		if ((read (fichier, &trameRecue, 1)) == -1)
		     {perror("open"); close (fichier); exit(-1);}
	
		printf ("trame recue: %02x %c \n\n", trameRecue, trameRecue);
	}
	close (fichier);
}


voila. Et donc le problème c'est que déjà à l'execution, quelque soit ce que je tape ça me renvoie toujours la même valeurs:
 ./robot
Entrez une trame : $
trame recue: fef317f0 ð

Entrez une trame : B+100:30
trame recue: fef317f0 ð

et si je relance l'execution ba ça m'affiche d'autre caractere:
./robot
Entrez une trame : B+100:30
trame recue: fef6a970 p

Entrez une trame : $
trame recue: fef6a970 p


Donc voilà quoi...
0
en fait je viens de remarquer que je ne fais que lire l'adresse de trameRecue.
En l'initialisant et modifiant la fin du code par
        /* Declaration des variables*/
	char trame[50];
	char trameRecue[10];
	int nbOctetLu, i=0;

   	int longueurTrame, fichier;

        /* Initialisation des trames */ 
	memset(trame, 0x00, 50);
	memset(trameRecue, 0x00, 10);
        (...)
        else
   		{
   			trame[longueurTrame] = ' ';
   			trame[longueurTrame+1] = '\n';
   			trame[longueurTrame+2] = '\0';
   						
			/* Ecriture dans fichier (envoie sur liaison serie (port COM1)) */
   			if ((write(fichier, &trame, strlen(trame))) == -1 ) 
				{perror("write"); close (fichier); exit(-1);} 
			sleep(2);
			/* Lecture dans fichier (reception sur liaison serie (port COM1)) */
			if ((read (fichier, trameRecue, 10)) == -1)
				{perror("open"); close (fichier); exit(-1);}
			printf ("trame recue : ");
			
			for (i=0; i<10; i++)
				printf (" %02x %c - ", trameRecue[i], trameRecue[i]);
		}

je constate que je lis rien du tout sur le port !!!!!
0