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; void main(void) DDRA=0xff; PORTA=0x01; // Déclaration d une variable globale // Fonction principale // Initialisation while (1) // Boucle inconditionnelle for (i=0; i<8; i++) // Structure FOR pour i=0 à i=8 avec un incrément de 1 PORTA= PORTA<<1; // On décale d un bit vers la gauche Tempo(100000); // appel fonction Tempo, passage du paramètre 100000 à l argument // valeur void Tempo (unsigned long valeur) // défnition de la fonction, pas de point virgule! unsigned long j; // Déclaration d une variable locale for (j=0; j<valeur; j++) // 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 Taille (bits) Domaine non signé Domaine signé Bit 1 0,1 Char 8 0 à 255-128 à 127 Int 16 0 à 65535-32768 à 32767 Long int 32 0 à 4294967295-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 20h Registres de travail Registres d entrées sorties 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 = 112 eme 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. Espace de 64 adresses réservé aux fonctions périphériques du microcontrôleur ( Ports, timer.). 60h + Data stack SRAM End 60h 60h + Data stack + var. globales «Data stack» Espace pointeur de pile Variables globales «Hardware stack» 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. 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 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. A cocher si vous utilisez la liaison série 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. 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. Valide la transformation char en type int. Voir exemple n 7 en fin de cours. Déclaration du nombre de variable de type bit, les registres inutilisés sont alloués aux variables globales. 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. 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 Exemple + Addition a + b - Soustraction a - b * Multiplication a * b / Division a / b % Modulo 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 Exemple == Égale à? a == b!= Différent de? a!= b <= Inférieur ou égal à? a <= b >= Supérieur ou égal à? a >= b < Inférieur à? a < b > Supérieur à? a > b 3.4 LES OPERATEURS LOGIQUES. Ces opérateurs permettent de relier logiquement des instructions. Opérateur Fonction Exemple && ET logique a && b OU logique a b! NON logique! 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 Exemple & ET a & b OU a b ^ OU exclusif a ^ b ~ NON ( complément ) ~ a >> Décalage de n bits vers la droite a >> n << Décalage de n bits vers la gauche a << n 7
3.6 LES OPERATEURS D INCREMENTATION ET D AFFECTATION COMBINEE. Opérateur Fonction Exemple Equivalence ++ Incrément de 1 a ++ a = a + 1 -- Décrément de 1 a -- a = a -1 += Addition, résultat dans l opérande de gauche a += b a = a + b -= *= /= %= >>= <<= &= = ^= Soustraction, résultat Multiplication, résultat Division, résultat Modulo, résultat Décalage à droite, résultat Décalage à gauche, résultat ET, résultat OU, résultat OU exclusif, résultat a -= b a *= b a /= b a %= b a >>= n a <<= n a &= b a = b a ^= b a = a - b a = a * b a = a / b a = a % b a = a >> n a = a << n a = a & b a = 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 >; condition fausse ou if (<condition>) <séquence(s)>; else <séquence(s)>; vrai Séquence A Séquence B Exemple : if (test) //on allume si test different de 0 allume(); else éteint(); 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 >; Expression == c1 Expression == c2 vrai vrai Séquence A Séquence B Exemple : Expression == c3 vrai Séquence C 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é ); //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). Expression == c4 fausse vrai Séquence D Séquence par défaut 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 vraie Séquence fausse 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. do <séquence>; while (<expression>); Séquence Expression fausse ou do <sequence(s)>; while (<expression>); vraie 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 For (<expression1>; <expression2>; <expression3>) <séquence>; Expression vraie Séquence fausse Equivalent à : <expression1> While (<expression2>) <séquence>; <expression3>; Remarque : For (;;) //Boucle infinie Exemples : For (i=1; i<9 ;i++) PORTA<<=1; Opération 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