LANGAGE C avec AVR

Transcription

LANGAGE C avec AVR
1. PRESENTATION. ............................................................................................................................................1
2. STRUCTURE D’UN PROGRAMME EN LANGAGE C. ................................................................................1
2.1 Première approche d’un programme en langage C.............................................................................. 2
2.1.1 Directives de compilation................................................................................................................. 2
2.1.2 Déclaration d’une fonction. ............................................................................................................. 2
2.1.3 Déclaration des variables globales, des variables locales. ....................................................... 3
2.1.4 Point d’entrée du programme.......................................................................................................... 3
2.2 Définitions des types les plus couramment employés...................................................................... 3
2.2.1 Les types simples : ............................................................................................................................ 3
2.2.2 Le type pointeur : ............................................................................................................................. 3
2.3 Compilation d’un programme C avec CodeVisionAVR. ....................................................................... 5
2.3.1 Organisation de la mémoire SRAM................................................................................................ 5
2.3.2 Configuration du compilateur C. .................................................................................................... 6
3. LES OPERATEURS DE BASES.................................................................................................................... 7
3.1 L’opérateur d’affectation. ...................................................................................................................... 7
3.2 Les opérateurs arithmétiques. .............................................................................................................. 7
3.3 Les opérateurs de comparaison. ........................................................................................................... 7
3.4 Les opérateurs logiques. ......................................................................................................................... 7
3.5 Les opérateurs logiques de bits et de décalage................................................................................ 7
3.6 Les opérateurs d’incrémentation et d’affectation combinée......................................................... 8
4. LES STRUCTURES DE CONTROLES. ....................................................................................................... 8
4.1 Les structures alternatives (test). ..................................................................................................... 8
4.1.1 Structure IF … ELSE (SI … ALORS … SINON)....................................................................... 8
4.1.2 Structure SWITCH … CASE (CHOIX MULTIPLES). ............................................................... 9
4.2 Les structures ITERATIVES (Repetitives)....................................................................................... 9
4.2.1 La structure WHILE (TANT QUE … FAIRE). ............................................................................ 9
4.2.2 La structure DO … WHILE (FAIRE …JUSQU'À) ................................................................... 10
4.2.3 La structure FOR (POUR …FAIRE) ............................................................................................ 10
5. LES FONCTIONS. ........................................................................................................................................ 11
5.1 ROle d’une fonction. ................................................................................................................................ 11
5.2 Déclaration d’une fonction. .................................................................................................................. 12
5.3 Passage de paramètres. ........................................................................................................................ 12
1. PRESENTATION.
La majorité des microcontrôleurs sur le marché actuel disposent parmi leurs outils de
développement d’un compilateur C.
Ces compilateurs utilisent le langage « small C » qui reprend un large sous-ensemble des
fonctionnalités du langage C issu de la norme ANSI.
Le guide de programmation que vous tenez entre vos mains vous permettra de vous initier à l’aide
d’exemples concrets aux concepts de base du langage C adapté au microcontrôleur. Pour plus de
détails sur le langage C veuillez consulter les nombreux ouvrages proposés sur ce sujet.
Contrairement à ce que l’on pourrait croire, l’utilisation du langage C ne vous dispense pas de
consulter la documentation technique du micro ATMEL AVR que vous avez choisie !
2. STRUCTURE D’UN PROGRAMME EN LANGAGE C.
#include <90s8515.h>
// directive de compilation permettant d’inclure la bibliothèque
// de définition des registres internes du microcontrôleur choisi
void Tempo (unsigned long valeur);
// Déclaration de la fonction Tempo, point virgule !
int i;
// Déclaration d’une variable globale
void main(void)
{
DDRA=0xff;
PORTA=0x01;
// Fonction principale
while (1)
{
for (i=0; i<8; i++)
{
PORTA= PORTA<<1;
Tempo(100000);
}
}
}
void Tempo (unsigned long valeur)
{
unsigned long j;
for (j=0; j<valeur; j++)
{}
}
// Boucle inconditionnelle
// Initialisation
// Structure FOR pour i=0 à i=8 avec un incrément de 1
// On décale d’un bit vers la gauche
// appel fonction Tempo, passage du paramètre 100000 à l’argument
// valeur
// défnition de la fonction, pas de point virgule !
// Déclaration d’une variable locale
// on ne fait rien
1
2.1 PREMIERE APPROCHE D’UN PROGRAMME EN LANGAGE C.
2.1.1 Directives de compilation.
Les directives de compilation permettent de définir au pré-processeur les informations
nécessaires lors de la compilation du programme, le symbole # indique que le texte est une
directive. Le fichier « include » du microcontrôleur cible doit être obligatoirement précisé en
début de programme.
Exemples :
La directive #include permet d’insérer un autre fichier dans votre fichier source.
La directive #define peut être utilisée pour définir une macro ou une constante.
2.1.2 Déclaration d’une fonction.
Exemple :
void Tempo (unsigned long valeur);
La fonction Tempo ne renvoie aucune valeur, elle possède un argument valeur de type unsigned
long.
#include <90s8535.h>
void Tempo (unsigned long
valeur)
{
unsigned long j;
for (j=0; j<valeur; j++)
{}
}
void main(void)
{
short int i;
DDRA=0xff;
PORTA=0x01;
{
for (i=0; i<8; i++)
{
PORTA= PORTA<<1;
Tempo(100000);
}
}
}
// Aucune erreur à la
compilation, la fonction tempo
est appelée après sa définition.
#include <90s8535.h>
void main(void)
{
short int i;
DDRA=0xff;
PORTA=0x01;
{
for (i=0; i<8; i++)
{
PORTA= PORTA<<1;
Tempo(100000);
}
}
}
void Tempo (unsigned long valeur)
{
unsigned long j;
for (j=0; j<valeur; j++)
{}
}
//Erreur "undefined symbol
tempo" à la compilation, la
fonction tempo est appelée avant
d'être définie.
#include <90s8535.h>
void Tempo (unsigned long
valeur);
void main(void)
{
short int i;
DDRA=0xff;
PORTA=0x01;
{
for (i=0; i<8; i++)
{
PORTA= PORTA<<1;
Tempo(100000);
}
}
}
void Tempo (unsigned long valeur)
{
unsigned long j;
for (j=0; j<valeur; j++)
{}
}
// Aucune erreur à la compilation,
le compilateur connaît la fonction
tempo grâce à la déclaration.
2
Les fonctions doivent être déclarées en dehors de la fonction main. La déclaration permet
d'appeler une fonction avant qu'elle ne soit définit.
Les fonctions ne retournant pas de résultat utilisent le mot clé void en début de déclaration.
2.1.3 Déclaration des variables globales, des variables locales.
Les variables globales sont déclarées en en-tête du programme et sont accessibles à n’importe
quel instant de l’exécution du programme, ce sont des variables permanentes, elles font l’objet
d’une réservation en mémoire. Les variables locales sont définies à l’intérieur d’une fonction, leur
durée de vie est limitée à l’exécution de cette fonction, ce sont des variables temporaires. Si on
désire conserver la valeur d’une variable locale celle-ci doit être déclarée avec le mot clé static.
2.1.4 Point d’entrée du programme.
Chaque programme C se compose au minimum de la fonction main, c’est le point d’entrée de notre
programme. C’est à partir de la fonction main que seront appelées les autres fonctions (main est
écrit volontairement en minuscules, le compilateur C distinguant les majuscules des minuscules).
2.2 DEFINITIONS DES TYPES LES PLUS COURAMMENT EMPLOYES.
2.2.1 Les types simples :
Type
Bit
Char
Int
Taille (bits)
1
8
16
Domaine non signé
0,1
0 à 255
0 à 65535
Long int
32
0 à 4294967295
Domaine signé
-128 à 127
-32768 à 32767
-2147483648 à
2147483647
Le mot clé unsigned placé devant la déclaration du type permet de préciser que le type est non
signé.
Pour les autres types voir la documentation de CodeVision AVR.
2.2.2 Le type pointeur :
Le pointeur est une variable contenant une adresse. Il doit toujours être initialisé à une adresse
avant son utilisation, il est comparable aux registres d’index des microcontrôleurs.
Exemple :
int *ptr
//on déclare un pointeur se nommant ptr de type int.
Ptr = 0x0100 //on définit une adresse au pointeur.
PORTB = *ptr //le contenu de l’adresse pointée est transmis en sortie sur le PORTB.
3
Spécificités du compilateur CodeVision AVR :
L’architecture Harvard des microcontrôleurs AVR impose trois espaces d’adresses différents :
L’espace des données (SRAM)
L’espace programme (FLASH)
L’espace mémoire EEPROM
Le compilateur gère donc trois types de pointeurs :
Les variables situées en SRAM sont accessibles avec des pointeurs classiques.
Les constantes placées en mémoire FLASH sont accessibles avec des pointeurs déclarés
avec le mot clé flash ou const.
Les variables situées en EEPROM sont accessibles avec des pointeurs déclarés avec le
mot clé eeprom.
Bien que les pointeurs permettent d’accéder aux différents espaces mémoires, ceux-ci sont
toujours rangés en mémoire SRAM.
Exemples :
Char
*résultat //Déclaration du pointeur résultat, le pointeur est localisé en SRAM.
Char flash *message [2] ={”message 1”,”message 2”} //message 1 et message2 sont placés-en
//mémoire flash, le pointeur message est localisé en
//SRAM
Char eeprom *pointeur_mémoire =”Ce texte est placé en EEPROM” //Le chaîne de caractère est
// placée en EEPROM, le
//pointeur pointeur_mémoire
//est localisé en SRAM
4
2.3 COMPILATION D’UN PROGRAMME C AVEC CODEVISIONAVR.
2.3.1 Organisation de la mémoire SRAM.
Un programme compilé avec CodeVisionAVR à l’organisation suivante :
0
Registres de travail
20h
12 registres utilisés par le compilateur (R0, R1, R22 à R31).
R2 à R15 peuvent être alloués aux variables de type bit ( LSB de R2 = Premier bit déclaré, MSB
de R15 = 112eme bit déclaré, les registres inutilisés peuvent être alloués au var. globale de type int
ou char ).
Les registres R16 à R21 sont réservés aux variables locales de type int ou char.
Registres d’entrées sorties
Espace de 64 adresses réservé aux fonctions périphériques du microcontrôleur ( Ports, timer ….).
« Data stack »
Espace pointeur de pile
Cet espace permet de sauvegarder les registres utilisés par le compilateur (R0, R1, R22 à R31), le
passage des paramètres et le registre SREG lors de l’utilisation des interruptions. Au départ la pile
pointe 5F + taille Data stack. L’adresse est décrémentée durant une sauvegarde, incrémentée
durant une restitution.
60h
60h + Data stack
Variables globales
60h + Data stack +
var. globales
« Hardware stack »
Cet espace permet de ranger les variables globales du programme pendant son exécution.
Cet espace est utilisé pour ranger l’adresse de retour des fonctions
SRAM End
5
2.3.2 Configuration du compilateur C.
Une configuration optimisée du Project|Configure|Compiler permet de mieux maîtriser le code généré par le compilateur
Valeurs par défaut selon le choix du
micro choisi, vous pouvez optimiser
l’espace data stack size si nécessaire ou
déclarer de la SRAM externe.
Valide la transformation char en type int.
Voir exemple n°7 en fin de cours.
A cocher si vous utilisez la liaison
série
Déclaration du nombre de variable de
type bit, les registres inutilisés sont
alloués aux variables globales.
Le modèle TINY génère des pointeurs 8 bits,
on a accès aux 256 premiers octets de la
SRAM.
Le modèle SMALL génère des pointeurs 16
bits, on a accès aux 64K octets de la SRAM.
Pour améliorer la taille du programme et la
vitesse d’exécution, vous devez toujours
essayer d’utiliser le modèle TINY.
Valide par défaut le type char comme non
signé.
Optimise l’allocation des registres R2 à
R15 non utilisés par les variables de type
bit.
Permet d’optimiser la taille du code généré
(option size) ou la vitesse d’exécution (option
speed).
Permet de générer automatiquement une
séquence d’initialisation après un reset du
microcontrôleur.
Validation de l’utilisation de la fenêtre du
terminal d’AVR studio pour la simulation de la
liaison UART.
Cette option est utile lors du débuggage
sous AVR studio, elle permet de vérifier
l’intégrité de la taille de l’espace data
stack size, pour plus de détails voir la page
85 de la doc CodeVisionAVR.
6
3. LES OPERATEURS DE BASES.
3.1 L’OPERATEUR D’AFFECTATION.
Cet opérateur fondamental a pour symbole le signe égale “=”, sa syntaxe est
left value = expression.
3.2 LES OPERATEURS ARITHMETIQUES.
Ces opérateurs procèdent à des opérations arithmétiques sur leurs opérandes.
Opérateur
+
*
/
%
Opération
Addition
Soustraction
Multiplication
Division
Modulo
Exemple
a+b
a-b
a*b
a/b
a%b
3.3 LES OPERATEURS DE COMPARAISON.
Ce sont des opérateurs binaires qui comparent la valeur de leurs opérandes.
Opérateur
==
!=
<=
>=
<
>
Fonction
Égale à ?
Différent de ?
Inférieur ou égal à ?
Supérieur ou égal à ?
Inférieur à ?
Supérieur à ?
Exemple
a == b
a != b
a <= b
a >= b
a<b
a>b
3.4 LES OPERATEURS LOGIQUES.
Ces opérateurs permettent de relier logiquement des instructions.
Opérateur
&&
||
!
Fonction
ET logique
OU logique
NON logique
Exemple
a && b
a || b
!b
3.5 LES OPERATEURS LOGIQUES DE BITS ET DE DECALAGE.
Ces opérateurs réalisent des opérations logiques sur les bits de même rang.
Opérateur
&
|
^
~
>>
<<
Fonction
ET
OU
OU exclusif
NON ( complément )
Décalage de n bits
vers la droite
Décalage de n bits
vers la gauche
Exemple
a&b
a|b
a^b
~a
a >> n
a << n
7
3.6 LES OPERATEURS D’INCREMENTATION ET D’AFFECTATION COMBINEE.
Opérateur
++
-+=
-=
*=
/=
%=
>>=
<<=
&=
|=
^=
Fonction
Incrément de 1
Décrément de 1
Addition, résultat dans
l’opérande de gauche
Soustraction, résultat
dans l’opérande de gauche
Multiplication, résultat
dans l’opérande de gauche
Division, résultat
dans l’opérande de gauche
Modulo, résultat
dans l’opérande de gauche
Décalage à droite, résultat
dans l’opérande de gauche
Décalage à gauche, résultat
dans l’opérande de gauche
ET, résultat
dans l’opérande de gauche
OU, résultat
dans l’opérande de gauche
OU exclusif, résultat
dans l’opérande de gauche
Exemple
a ++
a --
Equivalence
a=a+1
a = a -1
a += b
a=a+b
a -= b
a=a-b
a *= b
a=a*b
a /= b
a=a/b
a %= b
a=a%b
a >>= n
a = a >> n
a <<= n
a = a << n
a &= b
a=a&b
a |= b
a=a|b
a ^= b
a=a^b
4. LES STRUCTURES DE CONTROLES.
4.1 LES STRUCTURES ALTERNATIVES (TEST).
Ces structures permettent de ne pas exécuter systématiquement certaines instructions.
4.1.1 Structure IF … ELSE (SI … ALORS … SINON).
if (<condition>)
<séquence A> ;
else
< séquence B >;
ou
if (<condition>)
{
<séquence(s)>;
}
else
{
<séquence(s)>;
}
condition
fausse
vrai
Séquence A
Exemple :
if (test)
allume();
else
éteint();
Séquence B
//on allume si test different de 0
8
4.1.2 Structure SWITCH … CASE (CHOIX MULTIPLES).
Cette structure permet de choisir entre plusieurs alternatives. Lorsque l’expression située après
le SWITCH coïncide avec une des constantes, le programme exécute la séquence ainsi que les
séquences suivantes. Pour éviter ce désagrément l’instruction break doit être placée à la fin de
chaque séquence.
switch (<expression>)
{
case c1 : <séquence A>;
case c2 : <séquence B>;
case c3 : <séquence C>;
case c4 : <séquence D>;
default : < séquence par défaut >;
}
vrai
Séquence A
Expression
==
c2
vrai
Séquence B
vrai
Séquence C
vrai
Séquence D
Expression
==
c3
Exemple :
Switch (numéro_de_touche)
{
case 1 : lcd_putsf (“Touche n°1”);
break;
case 2 : lcd_putsf (“Touche n°2”);
break;
case 3 : lcd_putsf (“Touche n°3”);
break;
default : lcd_putsf (“Touche erroné”);
}
Expression
==
c1
Expression
==
c4
fausse
Séquence par défaut
//lcd_putsf permet d’envoyer une chaîne de
// caractère vers un afficheur LCD (bibliothèque LCD.h)
4.2 LES STRUCTURES ITERATIVES (REPETITIVES).
4.2.1 La structure WHILE (TANT QUE … FAIRE).
La structure WHILE permet de répéter la
séquence tant que l’expression est vraie.
while (<expression>)
<séquence>;
ou
while (<expression>)
{
<séquence(s)>;
}
Expression
fausse
vraie
Séquence
Exemple :
while (BUSY==0)
{
PORTA =0xaa ;
PORTB = 0X25;
}
9
4.2.2 La structure DO … WHILE (FAIRE …JUSQU'À)
Avec la structure DO … WHILE la séquence est exécutée au moins
une fois, elle est répétée tant que l’expression est vraie.
Séquence
do
<séquence>;
while (<expression>);
Expression
ou
fausse
vraie
do
{
<sequence(s)>;
} while (<expression>);
Exemple :
do
{
PORTA+=1 ; //incrément de 1 de PORTA
PORTB=PORTB+1 ; //incrément de 1 de PORTB
} while (PINC.2==0);
4.2.3 La structure FOR (POUR …FAIRE)
La structure FOR permet de répéter une séquence
tant que l’expression2 est vraie. Elle opère souvent sur
l’expression.
Initialisation
For (<expression1>; <expression2>; <expression3>)
<séquence>;
ou
Expression
For (<expression1>; <expression2>; <expression3>)
{
<séquence>;
}
fausse
vraie
Séquence
Equivalent à :
Opération
<expression1>
While (<expression2>)
{
<séquence>;
<expression3>;
}
Remarque :
For (;;)
//Boucle infinie
Exemples :
For (i=1; i<9 ;i++)
{
PORTA<<=1;
}
10
5. LES FONCTIONS.
5.1 ROLE D’UNE FONCTION.
Le corps d’une fonction est délimité par des accolades { ….. }. Un programme C doit se composer
de plusieurs fonctions pour permettre une meilleure lisibilité et maintenance du programme.
La fonction main () est exécutée en premier, elle gère le bon déroulement du programme et
l'échange des données entres les autres fonctions.
Exemple : Lecture de l'état de huit inters dils branchés sur la port A et affichage du résultat
sur huit leds branchés sur le port C.
#include <90s8515.h>
char valeur;
void init (void);
void lecture (void);
void affiche (void);
void main(void)
{
init();
lecture();
affiche ();
}
#include <90s8515.h>
char valeur;
void main(void)
{
DDRA=0x00;
PORTA=0x00;
DDRC=0x00;
PORTC=0xff;
valeur=PINA;
PORTC=valeur;
}
void init(void)
{
DDRA=0x00;
PORTA=0x00;
DDRC=0x00;
PORTC=0xff;
}
void lecture (void)
{
valeur=PINA;
}
void affiche (void)
{
PORTC=valeur;
}
Le programme est plus long à écrire, le code
généré est plus important (89 mots au lieu de
83 pour l'exemple droite), mais la fonction
main est structurée et gère les appels des
fonctions nécessaires à la réalisation de
notre programme. La tache réalisée par ce
programme est plus lisible et compréhensible
par une tierce personne, ceci facilite et
améliore les opérations de maintenance.
L'écriture est simplifiée, mais la tache
réalisé par le programme est plus difficile à
déterminer. Pour une tache plus compliquée la
lecture du programme par une tierce
personne peut devenir rapidement très
difficile voire impossible.
L'écriture de ce type de programme est donc
à proscrire.
11
5.2 DECLARATION D’UNE FONCTION.
Pour améliorer la lisibilité des programmes toutes les fonctions doivent être déclarées et « typées ».
Si la déclaration est omise le type de la fonction sera de type int.
Chaque fonction peut recevoir ou non des arguments en paramètres, attention à respecter les
types lors des passages d'arguments.
Le mot clé void permet de déclarer une fonction ne renvoie pas de paramètres, il permet aussi de
déclarer qu’une fonction ne reçoit pas d’arguments en paramètres.
5.3 PASSAGE DE PARAMETRES.
Le passage des paramètres peut s’effectuer par valeur ou par adresse.
Lors du passage par valeur, la fonction ayant reçu les arguments en paramètres travaille avec des
copies de ces variables, lors de la sortie de la fonction les variables originelles restent
inchangées.
Lorsque le passage s’effectue par adresse, la fonction travaille directement avec la variable
( la fonction connaît son adresse).
12