Tous | Basic Casio | C/C++/ASM | LuaFX | Graphisme | Transferts | Logiciels | Diverses astuces

Calculatrice
Toutes
Graphs 35 à 100
Graph 25
Graphs 75/85/95 (SD)
Graph 100(+)
Classpad 300/330 (+)
Fx-CG 10/20
Fx-CP 400

Retour à la liste des tutoriels
Tutoriel Casio : Communiquez avec le port 3-pins
Tutoriel rédigé le : 2014-04-08 18:42  par Dark storm  Catégorie : C/C++/ASM  Calculatrice : Graphs 75/85/95 (SD)

Discutez de ce tutoriel sur le forum >> Voir le sujet dédié (35 commentaires)

Communiquez avec le port 3-pins
Qui n'a jamais rêvé de faire un jeu multijoueurs sur sa calculatrice ? Ou alors un chat pour discuter en cours ? Dans ce tutoriel, nous allons apprendre comment envoyer et recevoir des données via le port série 3 broches ("serial 3-pins" en anglais) pour pouvoir échanger des informations entre deux calculatrices. Bonne lecture !


Sommaire :
1) Comment tester les programmes que je vais créer ?
2) Que faut-il utiliser ?
3) Ouvrir et fermer le port série
4) Émettre et recevoir des variables simples
5) Émettre et recevoir des tableaux de char et des variables "complexes"
6) Annexes



1) Comment tester les programmes que je vais créer ? :

Pour pouvoir communiquer, il faut être deux. Or, en règle générale, il est difficile de trouver chez soi deux Graph 35++/75/85/95. Pour cela, il ne faut pas hésiter à demander à vos amis du collège/lycée/fac, bref, ceux qui sont susceptibles de posséder une Graph "classique". Attention, si celle-ci est une Graph 35+USB non débridée, demandez bien à son propriétaire si il est d'accord pour la modifier en Graph 75. Bon, en règle générale, la promesse de pouvoir jouer à Sims City, Pokémon ou Fruit Ninja dessus est un bon argument, mais soyez responsable du matériel emprunté. :!:
Une fois en possession de vos deux caltos, installez sur les deux l'addin Serial Monitor de Ziqumu. Il servira à tester la connexion. Ensuite, vous connectez le câble aux deux caltos, puis vous lancez Serial Monitor. Appuyez sur les lettres, si elles sont bien envoyées, tout va bien. Sinon, vérifiez que le câble est bien enfoncé, en bon état, etc.
Vos programmes auront alors toutes les chances de fonctionner, tant que l'erreur ne vient pas de vous.

NB : Je savais pas où mettre ça, mais dans la suite du tutoriel, dès que l'on parlera de taille de données, tout sera exprimé en octets.


2) Que faut-il utiliser ? :

Comme d'habitude, voici les fichiers contenant les fonctions à inclure dans votre projet (en pièce-jointe). Le fichier .src est à ajouter aux fichiers du programme dans le SDK (comme un .c classique). Il contient des instructions en assembleur.
Voici tout de même le header dont nous commenterons les fonctions :
Serial.h
#ifndef _SERIAL
#define _SERIAL

/**********************************************************/
/** Les syscall suivants servent à l'acces au port série **/
/** Le buffer de réception fait 1ko,                     **/
/** et le buffer d'envoi fait 256 octets.                **/
/**********************************************************/

//Lit un caractère du buffer de réception et le copie a l'adresse pointée par 'dest'
//Retourne 0 en cas de succes, 1 si le buffer est vide, 3 si la connexion n'est pas établie
int Serial_ReadByte(unsigned char *dest);

//Lit 'max' octets du buffer de réception et les écrit dans 'dest'
//'size' donne le nombre d'octets lu
//Retourne 0 en cas de succes, 1 si le buffer est vide, 3 si la connexion n'est pas établie
int Serial_ReadBytes(unsigned char *dest, int max, short *size);

//Ecrit 'byte' dans le buffer d'envoi
//Retourne 0
int Serial_WriteByte(unsigned char byte);

//Ecrit 'size' octets dans le buffer d'envoi depuis l'adresse 'scr'
//Retourne 0 en cas de succes, 2 si le buffer est trop plein, 3 si la connexion n'est pas établie
int Serial_WriteBytes(unsigned char *src, int size);

//FIFO = first in first out
int Serial_WriteByteFIFO(unsigned char byte);

//Retourne la taille des données du buffer de réception
int Serial_GetRxBufferSize(void);

//Retourne l'espace disponible dans le buffer d'envoi
int Serial_GetTxBufferFreeCapacity(void);

//Vide le buffer de réception
//Retourne 0 en cas de succes, 3 si la connexion n'est pas établie
int Serial_ClearReceiveBuffer(void);

//Vide le buffer d'envoi
//Retourne 0
int Serial_ClearTransmitBuffer(void);

//Ouvre et prépare l'interface de communication
//Pour plus de détails, consulter fxreverse-doc-1.pdf ci joint
int Serial_Open(unsigned char *conf);

//Ferme l'interface de communication et vide les buffers d'envoi et de réception
//Si 'mode'==1, la communication est coupée sans regarder s'il reste des données a transmettre
//Si 'mode'≠1, la fonction ne ferme pas l'interface de communication s'il reste des données a transmettre
//et retourne 5
//Retourne 0 en cas de succes (communication terminée) et 5 s'il reste des données a transmettre
int Serial_Close(int mode);

//Copie l'octet numéro 'index' du buffer de réception vers 'dest' si 'index' ne dépasse pas les données du buffer
//Retourne 0 en cas de succes, 1 si 'index' dépasse les données du buffer, 3 si la communication n'est pas établie
int Serial_Peek(int index, unsigned char *dest);

//Récupère le statut de la connexion
//Retourne 1 si la connexion est établie, 3 sinon
int Serial_IsOpen(void);


#endif



3) Ouvrir et fermer le port série :

Encore une fois, on a le code base, mais comment l'utiliser ? Pour envoyer des données via le port série, il faut ouvrir ces ports. Pour cela, on a besoin d'une liste de configuration :
unsigned char config[] = {a, b, c, d, e, f};

Et les valeurs à mettre dans ce tableau :


Source : FxReverse de Andreas Bertheussen et Simon Lothar

Donc pour ouvrir les ports, les options les plus courantes sont :
unsigned char config[] = {0, 5, 0, 0, 0, 0};
// configuration des ports à 9600 bauds, pas de bit de parité, 8 bits de longueur, et 1 bit d'arret

Pour plus d'infos sur les bits de parité/longueur/arrêt, renseignez-vous ailleurs, c'est d'un niveau supérieur et pas forcément intéressant pour un usage courant. Pour les bauds, lisez la note en annexe de ce tutoriel.

Bref, maintenant qu'on a configuré les ports, on va les ouvrir, une seule fois tant que l'on ne les a pas fermés. Donc en début de jeu dans notre cas, en même temps que srand(), si vous utilisez de l'aléatoire.
Pour cela, exécutez cette fonction, et c'est tout :
erreur = Serial_Open(config);

erreur : 0 si tout s'est bien passé, 3 si c'est déjà ouvert, et 4 si config[0] est différent de 0.
Je vous habitue à utiliser des variables d'erreur pour que vous sachiez comment ça fonctionne, même si ce n'est pas nécessaire.

Pour le fermer, a la fin de votre programme, faites :
erreur = Serial_Close(0); // 0: arrête même si il reste des données à transmettre; 1: envoie les données puis ferme

erreur : 0 si tout s'est bien passé, 5 si il restait des données à envoyer.


4) Émettre et recevoir des variables simples :

On attaque les choses sérieuses : envoyer et recevoir des données. On va commencer avec un exemple simple, envoyer des (unsigned) char. J'insiste sur le char car les int, short, et float sont considérés comme des tableaux de char, et ça risque de ne pas fonctionner comme prévu si vous utilisez cette méthode.
Pour résumer brièvement, la calto possède un buffer, c'est à dire une zone de mémoire, réservé à l'envoi et à la réception de données. Le buffer d'envoi fait 256 octets, celui de réception 1ko. Lorsque vous écrivez ou lisez dedans, la calto se charge de mettre à jour le buffer correspondant : envoyer ou effacer les données.

Donc, pour écrire une valeur dans ce buffer, il faut faire :
erreur = Serial_WriteByte(monChar); // écrit le char dans le buffer d'envoi
// celui-ci est automatiquement envoyé dès que la calto le peux

erreur : 0 si tout s'est bien passé, et c'est tout.

Pour les recevoir, c'est presque pareil, sauf qu'il faut un pointeur :
erreur = Serial_ReadByte(&monChar);

erreur : 0 si tout s'est bien passé, 1 si le buffer de réception est vide, 3 si le port est fermé.

Ensuite, vous n'avez plus qu'à traiter les infos de votre coté.


5) Émettre et recevoir des tableaux de char et des variables "complexes" :

Nous allons maintenant passer à la vitesse supérieure : envoyer des tableaux de char, ainsi que d'autres types de variables et des structures.

Pour envoyer un tableau, il faut copier l'intégralité du tableau dans le buffer d'envoi. On pourrait faire :
void Send_Tab(char *tab, int size)
{
    int i;
    for(i=0; i<size; i++) Serial_WriteByte(*tab[i ]);
}

Mais il existe une fonction bien plus utile et efficace, qui prend en argument un pointeur sur le tableau, et la taille des données à écrire.
char monTableau[] = {0, 1, 2, 3, 4};
int taille = 5;
erreur = Serial_WriteBytes(monTableau, taille);

erreur : 0 si tout s'est bien passé, 2 si le buffer de transmission est plein, 3 si le port est fermé.

Cette fonction est très utile en ce qu'elle permet de copier tout type de données, y compris des short, int, floats, ou structures. Il suffit encore une fois d'envoyer les données avec un pointeur sur les données à copier :
short monShort = 42;
int monInt = 2048;
struct MA_STRUCTURE maStructure = {0x2A, 0xFF};

erreur1 = Serial_WriteBytes(&monShort, sizeof(short)); // envoie un short
erreur2 = Serial_WriteBytes(&monInt, sizeof(int)); // envoie un int
erreur3 = Serial_WriteBytes(&maStructure, sizeof(maStructure)); // envoie une structure de données


Pour lire ces données, vous pouvez récupérer une zone entière du buffer de réception avec Serial_ReadBytes(), qui demande en argument un pointeur sur la zone où copier les données, la taille maxi de données à copier, et un pointeur sur short, qui contiendra la taille des données lues - utile dans le cas où le buffer est vide avant d'avoir atteint la taille max à lire.
unsigned char monBuffer[10];
short tailleLue = 0;
erreur = Serial_ReadBytes(monBuffer, 10, &tailleLue);

erreur : 0 si tout s'est bien passé, 1 si le buffer de réception est vide, 3 si le port est fermé.

De même, on peut utiliser cette fonction pour lire d'autres types de variables :
short monShort = 42;
int monInt = 2048;
struct MA_STRUCTURE maStructure = {0x2A, 0xFF};

erreur1 = Serial_ReadBytes(&monShort, sizeof(short), &tailleLue); // récupère un short
erreur2 = Serial_ReadBytes(&monInt, sizeof(int), &tailleLue); // récupère un int
erreur3 = Serial_ReadBytes(&maStructure, sizeof(maStructure), &tailleLue); // récupère une structure de données


:!: Attention :!:
Il faut d'abord synchroniser la connexion entre les deux caltos avant d'envoyer - recevoir des données par paquets : en effet, si A envoie un int à B, et que B le lit avant que tout soit transmit, il n'aura qu'une partie des données, qui seront de plus décalées bit à bit !
Faites attention à cet aspect, cela peut provoquer des bugs ! Pour s'en protéger, la fonction int Serial_GetRxBufferSize(void) peut être utile.
Elle retourne le volume de données présentes dans le buffer de réception.


6) Annexes :

Les bauds :
Le baud est l'unité de mesure de vitesse de communication. Dans notre cas, il est équivalent au nombre d'octets/secondes, car la liaison série ne possède qu'une seule voie. Dans le cas où il existe plusieurs voies (carte SD, etc.) le nombre de bauds n'est pas égal à la vitesse en octets/secondes. Encore une fois, Google sait tout et vous éclairera sur vos questions subsidiaires.

Autres fonctions :
D'autres fonctions existent, la liste complète est dans la documentation FxReverse de Andreas Bertheussen et Simon Lothar.

Retour au sommaire

Fichier joint


Discutez de ce tutoriel sur le forum >> Voir le sujet dédié (35 commentaires)

Publicité et partenaires
Casio Education
Casio éducation

TI-Planet
Casiopeia
Casiopeia
CasioFan, la communauté ClassPad
CasioFan
CodeWalrus
CodeWalrus

Planète Casio v42 © créé par Neuronix et Muelsaco 2004 - 2015 | Il y a 76 connectés | Nous contacter | Qui sommes-nous ? | Licences et remerciements
Rugby Manager | Jeu de basket | Jeu de handball | Jeu de tennis | Nova Raider | Réparation téléphone | Soccer Rush | Tasty Tale

Planète Casio est un site communautaire indépendant, géré bénévolement et n'est donc pas affilié à Casio | Toute reproduction de Planète Casio, même partielle, est interdite
Les fichiers, programmes et autres publications présents sur Planète Casio restent la propriété de leurs auteurs respectifs et peuvent être soumis à des licences ou des copyrights.
CASIO est une marque déposée par CASIO Computer Co., Ltd