Rechercher : dans
Par :

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

Dernière réponse le 7 fév 2007 à 17:56:24 Grmi91, le 5 fév 2007 à 17:30:43 
 Signaler ce message aux modérateurs

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
Configuration: Linux Fedora Core 3

Meilleures réponses pour « [Linux prog en C] Lécture liaison série » dans :
[Langage C] C/C++ Erreur de segmentation VoirQu'est ce qu'une erreur de segmentation Vous êtes en train de développer une application sous Linux en C/C++. Tout va bien, ça compile, les oiseaux chantent. Donc vous lancez votre application pour la tester. Et vous obtenez l'un de ces deux...
Compiler du C sous Linux/UNIX VoirSous Linux, le compilateur de C est gcc. Il est installé de base sur plusieurs distributions, mais sur Debian (et celles qui en découlent) il faudra l'installer (aptitude install gcc). gcc Syntaxe de GCC gcc Tout d'abord, il faut savoir...
Comment lire un fichier ligne par ligne VoirComment lire un fichier ligne par ligne Préambule Boucle while Syntaxe Exemple Astuces Bonus Boucle for Syntaxe Préambule Une des erreurs les plus communes dans l'apprentissage des scripts "bash" sous GNU/LInux pour lire un fichier...

1

dubcek, le 6 fév 2007 à 14:58:40

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+

Répondre à dubcek

2

dubcek, le 6 fév 2007 à 16:03:20

Le programme sur ce site fait cela, lire un seul caractère: http://boudicca.tux.org/mhonarc/ma-linux/2001-Feb/msg00130.h­tml

Répondre à dubcek

3

Grmi'91, le 7 fév 2007 à 15:32:47

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?

Répondre à Grmi'91

4

dubcek, le 7 fév 2007 à 16:32:35
  • +3

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

Répondre à dubcek

5

Grmi'91, le 7 fév 2007 à 17:33:36

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...

Répondre à Grmi'91

6

 Grmi'91, le 7 fév 2007 à 17:56:24

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 !!!!!

Répondre à Grmi'91