OVH Cloud OVH Cloud

Communication par rs232

5 réponses
Avatar
Steph
Bonjour,

Je suis entrain de faire un programme communicant avec un kit herakles (kit
ITC).
Je suis sous linux.

Voici une partie du code que j'ai ecrit.

fichier : rs232.c

#include <sys/types.h>
#include <sys/stat.h>
#include <asm/ioctls.h>
#include <asm/termios.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <asm/io.h>
#include "rs232.h"

#define COM_PORT1 "/dev/ttyS0"

#define BAUDRATE B9600

int fd;
struct termios oldtio,newtio;

void main (void)

fd=open(COM_PORT1,O_RDWR | O_NOCTTY | O_NDELAY);

fcntl(fd,F_SETFL,0);
if (fd==-1) {
printf("Ne peux pas ouvrir le port com demandé\n");
exit (0);
}

if (debug) printf("\nfd : %i \r\n",fd);

tcgetattr(fd, &newtio);

cfsetospeed(&newtio,BAUDRATE);
cfsetispeed(&newtio,BAUDRATE);

newtio.c_cflag |= (CLOCAL | CREAD);
tcsetattr(fd, TCSANOW, &newtio);
newtio.c_cflag &= ~CSIZE; /*Mask the character size bits*/
newtio.c_cflag |= CS8; /*Select 8 data bits*/
newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
newtio.c_oflag &= ~OPOST;
newtio.c_cc[VMIN] = 0;
newtio.c_cc[VTIME] = 10;

read_write(); // appel a la fct read_write

}

void read_write(void){
char *s = "N0Sxx";
char buf[2];

write (fd, s, strlen(s));

read (fd, buf, 2);

printf(" recu : %s",s);

}


// -----------------------

ce n'est qu'une partie de mon code.

Le probleme que j'ai est le suivant :

je ne peux pas recevoir des données j'ai l'impression qu'elles se croisent
l'une sur Tx et l'autre sur Rx.

j'aimerais savoir si il n'existe pas 1 autre moyen pour ecrire ou lire sur
le port que celui d'utiliser un write et read qui semble poser probleme.

De plus, j'ai trouvé comment ne pas bloquer en cas de non reception de
données en read, mais justement ca ne lit plus rien.

Je sais que mon read fonctionne correctement puisque je peux lire
l'identification de la carte lors de son redemarrage si je suis en attente
de lecture.

On m'a conseillé d'utiliser 2 file descriptor, ca change quelque chose ?


Merci de m'aider un peu.

----

Stéphane
steph10200_no_spam@ifrance.com
retirez nospam pour répondre par mail

---

5 réponses

Avatar
steph
Voila ou j'en suis pour le moment.

le probleme que j'ai est toujours le meme, write, pas de probleme, et
read ne retourne rien.

je pense qu'il y a 1 probleme sur la config.
config : 9600,N,8,1

// includes
...


void main (void){

int fd;
struct newtio;
struct termios termios_p;

char buf[10];
int ecrit, lu;
int i;
char data='!';
int debug=2;
int com=1;
if (debug) printf("comport:%i n",com);
if (debug) printf("ntrying to open com 1 fd=");
fd = open(COM_PORT1,O_RDWR | O_NOCTTY | O_NONBLOCK); //
ouverture du port en non bloquant
if (debug) printf("nPort com 1 ouvert");
if (fd==-1) {
printf("Ne peux pas ouvrir le port com demandén");
exit (0);
}

if (debug) printf("nfd : %i rn",fd);

tcgetattr(fd,&termios_p);

termios_p.c_cflag &= ~CBAUD;
termios_p.c_cflag &= ~CBAUDEX;
termios_p.c_cflag |= BAUDRATE;

termios_p.c_cflag &= ~PARODD; // pas parité
termios_p.c_cflag &= ~PARENB; // Pas de parité
termios_p.c_cflag &= ~CSIZE; // 8 bits
termios_p.c_cflag |= CS8; // 8 bits

/* Sauvegarde des nouveaux parameres */
tcsetattr(fd,TCSANOW,&termios_p);

write
read

close
...
}
Avatar
jz
steph wrote:
Voila ou j'en suis pour le moment.

le probleme que j'ai est toujours le meme, write, pas de probleme, et


Comment sais-tu que write fonctionne correctement ?

read ne retourne rien.

je pense qu'il y a 1 probleme sur la config.
config : 9600,N,8,1


Suite du fil mal placé sur fr.comp.lang.c

Un question bête avant de commencer : ton terme COM_PORT1 est-il bien
initialisé sur le port de ta carte ? C'est tellement courant de se
planter là :)


Voici un programme d'exemple d'utilisation du port série en utilisant
select(...), et surtout pas un mode non bloquant sans contrôle.

Il se compile sans aucun warning avec gcc -Wall

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

#define PORT "/dev/tty0"

int main()
{
int fd;
char c;
struct timeval tv;
struct termios tty;

fd = open(PORT, O_RDWR | O_NOCTTY);
if (fd < 0) {
fprintf(stderr,"Can't open %sn", PORT);
perror("Error");
exit(1);
}

/* 9600 bauds, 8bits, 1 bit de stop, pas de parité */
bzero(&tty, sizeof(tty));
tty.c_cflag = CLOCAL | CS8 | CSTOPB;
cfsetospeed(&tty, B9600);
cfsetispeed(&tty, B9600);
tcflush(fd, TCIFLUSH);
tcsetattr(fd, TCSANOW, &tty);

/* lecture */
fd_set rfds;
int encore = 1;
while (encore)
{
FD_ZERO(&rfds);
FD_SET(fd, &rfds); /* pour surveiller fd */
tv.tv_sec = 5; /* timeout 5 secondes */
tv.tv_usec = 0; /* + 0 microsecondes */
if (select(fd+1, &rfds, NULL, NULL, &tv)) {
read(fd, &c, 1);
printf("%c", c); fflush(stdout); /* pour voir */
/* ... */
/* tes calculs à toi ici */
/* ... */
}
else {
printf("timeoutn");
encore = 0; /* bye */
}
}
return 0;
}
-----------------------------------


Cet exemple ne fait que la lecture.

Pour l'écriture c'est pareil, sauf pour l'ordre des paramètres de
select : select(fd+1, NULL, &rfds, NULL, &tv)

Attention : select() modifie les structures rfds et tv, donc il faut
les réinitialiser à chaque utilisation.

A+
Jacques

Avatar
Steph
"jz" a écrit dans le message news:
41f3735b$0$9740$
steph wrote:
Voila ou j'en suis pour le moment.

le probleme que j'ai est toujours le meme, write, pas de probleme, et


Comment sais-tu que write fonctionne correctement ?


c'est simple, suivant les commandes que je fait, ca allume 1 diode ou 1
autre. si j'envoie un R, ca remet a 0 la carte.

read ne retourne rien.

je pense qu'il y a 1 probleme sur la config.
config : 9600,N,8,1


Suite du fil mal placé sur fr.comp.lang.c

Un question bête avant de commencer : ton terme COM_PORT1 est-il bien
initialisé sur le port de ta carte ? C'est tellement courant de se
planter là :)


j'ai fait un défine
#define COM_PORT1 "/dev/ttyS0"



Voici un programme d'exemple d'utilisation du port série en utilisant
select(...), et surtout pas un mode non bloquant sans contrôle.


Merci.

j'ai enfin 1 exemple simple et parlant de l'utilisation de select.

Il se compile sans aucun warning avec gcc -Wall

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

#define PORT "/dev/tty0"

int main()
{
int fd;
char c;
struct timeval tv;
struct termios tty;

fd = open(PORT, O_RDWR | O_NOCTTY);
if (fd < 0) {
fprintf(stderr,"Can't open %sn", PORT);
perror("Error");
exit(1);
}

/* 9600 bauds, 8bits, 1 bit de stop, pas de parité */
bzero(&tty, sizeof(tty));
tty.c_cflag = CLOCAL | CS8 | CSTOPB;
cfsetospeed(&tty, B9600);
cfsetispeed(&tty, B9600);
tcflush(fd, TCIFLUSH);
tcsetattr(fd, TCSANOW, &tty);

/* lecture */
fd_set rfds;
int encore = 1;
while (encore)
{
FD_ZERO(&rfds);
FD_SET(fd, &rfds); /* pour surveiller fd */
tv.tv_sec = 5; /* timeout 5 secondes */
tv.tv_usec = 0; /* + 0 microsecondes */
if (select(fd+1, &rfds, NULL, NULL, &tv)) {
read(fd, &c, 1);
printf("%c", c); fflush(stdout); /* pour voir */
/* ... */
/* tes calculs à toi ici */
/* ... */
}
else {
printf("timeoutn");
encore = 0; /* bye */
}
}
return 0;
}
-----------------------------------


il me retourne un timeout.

Question : Es ce que je peux lire en utilisant un inb ? avec une boucle for
de 0à7 ?
Si oui, quel est le port en général d'un port serie com1.
Et es ce que ca va poser un probleme vu que le com1 est deja ouvert par une
autre methode ?


Cet exemple ne fait que la lecture.

Pour l'écriture c'est pareil, sauf pour l'ordre des paramètres de
select : select(fd+1, NULL, &rfds, NULL, &tv)

Attention : select() modifie les structures rfds et tv, donc il faut
les réinitialiser à chaque utilisation.

A+
Jacques





--
----

Stéphane

retirez nospam pour répondre par mail

---


Avatar
jz
Steph wrote:
Comment sais-tu que write fonctionne correctement ?
c'est simple, suivant les commandes que je fait, ca allume 1 diode ou 1

autre. si j'envoie un R, ca remet a 0 la carte.
Donc la carte fonctionne, et la liaison aussi, 2 bonnes nouvelles.

C'est confirmé aussi en lecture, puisque la carte te dit qui elle est
quand tu la démarre.

Merci.
pas de quoi.


Question : Es ce que je peux lire en utilisant un inb ? avec une boucle for
de 0à7 ?
Non, l'accès au port série se fait à travers le device, ou alors il

faut écrire le driver et c'est vraiment un autre monde.

Si oui, quel est le port en général d'un port serie com1.
Ça dépend des machines, mais /dev/ttyS0 semble pas mal pour ton cas.

C'est confirmé puisque tu arrives à communiquer... un peu.


Le blocage peut aussi être lié au protocole de communication :

Ne faut-il pas valider chaque requête par un code spécial genre 'n'
(13, ou 10, ou les 2, ça dépend des cartes) ?

C'est fréquent lorsque les commandes sont envoyées en mode texte.

Tu peux utiliser minicom (ou un autre) pour valider les échanges avec
la carte. Ça fait souvent gagner beaucoup de temps. Ton programme sera
ensuite bien plus simple à écrire, en sachant exactement comment la
carte réagit.

A+
Jacques


Avatar
Steph
Franchement Merci, ca marche,

"jz" a écrit dans le message news:
41f386b9$0$16419$
Steph wrote:
Comment sais-tu que write fonctionne correctement ?
c'est simple, suivant les commandes que je fait, ca allume 1 diode ou 1

autre. si j'envoie un R, ca remet a 0 la carte.
Donc la carte fonctionne, et la liaison aussi, 2 bonnes nouvelles.

C'est confirmé aussi en lecture, puisque la carte te dit qui elle est
quand tu la démarre.

Merci.
pas de quoi.


Question : Es ce que je peux lire en utilisant un inb ? avec une boucle
for


de 0à7 ?
Non, l'accès au port série se fait à travers le device, ou alors il

faut écrire le driver et c'est vraiment un autre monde.

Si oui, quel est le port en général d'un port serie com1.
Ça dépend des machines, mais /dev/ttyS0 semble pas mal pour ton cas.

C'est confirmé puisque tu arrives à communiquer... un peu.
maintenant j'arrive a communiquer


Le blocage peut aussi être lié au protocole de communication :

Ne faut-il pas valider chaque requête par un code spécial genre 'n'
(13, ou 10, ou les 2, ça dépend des cartes) ?
Bin non,

C'est fréquent lorsque les commandes sont envoyées en mode texte.

Tu peux utiliser minicom (ou un autre) pour valider les échanges avec
la carte. Ça fait souvent gagner beaucoup de temps. Ton programme sera
ensuite bien plus simple à écrire, en sachant exactement comment la
carte réagit.

A+
Jacques



Merci vraiment pour toute votre aide, la lecture fonctionne impécablement.

copie ici de ce que j'ai pour le moment et ca marche !!

int fd;

char tx(char data){
// Fonction tx
char cha;
int ecrit, lu;


fcntl(fd, F_SETFL, 0);

ecrit=write (fd, &data,1); // strlen(data));
tcdrain(fd);
usleep(1000);
lu=read (fd, &cha, 1);
return cha;
}

void Open_port(void){
struct termios termios_p;
fd = open(COM_PORT1,O_RDWR | O_NOCTTY);
bzero(&termios_p, sizeof(termios_p));
termios_p.c_cflag = CLOCAL | CS8 | CSTOPB; // 9600,8,N,1
cfsetospeed(&termios_p, B9600); // 9600
cfsetispeed(&termios_p, B9600); // 9600
termios_p.c_oflag &= ~OPOST;
termios_p.c_oflag &= ~(IXON | IXOFF | IXANY); /* no flow control */

termios_p.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
termios_p.c_oflag &= ~OPOST; /* No output processing */
termios_p.c_oflag &= ~ONLCR; /* Don't convert linefeeds */
termios_p.c_cflag |= CREAD;
// termios_p.c_lflag = 0; /* no local flags */
// termios_p.c_cflag |= HUPCL; /* Drop DTR on close */

tcflush(fd, TCIFLUSH); // clear the line
tcsetattr(fd, TCSANOW, &termios_p);

}

La fonction Tx envoie le caractère donné en param et retourne le caractere
retourné en echange.

Merci a tout ceux qui ont participé a ce post.

A+


--

Stéphane

retirez nospam pour répondre par mail
---