Académique Documents
Professionnel Documents
Culture Documents
Introduction Progressive Au C
Introduction Progressive Au C
1) STRUCTURE MINIMALE DUN PROGRAMME POUR SYSTME EMBARQU ......... 2 2) OPRATIONS SIMPLES SUR LES ENTRES / SORTIES ................................................ 2
Oprations de sortie.................................................................................................................... 2 Oprations dentres................................................................................................................... 3 Le programme pdagogique le plus simple avec une opration dentre et une opration de sortie............................................................................................................................................. 3
6) DCLARATIONS DE DONNES. VARIABLES LOCALES ET GLOBALES ................... 11 7) PASSAGES DINFORMATIONS VERS UNE FONCTION ........................................... 11 8) TABLEAUX, POINTEURS .............................................................................................. 12
8.1) Exemple dutilisation dun tableau pour gnrer des signaux ........................................ 13 8.2) Exemple dutilisation dun tableau pour des motifs afficher........................................ 14 8.3 Utilisation dun pointeur pour accder aux lments dun tableau ................................ 14
#include <pic.h>
permet dinclure (lors de la phase pr processeur) le fichier texte qui contient la dclaration des registres fonctions spciales du C (port dE/S, registres de contrle, etc.)1 programme principal devant obligatoirement sappeler main
void main(void) { /* instructions pour linitialisation */ DebBclSansFin : /* instructions de la boucle sans fin */ . goto DebBclSansFin ; }
1 : chaque compilateur est livr avec un ou plusieurs fichiers contenant chacun les dclarations des registres fonction spciale. Ces fichiers sont dits fichiers en-tte (header). Voir abrg Structure simplifie dun programme source / Inclusion de fichier Les dclarations des registres mentionnent les adresses. Ceci est prsent plus loin dans ce document. Remarque : Les programmeurs nutilisent jamais une tiquette + un goto pour raliser une boucle sans fin. La forme employe ncessite de connatre les structures de contrle de flux. Voir plus loin.
OPRATIONS DE SORTIE
Modification des 8 bits dun port PORTx = valeur ; Mise 0 de certains bits dun Mise 1 d certains bits dun port port PORTx = PORTx & MASQUE ; PORTx = PORTx | MASQUE ;
PORTx doit avoir t au pralable dclar (par exemple dans un ficher en-tte inclus avec #include). & et | sont des oprateurs logiques du langage C. Voir abrg Oprateurs MASQUE peut tre une valeur numrique ou un symbole quivalent une valeur numrique dfini avec la directive #define. On crit en gnral les constantes avec des majuscules, pour les
Introduction progressive au C / Philippe Morenton LT PE Martin - Bourges
distinguer des variables, crites en minuscules (voir abrg Donnes : variables & constantes / Constantes / Constante symbolique). Exemple dextrait de programme : #include <pic.h> . #define MASQUE 0x25 void main(void) { . TRISD=0xFF ; DebBclSansFin : PORTD=PORTD & MASQUE ; goto DebBclSansFin }
dfinition du symbole MASQUE. En dbut de compilation, chaque occurrence de MASQUE sera remplace par la valeur 0x251
Configuration du port D du C en sortie. TRISD est dclar dans pic.h. TRISD est un registre, donc une variable. Il est crit en majuscule, car cest ainsi quil est dclar Instruction dcrite plus haut. Chaque bit 0 de MASQUE bit correspondant du port D 0. Les autres bits sont inchangs.
1 : 0x25 est une constante crite en hexadcimal. Voir abrg Donnes : variables & constantes / Constantes / Rgles dcriture des constantes. Remarques : Certains compilateurs ont une extension du C ANSI qui permet de manipuler un seul bit sur une variable (port de sortie, mot en mmoire). Une dclaration spcifique permet de dclarer un bit. Une fois cette dclaration effectue, on peut utiliser une instruction du type : RD1 = 0 ; /* mise 0 du bit 1 du port D */ Les compilateurs HiTech et CC5X admettent cette syntaxe. De plus le compilateur CC5X admet daccder un bit dune variable (port ou case mmoire quelconque) avec la syntaxe suivante PORTD.0 pour le bit 0 du port D.
OPRATIONS DENTRES
VarE est une variable pralablement dfinie destine contenir la valeur dun port dentre. Lecture des 8 bits dun port VarE = PORTx ; Lecture avec masquage VarE = PORTx & MASQUE
LE PROGRAMME PDAGOGIQUE LE PLUS SIMPLE AVEC UNE OPRATION DENTRE ET UNE OPRATION DE SORTIE
Ce programme na quune valeur pdagogique. Cest souvent le 1er programme crit, compil, etc. avec un systme embarqu.
Introduction progressive au C / Philippe Morenton LT PE Martin - Bourges
On prend comme exemple une maquette pdagogique avec un C PIC dont le port D est connect des LEDs et le port C est connect des micro interrupteurs #include <pic.h> void main(void) { TRISD=0 ; TRISC=0xFF ; DebBclSansFin : PORTD= PORTC ; goto DebBclSansFin ; }
programmation du port D en sortie programmation du port C en entre le port C est dabord lu, puis la valeur est envoye sur le portD. Si une variable intermdiaire est ncessaire, elle est cre lors de la compilation1.
1 : avec une instruction de ce type, une variable intermdiaire nest pas ncessaire : la valeur sur le port D est dabord recopie dans laccumulateur (ou registre de travail avec le PIC) puis le contenu de laccumulateur est transfr sur le port C.
exemples : unsigned1 char i ; unsigned1 char i, j, k ; unsigned1 char i, j, k; signed1 char u ; int m ; dfinition dun entier non sign sur 8 bits dfinition de 3 entiers non signs sur 8 bits mme chose que ci-dessus, mais avec ce style dcriture, il est possible de placer un commentaire en face de chaque variable. dfinition dun entier sign sur 8 bits. Il est possible dutiliser u dans if(u<0) {.}. dfinition dun entier sign sur 16 bits
1 : si seulement char est mentionn, le compilateur utilise un type sign ou non sign par dfaut, selon les options de compilation. Voir la documentation du compilateur utilis.
ENTRE
ET DUNE
FIN DE
while ( (FinTempo == FAUX) && ((PORTx & MASQUE) != 1))) ; Lexpression qui correspond la condition entre () comprend 2 expressions valeur boolenne connectes par un ET logique. La deuxime de ces expressions ((PORTx & MASQUE) != 1) ralise un masquage avec un ET bit bit qui nest pas de mme nature que le ET logique.
/* instruction pour extraire un octet dun tableau et lenvoyer vers laffichage. La position de loctet extraire dpend de NumAff */ /* diverses autres instructions */ }
La suite dinstructions ci-dessous ralise la mme chose que ci-dessus : NumAff =0 ; while (NumAff <12) { NumAff ++ ; }
Une variante utilisant la possibilit de postincrmentation NumAff=0 ; while (NumAff++<12) /* NumAff est incrment aprs valuation de lexpression */ { }
5) UTILISATION DE FONCTIONS
Une fonction correspond un sous programme1. Voir le sur les fonctions dans labrg sur le C (dfinition, utilisation, valeur retourne, etc.) Les fonctions sont utilises pour diminuer la taille du code produit et/ou pour amliorer la lisibilit dun programme
Dans quelques cas exceptionnels, une fonction ne correspond pas un sous programme. Cest le cas avec certains compilateurs pour des Cs avec trs faibles ressources.
6
FONCTION SANS PARAMTRE Ex : void main(void) { for ( ;;) { Tempo1() ; // appel de la fonction Tempo1() ; } } Avant lappel de la fonction, il faut absolument placer soit la dfinition de la fonction, soit une dclaration si la dfinition est place aprs ou sur un autre fichier. La dfinition dcrit ce que fait la fonction et donne des informations au compilateur sur la valeur de retour et sur le ou les paramtres. La dclaration donne au compilateur des informations sur la valeur de retour et le ou les paramtres pour que le compilateur prvoie les emplacements mmoire ncessaires. Structure du programme avec dfinition avant lappel void Tempo1 (void) /* en-tte de la fonction*/ {.} /* corps de la fonction qui dcrit ce que ralise la fonction */ void main(void) { for ( ;;) { Tempo1() ; // appel de la fonction Tempo1() ; } } Structure du programme avec dfinition aprs lappel void Tempo1 (void) ; /* dclaration fonct.*/ void main(void) { for ( ;;) { Tempo1() ; // appel de la fonction Tempo1() ; } } void Tempo1 (void) /* en-tte de la fonction*/ {.} /* corps de la fonction qui dcrit ce que ralise la fonction */
FONCTION AVEC PARAMTRE / PASSAGE DE PARAMTRE La fonction de lexemple prcdent nutilise aucun paramtre et ne renvoie aucune valeur. Il est possible dutiliser la mme fonction pour diffrentes temporisations. Lors de lappel, on utilise un paramtre qui correspond ici la dure de la temporisation. Ex : void main(void) {
Introduction progressive au C / Philippe Morenton LT PE Martin - Bourges
for ( ;;) { Tempo(10) ; // appel de la fonction avec le paramtre 10 Tempo1(100) ; // appel de la fonction avec le paramtre 100 } } La dfinition de la fonction est la suivante : void Tempo1(unsigned char Nb_ms) { unsigned char i; /* variable locale voir plus loin 6 et abrg C, Constitution dun programme / Donne / Porte */ for (i=0 ; i<Nb_ms ;i++) { .. // instructions pour tempo lmentaire 1 ms } } Le paramtre pass lors de lappel de la fonction sappelle le paramtre effectif ou largument. Le paramtre utilis lors de la dfinition est dit paramtre muet. Son nom nest utilis que dans la dfinition. Lors de lexcution du programme, avant lappel du sous programme (qui correspond la fonction), le paramtre est plac dans un ou plusieurs registres ou cases mmoire. Si dans le programme source le paramtre est une variable, une copie de cette variable est faite. Le sous programme lit le ou les registres ou cases mmoire qui contiennent la copie de la variable. Ce type de passage de paramtre est dit par copie de valeur. Cest le plus frquent dans le cas de programmes simples. Si on raisonne uniquement au niveau du programme source, on peut dire que lors de lappel de la fonction, le code de la fonction est excut avec le paramtre formel qui reoit une copie du paramtre effectif ou argument.
FONCTIONS AVEC PLUSIEURS PARAMTRES Une fonction peut avoir plusieurs paramtres. Pour la transmission des paramtres, seul importe lordre des paramtres. Ex : AfficheUneLigneLCD( Bonjour , LIGNE_1) ; // appel de la fonction avec 2 paramtres Len-tte de la dfinition de la fonction est : void AfficheUneLigneLCD(unsigned char* PtMsg, unsigned char NumLigne) Lors de lexcution de la fonction, si on raisonne uniquement au niveau du programme source, PtMsg reoit une copie du 1er paramtre (type non dtaill ici) et NumLigne reoit la valeur LIGNE_1 (constante dfinie auparavant. Voir plus loin pour la dfinition)
Pour se souvenir du mcanisme de passage, on peut utiliser le schma ci-dessous : Appel AfficheUneLigneLCD( Bonjour , LIGNE_1 ) Dfinition void AfficheUneLigneLCD( unsigned char* PtMsg, unsigned char NumLigne )
Lappel et len-tte de la dfinition sont placs sur plusieurs lignes pour une meilleure lisibilit.
Au lieu dutiliser les variables globales pour le passage de paramtres, on peut utiliser la copie de valeur, comme prsent en 5.2) Dans lexemple prcdent, la place de : AcquisitionAN1() ; Calcul() ; Affichage() On peut utiliser : Affichage(Calcul(AcquisitionAN1())) ;
Les dfinitions des fonctions doivent bien entendu tre diffrentes dans les 2 cas. Dans le 2me cas, la fonction AcquisitionAN1() est dabord appele. Elle renvoie un rsultat qui est utilis en paramtre de la fonction Calcul() qui est ensuite appele. Cette fonction Calcul renvoie elle mme une valeur qui est le paramtre de la fonction Affichage() appele en dernier.
Introduction progressive au C / Philippe Morenton LT PE Martin - Bourges
Rappel : pour que les interruptions puissent tre prises en compte, il faut les autoriser en positionnant correctement certains bits de registres de contrle. Voir pour le PIC les bits GIE, PIE pour les autorisations globales et les diffrents bits pour les interfaces et les priphriques intgrs. GESTIONNAIRE DINTERRUPTION AVEC LE PIC ET LE COMPILATEUR HITECH Comme le PIC na quun seul programme de traitement dinterruption, il faut absolument commencer par rechercher la source de linterruption, lorsque plusieurs sources sont possibles. Ceci seffectue en testant les drapeaux (bits dtat). Une interruption provoque une mise 1 du drapeau correspondant. Pour ne pas retourner dans le programme de traitement dinterruption, il faut remettre le drapeau 0 avant de revenir au programme principal.
void interrupt NomQuelconque(void) { . if (drapeau1==1) {.. drapeau1=0 ;} if (drapeau2==1) { drapeau2=0;} } EXEMPLE SIMPLE
Lidentificateur de la fonction nest utilis que dans la dfinition Son non importe peu Dclarations ventuelles des variables locales recherche de la source dinterruption si plusieurs sources possibles acquittement indispensable
Avec un PIC, une interruption fait clignoter 4 fois un voyant situ sur le PORTD. Le programme source du gestionnaire dinterruption est le suivant : interrupt void TraitInter(void) { unsigned int i ; // variable locale unsigned char NbClignot ; // variable locale if (INTF ==1) { for(NbClignot=4;NbClignot!=0;NbClignot--) { RD0=1; // RD0 de type bit (extension C ANSI) dfini auparavant
Introduction progressive au C / Philippe Morenton LT PE Martin - Bourges
10
for(i=0xFFFF;i!=0;i--) // temporisation usage pdagogique ; RD0=0; for(i=0xFFFF;i!=0;i--) ; } INTF=0; } // recherche pour les autres sources dinterruption }
11
par copie de valeur (dj prsent au 5.1) par adresse Le passage de paramtres par copie de valeur est le plus utilis pour les cas simples. Avec un passage de paramtres de ce type, la fonction ne peut modifier la valeur de la variable dont la copie est utilise. En effet lemplacement de la variable nest pas connu de la fonction, seul lemplacement de la copie est connu. Avec le passage de paramtre par adresse, cest ladresse dune donne qui est passe la fonction. Ce type de passage de paramtre est utilis pour passer un tableau ou une chane de caractre en paramtre. Cest ladresse de ce tableau ou de la chane de caractre qui est rellement passe. Pour plus de dtail, voir Abrg du langage C / Fonctions / Transmission et type de paramtres. Voir aussi Types de donnes complexes / Tableaux en paramtres dune fonctions.
8) TABLEAUX, POINTEURS
Dans les systmes embarqus, les tableaux sont principalement utiliss pour mmoriser une succession de : signaux dlivrer informations afficher (codes des caractres afficher, etc.) rsultats de mesures Les tableaux peuvent tre manipuls : directement avec leurs identificateurs et des indices indirectement par ladresse de lemplacement mmoire utilis Dans ce dernier cas, on utilise un pointeur. Un pointeur est obligatoire pour le passage de tableau en paramtre dune fonction. Dans certains cas, lutilisation dun pointeur la place de lidentificateur et dindice(s) permet de diminuer la taille du code produit.
12
2 RD1
10
12
t (ms)
RD2
t (ms)
RD3
t (ms)
A chaque fois que la sortie doit tre modifie, il faut utiliser le tableau. Une variable, dont la valeur est conserve entre 2 appels est utilise. Cette variable vaut de 0 4 ; elle est incrmente avant ou aprs lutilisation du tableau. Elle est rinitialise 0 lorsque tous les lments du tableau ont t utiliss.
RD4
t (ms)
t (ms)
Ex de code PORTD= CdesSorties[EtatSorties] ; EtatSorties += 1 ; // ou EtatSorties ++ if (EtatSorties == 5) EtatSorties = 0 ; // rinitialisation variante PORTD= CdesSorties[EtatSorties++] ;
Ce code remplace de faon trs compacte les lignes suivantes : switch (EtatSorties) { case 0 : PORTD = 0b00000001 ; break ; case 1 : PORTD = 0b00000010 ; break ; case 2 : PORTD = . . Remarque : le compilateur ne produit pas ncessairement un code compact partir dune partie de programme source compacte.
13
Col[GrpCol4][Aff0]
8.3 UTILISATION DUN POINTEUR POUR ACCDER AUX LMENTS DUN TABLEAU
Voir labrg sur le C. Lutilisation dcrite ici nest pas lemploi le plus frquent dun pointeur. Elle permet cependant de diminuer sensiblement la taille du code produit dans certains cas (C PIC et compilateur Hitech par exemple). On reprend lexemple du 8.1) Il peut tre traduit par : unsigned char* PtCdesSorties ; . PtCdesSorties = CdesSorties ; . PORTD=*PtCdesSorties ; PtCdesSorties +=1 ; dclaration dun pointeur sur un charactre CdesSorties est ladresse de dbut du tableau. PtCdesSorties est initialis cette adresse. PORTD = le contenu de ladresse donne par PtCdesSorties PtCdesSorties est incrment de la taille en octet de la donne pointe (ici un octet).
Il faut ensuite rinitialiser le pointeur avec ladresse de dbut du tableau lorsque tous les lments ont t utiliss if (PtCdesSorties == PtCdesSorties + 5) // on utilise ici larithmtique des pointeurs. PtCdesSorties = CdesSorties ;
14