Envoie et réception de trames à une IHM

Fermé
valentin7650 - 13 nov. 2013 à 09:41
valentin7650 Messages postés 6 Date d'inscription mardi 29 octobre 2013 Statut Membre Dernière intervention 6 décembre 2013 - 18 nov. 2013 à 10:01
Bonjour,


Je suis actuellement en stage et je dois faire une communication entre une carte beagleboard ( linux) et une IHM par l'intermédiaire d'une petite carte électronique comportant 2 ports COM.
Donc j'ai décidé de faire ça en C++, je me suis renseigné un peu sur google et en fait je dois traduire un programme déja fait en C# le traduire en C/C++ mais il fait plus de 4000 lignes donc j'ai décidé de faire d'abord un petit programme de test pour essayer d'allumer des leds sur l'IHM et d'afficher du texte mais il ne se passe rien.
Voici le code que j'ai fait:


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

int main()
{

char text1[32]{ 0x20, 0x42, 0x6F, 0x6E, 0x6A, 0x6F, 0x75, 0x72, 0x20, 0x61, 0x70, 0x70, 0x75, 0x79, 0x65, 0x72, 0x20, 0x73, 0x75, 0x72, 0x20, 0x75, 0x6E, 0x65, 0x20, 0x74, 0x6F, 0x75, 0x63, 0x68, 0x65, 0x20 };
char outBuffer[57];
struct termios options;
int fd,i=0,reception;
std::string code = "";
std::string code2 = "";
int tailleinbuffer = 16;
int departoutbuffer = 3;
unsigned char nombre =0x01;
char inBuffer[16];
char P1_Led[3]{ 0x01, 0x00, 0x00 };
char P3_Led[3]{ 0x01, 0x00, 0x00 };
char c;
fd=open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
if(fd<0)
{
printf("problème port serie %d\n",fd);
exit(-1);
}
else
{
printf("port serie %d ouvert\n",fd);

tcgetattr(fd,&options);
cfsetospeed(&options, B9600);

options.c_cflag |= (CLOCAL | CREAD);
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= ~CS8;
tcsetattr(fd, TCSANOW, &options);
printf("fin de la configuration\n");
for (int i = 0; i < 56; i++)
{
outBuffer[i] = 0x00;
}
P1_Led[0]=0x00;
P1_Led[1]=0x00;
P1_Led[2]=0x01;

outBuffer[0] = 0xAA;
outBuffer[1] = 0x57;
outBuffer[2] = 0x08;
outBuffer[44] = P1_Led[0];
outBuffer[45] = P1_Led[1];
outBuffer[46] = P1_Led[2];
outBuffer[50] = P3_Led[0];
outBuffer[51] = P3_Led[1];
outBuffer[52] = P3_Led[2];
/* code = code2.substr(9, 1);
code += code2.substr(11, 1);
code += code2.substr(13, 1);
code += code2.substr(15, 1);
*/

while(inBuffer[13] != 01)
{
outBuffer[44] = P1_Led[0];
outBuffer[45] = P1_Led[1];
outBuffer[46] = P1_Led[2];
outBuffer[50] = P3_Led[0];
outBuffer[51] = P3_Led[1];
outBuffer[52] = P3_Led[2];
int longueur =sizeof(text1)/sizeof(*text1);
for (int i = 0; i < longueur; i++)
{
outBuffer[departoutbuffer] = text1[i];
departoutbuffer++;
}
departoutbuffer = 3;
P1_Led[0] =0x00;
P1_Led[1] =0x00;
P1_Led[2] =0x01;
P3_Led[0] = 0x00;
P3_Led[1] = 0x01;
P3_Led[2] = 0x00;
char inBuffer[16];
if(code == "1222")
{
outBuffer[0] = 0xAA;
outBuffer[1] = 0x57;
outBuffer[2] = 0x08;
outBuffer[44] = P1_Led[0];
outBuffer[45] = P1_Led[1];
outBuffer[46] = P1_Led[2];
outBuffer[departoutbuffer] = text1[i];

P1_Led[0] =0x01;
P1_Led[1] =0x00;
P1_Led[2] =0x00;

}
else
{
printf("code pas bon\n");

outBuffer[44] = P1_Led[0];
outBuffer[45] = P1_Led[1];
outBuffer[46] = P1_Led[2];
P1_Led[0] =0x00;
P1_Led[1] =0x01;
P1_Led[2] =0x00;

}
}
printf("envoie des données\n");

P1_Led[0]=0x00;
P1_Led[1]=0x00;
P1_Led[2]=0x01;

if(write(fd,&outBuffer, 1)<0 )
printf("écriture");
printf("fin de l'envoie\n");
sleep(1);
fcntl(fd,F_SETFL,8); // lecture des données
//while(1)
//{
reception=read(fd,outBuffer,100);
printf("nb de caracteres lu: %s\n",reception,outBuffer);
//}

if(reception==-1)
printf("erreur lecture port \n");

printf("fin de la réception");
}
close(fd);
}



Au final je détecte bien la carte qui a les 2 ports COM ( soit ttyUSB0 soit ttyUSB1 maisj en e sais pas lequel est pour l'ihm j'ai essayé les 2 mais aucun changement ), il m'affiche bien prot série numéro.... ouvert quand la carte avec les 2 ports COM est bien connecté , il m'affiche "fin de la configuration" et ensuite plus rien je ne voit pas trop ou est ce que cela gène ?


Merci d'avance
A voir également:

6 réponses

valentin7650
13 nov. 2013 à 10:39
J'ai oublié de donner quelques détails pour que le code soit plus clair:
-la variable text1 a été fait en ASCII
-"outBuffer[57]" contient 57 octets dont chaque octet a un rôle a jouer ( le 44 par exemple met la LED 1 en position "dispo" ) et donc je dois écrire dans ce buffer les trames que je veut envoyer ( enfin en principe si j'ai bien compris ) et après recevoir ses valeurs en lecture

-"std::string code" = ""; c'est un code que l'on peut taper avec le clavier de l'IHM

-char "P1_Led[3]{ 0x01, 0x00, 0x00 }" les 3 positions de la 1 ère LED : dispo,charge,défaut


Je ne suis pas très bon pour programmer des ports com et envoyer des trames donc j'ai un peu de mal a comprendre.

Voila en principe cela devrait être plus clair.
0
sambia39 Messages postés 610 Date d'inscription vendredi 31 juillet 2009 Statut Membre Dernière intervention 9 février 2023 49
13 nov. 2013 à 12:59
Salut à toi l'amis
bon je t'avoue que la lecture d'un code si long je le fait pas trops
va à essentiel deja renseigne toi sur les commande port serie et leur fonctions
je parle de ça
options.c_cflag |= (CLOCAL | CREAD);

options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= ~CS8;
tcsetattr(fd, TCSANOW, &options);
printf("fin de la configuration\n");
for (int i = 0; i < 56; i++)
{
outBuffer[i] = 0x00;
}
P1_Led[0]=0x00;
P1_Led[1]=0x00;
P1_Led[2]=0x01;

outBuffer[0] = 0xAA;
outBuffer[1] = 0x57;
outBuffer[2] = 0x08;
outBuffer[44] = P1_Led[0];
outBuffer[45] = P1_Led[1];
outBuffer[46] = P1_Led[2];
outBuffer[50] = P3_Led[0];
outBuffer[51] = P3_Led[1];
outBuffer[52] = P3_Led[2];
/* code = code2.substr(9, 1);
code += code2.substr(11, 1);
code += code2.substr(13, 1);
code += code2.substr(15, 1);
*/

mais sinon je pourrais te founir un petit exemple sur utilisation du port serie a savoir
envoie/resception de trame
puis par exemple un projet personnel avec le rasberry l'alumage des leed en C C++
peut etre à ce soir ou tout à l'heure
et encore dsl pour les fautes
0
valentin7650
13 nov. 2013 à 14:19
Merci sambia39 de ta réponse, déja le programme que j'ai fait est tout petit comparé à celui en C# que je dois traduire en C/C++ c'est pour ça que j'ai essayé de faire un petit programme de test ou j'envoie peu de trame et en reçoit peu pour gérer peu d'appareils au début ( pour l'instant je gère que 2 led et l'affichage j'ai essayé vite fait les boutons aussi) mais l'ihm reçoit absolument rien!!!! parce que je détecte bien quand la carte avec les 2 ports com est connecté ou pas mais les leds sur cette carte qui montrent si il y a des trames qui circulent ne s'allument pas .

Pour les commandes port série et leur fonction je me suis renseigné justement et je pense avoir compris sauf peut être les 2 fonctions read et write ou je suis pas complètement sûr d'avoir tout compris.

Ce qu'il me faudrait c'est un petit programme qui gère les port série justement comme tu la cité car je pourrais m'en inspirer pour ajouter ce qu'il me faut et le transformer pour mon projet car pour l'instant je me suis inspiré de ce programme:

http://fr.openclassrooms.com/forum/sujet/envoie-de-trame-hexa-39051

Je n'ai pas d'erreur quand je l'exécute mais pareil il ne semble pas y avoir de communication , j'avoue être un peu perdu car j'ai fait pas mal de C mais jamais sur les ports COM.
Par contre il me faudrait un programme qui tourne sous linux ( donc pas de bibliothèque windows et tout ) car je suis sous linux.
0
valentin7650
14 nov. 2013 à 10:06
J'ai l'impression que cela vient de la fonction write parce que j'ai copier coller ce programme: http://fr.openclassrooms.com/forum/sujet/envoie-de-trame-hexa-39051

et sur ma carte port série il y a des leds qui indiquent si ils y a des trames envoyés ( du pc vers l'ihm ou l'inverse) et même en essayant ce programme cela n'a pas l'air d'envoyer de trames!!!! pourtant c'est bien le bon port série ( ttyUSB0 ) j'ai essayé de remplacer leur exemple ou il envoit 0xC1 par une trame de 5 octets parce que je croyais que envoyé un seul octet était trop rapide pour que je voie la led s'allumer mais ça ne change rien !!!! la j'avoue que je suis complètement perdu.

SI quelqu'un a une solution je suis preneur.
0

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

Posez votre question
sambia39 Messages postés 610 Date d'inscription vendredi 31 juillet 2009 Statut Membre Dernière intervention 9 février 2023 49
16 nov. 2013 à 14:48
effectivements je tes promis une petite démos sur le site je n'est pas testé mon code ou compillé mais je suis sur que cela peut fonctionner dsl de le posté ainsi car

pas le temps tout faire je cours de gauche à droit c'est temps si pour

alors voilà
/*

* Fonction qui lit sur une liaison série elle prend en parametre
* le controleur (fd=file descriptor)qui est l'état de la liason série
* (1=active/0=erreur) & un cmd qui est buffers commande reçut
* en peut faire l'operation inverse pour l'écriture
* en peut egalement utiliser les séquence du tableaux ascii
* (STX)=commencement d'ecriture/lecture de caractère
* (ETX)=fin de lecture/ecriture de caractère
* il est possible aussi d'evité de mettre (if(tmp==1)) pour
* le contrôle d'un caractère et traiter directement dans le else
*/
char *lireCmd(const int fd){
unsigned int i=0,tmp=0;
unsigned char *cmd='\0';
char buffer[30]={'\0'};
while(buffer[i]!='\0'){
tmp=read(fd,&cmd,1);
if(tmp<=0){perror("Erreur lecture de commande\n");}
else{buffer[i]=cmd[i];i++;}
}return buffer;
}

/*
* Fonction permettant de crée et configurée un term
* elle prend en paramètre le chemin de la liaison série
* Avis:toujours être en 'su' pour pouvoir utilisé cette
* fonction si vous ête sur GNU/Linux
*/
int openLiaison(char *addr_Liaison){
struct termios oldTerm,newTerm;
unsigned int fd=open(addr_Liaison,O_RDWR|O_NOCTTY);
if(fd<=0){perror("Erreure ouverture liason/liaison occupé");return fd;}
else{
tcgetattr(fd,&oldTerm); //savegarde état précédent termios
tcgetattr(fd,&newTerm); //aquisition état & utilisation new Termios

//configuration termios
newTerm.c_iflag=IGNBRK; //ignoré signaux break
newTerm.c_oflag=0L;
newTerm.c_lflag=0L;
newTerm.c_cc[VMIN]=1;
newTerm.c_cc[VTIME]=0;
newTerm.c_cflag|=CREAD;
newTerm.c_cflag&=~(CSIZE|PARENB|CSTOP|CRTSCTS);
newTerm.c_cflag|=CS8;
newTerm.c_cflag|=CLOCAL;
newTerm.c_iflag&=~(IXON|IXOFF|IXANY);

//configuration du baudrate
cfsetispeed(&newTerm,BAUDRATE);
cfsetospeed(&newTerm,BAUDRATE);
tcsetattr(fd,TCSANOW,&newTerm);
tcflush(fd,TCIFLUSH); //libére term
return fd;
}
}


une autre piste renseigne toi sur les fonction du termios
pour la lecture des donner je précise encore que jai pas compilé ou teste le code
mais je suis sur que la fonction lirecmd comporte certaine erreure mais le reste est bon
car la boucle while peut cause default segment
on peut faire autrement comme
/*

* Fonction qui lit sur une liaison série elle prend en parametre
* le controleur (fd=file descriptor)qui est l'état de la liason série
* (1=active/0=erreur) & un cmd qui est buffers commande reçut
* en peut faire l'operation inverse pour l'écriture
* en peut egalement utiliser les séquence du tableaux ascii
* (STX)=commencement d'ecriture/lecture de caractère
* (ETX)=fin de lecture/ecriture de caractère
* il est possible aussi d'evité de mettre (if(tmp==1)) pour
* le contrôle d'un caractère et traiter directement dans le else
*/
char *lireCmd(const int fd){
unsigned int i=0,tmp=0;
unsigned char cmd[500]={'\0'}; //depend la taille de la commande
char buffer[5000]={'\0'};
do{
tmp=read(fd,&cmd,1);
if(tmp<=0){perror("Erreur lecture de commande\n");}
else{
if(tmp>=1){ //debut de lecture avec un caractère detecté
buffer[i]=cmd;
i++;
}
}
}while(i<500); //Attention y'a un bug car il doit remplir 500
return buffer; //revoir
}
donc voilà bon pour l'envoie pas grand chose a faire je te laisse le souin de le faire mais sinon si tu veux un prog fiable envoy un mail pv avec ton prog et enoncé
encore dsl pour les fautes
0
valentin7650 Messages postés 6 Date d'inscription mardi 29 octobre 2013 Statut Membre Dernière intervention 6 décembre 2013
18 nov. 2013 à 10:01
Merci pour les programmes sambia39 mais il y a quelques erreurs:

Pour la 1ère méthode de lecture j'ai une erreur pour ces lignes " else{buffer[i]=cmd[i];i++;}

}return buffer;"

ou il me dit que je fait une conversion invalide de unsigned char* en char ( j'ai essayé d'enlever le unsigned mais sa change rien ) et pour la 2 ème méthode de lecture j'ai une erreur a ces lignes:


"buffer[i]=cmd;

return buffer; //revoir

}"
Comme erreur pour le buffer[i]=cmd; invalid conversion from 'unsigned char*' to 'char' et pour le return buffer invalid conversion from 'char*' to 'int' donc bon cela ne m'aide pas trop :/

Sinon je t'envoie en pm le programme que j'ai fait actuellement ( j'ai un début de communication avec mon programme ou la fonction write a l'air de fonctionner mais j'arrive pas a vérifier que sa écrit les bonnes données )
0