Date de création: 21.07.2001
Rubrique du:
Auteur(s): hpbaby
Navigation: precedent principal
Version:     FR

Voir en: 1024*768

LA PRATIQUE POUSSEE

Le protocole RS232



I - APPROCHE THEORIQUE

1) La trame complète

Elle est constituée de 10 motifs répartis dans 3 blocs qui sont ordonnés comme suit:

avec ?=0 ou 1 pour valeur du motif (selon la valeur du bloc à transmettre).

 

2) Signification des blocs de la trame


START:Indique le début de transmission et permet au récepteur de se synchroniser
DATA:Contient la valeur du caractère envoyé,c-à-d DATA=D7*128+D6*64+D5*32+D4*16+D3*8+D2*4+D1*2+D0*1
STOP:Indique la fin de transmission au récepteur

3) Motifs de base

Ce sont les morceaux élémentaires et répétitif du signal électrique qui:

  • qui représentent soit la valeur 0 soit la valeur 1 des motifs.
  • qui mis bout à bout forment le signal électrique de la trame complète.


Motif START
D0 à D7
STOP
Valeur possible 1 0 1 0
Représentation

Attention, le raccord entre deux motifs successifs n'est pas indiqué ici.

 

4) Le modèle dynamique

Vous avez rien compris? alors c'est ici que cela se passe. Les données (et certains champs de contrôle les gérant, c'est à dire non figés) de la trame sont localisées dans les motifs variables que vous pouvez manipuler par des boutons. La valeur affichée sur le bouton est soit la valeur d'un bloc (cf signification ci-dessus) soit la valeur d'un des motifs le représentant. Cliquez sur les boutons , observez et analysez les répercussions sur le signal électrique..

  • si la trame véhicule:

  • alors électriquement, on aura le signal:

 

Plus dur, essayez de faire l'inverse en partant du signal électrique déterminez la valeur véhiculée par chacun des motifs , de déduire celle des blocs et d'en conclure sur ce qui est déclenché. Cliquez sur un ou plusieurs motifs du signal et vous obtiendrez la réponse! En laissant votre curseur de souris sur l'un des motifs, il vous sera même révélé son nom.


RS232 PRATIQUE

II - APPROCHE PRATIQUE

Un rapide coup d'oeil sur les motifs de base permet d'en déduire que la valeur réelle du motif est l'inverse du niveau lu sur le motif. Il nous faudrait inverser les signal avant de le lire.Comme le max232 est notre copain, il nous fait ce boulot à notre place dans les deux sens. Il nous suffit alors de lire à la motié du motif pour récupérer sa valeur.

 

1) Décodage d'une trame RS232

J'ai reproduit avec des pulse bas sur le chronogramme jaune les instants où il faudrait lire la trame pour récupérer de facon cohérente les 8 valeurs des motif de DATA , c'est à dire les 8 bits de données formant le caractère envoyé sur la laison série.

Le motif START a été ignoré, on commence à lire à la moitié du premier motif de DATA.


Ensuite, on passe au bit suivant en laissant passer la durée d'un motif ou bit. La valeur du motif correspond en fait à la valeur lue à la moitié de chaque motif. Dans cet exemple, le mot de 8 bit lu est 72 correspondant au caractère H (72 CHR ENTER)

mot binaire lu 1 1 1 0 1 1 0 1
Total
mot binaire réel (inversion MAX232) 0 0 0 1 0 0 1 0
facteur multiplicatif (poids binaire) 1 2 4 8 16 32 64 128
Résultat multiplication 0 0 0 8 0 0 64 0
72

 

Les tableaux qui suivent donnent les deux valeurs de référence: 85 et 170.

Phénomène non négligeable, le microcontroleur ne prends en compte le signal qu'après un certain temps de lattence (TirqLatency) qui vaut 60 microsecondes.


En conclusion, si le signal dure moins que TirqLatency, le microcontroleur ne le voit pas et ne déclenche pas le programme associé de gestion de la broche associé au signal.

mot binaire lu 1 0 1 0 1 0 1 0
Total
mot binaire réel (inversion MAX232) 0 1 0 1 0 1 0 1
facteur multiplicatif (poids binaire) 1 2 4 8 16 32 64 128
Résultat multiplication 0 2 0 8 0 32 0 128
170


Ici, je montre avec les marqueurs verticaux qu'il faut sauter le motif start et commencer notre série de lecture en partant de la moitié du premier motif de DATA.

Il faut être aussi très précis quand à la durée à sauter entre chaque motif de DATA. Toute imprécision est amplifiée de 8 fois. Aussi tout décalage au départ ou durée du saut inter motif inexacte, se paie par une mauvaise lecture du dernier motif de donnée.(lecture sur la transition ou front par exemple ou du bit stop)

mot binaire lu 0 1 0 1 0 1 0 1 Total
mot binaire réel (inversion MAX232) 1 0 1 0 1 0 1 0
facteur multiplicatif (poids binaire) 1 2 4 8 16 32 64 128
Résultat multiplication 1 0 4 0 16 0 64 0
85


2) Encodage d'une trame RS232

On génére le signal éléctrique logicielement avec des temporisations à la durée du motif

A gauche, lors de la recopie (en jaune) du caractère reçu (en blanc), j'ai mis en évidence un parasite (ou glitch) .

En fait ce n'est pas vraiment un parasite mais un problème connu avec les micocontrôleur pic : si l'on écrit deux fois de suite la même valeur sur un port (phénomène que l'on voit bien ici avec la récriture de 0), le micontrôleur refait une écriture alors qu'il ne devrait pas.

 

Malheureusement, comme tout opération, celle ci est loin dêtre instantanée et laisse le port instable pendant un cours moment. Bien que cela ne soit pas gênant pour le décodage, j'ai tout de même corrigé mon programme.

 

Ci dessous l'envoi successif du meme caractère U (chronogramme du bas)

En comparant le chronogramme du dessous avec celui du dessus, on contate que le deuxième caractère est ignoré.

Ceci est dû à notre programme qui attends la fin de la trame contenant le premier caractère alors qu'il pourrait , en même temps la recopier sur le port d'envoi.

III - MISE EN OEUVRE

J'expose donc mon programme qui gère ce type de liaison entre PICSYS et n'importe quel autre système muni d'un port RS232.

rs232.c

#include <pic.h> //obligatoire, de base

//Quartz 4Mhz
#define PIC_CLK 4000000

//Les routines de temporisation
#include "delay.h"

//J'utilise un quartz, mon code n'est pas protégé
__CONFIG(FOSC0|PWRTE |CP);

/**
* Gestion laison RS232 à 9600 bauds
*
*/

//Fonctions de manipulation des bits en remplacement des structures unions et typedef

#define PORTBIT(adr, bit) ((unsigned)(&adr)*8+(bit))
#define getbit(data,bitno) ((data>>bitno)&0x01)
#define setnbit(data,bitno) (data<<bitno)
#define setbit(data,bitno,value) (data&(~setnbit(1,bitno))|setnbit(value,bitno))
#define togglebit(data) (data^0x01)

//temps en microseconde pendant lequel le microcontroleur est aveugle à un changement d'état sur une de ses broches d'IT
#define TirqLatency 60

/************Liaison série *******************************/

//Paramètres de Reception
//-----------------------

#define Tbit_rx_RS232 104 //Reception T=1/9600=104us à 9600 bauds
#define Jump_over_RS232_rx_startbit (Tbit_rx_RS232-TirqLatency+(Tbit_rx_RS232/2))
#define Nb_RS232_rx_databits 8 // 8 bits de données
#define Jump_over_RS232_rx_databits (Tbit_rx_RS232-15) //la boucle d'éxécution prends 12us
#define Nb_RS232_rx_stopBits 1 //1 bit stop
#define Jump_over_RS232_rx_stopbits (Nb_RS232_rx_stopBits*Tbit_rx_RS232)

//Paramètres d'envoi
//------------------

#define Tbit_tx_RS232 104
#define Duration_RS232_tx_startbit (Tbit_tx_RS232-30)
#define Nb_RS232_tx_databits 8
#define Duration_RS232_tx_databits (Tbit_tx_RS232-30) //la boucle d'‚x‚cution prends 12us
#define Nb_RS232_tx_stopBits 1
#define Duration_RS232_tx_stopbits (Nb_RS232_tx_stopBits*Tbit_tx_RS232)


#define ITMask 0B10110000

//-----Attribution des broches -------------

static bit RS_OUT @ PORTBIT(PORTA, 4); //Borche d'envoi
static bit RS_IN @ PORTBIT(PORTB, 7); //Broche de reception

//Pour voir le caractère envoyé sur 8 leds
volatile bit D1 @ PORTBIT(PORTB, 3);
volatile bit D2 @ PORTBIT(PORTB, 2);
volatile bit D3 @ PORTBIT(PORTB, 1);
volatile bit D4 @ PORTBIT(PORTB, 0);
volatile bit D5 @ PORTBIT(PORTA, 3);
volatile bit D6 @ PORTBIT(PORTA, 2);
volatile bit D7 @ PORTBIT(PORTA, 1);
volatile bit D8 @ PORTBIT(PORTA, 0);

//---- Variables de travail ---------------------------
//variable utilisée par les routines de temporisation
volatile unsigned int timeout;

//variable tampon
unsigned char Buff;

unsigned char TxBuff; // caractère à emettre
unsigned char RxBuff;// caractère reçu

//------ Déclaration des routines RS232 -------------------------------

void RSsend(void); /* Send the char Buff on the serial port */
void RSget(void); /* Read the serial port and save it into Buff*/

//------- Déclaration des routines pour afficher sur les leds--------------

void WriteParport(void);
void ReadParport(void);

//------ Le programme principal intialise les ports et autorise les interruptions ---------
main()
{

//Indique si les broches sont des entrées ou des sorties
TRISB = ITMask;
TRISA = 0;

//Fixe les valeurs des ports par défaut
PORTA = 0;
PORTB = 0b10000000; //Initialize RS_IN
RS_OUT=1;

//autorise les interruptions sur le port B
RBIE=1;
GIE=1;

//boucle infinie qui n'attend qu'à être interrompue
for(;;) {

}

}

//-----Affiche le contenu de Buff sur le port des 8 leds
void WriteParport(void) {

D1=getbit(Buff,0);
D2=getbit(Buff,1);
D3=getbit(Buff,2);
D4=getbit(Buff,3);
D5=getbit(Buff,4);
D6=getbit(Buff,5);
D7=getbit(Buff,6);
D8=getbit(Buff,7);

}

//----récupère la valeur de Buff en fonction de la valeur sur les leds D1-D8
void ReadParport(void) {

Buff=setbit(Buff,0,D1);
Buff=setbit(Buff,1,D2);
Buff=setbit(Buff,2,D3);
Buff=setbit(Buff,3,D4);
Buff=setbit(Buff,4,D5);
Buff=setbit(Buff,5,D6);
Buff=setbit(Buff,6,D7);
Buff=setbit(Buff,7,D8);

}

unsigned char prev_portb=0B10000000; //mémorisation de la valeur du port B

// Routine d'interruption déclenchée si un signal change d'état sur une des broches prévues à cet effet:
// RB7, RB6,RB5,RB4 et RB0

interrupt isr()
{


//Détermine quelle broche du port B a changé d'état et a généré cette interruption
if (RBIF)
{
RBIF=0; //on acquite l'interruption


if ((prev_portb ^ (PORTB&ITMask)) == 0B10000000)
{


//C'est la Broche RB7=RS IN qui a changé, un caractère est à réceptionner
if ((PORTB & 0B10000000) == 0) //Si c'est le front descendant du bit start alors
{
//On réceptionne le caractère
RSget();
//on l'affiche sur les leds
Buff=RxBuff;
WriteParport();
//et on fait un echo en envoyant à celui qui nous l'a envoyé
TxBuff=RxBuff;
RSsend();
}

}

prev_portb=PORTB&ITMask; //on prépare le port b au prochain changement..

}


}



// RS232 routines
//------------------

/* Envoie sur la broche RA4 le caractère contenu dans TxBuff au format RS232*/

void RSsend(void) {
unsigned b;
unsigned prevbit;

// Bit start
RS_OUT=0;
DelayUs(Duration_RS232_tx_startbit); //durée du motif start

//pour tous les bits de données..
for(b=Nb_RS232_tx_databits;b--;) {

prevbit=(TxBuff&0x01);

if(prevbit^RS_OUT) //si la valeur est différente du pécédent bit
RS_OUT=TxBuff&0x01; //on l'envoie sinon on laisse la ligne comme est l'est

if(b>0) //si ce n'est pas le premier bit de donnée, c'est qu'il m'en reste encore à traiter
TxBuff=TxBuff>>1; //j'ai fini avec ce bit je le met à la poubelle , au bit suivant

DelayUs(Duration_RS232_tx_databits);//durée d'un motif data

}

//Bit stop
RS_OUT=1;
DelayUs(Duration_RS232_tx_stopbits);//durée d'un motif stop

}

/* Recoit un caractère série sur RA1 et le stocke dans RXBuff **/

void RSget(void) {


unsigned b;
RxBuff='\0';


//Saute par dessus le bit start et se positionne à la moitié du premier bit de données
//RS_OUT=0;
DelayUs(Jump_over_RS232_rx_startbit); // la tempo qu'il faut
//RS_OUT=1;

//Lit consécutivement les 8 bits de données que l'on m'envoie
for(b=Nb_RS232_rx_databits;b--;) {

RxBuff=RxBuff | ((RS_IN&0x01)<<(Nb_RS232_rx_databits-1));

/* Pour déboguage */
//RS_OUT=0;

if(b>0) //reste il des bits à traiter?
RxBuff=RxBuff >> 1; //oui,alors au suivant

DelayUs(Jump_over_RS232_rx_databits); //on laisse passer la durée d'un bit
//RS_OUT=1;

}


DelayUs(Jump_over_RS232_rx_stopbits); //facultatif car les bits stops ne contiennent pas d'info

}

 

 



Lab48 :

Oscilloscope pour HP et
générateur de signaux +5/-5V
 
ou centrale domotique de
8 Entrées/ Sorties Numériques
Hpmodem :
Dialoguer par voie hertzienne entre
2 HP - nécessite des alimentations externes.
HptaHptalk:
Faire épeller des lettres de l'alphabet à l'aide d'un synthétiseur vocal type ISDlk:
Faire épeller des lettres de l'alphabet à l'aide d'un synthétiseur vocal type ISD
HpDomotic :
1)Construire son programmateur PIC
2)Construire son interface domotique 
3)Le module Infrarouge multiusage
4)Les protocoles série asynchones
  a) RS232: liaison câble HP/PC
  b) HP48IR:liaison IR de la HP48
  c) RC5: liaison télécommandé