sdcc course

61
Initiation au développement C sur microcontrôleur $Revision: 1153 $ 1 Initiation au développement C sur microcontrôleur Philippe Latu philippe.latu(at)linux-france.org http://www.linux-france.org/prj/embedded/ Historique des versions $Revision: 1153 $ $Date: 2007-06-14 14:25:15 +0200 (jeu, 14 jun 2007) $ $Author: latu $ Année universitaire 2006-2007. Résumé Ce support est une initiation au développement en Langage C sur les systèmes embarqués. Cette version s'appuie sur le microcontrôleur MSC1210 de Texas Instruments. Le support est destiné aux débutants. On présente sommairement l'environnement système, les chaînes de développement, le Langage C et on illustre les applications classiques de ces systèmes spécialisés.Aujourd'hui, la grande majorité des étudiants ont l'habitude d'utiliser des systèmes informatiques sans se poser de questions sur la présence ou non d'un système d'exploitation qui prend en charge la gestion du temps processeur, de la mémoire et des périphériques. Ce document essaie d'illustrer les différences entre les deux contextes d'utilisation avec et sans noyau de système d'exploitation. Le maximum d'exemples de programmes sont présentés dans ces deux contextes. Table des matières 1. Copyright et Licence .............................................................................................................................. 3 1.1. Méta-information ........................................................................................................................ 3 2. Avant Propos ........................................................................................................................................ 4 2.1. C/C++ & Unix ........................................................................................................................... 4 2.2. Programmation procédurale ou orientée objet ................................................................................. 4 2.3. Logiciels libres ........................................................................................................................... 4 3. Développement et Système ..................................................................................................................... 5 3.1. Ordinateur cible avec système d'exploitation .................................................................................. 5 3.2. Ordinateur cible sans système d'exploitation ................................................................................... 7 4. Cycle de développement ......................................................................................................................... 8 5. Un premier programme : «Hello, World!» ................................................................................................ 9 5.1. Codes source .............................................................................................................................. 9 5.2. Compilation & exécution sur Windows XP .................................................................................. 11 5.3. Compilation & exécution sur GNU/Linux .................................................................................... 12 5.4. Compilation sur Windows & exécution sur cible MSC1210 ............................................................ 12 5.5. Compilation sur GNU/Linux & exécution sur cible MSC1210 ........................................................ 15 6. Caractéristiques des microcontrôleurs de la famille MSC12xx ................................................................... 18 7. Éléments de Langage C ........................................................................................................................ 19 7.1. Délimiteurs ............................................................................................................................... 21 7.2. Représentation des données ........................................................................................................ 21 7.3. Types de représentation des données ........................................................................................... 22 7.4. Constantes ................................................................................................................................ 23 7.5. Opérateurs de calcul .................................................................................................................. 25 7.6. Opérateurs relationnels ............................................................................................................... 25 7.7. Opérateurs logiques de bits ........................................................................................................ 25 7.8. Instruction de test if-else ............................................................................................................ 26 7.9. Instructions de choix multiples : switch & if-else-if ....................................................................... 26 7.10. Instructions de boucles : for, while, do-while .............................................................................. 27 7.10.1. Syntaxe de la boucle pour (for) ...................................................................................... 27 7.10.2. Syntaxe de la boucle répéter jusqu'à (do-while) ................................................................ 28 7.10.3. Syntaxe de la boucle tant que (while) .............................................................................. 28 7.11. Sous-programmes .................................................................................................................... 28 8. Entrées et sorties standard : fonctions getchar & putchar ........................................................................... 31

Upload: marmar07

Post on 24-Jun-2015

119 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Sdcc Course

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 1

Initiation au développement C surmicrocontrôleur

Philippe Latuphilippe.latu(at)linux-france.org

http://www.linux-france.org/prj/embedded/

Historique des versions

$Revision: 1153 $ $Date: 2007-06-14 14:25:15 +0200 (jeu, 14 jun 2007) $ $Author: latu $

Année universitaire 2006-2007.

Résumé

Ce support est une initiation au développement en Langage C sur les systèmes embarqués. Cette version s'appuie sur le microcontrôleurMSC1210 de Texas Instruments. Le support est destiné aux débutants. On présente sommairement l'environnement système, leschaînes de développement, le Langage C et on illustre les applications classiques de ces systèmes spécialisés.Aujourd'hui, la grandemajorité des étudiants ont l'habitude d'utiliser des systèmes informatiques sans se poser de questions sur la présence ou non d'unsystème d'exploitation qui prend en charge la gestion du temps processeur, de la mémoire et des périphériques. Ce document essaied'illustrer les différences entre les deux contextes d'utilisation avec et sans noyau de système d'exploitation. Le maximum d'exemples deprogrammes sont présentés dans ces deux contextes.

Table des matières1. Copyright et Licence .............................................................................................................................. 3

1.1. Méta-information ........................................................................................................................ 32. Avant Propos ........................................................................................................................................ 4

2.1. C/C++ & Unix ........................................................................................................................... 42.2. Programmation procédurale ou orientée objet ................................................................................. 42.3. Logiciels libres ........................................................................................................................... 4

3. Développement et Système ..................................................................................................................... 53.1. Ordinateur cible avec système d'exploitation .................................................................................. 53.2. Ordinateur cible sans système d'exploitation ................................................................................... 7

4. Cycle de développement ......................................................................................................................... 85. Un premier programme : «Hello, World!» ................................................................................................ 9

5.1. Codes source .............................................................................................................................. 95.2. Compilation & exécution sur Windows XP .................................................................................. 115.3. Compilation & exécution sur GNU/Linux .................................................................................... 125.4. Compilation sur Windows & exécution sur cible MSC1210 ............................................................ 125.5. Compilation sur GNU/Linux & exécution sur cible MSC1210 ........................................................ 15

6. Caractéristiques des microcontrôleurs de la famille MSC12xx ................................................................... 187. Éléments de Langage C ........................................................................................................................ 19

7.1. Délimiteurs ............................................................................................................................... 217.2. Représentation des données ........................................................................................................ 217.3. Types de représentation des données ........................................................................................... 227.4. Constantes ................................................................................................................................ 237.5. Opérateurs de calcul .................................................................................................................. 257.6. Opérateurs relationnels ............................................................................................................... 257.7. Opérateurs logiques de bits ........................................................................................................ 257.8. Instruction de test if-else ............................................................................................................ 267.9. Instructions de choix multiples : switch & if-else-if ....................................................................... 267.10. Instructions de boucles : for, while, do-while .............................................................................. 27

7.10.1. Syntaxe de la boucle pour (for) ...................................................................................... 277.10.2. Syntaxe de la boucle répéter jusqu'à (do-while) ................................................................ 287.10.3. Syntaxe de la boucle tant que (while) .............................................................................. 28

7.11. Sous-programmes .................................................................................................................... 288. Entrées et sorties standard : fonctions getchar & putchar ........................................................................... 31

Page 2: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 2

8.1. Avec Système d'exploitation ....................................................................................................... 318.2. Sans système d'exploitation & cible MSC1210 .............................................................................. 33

9. Entrées et sorties formatées : fonctions scanf & printf .............................................................................. 359.1. Définitions générales ................................................................................................................. 359.2. Exemple avec GCC ................................................................................................................... 369.3. Exemple avec SDCC sur cible MSC1210 ..................................................................................... 379.4. Utilisation des caractères spéciaux ............................................................................................... 38

10. Gestion d'un afficheur à cristaux liquides (LCD) .................................................................................... 3910.1. Caractéristiques d'un afficheur du type HD44780U ...................................................................... 3910.2. Utilisation d'un afficheur LCD avec SDCC sur cible MSC1210 ..................................................... 39

11. Gestion des entrées/sorties logiques ...................................................................................................... 4311.1. Exemple d'entrées/sorties sur un bit ........................................................................................... 4311.2. Exemple d'entrées/sorties sur plusieurs bits ................................................................................. 45

12. Contraintes de temps sur les sorties numériques ..................................................................................... 4812.1. Temps d'exécution d'une instruction nop .................................................................................... 4812.2. Temps d'exécution d'une temporisation codée en assembleur en ligne ............................................. 4812.3. Temps d'exécution d'une temporisation basée sur une boucle tant-que ............................................ 5012.4. Temps d'exécution d'une temporisation basée sur une boucle pour ................................................. 5112.5. Récapitulatif des temps d'exécution ........................................................................................... 52

13. Outils de développement ..................................................................................................................... 5313.1. C/C++ sur Windows : Dev-Cpp ................................................................................................. 5313.2. C/C++ sur GNU/linux .............................................................................................................. 5313.3. C sur MSC1210 : SDCC .......................................................................................................... 5313.4. Logiciel de programmation de la mémoire Flash du MSC1210 via le port série ................................ 56

14. Codes source ..................................................................................................................................... 5714.1. Sources GNU/GCC .................................................................................................................. 5714.2. Sources MSC1210 ................................................................................................................... 57

15. Documentations de référence ............................................................................................................... 6015.1. Système d'exploitation GNU/Linux ............................................................................................ 6015.2. SDCC - Small Device C Compiler ............................................................................................ 6015.3. Microcontrôleurs MSC12xx ...................................................................................................... 6015.4. Bus I²C .................................................................................................................................. 61

A. En-tête ser_msc1210.h ......................................................................................................................... 61

Page 3: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 3

1. Copyright et LicenceCopyright (c) 2000,2007 Philippe Latu.Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free SoftwareFoundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".

Copyright (c) 2000,2007 Philippe Latu.Permission est accordée de copier, distribuer et/ou modifier cedocument selon les termes de la Licence de Documentation Libre GNU(GNU Free Documentation License), version 1.2 ou toute versionultérieure publiée par la Free Software Foundation ; sansSections Invariables ; sans Texte de Première de Couverture, etsans Texte de Quatrième de Couverture. Une copie dela présente Licence est incluse dans la section intitulée« Licence de Documentation Libre GNU ».

1.1. Méta-information

Cet article est écrit avec DocBook1 XML sur un système Debian GNU/Linux2. Il est disponible en version imprimableaux formats PDF et PostScript : sdcc_course.pdf3| sdcc_course.ps.gz4.

1 http://www.docbook.org2 http://www.debian.org3 http://www.linux-france.org/prj/embedded/telechargement/sdcc_course.pdf4 http://www.linux-france.org/prj/embedded/telechargement/sdcc_course.ps.gz

Page 4: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 4

2. Avant Propos

2.1. C/C++ & Unix

Le système d'exploitation Unix a été conçu au début des années 70. Le Langage C a été développé parallèlement à lamise au point de ce système. Sa première standardisation «de fait» a été publiée dans l'ouvrage de B.W. KERNIGHANet D.M. RITCHIE en 1978.

Même si l'évolution des Langages de programmation C puis C++ est liée à la progression des systèmes Unix, ceslangages sont universellement connus et utilisés. On peut pratiquement affirmer qu'il n'existe pas de plate-formeinformatique actuelle sur laquelle il n'existe pas une chaîne de développement C/C++.

Le Langage C a été conçu pour de multiples utilisations, il n'offre que des structures de programme permettantl'ordonnancement séquentiel, des tests, des boucles et des sous-programmes. Cet aspect, limité en apparence, garantitla «portabilité» des codes sources écrits en C.

Dans le domaine des systèmes embarqués, le C est le langage de programmation le plus répandu. Il convientparfaitement au développement des pilotes de périphériques spécialisés tels que les convertisseurs analogiques/numériques, les capteurs, etc. Les outils de développement modernes possèdent des fonctions d'optimisationperformantes et le recours au langage assembleur est devenu inutile.

2.2. Programmation procédurale ou orientée objet

Jusqu'à la fin des années 80, la seule méthode de programmation utilisable était procédurale ou structurée. Cetteapproche consiste à décomposer un problème complexe en un ensemble de tâches ou «procédures» faciles à réaliser.Les données sont alors choisies en fonction des procédures qui vont les manipuler.

En fait, cette méthodologie convient parfaitement aux logiciels écrits par des informaticiens à l'usage desinformaticiens.

Curieusement, le développement des outils informatiques à l'usage de non spécialistes a considérablement augmentéla complexité des programmes. Ces logiciels de plus en plus sophistiqués ont amené les concepteurs à changer dedémarche. Il est devenu indispensable de penser d'abord aux données et ensuite aux actions que l'on doit réaliser avec.

Un autre aspect très important dans la conception est la réutilisation des développements précédents. Ce principed'héritage permet de construire des composants logiciels avec des propriétés connues que l'on réutilise suivant sesbesoins. De tels composants peuvent même être complétés lors des évolutions des applications.

Si la programmation orientée objet n'est pas largement utilisés dans la mise au point des systèmes embarqués, certains deses concepts ont été repris avec succès. La surdéfinition et l'héritage se retrouvent très souvent dans les développementsd'interfaces spécialisées.

Comme le développement de pilotes de périphériques matériels est une problématique assez éloignée de l'interfaceutilisateur, le recours à la programmation orientée objet reste très limité dans ce domaine. Le noyau Linux est unexemple caractéristique ; il est entièrement développé en Langage C.

2.3. Logiciels libres

Les évolutions des systèmes d'exploitation basés sur les principes d'Unix et des langages de programmation C/C++ sontassociés au développement de l'Internet. Tous ces éléments utilisant un modèle de développement ouvert ont favorisél'émergence des logiciels libres.

De nombreux concepteurs ont produit des bibliothèques d'objets qu'ils ont rendu libres d'utilisation à l'aide de laGeneral Public License5. Cette disponibilité d'outils de très grande qualité a permis à d'autres concepteurs de fournirde nouveaux outils et etc.

5 http://www.gnu.org/philosophy/license-list.html

Page 5: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 5

Ainsi, avec un minimum de coordination, on trouve aujourd'hui des systèmes d'exploitation, des environnementsgraphiques, des chaînes de développement et des suites d'applications de plus en plus performantes.

Les principaux outils utilisés dans le présent document sont issus de projets de logiciels libres. La chaîne dedéveloppement SDCC - Small Device C Compiler6 pour microcontrôleurs en est le meilleur exemple. VoirSection 13.3, « C sur MSC1210 : SDCC ».

3. Développement et SystèmeÀ l'heure actuelle, la majorité des chaînes de développement suivent le modèle initié par les outils GNU au milieu desannées 1980. Les principes sont les suivants.

• Les outils de base comme le compilateur, l'éditeur de liens et le debugger, etc. sont des briques logiciellesindividuelles accessibles au niveau Shell. Ils disposent d'un grand nombre d'options ou de commandes permettantde répondre à pratiquement tous les besoins.

• Ils partagent avec le système d'exploitation de nombreuses bibliothèques telles que la ou bibliothèque standard duLangage C courament appelée libc. Les fonctions ou les appels systèmes fournis par cette bibliothèque sont supportésdepuis plus de 25 ans. Elles ont donc été largement adoptées sur un très grand nombre de systèmes différents.

• Les interfaces de développement sont indépendantes des outils. Les environnements graphiques utilisateurs ne sontque des interfaces facilitant l'utilisation des jeux de commandes des outils GNU. Compte tenu du nombre et de laqualité de ces environnements, les développeurs se «composent» souvent une interface graphique à la carte.

Suivant le contexte de développement, les modes d'exploitation diffèrent. Généralement, on distingue les ordinateurscibles avec système d'exploitation tels que les PCs et les ordinateurs cibles sans système d'exploitation comme lessystèmes embarqués qui utilisent des microcontrôleurs spécialisés.

3.1. Ordinateur cible avec système d'exploitation

Ce contexte correspond aux enseignements «traditionnels» de programmation. L'utilisateur dispose d'une interfacegraphique (voir Section 13.1, « C/C++ sur Windows : Dev-Cpp ») pour éditer, compiler et exécuter les programmes(voir Section 4, « Cycle de développement »).

En règle générale, lorsque le programme est exécuté sur une machine cible avec système d'exploitation, lespériphériques tels que le clavier, l'écran et la souris sont toujours disponibles.

Cette situation «confortable» suppose plusieurs couches intermédiaires de logiciel entre l'utilisateur et le matériel.L'ensemble de ces couches intermédiaires s'appelle un système d'exploitation. L'image ci-dessous représente lescouches constituant un système d'exploitation.

6 http://sdcc.sf.net/

Page 6: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 6

Les couches logicielles d'un système d'exploitation7

BIOS, Basic Input Output SystemCe logiciel ne fait pas vraiment partie du système d'exploitation. À la mise sous tension de l'équipement (PC ouautre), son rôle est de recenser les ressources matérielles disponibles : type de processeur, quantité de mémoire,nombre et type de périphériques de stockage, interfaces réseau, écran, clavier, etc. Une fois l'étape de recensementpassée, les périphériques de stockage sont scrutés un à un à la recherche d'un code particulier qui permet lelancement du système d'exploitation.

Kernel, noyauCe logiciel constitue le coeur du système d'exploitation. Il assure 3 fonctions principales :

La gestion des entrées-sortiesLe noyau intègre ses propres fonctions de recensement des ressources matérielles. Il peut très bien netenir aucun compte des informations fournies par le BIOS. Le noyau doit posséder un pilote pour chaquepériphérique d'entrée-sortie «présent» dans le système.

Un noyau moderne doit aussi gérer l'ajout et le retrait de périphériques en cours de fonctionnement. On parlede branchement «à chaud» ou hotplug.

La gestion des accès mémoireUn système peut intégrer différents types de mémoires dynamiques et le noyau doit gérer ces différentséléments comme un tout cohérent. Les programmes doivent accéder à ce «plan mémoire» de façon transparenteen utilisant des segments alloués en fonction de leurs besoins.

De plus, si le plan mémoire est partagé entre plusieurs programmes, le noyau doit utiliser un algorithmespécifique de planification et de distribution des accès entre ces programmes. On parle alors de système multi-tâches. Linux est un exemple caractéristique de ce type de noyau.

La gestion du temps processeurLe temps du processeur doit être partagé entre les programmes comme le plan mémoire. On découpe donc cetemps processeur en tranches qui sont attribuées aux programmes à la demande.

La fonction correspondante du noyau est appelée ordonnanceur ou scheduler. Sur un système modernedans lequel les temps d'accès aux périphériques et les transmissions réseau sont suffisamment rapides, c'estl'ordonnanceur qui est le «maître» du temps. On peut le comparer à une horloge de réglage du rythme cardiaqued'un système.

Shell

L'interface des commandes utilisateurUn Shell permet à l'utilisateur du système de lancer des programmes ou commandes. On parle de commandelorsqu'il s'agit de «manipuler» le système : lister les fichiers d'un répertoire, afficher la quantité de mémoiredisponible, etc.

Sur les systèmes multi-tâches et multi-utilisateurs tels que GNU/Linux et *BSD, de nombreux Shells peuventêtre actifs en même temps. À l'inverse, sur les systèmes mono-tâches hérités du DOS (Disk Operating System)de Micro$oft™, on ne dispose que d'un Shell unique.

Le séquencement entre le les programmesLorsque plusieurs programmes doivent être exécutés sur un même système, il est fréquent que ces programmeséchangent des paramètres où se lancent en fonction d'actions réalisées par d'autres programmes. Lorsque l'onutilise une interface graphique et que l'on clique sur une fenêtre pour l'activer, on réalise une opération dece type.

ApplicationÀ ce niveau on trouve généralement l'interface graphique utilisateur qui permet de réaliser les manipulationssystème de façon plus intuitives qu'au niveau Shell. À ce gestionnaire de fenêtres sont associées toutes

7 images/os.png

Page 7: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 7

les applications usuelles d'un système généraliste : navigation Web, traitement de textes, Environnement dedéveloppement intégré (comme Section 13.1, « C/C++ sur Windows : Dev-Cpp »), etc.

C'est aussi à ce niveau que les programmes développés par nos soins sont exécutés.

3.2. Ordinateur cible sans système d'exploitation

Ce contexte correspond aux enseignements pratiques d'informatique industrielle. Si l'utilisateur dispose d'une interfacegraphique de développement intégrée, le logiciel développé doit être exécuté sur un système spécialisé. On parle desystème embarqué dédié à la réalisation de fonctions spécifiques. Il est rare que ces systèmes disposent d'un écran etd'un clavier.

Contrairement à la situation précédente avec système d'exploitation, les conditions de développement sont moins«confortables». Ceci-dit, comme le nombre de couches logicielles est nettement réduit, la description est plus simple.

Les couches logicielles d'un système embarqué simple8

Le moniteurLe seul point commun entre le moniteur et le BIOS se situe au niveau du lancement de programme. Là où le BIOSidentifie le code de lancement du système sur le premier secteur d'un périphérique, le moniteur identifie l'adressede lancement d'une application dans le plan mémoire du microcontrôleur.

Sur un système spécialisé avec microcontrôleur, la configuration matérielle est figée. Il est donc totalement inutilede procéder à un recensement des ressources du système.

Le premier rôle d'un moniteur est d'assurer le téléchargement des programmes entre le système de développement(généralement un PC) et le système spécialisé (le microcontrôleur). Ce téléchargement est réalisé à l'aide uneliaison série ou réseau.

Les microcontrôleurs récents intègrent en plus du moniteur un ensemble de sous-programmes (routines) qui offrentdes fonctions simples de pilotage de périphériques et de manipulations de la mémoire intégrée au composant.

ApplicationÀ ce niveau le microcontrôleur exécute le ou les programme(s) utilisateur. Comme on n'utilise pas de noyau, lesprogrammes utilisateur doivent intégrer directement le pilotage des périphériques : liaison série, affichage LCD,conversion analogique/numérique, capteurs, etc.

8 images/eos.png

Page 8: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 8

4. Cycle de développementSi tous les programmes que vous avez à écrire fonctionnaient parfaitement du premier coup le cycle de développementse résumerait aux 3 étapes suivantes :

1. Écrire le code source,2. le compiler,3. lancer le programme.

Malheureusement, quelque soit le programme et quelque soit le niveau d'expérience en programmation, on rencontretoujours des erreurs à chacune des étapes énoncées ci-dessus. Le cycle de développement devient alors le suivant :

Synoptique du cycle de développement9

9 images/dev-cycle.png

Page 9: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 9

5. Un premier programme : «Hello, World!»Pour illustrer les contextes et le cycle de développement présentés ci-avant, on prend un premier exemple de programmetrès connu : afficher «Hello, World!» à l'écran.

La «mise au point» de ce programme simpliste sert aussi à prendre en main les outils de la chaîne de développement.

5.1. Codes source

Voici le code source du premier programme hello.c sous sa forme «usuelle».

Exemple 1. Affichage de la chaîne «Hello, World!» sur GNU/Linux avec GCC

#include <stdio.h> ❶

int main() { ❷

printf ("Hello, World!\n"); ❸ return 0; ❹}

❶ #include <stdio.h> : inclusion des prototypes de sous-programmes de la bibliothèque standard d'entrée-sortie (stdio ou standard input output).

D'une manière générale, pour que l'on puisse utiliser les fonctions d'une bibliothèque, il faut que les prototypes(ou en-têtes) de ces fonctions soient parcourus par le pré-processeur (voir Section 4, « Cycle de développement »).Si cette condition est satisfaite, le pré-processeur «connaît» la liste des paramètres possibles d'une fonction etleurs types. Il peut ensuite contrôler que les appels à ces fonctions sont conformes.

Cet exemple de programme utilise la fonction printf qui appartient à la bibliothèque stdio.❷ int main() { : début du programme principal.

En C, le programme principal peut être assimilé à une «fonction comme les autres» à qui on peut passer desparamètres (entre les parenthèses) depuis le Shell et qui renvoie à ce même Shell une indication sur ses conditionsd'exécution (un nombre entier).

L'accolade '{' est le délimiteur de début des instructions du programme principal.❸ printf ("Hello, World!\n"); : appel de la fonction printf de la bibliothèque standard d'entrée-sortie.

Une chaîne de caractères est délimitée par des guillemets et les caractères spécifiques sont précédés par '\'. Onparle de caractères d'échappement. Dans cet exemple, '\n' correspond au saut de ligne.

Les instructions sont séparées par le caractère ';'.❹ return 0; : valeur renvoyée au système d'exploitation (via le Shell) en fin de programme.

La valeur 0 correspond à une sortie «sans erreur» du programme.

Cette instruction n'a de sens que lorsque le programme est exécuté via un système d'exploitation avec lequel ilest possible d'échanger des informations.

Voici le code source du même premier programme ser_hello.c sous sa forme «embarquée». Le code n'est pas aussisimple que dans le cas précédent. Comme indiqué dans la Section 3.2, « Ordinateur cible sans système d'exploitation »on ne dispose pas de noyau dans ce contexte. Le programme doit donc intégrer le pilotage du périphérique d'affichage.Ici, il s'agit de la liaison série qui est utilisée pour «l'affichage» de la chaîne «Hello, World!».

Page 10: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 10

Environnement de développement sur système embarqué10

Avec le synoptique ci-dessus, on développe (voir Section 4, « Cycle de développement ») le programme sur le PC. Unefois que l'on a obtenu le fichier contenant le code exécutable du programme, on le transfère via la liaison série à l'aidedu moniteur. Enfin, après avoir réinitialisé le microcontrôleur en mode exécution, le programme utilisateur est lancé.

En mode exécution, le programme utilisateur peut piloter la liaison série de façon complètement autonome si on luifournit les sous-programmes nécessaires. C'est le cas de l'exemple de code source ci-dessous.Exemple 2. Affichage de la chaîne «Hello, World!» avec un microcontrôleur MSC1210 & SDCC

#include <stdio.h> ❶#include <msc1210.h>#include "ser_msc1210.h"

// (sur)définition du sous-programme putchar utilisé par printfvoid putchar(char c) { ❷ ser_putc(c); }

void main(void) { ❸

// Appuyer sur <Entrée> pour ajuster automatiquement // le débit de la liaison autobaud(); ❹

// Initialisations pour SDCC EA=1;

// Affichage sur le terminal printf("Hello, World!"); ❺ putcr();

while(1); ❻}

❶ Comme indiqué dans le premier cas, les directives #include servent à inclure des définitions pour le pré-processeur. Dans le cas présent, 3 fichiers de définitions sont utilisés.

• stdio.h : fichier d'en-tête contenant les prototypes des fonctions d'entrées-sorties standard. Si ce fichierporte le même nom que celui donné dans le premier fichier source, le catalogue des sous-programmes mis àdisposition sur un microcontrôleur est nettement réduit relativement au cas général d'une machine avec systèmed'exploitation.

Dans le cas présent, ce fichier fournit le prototype de la fonction printf utilisée pour émettre la chaîne decaractères depuis le microcontrôleur sur la liaison série.

• msc1210.h : fichier d'en-tête contenant les définitions des registres des microcontrôleurs de la familleMSC12xx.

10 images/no_os_dev.png

Page 11: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 11

• ser_msc1210.h : fichier d'en-tête contenant les prototypes des sous-programmes intégrés dans la mémoireROM du composant microcontrôleur. Dans cet exemple, ce sont les fonctions de pilotage de la liaison sériequi sont utiles : autobaud et ser_putc.

Le fait que ce fichier soit noté «entre guillemets» indique qu'il s'agit d'un fichier local qui n'est pas fourni avecla chaîne de développement. Voir le fichier ser_msc1210.h et la documentation MSC1210 ROM Routines surces fonctions intégrées.

❷ void putchar(char c); : surdéfinition de la fonction d'affichage d'un caractère.

Cette fonction fait «normalement» partie de la bibliothèque standard et son rôle est d'envoyer un caractère àl'écran. Dans le cas présent, on utilise une nouvelle définition de cette fonction. Son rôle est maintenant d'envoyerle caractère sur la liaison série. La fonction tx_byte fait partie de la bibliothèque intégrée du microcontrôleur.Sa définition est donnée dans le fichier d'en-tête rom1210.h. Voir MSC1210 ROM Routines.

Le mot clé void signifie que la fonction ne renvoie aucun paramètre. Le paramètre d'entrée c est défini commeétant de type caractère (représenté sur un octet) par le mot clé char. Voir Section 7.3, « Types de représentationdes données »

❸ void main(void) { : début du programme principal.

Par différence avec le premier programme, on constate avec l'emploi des mots clé void qu'aucun paramètren'est passé en entrée et qu'aucun paramètre n'est renvoyé en sortie. Ce codage est tout à fait normal dans uncontexte sans système d'exploitation. Ce programme sera le seul exécuté sur le microcontrôleur. Il n'aura doncpas à échanger avec un autre logiciel.

❹ autobaud(); : appel de la fonction de détection automatique du débit sur la liaison série.

Cette fonction est très pratique. Le programme reste en attente d'un appui sur la touche <Entrée> du système dedéveloppement (le PC) pour déterminer le débit de transmission en bauds. Sans cette «attente», le programme selancerait directement après le reset du microcontrôleur ce qui est trop rapide si des manipulation sont à effectuermanuellement sur le système embarqué.

❺ printf("Hello World !"); : appel de la fonction printf.

Cet appel de fonction se présente comme dans le cas du premier programme excepté pour le traitement du sautde ligne en fin de chaîne de caractères. Avec la liaison série, on est obligé d'envoyer deux caractères spécifiques :'\r' (retour chariot ou Carriage Return ou CR) pour renvoyer le curseur en début de ligne et '\n' (saut deligne ou Line Feed ou LF) pour descendre le curseur d'une ligne. Cette opération est réalisée par l'appel à lafonction putcr().

❻ while(1); : boucle «d'attente» infinie.

Comme le programme est la seule application en cours d'exécution sur le microcontrôleur, et qu'il n'y a plusd'opération à effectuer, on place le processeur dans un état d'attente infinie grâce à cette instruction de bouclage.C'est une technique usuelle qui permet de s'assurer que le processeur ne cherche pas à interpréter le contenu dela mémoire située après l'application utilisateur comme un programme.

5.2. Compilation & exécution sur Windows XP

Ce contexte est décrit dans la Section 3.1, « Ordinateur cible avec système d'exploitation ».

On distingue deux familles de systèmes d'exploitation : Windows et GNU/Linux.

Page 12: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 12

Copie d'écran Dev-Cpp & exécution Hello, World!11

Pour que le résultat de l'exécution du programme soit «visible», on a ajouté l'instruction system("pause"); quidemande à l'utilisateur d'appuyer sur une touche. Sans cette instruction, le Shell serait refermé dès la fin de l'exécutiondu programme et le message ne serait pas visible.

5.3. Compilation & exécution sur GNU/LinuxLes outils de la chaîne de développement sont installés par défaut avec le système d'exploitation. On peut donc appelerdirectement le compilateur gcc (voir Section 13.2, « C/C++ sur GNU/linux ».phil@b0x:~/src$ cat hello.c#include <stdio.h>

int main() {

printf ("Hello, World!\n"); return 0;}

phil@b0x:~/src$ gcc hello.cphil@b0x:~/src$ ./a.outHello, World!phil@b0x:~/src$

Dans ce contexte, on commence par ouvrir un nouveau Shell dans lequel on effectue toutes les opérations individuelles :édition du code source, compilation et exécution.

5.4. Compilation sur Windows & exécution sur cible MSC1210Ici, les programmes sont développés sur un PC et exécutés sur la machine cible. C'est le contexte décrit dans laSection 3.2, « Ordinateur cible sans système d'exploitation ».

Pour l'exemple de programme retenu, on choisit d'afficher la chaîne de caractères sur le terminal du système dedéveloppement (ie. le PC) via une liaison série.

Outils de développementPour que la chaîne de développement SDCC soit plus facile à utiliser sur un système d'exploitation Microsoft™,il est vivement conseillé de reconstituer un environnement de travail GNU/Linux-like à l'aide des outils Cygwin12.

11 images/xp.hello.png12 http://www.cygwin.com/

Page 13: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 13

Une fois les outils Cygwin13 installés, on dispose d'un shell Bash14 et surtout de l'application de contrôle ducompilateur make15 qui permet de gérer les dépendances entre les différents fichiers sources et en-têtes.

Après avoir travaillé avec ces outils pendant «un certain temps», il ne restera plus qu'une dernière étape à franchir :abandonner le système Microsoft™ GNU/Linux-like au profit d'un véritable système GNU/Linux.

Compilation avec Windows XPOn appelle le compilateur SDCC à partir d'une console.

Copie d'écran compilation hello.c sur Windows XP avec SDCC16

Le fichier ser_hello.ihx contient le code exécutable du programme au format Intel Hex. Il s'agit d'un formattexte ASCII de représentation du code machine du microcontrôleur utilisé pour le transfert du système dedéveloppement vers le système cible.

Le fichier ser_hello.asm contient le code source du programme en langage assembleur. Une lecture rapide dece fichier montre que les fonctions d'optimisation du compilateur ont été efficaces.

Utilisation d'un MakefilePour faciliter les développements de programmes «plus complets» que cet exemple, un patron de Makefile estfourni avec les fichiers sources distribués avec ce document : Makefile.

Pour démarrer un nouveau développement, il suffit de copier ce patron dans un nouveau répertoire et d'affecter àla variable BASENAME le nom du nouveau fichier source en langage C.

Ce patron de Makefile suppose que l'on utilise systématiquement la liaison série comme interface utilisateur. Il faitdonc référence au fichiers sources et en-têtes qui permettent d'utiliser cette liaison série. Ces fichiers sont aussiprésentés dans ce document à la Section 14.2, « Sources MSC1210 ».

Transfert du programme avec Windows XPTexas Instruments™ fournit un logiciel appelé TIDownloader qui pilote la liaison série entre le PC et le systèmeembarqué. Ce logiciel sert à la fois au transfert du code du programme et aux tests d'exécution avec son terminal.Il est téléchargeable à l'adresse : Software for Programming the Flash Memory Using the Serial Port v1.3.4 (Rev.C) (sbac018c.zip, 2381 KB )17.

Il faut positionner l'interrupteur «vers le haut» pour accéder au moniteur intégré du microcontrôleur. Après unappui sur le bouton Reset, les opérations de transfert peuvent débuter.

13 http://www.cygwin.com/14 http://fr.wikipedia.org/wiki/Bash15 http://fr.wikipedia.org/wiki/Make16 images/sdcc.xp.hello.png17 http://www.ti.com/litv/zip/sbac018c

Page 14: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 14

Sélection du fichier ser_hello.ihx18

Paramétrage de la liaison série pour le transfert19

18 images/tidownload-select.png19 images/tidownload-setup.png

Page 15: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 15

Transfert du code du programme vers le système cible20

Exécution du programme depuis Windows XPUne fois le transfert achevé, on positionne l'interrupteur «vers le bas» et on appuie sur le bouton Reset pour lancerle programme.

Exécution du programme21

5.5. Compilation sur GNU/Linux & exécution sur cible MSC1210

Ce contexte est identique au précédent. Les programmes sont développés sur une machine avec un système GNU/Linuxet exécutés sur le microcontrôleur du système cible. Ces conditions sont décrites dans la Section 3.2, « Ordinateur ciblesans système d'exploitation ».

Relativement à la section précédente, il est inutile d'installer des outils supplémentaires pour mettre en oeuvre la chaînede développement SDCC puisque les applications telles que le shell bash et make sont systématiquement fournies avecles distributions GNU/Linux.

20 images/tidownload-upload.png21 images/tidownload-run.png

Page 16: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 16

Pour l'exemple de programme retenu, on choisit d'afficher la chaîne de caractères sur le terminal du système dedéveloppement (ie. le PC) via une liaison série.

Compilation avec GNU/LinuxL'appel du compilateur est identique entre les deux systèmes. Les formats de fichiers sont aussi identiques. Le codeexécutable du programme est contenu dans le fichier ser_hello.ihx.

$ sdcc ser_hello.c

$ lltotal 144K-rw-r--r-- 1 phil phil 8.4K Apr 19 22:19 ser_hello.asm-rw-r--r-- 1 phil phil 466 Apr 18 21:38 ser_hello.c-rw-r--r-- 1 phil phil 12K Apr 19 22:19 ser_hello.ihx-rw-r--r-- 1 phil phil 193 Apr 19 22:19 ser_hello.lnk-rw-r--r-- 1 phil phil 22K Apr 19 22:19 ser_hello.lst-rw-r--r-- 1 phil phil 14K Apr 19 22:19 ser_hello.map-rw-r--r-- 1 phil phil 1.1K Apr 19 22:19 ser_hello.mem-rw-r--r-- 1 phil phil 3.7K Apr 19 22:19 ser_hello.rel-rw-r--r-- 1 phil phil 22K Apr 19 22:19 ser_hello.rst-rw-r--r-- 1 phil phil 37K Apr 19 22:19 ser_hello.sym

Utilisation d'un MakefilePour faciliter les développements de programmes «plus complets» que cet exemple, un patron de Makefile estfourni avec les fichiers sources distribués avec ce document : Makefile.

Pour démarrer un nouveau développement, il suffit de copier ce patron dans un nouveau répertoire et d'affecter àla variable BASENAME le nom du nouveau fichier source en langage C.

Ce patron de Makefile suppose que l'on utilise systématiquement la liaison série comme interface utilisateur. Il faitdonc référence au fichiers sources et en-têtes qui permettent d'utiliser cette liaison série. Ces fichiers sont aussiprésentés dans ce document à la Section 14.2, « Sources MSC1210 ».

Transfert du programme avec GNU/LinuxPour effectuer le transfert de fichier en mode ASCII entre le PC de développement et le microcontrôleur, on utiliseune application appelée minicom sur les systèmes GNU/Linux.

À partir d'un Shell, on appelle minicom avec les options :• -o pour désactiver le dialogue Hayes entre les équipements connectés sur la liaison série.• -8 pour pouvoir utiliser les codes ASCII sur 8 bits.

$ minicom -o -m -8

Le paramétrage de la liaison se fait avec les options suivantes :

A - Serial Device : /dev/ttyS0B - Lockfile Location : /var/lockC - Callin Program :D - Callout Program :E - Bps/Par/Bits : 19200 8N1F - Hardware Flow Control : NoG - Software Flow Control : No

Il est important de désactiver le contrôle matériel de flux pour que la fonction de détection automatique du débitpuisse s'exécuter normalement.

Il faut positionner l'interrupteur «vers le haut» pour accéder au moniteur intégré du microcontrôleur. Après unappui sur le bouton Reset, on doit obtenir l'invite de commande suivante :

MSC1210 Ver:000305F10>

Page 17: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 17

Il faut effacer le contenu de la mémoire du microcontrôleur avant de procéder au transfert. La séquence à saisirest la suivante :>M0000 ok>M8000 ok>E>L

On peut ensuite lancer le transfert de fichier en mode ASCII après avoir sélectionné le fichier ser_hello.ihx :+---------[ascii upload - Press CTRL-C to quit]---------+|.......................................................||7.8 Kbytes transferred at 1991 CPS.....................||.......................................................||.......................................................||11.5 Kbytes transferred at 1962 CPS... Done. || || READY: press any key to continue...

Exécution du programme depuis GNU/LinuxUne fois le transfert achevé, on positionne l'interrupteur «vers le bas» et on appuie sur le bouton Reset pour lancerle programme.

On obtient alors un affichage de la chaîne de caractères «tant attendue» sur le terminal du PC de développement.MSC1210 Ver:000305F10>M0000 ok>M8000 ok>E>T>>Hello World !

Page 18: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 18

6. Caractéristiques des microcontrôleurs de la famille MSC12xxLes composants de la famille MSC12xx reprennent les caractéristiques usuelles d'un microcontrôleur :

• des fonctions de conversion analogique numérique,• un coeur «amélioré» de la famille Intel™ MCS51,• de la mémoire de type RAM et de type FLASH,• des périphériques logiques performants.

Le coeur MCS51 «amélioré» comprend deux pointeurs de données et exécute la plupart des instructions trois fois plusvite qu'un coeur 8051 standard. Avec une vitesse d'exécution plus grande, ce composant est utilisable avec un grandnombre d'applications qui réclament des performances en fréquence.

La liste des documents de référence sur cette famille de microcontrôleurs est donnée à la Section 15.3,« Microcontrôleurs MSC12xx ».

Page 19: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 19

7. Éléments de Langage CCette section présente succinctement les éléments essentiels du Langage C en donnant un maximum d'exemples adaptésau développement sur système spécialisé.

On utilise un exemple de programme presque aussi connu que le très fameux «Hello, World!» ; le calcul des nombresde Fibonacci. On commence par présenter le listing complet, puis on détaille les éléments de la syntaxe du Langage C.

Le même programme est présenté sous plusieurs formes différentes en fonction du contexte de développement.

Exemple 3. Calcul des nombres de Fibonacci sur GNU/Linux avec GCC

01: /* $Id: gcc_fibonacci_single.c 1129 2007-05-07 15:07:52Z latu $02: * Un programme simple pour calculer les n premiers nombres de Fibonacci */03: 04: #include <stdio.h>05: #include <stdlib.h>06: 07: #define MAX_FIB 4908: 09: main() {10: 11: int n, i;12: unsigned int nombrePrecedent, nombreCourant, fibonacci;13: 14: 15: printf("Saisir le nombre de calculs de Fibonacci(n) :\n"); 16: scanf("%d", &n);17: if (n >= MAX_FIB) {18: printf("Fibonacci(%d) depasse la capacite d'un mot de 32 bits\n", n); 19: exit(1);20: }21: 22: nombrePrecedent = 0;23: nombreCourant = 1;24: for (i = 0; i < n; i++) {25: if (i > 1) {26: fibonacci = nombrePrecedent + nombreCourant;27: nombrePrecedent = nombreCourant;28: nombreCourant = fibonacci;29: printf("Fibonacci (%d) = %u\n", i, fibonacci);30: }31: else32: printf("Fibonacci (%d) = %u\n", i, i);33: }34: }

Voici un exemple d'exécution du programme gcc_fibonacci_single.c :

$ ./gcc_fibonacci_single.outSaisir le nombre de calculs de Fibonacci(n) :11Fibonacci (0) = 0Fibonacci (1) = 1Fibonacci (2) = 1Fibonacci (3) = 2Fibonacci (4) = 3Fibonacci (5) = 5Fibonacci (6) = 8Fibonacci (7) = 13Fibonacci (8) = 21Fibonacci (9) = 34

Page 20: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 20

Fibonacci (10) = 55

Comme dans le cas du premier programme présenté, le code source du programme destiné au microcontrôleurMSC1210 inclut le pilotage de l'interface série. Dans ce contexte de développement, on ne dispose pas de systèmed'exploitation.Exemple 4. Calcul des nombres de Fibonacci sur microcontrôleur MSC1210 avec SDCC

01: #include <stdio.h>02: #include <stdlib.h>03: #include <msc1210.h>04: #include "ser_msc1210.h"05: 06: #define MAX_FIB 4907: 08: // surdefinition du sous-programme putchar09: void putchar(char c) {10: ser_putc(c);11: }12: 13: void main(void) {14: 15: unsigned char s[3] = {'\0','\0','\0'};16: int n, i;17: unsigned long nombrePrecedent, nombreCourant, fibonacci;18: 19: // Appuyer sur <Entree> pour ajuster automatiquement20: // le debit de la liaison21: autobaud();22: EA=1;23: 24: do {25: printf("Saisir le nombre de calculs de Fibonacci :\r\n");26: ser_gets_echo(s, 2);27: n = atoi(s);28: if (n >= MAX_FIB)29: printf("\nFibonacci(%d) depasse la capacite d'un mot de 32 bits\r\n", n);30: } while (n >= MAX_FIB);31: 32: printf("\r\n\n");33: nombrePrecedent = 0;34: nombreCourant = 1;35: for (i = 0; i < n; i++) {36: if (i > 1) {37: fibonacci = nombrePrecedent + nombreCourant;38: nombrePrecedent = nombreCourant;39: nombreCourant = fibonacci;40: printf("Fibonacci (%d) = %lu\r\n", i, fibonacci);41: }42: else43: printf("Fibonacci (%d) = %d\r\n", i, i);44: }45: while(1);46: }

Voici un exemple de résultat d'exécution du programme sdcc_fibonacci_single.c :MSC1210 Ver:000305F10>M0000 ok>M8000 ok>E>Saisir le nombre de calculs de Fibonacci :11

Page 21: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 21

Fibonacci (0) = 0Fibonacci (1) = 1Fibonacci (2) = 1Fibonacci (3) = 2Fibonacci (4) = 3Fibonacci (5) = 5Fibonacci (6) = 8Fibonacci (7) = 13Fibonacci (8) = 21Fibonacci (9) = 34Fibonacci (10) = 55

7.1. DélimiteursGénéralités sur les délimiteurs de syntaxe du Langage C des exemples ci-dessus :

Les commentairesIls sont repérés par deux slashes (//) si le texte du commentaire ne comprend qu'une seule ligne. Ils sont délimitésentre les balises /* et */ si le texte du commentaire comprend plusieurs lignes.• Exemple 3, « Calcul des nombres de Fibonacci sur GNU/Linux avec GCC » : les lignes 1 et 2 correspondent

à un même commentaire.• Exemple 4, « Calcul des nombres de Fibonacci sur microcontrôleur MSC1210 avec SDCC » : les lignes 8, 19

et 20 sont des commentaires sur une ligne unique.

Les directives du préprocesseurElles sont repérées par le caractère dièse en début de ligne : #include <stdio.h> #define TRUE 1

Ces directives ne sont pas considérées comme faisant partie du code. Elles ne sont donc pas délimitées commedes instructions «classiques».• Exemple 3, « Calcul des nombres de Fibonacci sur GNU/Linux avec GCC » : lignes 4, 5 et 7.• Exemple 4, « Calcul des nombres de Fibonacci sur microcontrôleur MSC1210 avec SDCC » : lignes 1 à 4 puis 6.

Les instructionsElles sont séparées par le caractère point-virgule : printf ("Hello,"); printf (" World!");

Dans les deux exemples de référence ci-dessus, on relève que toutes les instructions (déclarations de variables,opérations, etc.) sont délimitées par des caractères ';' à l'exception des directives du préprocesseur.

Les groupes d'instructionsIls sont délimités par les caractères accolades ouvertes et fermées : while(1) { printf ("Hello,"); printf (" World!"); }

• Exemple 3, « Calcul des nombres de Fibonacci sur GNU/Linux avec GCC » : les lignes 9 et 34 contiennent lesaccolades qui délimitent le début et la fin du programme principal.

• Exemple 4, « Calcul des nombres de Fibonacci sur microcontrôleur MSC1210 avec SDCC » : les lignes 24 et 30délimitent le groupe d'instructions qui doivent être répétées tant que le test (n >= MAX_FIB) n'est pas satisfait.

7.2. Représentation des donnéesEn programmation, les données manipulées sont appelées variables ou constantes.

Une variable sert au stockage d'une information en vue de sa réutilisation dans le programme principal et|ou un sous-programme.

Page 22: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 22

Du point de vue gestion de la mémoire (RAM ou Random Access Memory), une variable est une zone mémoire réservéeet «étiquetée» avec le nom de cette variable.

Sur une machine avec système d'exploitation, la phase de déclaration d'une variable correspond à une demande deréservation mémoire au gestionnaire de mémoire virtuelle du noyau. Ce gestionnaire doit gérer au mieux ces demandesen fonction des programmes actifs sur le système.

Sur un système spécialisé, c'est au développeur de gérer «manuellement» son espace mémoire. Il n'existe aucuneprotection contre le débordement de la capacité mémoire.

Du point de vue syntaxique, il existe certaines restrictions dans l'emploi des noms de variables et de constantes. Lescaractères de ponctuation ne sont pas utilisables. Le caractère «souligné» (underscore) est considéré comme une lettre ;il est beaucoup utilisé par le préprocesseur.

Avertissement

En Langage C, les majuscules et les minuscules sont traitées différemment. On utilise généralement lesmajuscules pour les définitions de constantes et les minuscules pour les variables.

Suivant la génération du compilateur utilisé, le nombre de caractère pris en compte pour les noms de variables estplus ou moins limité. Historiquement, cette limite était fixée à 8 bien que l'on puisse en utiliser davantage dans lecode source.

Dans les deux exemples ci-dessus, on trouve les déclarations des variables après l'accolade de début de programmeprincipal (fonction main()).

• Exemple 3, « Calcul des nombres de Fibonacci sur GNU/Linux avec GCC » : lignes 11 et 12.• Exemple 4, « Calcul des nombres de Fibonacci sur microcontrôleur MSC1210 avec SDCC » : lignes 15 à 17.

7.3. Types de représentation des données

Pour représenter les données à manipuler on distingue différents types élémentaires définis dans la syntaxe du langagede programmation. La table ci-dessous donne une liste complète de ces types.

Tableau 1. Types élémentaires du Langage C

Type de donnée syntaxe C

rien ou vide void

caractère char

nombre entier court short

nombre entier int

nombre entier long long

nombre entier longdouble

long long

nombre réel float

nombre réel double double

nombre réel longdouble

long double

À la lecture de la table ci-dessus, on constate que le langage C n'offre pas de type booléen. Pour autant, la valeur entière0 correspond à l'état faux et toutes les autres valeurs entières correspondent à l'état vrai. La technique usuelle pourreprésenter les deux états booléens consiste à définir deux constantes. Voir Section 7.4, « Constantes ».

Page 23: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 23

En Langage C, si les noms de types sont toujours les mêmes, leurs formats diffèrent suivant les chaînes dedéveloppement et les processeurs utilisés. Les deux exemples ci-dessous illustrent ces différences.

Dans le cas de la chaîne de développement GNU utilisée sur PC, il est possible de représenter de très grands nombresréels sur 12 octets soit 96 bits. À l'inverse, il n'est pas possible de représenter une donnée sur moins d'un octet.

Voici le résultat d'un programme utilisant la fonction sizeof pour chacun des types donnés dans la liste ci-dessus. Lecode source de ce programme est disponible à l'adresse : gcc_sizeof.tar.bz222.Exemple 5. Formats des types supportés par GCC

Dimension de chaque type en octets :'char' : 1'unsigned char' : 1'short' : 2'int' : 4'long' : 4'long long' : 8'float' : 4'double' : 8'long double' : 12

Dans le cas du compilateur SDCC et du microcontrôleur cible MSC1210, il n'est pas possible d'utiliser des nombresréels au delà de la représentation simple sur 4 octets. La plus petite unité représentée est le bit même si l'appel à lafonction sizeof pour ce type produit un résultat surprenant 1 octet pour 1 bit.

Comme avec la chaîne de développement GNU/GCC, voici le résultat d'un programme utilisant la fonction sizeofpour chacun des types donnés dans la liste ci-dessus. Le code source de ce programme est disponible à l'adresse :sdcc_sizeof.tar.bz223.Exemple 6. Formats des types supportés par SDCC

>Dimension de chaque type en octets :'char' : 1'unsigned char' : 1'short' : 2'int' : 2'long' : 4'long long' : 4'float' : 4Attention ! le type bit existe :'bit' : 1

• Exemple 3, « Calcul des nombres de Fibonacci sur GNU/Linux avec GCC » : lignes 11 et 12. Ce programme estlimité au calcul des nombres de Fibonacci qui ne dépassent pas la capacité d'un entier représenté sur 32 bits (soit 4octets). On utilise donc le type int dans le code source du programme.

• Exemple 4, « Calcul des nombres de Fibonacci sur microcontrôleur MSC1210 avec SDCC » : ligne 16 et 17. Ceprogramme est aussi limité à une représentation des nombres entiers sur 32 bits. Avec le compilateur SDCC, c'estle type long qui est utilisé dans le code source du programme pour répondre au critère de calcul.

7.4. Constantes

Une constante est une valeur particulière que l'on utilise tout au long du programme. Si cette valeur doit être modifiée,il est préférable de n'avoir qu'une seule ligne à éditer. En terme de maintenabilité du code source, l'utilisation deconstantes est très avantageux. De plus, l'utilisation d'une représentation littérale d'une valeur numérique particulièrepermet de gagner en lisibilité.

En informatique industrielle, on fait un usage «massif» des constantes. En effet tous les registres et les adresses depilotage des périphériques spécialisés sont représentés à l'aide de constantes. Si ce mode de représentation n'existait

22 http://www.linux-france.org/prj/embedded/sources/gcc_sizeof.tar.bz223 http://www.linux-france.org/prj/embedded/sources/sdcc_sizeof.tar.bz2

Page 24: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 24

pas, on ne pourrait utiliser que des valeurs hexadécimales. Les difficultés de développement des programmes seraientbeaucoup plus importantes du fait des confusions possibles entre des valeurs voisines.

En Langage C, les constantes sont en fait des directives destinées au préprocesseur. En effet, comme le rôle dupréprocesseur est d'analyser la syntaxe du code source d'un programme, il peut se charger de substituer toutes lesoccurrences des constantes par leurs valeurs numériques avant de passer à la compilation proprement dite.

Cette technique est très avantageuse puisque l'utilisation des constante ne nécessite aucune réservation en mémoire.

Les deux exemples de programmes montrent la même constante MAX_FIB déclarée à l'aide de la directive #define.Cette constante correspond aux rang maximum du nombre de Fibonacci que l'on peut représenter sur 32 bits.

Avertissement

Il faut noter qu'une directive de préprocesseur n'est pas instruction du langage C. C'est la raison pourlaquelle on n'utilise pas le caractère ';' comme délimiteur. Cette absence de délimitation ne pose pas dedifficulté dans la mesure où on ne peut trouver qu'une directive par ligne.

• Exemple 3, « Calcul des nombres de Fibonacci sur GNU/Linux avec GCC » : ligne 7.• Exemple 4, « Calcul des nombres de Fibonacci sur microcontrôleur MSC1210 avec SDCC » : ligne 6.

Dans les exemples «rituels» de définition de constantes on trouve les deux états booléens :#define FALSE 0#define TRUE 1

Le fichier d'en-tête standard limits.h est un exemple caractéristique de liste de définitions de constantes. Ce fichiercontient les définitions des valeurs entières maximales pour chaque type connu. Voici un extrait du fichier fourni avecla chaîne GNU/GCC :/* Number of bits in a `char'. */# define CHAR_BIT 8

/* Minimum and maximum values a `signed char' can hold. */# define SCHAR_MIN (-128)# define SCHAR_MAX 127

/* Maximum value an `unsigned char' can hold. (Minimum is 0.) */# define UCHAR_MAX 255

/* Minimum and maximum values a `char' can hold. */# ifdef __CHAR_UNSIGNED__# define CHAR_MIN 0# define CHAR_MAX UCHAR_MAX# else# define CHAR_MIN SCHAR_MIN# define CHAR_MAX SCHAR_MAX# endif

/* Minimum and maximum values a `signed short int' can hold. */# define SHRT_MIN (-32768)# define SHRT_MAX 32767

/* Maximum value an `unsigned short int' can hold. (Minimum is 0.) */# define USHRT_MAX 65535

/* Minimum and maximum values a `signed int' can hold. */# define INT_MIN (-INT_MAX - 1)# define INT_MAX 2147483647

/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */# define UINT_MAX 4294967295U

Page 25: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 25

7.5. Opérateurs de calculOn retrouve les opérateurs usuels en Langage C : +, -, * et /. À cette liste, il faut ajouter les éléments propres auxcalculs en Langage C.

Opérateur modulo, %Cet opérateur, noté %, renvoie le reste de la division entre 2 entiers. Par exemple : 24 % 9 = 6

Opérateurs d'incrémentation et de décrémentation, ++ et --Pour ajouter une unité à une variable, on utilise l'opérateur d'incrémentation ++. Pour soustraire une unité à unevariable, on utilise l'opérateur de décrémentation --.

La position de l'opérateur, à la gauche ou à la droite du nom de variable à une signification particulière. Dansl'expression 'while (++n < 10)', la variable n sera incrémentée avant d'être comparée à 10. À l'inverse, dansl'expression 'while (n++ < 10)', la variable n est comparée à 10 avant d'être incrémentée.

Opérateurs et expressions d'affectationEn Langage C, on peut appliquer la règle suivante sur les 2 expressions e1 et e2 :'(e1) = (e1) (opérateur) (e2)' est équivalent à '(e1) (opérateur)= (e2)'. Tous les opérateursusuels de calculs sont utilisables avec cette règle. Ainsi, i = i + 2; est équivalent à i += 2;.

• Exemple 3, « Calcul des nombres de Fibonacci sur GNU/Linux avec GCC » : à la ligne 24, on trouve un opérateurd'incrémentation du compteur des calculs à effectuer.

• Exemple 4, « Calcul des nombres de Fibonacci sur microcontrôleur MSC1210 avec SDCC » : à la ligne 35, onretrouve le même opérateur d'incrémentation.

7.6. Opérateurs relationnelsCes opérateurs évaluent une condition sur des nombres entiers ou réels et renvoient une valeur booléenne 0 ou 1.Tableau 2. Opérateurs relationnels

Symbole Opérateur|Condition

== égalité

!= différence

> supérieur à

< inférieur à

>= supérieur ou égal à

<= inférieur ou égal à

• Exemple 3, « Calcul des nombres de Fibonacci sur GNU/Linux avec GCC » : lignes 17, 24 et 25. Ces opérateursrelationnels sont utilisés pour évaluer une condition sur des valeurs entières dans les calculs.

• Exemple 4, « Calcul des nombres de Fibonacci sur microcontrôleur MSC1210 avec SDCC » : lignes 28, 30, 35 et36. Comme dans le cas précédent, on évalue une condition sur des valeurs entières.

7.7. Opérateurs logiques de bitsTableau 3. Opérateurs logiques de bits

Symbole Opérateur

& ET

| OU (inclusif)

^ OU (exclusif)

<< décalage à gauche avec remplissage par 0

Page 26: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 26

Symbole Opérateur

>> décalage à gauche avec remplissage par 0

~ négation binaire ou complément à 1

7.8. Instruction de test if-else

On utilise l'instruction if-else pour prendre des décisions. Sa forme générale est : if ( expression ) instruction1; else instruction2;

Si l'expression est vraie, c'est l'instruction 1 qui est exécutée ; sinon c'est l'instruction 2. Les instructions 1 et 2 peuventcorrespondre à des groupes délimités par des caractères { et }. La partie else est optionnelle. Si l'instruction 2 n'existepas, on n'utilise pas ce mot clé.

Une condition fausse vaut toujours 0

Si la condition codée dans l'expression n'est pas vérifiée (est fausse) c'est la valeur numérique 0 qui estrenvoyée. Pour toutes les autres valeurs renvoyées par l'expression, la condition est considérée commevérifiée (est vraie).

En langage C, il est très fréquent d'utiliser directement les valeurs numériques dans les instructions if-else sans coder explicitement la condition dans l'expression. De nombreux exemples de ce mode decodage ont été volontairement placés dans les exemples de programmes fournis dans le présent document.

• Exemple 3, « Calcul des nombres de Fibonacci sur GNU/Linux avec GCC » : les lignes 17 à 20 permettent decontrôler que l'utilisateur a bien saisi un nombre de calculs compatible avec la représentation sur 32 bits du résultat.Si l'utilisateur saisit une valeur supérieure à la constante MAX_FIB, on affiche le message d'erreur à la console etl'exécution du programme s'arrête. Les deux instructions à traiter si l'expression est vraie sont encadrées par desaccolades.

Les lignes 25 à 30 montrent que l'on effectue le calcul des nombres de Fibonacci pour les valeurs de la variable istrictement supérieures à 1. Si cette condition n'est pas respectée, on affiche directement le numéro du calcul commerésultat.

• Exemple 4, « Calcul des nombres de Fibonacci sur microcontrôleur MSC1210 avec SDCC » : les lignes 28 et30 permettent de contrôler que l'utilisateur a bien saisi un nombre de calculs dont les résultats sont correctementreprésentés sur 32 bits. Dans ce cas, on se contente d'afficher le message d'erreur. On n'utilise pas d'accolades dedélimitation de groupe d'instructions.

Comme dans la version GNU/GCC, les lignes 36 à 41 montrent que l'on effectue le calcul des nombres de Fibonaccipour les valeurs de la variable i strictement supérieures à 1.

7.9. Instructions de choix multiples : switch & if-else-if

Le traitement des choix multiples peut devenir compliqué lorsque l'imbrication des blocs d'instructions entreinstructions if-else augmente. C'est pour cette raison qu'une syntaxe particulière à été introduite : l'instructionswitch dont le synoptique est le suivant.switch (expression) { case Valeur1: // Instructions break; case Valeur2: // Instructions break; ...

Page 27: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 27

case ValeurN: // Instructions break; default: // Instructions}

Le cas classique d'utilisation de l'instruction switch consiste à programmer un menu à choix multiples. La variableà tester est de type simple puisqu'il s'agit d'un caractère. Le programme sdcc_switch.c illustre justement l'utilisationd'un menu suivi d'un test à choix multiples.

Cette structure est très pratique lorsque le résultat de l'expression est de type simple. Lorsque l'on doit évaluer non pasune valeur mais une plage de valeurs, il devient alors plus pratique de retenir un codage du type suivant.

if (condition1) { // Instructions } else if (condition2) { // Instructions } else if (condition3) { // Instructions } // autres conditions else { // Instructions }

7.10. Instructions de boucles : for, while, do-while

Dès lors qu'une ou plusieurs instructions doivent être répétées, on utilise les instructions de boucles disponibles avecle Langage C.

Indépendemment du langage de programmation utilisé, il existe des règles dans l'emploi des boucles.

1. On emploie la boucle pour (for) lorsque l'on connaît le nombre d'itérations (ie. le nombre de fois où le traitementdoit être répété dans la boucle).

2. On emploie la boucle répéter jusqu'à (do-while) lorsque le corps de la boucle doit être exécuté au moins une fois.

3. On emploie la boucle tant que (while) lorsque le corps de la boucle peut ne pas être exécuté.

7.10.1. Syntaxe de la boucle pour (for)

La boucle pour (for) en C/C++ comprend 3 champs distincts : l'initialisation, le test de sortie et l'incrémentation.

for (initialisation; test; incrémentation ) { // Instructions }

Les 3 champs définis ci-dessus peuvent être composés à l'aide de n'importe quelle expression C/C++ valide. Ce modede construction des boucles pour est une originalité importante du C/C++. Il faut cependant être vigilant lors du choixdes expressions placées dans ces champs. Un codage trop compact (avec des appels multiples de fonctions par exemple)et|ou des opérations sur des variables sans relations sont très pénalisant pour la mise au point des programmes.

• Exemple 3, « Calcul des nombres de Fibonacci sur GNU/Linux avec GCC » : lignes 24 à 30. On trouve ici unexemple de boucle pour servant à compter le nombre de calculs à effectuer. La variable i sert au comptage. Elleest initialisée à 0 dans le premier champ. Le comptage se poursuit tant que la variable i est strictement inférieur aunombre n. À chaque «tour» la variable i est incrémentée.

• Exemple 4, « Calcul des nombres de Fibonacci sur microcontrôleur MSC1210 avec SDCC » : lignes 35 à 41. Onretrouve une syntaxe identique à l'exemple précédent.

Page 28: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 28

7.10.2. Syntaxe de la boucle répéter jusqu'à (do-while)

Conformément à la règle énoncée ci-dessus, le test est effectué après une première exécution du corps de la bouclerépéter jusqu'à (do-while). do { // Instructions } while (test);

Comme dans le cas de la boucle précédente, la condition testée peut être composée à l'aide de n'importe quelleexpression C/C++ valide. Il est donc préférable de limiter la complexité de cette expression pour faciliter la mise aupoint des programmes.

• Exemple 4, « Calcul des nombres de Fibonacci sur microcontrôleur MSC1210 avec SDCC » : lignes 24 à 30. Ici, lasaisie du nombre de calculs à effectuer dans la suite du programme est répétée tant que la valeur est supérieure ouégale à la limite MAX_FIB. La limite MAX_FIB correspond au maximum pour lequel le calcul du nombre de Fibonacciest représentable sur 32 bits.

7.10.3. Syntaxe de la boucle tant que (while)

Conformément à la règle énoncée ci-dessus, le test est effectué avant que le corps de la boucle tant que (while) nesoit exécuté. while (test) { // Instructions }

Une fois encore ! attention à l'expression de test.

• Exemple 9, « Utilisation des fonctions getchar & putchar avec GCC » : lignes 7 et 8. On trouve ici un exemplede boucle tant que servant à reproduire à la console le caractère saisi au clavier tant que celui-ci est différent du codeASCII EOF. On remarque que la boucle ne comprend qu'une seule instruction putchar(c). C'est la raison pourlaquelle les accolades ne sont pas nécessaires. Voir Section 7.1, « Délimiteurs ».

• Exemple 10, « Utilisation des fonctions getchar & putchar sur microcontrôleur MSC120 avec SDCC » : lignes24 à 28. On retrouve le même traitement que dans l'exemple précédent. On a simplement ajouté un test nécessaireau saut le ligne lors d'un appui sur la touche Entrée.

7.11. Sous-programmesLa démarche classique de construction d'un programme informatique veut que l'on découpe un problème complexe ensous-ensembles plus faciles à traiter. Du point de vue du codage, cette démarche se traduit par l'utilisation de sous-programmes correspondant à ces sous-ensembles.

La réutilisation de code est un autre argument pour l'emploi des sous-programmes. Si un même traitement doit êtrerépété à plusieurs reprises dans un programme, il est préférable de le placer dans un sous-programme qui sera appeléautant de fois que nécessaire.

Enfin, le recours aux sous-programmes doit faciliter la lecture et la mise au point des programmes. Un jeu de sous-programmes bien écrit et compréhensible par un grand nombre de programmeurs peut être réutilisé sous forme debibliothèque.

La bibliothèque glibc est probablement l'exemple le plus emblématique de bibliothèque partagée. Elle est disponibleavec la totalité des chaînes de développement en Langage C sur tous les systèmes d'exploitation et pour presque tousles processeurs.

Les fonctions getchar, putchar, printf et atoi sont quelques exemples de sous-programmes partagés à l'aide dela bibliothèque glibc. On les retrouve dans les programmes d'illustration présentés dans ce document.Exemple 7. Utilisation d'un sous-programme dans le calcul des nombres de Fibonacci01: #include <stdio.h>02: #include <stdlib.h>03:

Page 29: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 29

04: #define MAX_FIB 4905: 06: unsigned long iterative_fibonacci(unsigned long f) {07: 08: unsigned long nombrePrecedent = 0, nombreCourant = 1, fibonacci = 0;09: int i;10: 11: if (f > 1 )12: for (i = 1; i < f; i++) {13: fibonacci = nombrePrecedent + nombreCourant;14: nombrePrecedent = nombreCourant;15: nombreCourant = fibonacci;16: }17: else18: fibonacci = f;19: 20: return fibonacci;21: }22: 23: main() {24: 25: int n, i;26: 27: printf("Saisir le nombre de calculs de Fibonacci(n) :\n"); 28: scanf("%d", &n);29: if (n >= MAX_FIB) {30: printf("Fibonacci(%d) depasse la capacite d'un mot de 32 bits\n", n); 31: exit(1);32: }33: 34: for (i = 0; i < n; i++)35: printf("Fibonacci (%d) = %lu\r\n", i, iterative_fibonacci(i));36: }

On retrouve des résultats identiques aux précédents avec le programme gcc_fibonacci_iterative.c.Exemple 8. Utilisation d'un sous-programme dans le calcul des nombres de Fibonacci sur la cible MSC121001: #include <msc1210.h>02: #include "ser_msc1210.h"03: #include <stdio.h>04: #include <stdlib.h>05: 06: #define MAX_FIB 4907: 08: // surdefinition du sous-programme putchar09: void putchar(char c) {10: ser_putc(c);11: }12: 13: unsigned long iterative_fibonacci(unsigned long f) {14: 15: unsigned long nombrePrecedent = 0, nombreCourant = 1, fibonacci = 0;16: int i;17: 18: if (f > 1 )19: for (i = 1; i < f; i++) {20: fibonacci = nombrePrecedent + nombreCourant;21: nombrePrecedent = nombreCourant;22: nombreCourant = fibonacci;23: }24: else25: fibonacci = f;26:

Page 30: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 30

27: return fibonacci;28: }29: 30: void main(void) {31: 32: unsigned char s[3] = {'\0','\0','\0'};33: int n, i;34: 35: // Appuyer sur <Entree> pour ajuster automatiquement36: // le debit de la liaison37: autobaud();38: EA=1;39: 40: do {41: printf("Saisir le nombre de calculs de Fibonacci :\r\n");42: ser_gets_echo(s, 2);43: n = atoi(s);44: if (n >= MAX_FIB)45: printf("\nFibonacci(%d) depasse la capacite d'un mot de 32 bits\r\n", n);46: } while (n >= MAX_FIB);47: 48: printf("\r\n\n");49: for (i = 0; i < n; i++)50: printf("Fibonacci (%d) = %lu\r\n", i, iterative_fibonacci(i));51: 52: while(1);53: }

On retrouve aussi des résultats identiques aux précédents avec le programme sdcc_fibonacci_iterative.c.MSC1210 Ver:000305F10>M0000 ok>M8000 ok>E>T>>Saisir le nombre de calculs de Fibonacci :11

Fibonacci (0) = 0Fibonacci (1) = 1Fibonacci (2) = 1Fibonacci (3) = 2Fibonacci (4) = 3Fibonacci (5) = 5Fibonacci (6) = 8Fibonacci (7) = 13Fibonacci (8) = 21Fibonacci (9) = 34Fibonacci (10) = 55

• Exemple 7, « Utilisation d'un sous-programme dans le calcul des nombres de Fibonacci » : Dans le programmeprincipal (main()), à la ligne 35, on trouve l'appel au sous-programme iterative_fibonacci(i). La variablei est passée comme paramètre d'entrée lors de l'appel au sous-programme.

Entre les lignes 6 et 21, on trouve le sous-programme iterative_fibonacci(i). La ligne 6 correspond auprototype du sous-programme : c'est là que l'on désigne le nom du sous-programme ainsi que les types des paramètresd'entrée et de sortie. Dans l'exemple, les paramètres échangés sont de type unsigned long.

• Exemple 8, « Utilisation d'un sous-programme dans le calcul des nombres de Fibonacci sur la cible MSC1210 » :On retrouve les mêmes éléments que dans le cas précédent. Le sous-programme iterative_fibonacci(i) estappelé au niveau de la ligne 50. Ce sous-programme est défini entre les lignes 13 et 28. Les paramètres échangéssont du même type entre les deux programmes.

Page 31: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 31

8. Entrées et sorties standard : fonctions getchar & putchar8.1. Avec Système d'exploitation

Entrée standard, Fonction getchar, Flux stdinLe mécanisme d'entrée le plus simple consiste à lire un caractère provenant de l'entrée standard. Suivant lecontexte, cette entrée standard peut prendre différente formes.

Sur un ordinateur, les caractères sont généralement lus à partir d'un clavier. Ils peuvent cependant provenir dedifférents «canaux» : fichiers, redirections de flux ou opérations de séquencement entre les programmes de lacouche Shell (pipes ou tubes).

Sur un système embarqué les caractères peuvent provenir des même canaux. Sans système d'exploitation, la listedes canaux est limitée aux interfaces disponibles. Dans les exemples présentés dans ce document, c'est la liaisonsérie qui sert le plus souvent de flux d'entrée standard.

Par principe, la fonction getchar transmet au programme appelant le caractère suivant de la file d'entrée à chaqueappel.

Sortie standard, Fonction putchar, Flux stdoutPar analogie avec le cas de l'entrée standard, le mécanisme le plus simple consiste à émettre un caractère vers lasortie standard. Suivant le contexte cette sortie standard peut aussi prendre différentes formes.

Sur un ordinateur, les caractères sont émis par défaut vers le terminal (ie. la fenêtre du Shell courant). Comme pourtoute manipulation au niveau Shell, les opérations de séquencement, de redirection et les tubes sont utilisables.Voir les exemples d'exécution ci-après.

Ces mécanismes d'entrées-sorties standard ont été définis avec les systèmes d'exploitation UNIX au début des années70. On les retrouve aujourd'hui sur la totalité des systèmes d'exploitation contemporains. Les files d'attentes descaractères issus de l'écran, du clavier, des fichiers stockés sur tous types de supports, etc. sont appelés flux d'entrées-sorties (input-output streams). Des flux standards ont été définis ; chacun étant dédié à un «pseudo-périphérique».

• stdin : flux d'entrée ; généralement le clavier,• stdout : flux de sortie ; généralement l'écran,• stderr : flux d'erreurs vers lequel sont redirigés tous les messages d'erreurs lors de l'exécution d'un programme,• stdprn : flux d'impression ; généralement le port parallèle,• stdaux : flux auxiliaire ; généralement le port série.

Flux d'entrées-sorties standard et système d'exploitation24

24 images/os_stdio.png

Page 32: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 32

Voici un exemple simple de programme utilisant les flux d'entrées-sorties standard via les fonctions getchar etputchar. Ce programme recopie les caractères reçus sur le flux d'entrée stdin vers le flux de sortie stdout. Cettecopie se poursuit tant que le caractère saisi est différent du code ASCII de délimitation de fin de fichier EOF (codeobtenu en appuyant simultanément sur les touches Ctrl + D).

Exemple 9. Utilisation des fonctions getchar & putchar avec GCC

01: #include <stdio.h>02: 03: int main() {04: 05: char c;06: 07: while ((c = getchar()) != EOF)08: putchar(c);09: 10: return 0;11: }

L'exemple d'exécution du programme ci-dessous montre que l'opération de transfert d'un flux vers l'autre est séquencéepar le caractère de saut de ligne \n. Le flux d'entrée se «remplit» tant qu'aucun appui sur la touche Entrée n'intervient.Dès que le code ASCII du saut de ligne entre dans le flux d'entrée standard, son contenu est transféré au programmeutilisateur via l'appel à la fonction getchar.

Les appels à la fonction putchar suivent le même fonctionnement vis-à-vis du flux de sortie standard.

Voici un exemple d'exécution du programme gcc_stdio.c :

$ ./gcc_stdio.outtesttest123123

Voici deux autres exemples d'exécution du même programme en utilisant les opérations de séquencement entre lesprogrammes offertes par le Shell.

• On commence par créer un fichier test.txt à l'aide de la commande cat. Tous les caractères saisis au clavier sontredirigés vers le fichier. L'opération s'arrête avec la saisie du code ASCII EOF (Ctrl + D).

• Le programme est exécuté avec une nouvelle redirection : ./stdio <test.txt. Avec cette redirection, le contenudu fichier test.txt se substitue au flux d'entrée standard stdin.

• Le programme est à nouveau exécuté en utilisant un tube (pipe). En fait, deux programmes sont exécutés : cattest.txt et stdio. Le premier à pour but d'afficher le contenu du fichier texte sur le flux de sortie standard stdout(ie. la console). Le fonctionnement du second programme a déjà été décrit ci-dessus. L'utilisation du tube permet detransférer la sortie du premier programme vers l'entrée du second.

phil@b0x:~/src$ cat >test.txtFichier texteexemplephil@b0x:~/src$ ./stdio <test.txtFichier texteexemplephil@b0x:~/src$ cat test.txt | ./stdioFichier texteexemple

Pour plus de détails sur les manipulations à la console, voir Linux - Base d'administration pour le superutilisateur.

Page 33: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 33

8.2. Sans système d'exploitation & cible MSC1210

Flux d'entrées-sorties standard sans système d'exploitation25

Voici maintenant le même exemple simple de programme utilisant les flux d'entrées-sorties standard sur un systèmespécialisé. Dans ce contexte sans système d'exploitation, on ne dispose pas de définition des flux stdin et stdoutentre le noyau et le Shell. On continue cependant à utiliser les fonctions getchar et putchar.

La technique usuelle sur les systèmes spécialisés consiste à donner une nouvelle définition de ces deux fonctions endésignant explicitement le canal de réception et d'émission des caractères. Dans l'exemple, c'est la liaison série entrele PC de développement et le système spécialisé qui sert à faire transiter les caractères dans les deux sens.Exemple 10. Utilisation des fonctions getchar & putchar sur microcontrôleur MSC120 avec SDCC

01: #include <stdio.h>02: #include <msc1210.h>03: #include "ser_msc1210.h"04: 05: #define EOF 0x0406: #define CR 0x0d07: 08: char getchar(void) {09: return ser_getc();10: }11: 12: void putchar(char c) {13: ser_putc(c);14: }15: 16: void main(void) {17: 18: char c;19: 20: // Press <Enter> for auto baudrate adjust21: autobaud();22: EA=1;23: 24: while ((c = getchar()) != EOF) {25: if (c == CR)26: putcr();27: putchar(c);28: }29: putcr();30: putchar('!');31: putcr();32: 33: while (1);34: }

25 images/no_os_stdio.png

Page 34: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 34

Comme on l'a déjà indiqué, il n'existe pas de couche Shell dans ce contexte. On ne dispose donc pas d'opération deséquencement entre programmes puisque cet exemple est le seul programme exécuté par le microcontrôleur.

Voici un exemple d'exécution du programme sdcc_stdio.c :MSC1210 Ver:000305F10>M0000 ok>M8000 ok>E>T>>azerty123

!

• Exemple 3, « Calcul des nombres de Fibonacci sur GNU/Linux avec GCC » : ce programme ne fait pas directementappel aux fonctions getchar et putchar. Il utilise plutôt les fonctions d'entrées-sorties formatées décrites ci-après.

• Exemple 4, « Calcul des nombres de Fibonacci sur microcontrôleur MSC1210 avec SDCC » : lignes 11 à 13. Laliaison série étant utilisée comme canal d'entrée-sortie standard, on définit la fonction putchar en conséquence.Cette définition est ensuite réutilisée pour les sorties formatées lors des appels à la fonction printf : lignes 27,31, 34, 42 et 45. Pour la saisie du nombre de calcul, la fonction ser_gets_echo est définie dans le fichier d'en-tête ser_msc1210.h.

Page 35: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 35

9. Entrées et sorties formatées : fonctions scanf & printf9.1. Définitions générales

Les flux d'entrées-sorties standards sont limités aux manipulations sur des caractères codés en ASCII. Cette limitationest très contraignante lorsque l'on cherche à formater l'affichage de valeurs numériques. C'est pour dépasser cescontraintes que l'on a introduit deux fonctions dédiées à la «traduction» entre valeurs numériques et chaînes decaractères. La fonction printf sert à formater les sorties sur le flux stdout et la fonction scanf sert à formater lesentrées reçues sur le flux stdin.

Les prototypes génériques de ces deux fonctions se présentent sous la forme :scanf(control, arg1, arg2, ...)printf(control, arg1, arg2, ...)

• control est une chaîne de caractère qui sert à mettre en forme les arguments. Cette chaîne peut contenir descaractères «ordinaires» qui sont recopiés directement depuis ou vers le flux d'entrée-sortie standard et des formatsde conversion positionnés dans la chaîne à l'aide du caractère balise % suivi du format choisi.

• Les arguments arg1, arg2, ..., doivent correspondre à chaque caractère % placé dans la chaîne control.

Le caractère % est une balise de positionnement suivie d'une spécification de traduction dont le prototype est :%[indicateur][largeur][.precision][modification]type.

• Tous les champs notés entre crochets sont optionnels.• Spécifications du champ obligatoire type :Tableau 4. Types de conversion

type signification

%c caractère

%s chaîne de caractères

%d nombre entier en décimal

%e nombre réel sous la forme mantisse/exposant [-]m.nnnnnne[+|-]xx

%E nombre réel sous la forme mantisse/exposant en majuscule [-]m.nnnnnnE[+|-]xx

%f nombre réel sous la forme [-]mmm.nnnnnn

%g nombre réel sous la forme la plus courte entre les types %e et %f

%G nombre réel sous la forme la plus courte entre les types %E et %f

%o nombre entier en octal

%p pointeur ou adresse de la valeur numérique

%u nombre entier non signé en décimal

%x nombre entier en hexadécimal

%X nombre entier en hexadécimal ; lettres affichées en majuscules• Spécifications du champ optionnel [indicateur] :Tableau 5. Indicateur d'affichage

[indicateur] signification

- alignement à gauche pour la largeur donnée

+ affichage forcé du signe de la valeur numérique

Page 36: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 36

[indicateur] signification

espace insertion d'un caractère d'espacement si la valeur numérique est positive

affichage précédé de 0, 0x ou 0X avec les types respectifs o, x ou X

force l'affichage du point décimal avec les types e, E et f même si la partie décimale necontient que des zéros#

force l'affichage du point décimal avec les types g et G sans supprimer les zéros inutiles• Spécifications du champ optionnel [largeur] :Tableau 6. Largeur de l'affichage

[largeur] signification

nombre nombre minimum de caractères à afficher ; ajout de caractères d'espacement si la valeur estplus «courte» que l'affichage demandé

0nombre idem ci-dessus ; ajout de caractères 0 si la valeur est plus «courte» que l'affichage demandé

*nombre la largeur n'est pas spécifiée dans la chaîne control mais par un entier précédentl'argument à afficher

• Spécifications du champ optionnel [precision] :Tableau 7. Precision de l'affichage

[precision] signification

pour les types d, i, o, u, x et X : nombre minimum de chiffres décimaux à afficher ; ajout decaractères d'espacement si la valeur est plus «courte» que l'affichage demandé

pour les types e, E et f : nombre de chiffres à afficher après le point décimal

pour les types g et G : nombre maximum de chiffres significatifs à afficher

pour le type s : nombre maximum de caractères à afficher

.nombre

pour le type c : pas d'effet• Spécifications du champ optionnel [modification] :Tableau 8. Modification de l'affichage

[modification] signification

h argument traité comme un entier court (short)

l argument traité comme un entier long pour les types entiers (long) ou comme un réel doublepour les types réels (double)

L argument traité comme un réel long double

Voici deux programmes d'illustration de sorties formatées avec la fonction printf. Le premier bénéficie du jeu dedéfinitions complet sur GNU/Linux. Le second, exécuté sur un microcontrôleur MSC1210 et compilé avec SDCC, nedispose que d'un jeu de définitions de formats plus restreint.

9.2. Exemple avec GCCExemple 11. Sorties formatées avec printf sur GNU/Linux avec GCC

01: /* $Id: gcc_printf.c 1129 2007-05-07 15:07:52Z latu $ */02: 03: #include <stdio.h>04: 05: #define M_PI 3.14159265358979323846 /* pi */06:

Page 37: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 37

07: #define YEAR 200708: 09: int main() {10: 11: printf ("Caracteres : %c %c %c %c\n", 'a', 65, 0x30, '0');12: printf ("Entiers : %d %ld\n", YEAR, 650000);13: printf ("Affichage avec espaces : |%10d|\n", YEAR);14: printf ("Affichage avec zeros : |%010d|\n", YEAR);15: printf ("Differentes bases : %d %x %o %#x %#o \n", 100, 100, 100, 100, 100);16: printf ("Reels : |%4.2f| |%+.4e| |%E|\n", M_PI, M_PI*YEAR, M_PI);17: printf ("Largeur en argument : |%*d|\n", 5, 10);18: printf ("%s\n", "Debian GNU/Linux");19: return 0;20: }

Voici un exemple d'exécution du programme gcc_printf.c :$ ./gcc_printf.outCaracteres : a A 0 0Entiers : 2007 650000Affichage avec espaces : | 2007|Affichage avec zeros : |0000002007|Differentes bases : 100 64 144 0x64 0144Reels : |3.14| |+6.3052e+03| |3.141593E+00|Largeur en argument : | 10|Debian GNU/Linux

9.3. Exemple avec SDCC sur cible MSC1210

Par défaut, le support des nombres réels est désactivé dans la chaîne de développement SDCC. Il est nécessaire depasser par une recompilation manuelle des outils de compilation pour obtenir le résultat ci-dessous. Voir Section 13.3,« C sur MSC1210 : SDCC ».Exemple 12. Sorties formatées avec printf sur un microcontrôleur MSC1210 avec SDCC

01: #define YEAR 200702: 03: void putchar(char c) {04: ser_putc(c);05: }06: 07: int main() {08: 09: autobaud();10: EA = 1;11: 12: printf ("Caracteres : %c %c %c %c\n\r", 'a', 65, 0x30, '0');13: printf ("Entiers : %d %ld\n\r", YEAR, 650000);14: printf ("Affichage avec espaces : |%10d|\n\r", YEAR);15: printf ("Affichage avec zeros : |%010d|\n\r", YEAR);16: printf ("Differentes bases : %d %x %o %#x %#o \n\r", 100, 100, 100, 100, 100);17: printf ("Reels : |%f| |%+.4f| |%e|\n\r", M_PI, M_PI*YEAR, M_PI);18: printf ("Largeur en argument : |%*d|\n\r", 5, 10);19: printf ("%s\n\r", "Debian GNU/Linux");20: return 0;21: }

Voici un exemple d'exécution du programme sdcc_printf.c :MSC1210 Ver:000305F10>M0000 ok>M8000 ok>E>T

Page 38: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 38

>>Caracteres : a A 0 0Entiers : 2007 650000Affichage avec espaces : | 2007|Affichage avec zeros : |0000002007|Differentes bases : 100 64 144 #x #oReels : |3.141593| |+6305.1762| |E|Largeur en argument : |*d|Debian GNU/Linux

La copie d'écran ci-dessus montre que toutes les options de formatage des sorties ne sont pas supportées par labibliothèque standard implantée dans la chaîne de développement SDCC. C'est une situation classique, sachant qu'unsystème spécialisé n'est pas fait pour réaliser une interface utilisateur.

9.4. Utilisation des caractères spéciauxTableau 9. Caractères spéciaux

Séquenced'échappement

signification

%% affichage du caractère '%'

\0 caractère null ; valeur 0, délimiteur de fin de chaîne de caractères

\a alerte ; beep système

\b backspace ; déplacement du curseur d'un caractère en arrière

\f form feed ; saut de page

\n new line ; saut de ligne

\r carriage return ; retour chariot

\t tabulation horizontale

\v tabulation verticale

\\ affichage du caractère '\'

\' affichage du caractère '''

\" affichage du caractère '"'

\Onn affichage de la valeur nn en octal

\Xnn affichage de la valeur nn en hexadécimal

Page 39: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 39

10. Gestion d'un afficheur à cristaux liquides (LCD)L'utilisation d'un afficheur à cristaux liquides ou LCD est assez courante sur les systèmes embarqués. C'est un écrande faible dimension employé pour informer l'utilisateur sur l'état du système ou pour afficher les mesures effectuéespar différents capteurs.

Il existe un standard très populaire qui permet de gérer les communications avec la grande majorité des modèlesd'afficheurs LCD quelque soit le fabricant. Ce standard est connu sous le le nom HD44780U. Ce nom correspond aucontrôleur qui reçoit les données du microcontrôleur et qui les communique directement avec l'afficheur à cristauxliquides.

10.1. Caractéristiques d'un afficheur du type HD44780ULa standard HD44780U utilise 3 signaux de contrôle ainsi que 4 ou 8 lignes d'entrée-sortie pour le bus de données.L'utilisateur peut choisir si l'afficheur à cristaux liquides doit fonctionner avec un bus de données de 4 bits ou un busde données de 8 bits. Si un bus de données de 4 bits est utilisé l'afficheur LCD utilise un total de 7 lignes (3 signauxde contrôle plus les 4 lignes pour le bus de données). Si un bus de données de 8 bits est utilisé l'afficheur LCD utiliseun total de 11 lignes (3 signaux de contrôle plus les 8 lignes pour le bus de données).

Les trois signaux de contrôle sont appelés : EN, RS et RW.

EN, enableLe signal enable est utilisé pour indiquer à l'afficheur à cristaux liquides qu'on va lui envoyer des données. Pourenvoyer des données à l'afficheur, le programme doit s'assurer que le signal est au niveau bas (0) avant de faireévoluer les deux autres signaux de contrôle et de placer des données sur le bus de données. Quand l'ensemble desautres lignes sont correctement positionnées, le signal EN doit être placé au niveau haut (1) et il faut attendre untemps minimum requis par le composant (ce temps varie d'un afficheur à l'autre) avant de le placer au niveau bas(0) à nouveau.

RS, register selectLe signal register select est utilisé pour distinguer les instructions de commande des données à afficher. Si onplace RS au niveau bas (0), les données sont traitées comme une commande ou instruction spéciale (effacer l'écran,positionner le curseur de position, etc.). Si on place RS au niveau haut (1), les données envoyées sont des caractèresque l'écran doit afficher.

RW, read/writeLe signal read/write est utilisé pour distinguer si les informations sur le bus de données sont lues ou écrites. Sion place le signal RW au niveau haut (1), le programme interroge l'afficheur à cristaux liquides sur son état (GetLCD status). Dans tous les autres cas des commandes sont écrites. Ainsi, le signal RW sera presque toujours auniveau bas.

10.2. Utilisation d'un afficheur LCD avec SDCC sur cible MSC1210Le premier exemple reprend le programme «Hello, World!» en utilisant l'afficheur LCD comme écran.Exemple 13. Programme «Hello, World!» sur afficheur LCD01: #include <stdio.h>02: #include <msc1210.h>03: #include "ser_msc1210.h"04: #include "lcd_msc1210.h"05: 06: void putchar(char c) {07: if (print2lcd)08: lcd_putc(c);09: else10: ser_putc(c);11: }12: 13: void main(void) {

Page 40: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 40

14: 15: // Appuyer sur <Entrée> pour ajuster16: // automatiquement le (débit|baudrate)17: autobaud();18: 19: // Initialisations pour SDCC20: EA=1;21: 22: print2lcd = 0;23: 24: // initialisation de l'afficheur LCD25: lcd_init();26: 27: // effacement de l'écran28: lcd_clear();29: 30: // positionnement du curseur dans 31: // le coin supérieur gauche32: lcd_home();33: 34: print2lcd = 1;35: printf("Hello, World !");36: 37: // Affichage du même message 38: // sur la console39: print2lcd = 0;40: printf("Hello, World!");41: putcr();42: 43: while(1);44: }

Voici le résultat de l'exécution du programme hello_lcd.c :

Programme «Hello, World!» sur afficheur LCD26

Le second exemple illustre le positionnement du curseur d'affichage sur l'écran à cristaux liquides.

Le modèle d'écran à cristaux liquides utilisé dans les exemples suivants dispose de 4 lignes de 20 caractères. Chaquecaractère alphanumérique est accessible via une adresse définie dans le plan ci-dessous. On remarque que les adressesde chaque ligne ne sont pas consécutives ; ce qui n'est pas des plus pratique pour gérer le positionnement du curseurd'affichage.ligne 0 : 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13ligne 1 : 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53ligne 2 : 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27ligne 3 : 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 60 61 62 63 64 65 66 67

Exemple 14. Programme de positionnement du curseur sur un afficheur LCD01: #include <stdio.h>02: #include <stdlib.h>03: #include <msc1210.h>04: #include "ser_msc1210.h"

26 images/hello_lcd.png

Page 41: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 41

05: #include "lcd_msc1210.h"06: 07: #define MAXCHAR 1008: #define EOF 409: 10: void putchar(char c) {11: if (print2lcd)12: lcd_putc(c);13: else14: ser_putc(c);15: }16: 17: void main(void) {18: 19: unsigned int x, y;20: unsigned char s[MAXCHAR];21: 22: // Appuyer sur <Entrée> pour ajuster automatiquement le (débit|baudrate)23: autobaud();24: 25: // Initialisations pour SDCC26: EA=1;27: 28: print2lcd = 0;29: 30: // Initialisation de l'afficheur LCD31: lcd_init();32: 33: ser_puts("Programme de positionnement du curseur");34: putcr();35: ser_puts("L'abscisse X est comprise entre 0 et 19");36: putcr();37: ser_puts("L'ordonnee Y est comprise entre 0 et 3");38: putcr();39: ser_puts("(Sortie pour une valeur X > 19)");40: putcr();41: 42: do {43: ser_puts("Saisie de x : ");44: ser_gets_echo(s, MAXCHAR);45: putcr();46: x = atoi(s);47: ser_puts("Saisie de y : ");48: ser_gets_echo(s, MAXCHAR);49: putcr();50: y = atoi(s);51: lcd_clear();52: lcd_set_xy(x, y);53: print2lcd = 1;54: printf("!ici");55: print2lcd = 0;56: } while (x < 20);57: 58: // Affichage sur la console59: ser_puts("The End!");60: putcr();61: 62: while(1);63: }

Voici le résultat de l'exécution du programme sdcc_lcd_set_xy.c :

MSC1210 Ver:000305F10

Page 42: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 42

>M0000 ok>M8000 ok>E>T>>Programme de positionnement du curseurL'abscisse X est comprise entre 0 et 19L'ordonnee Y est comprise entre 0 et 3(Sortie pour une valeur X > 19)Saisie de x : 5Saisie de y : 2

Positionnement du curseur sur un afficheur LCD27

27 images/lcd_set_xy.png

Page 43: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 43

11. Gestion des entrées/sorties logiquesLe type de gestion d'entrées/sorties le plus simple à gérer pour un microcontrôleur consiste à utiliser directement desniveaux logiques '0' ou '1'. En effet, l'exploitation des niveaux logiques ne nécessite aucune transformation du signal.

11.1. Exemple d'entrées/sorties sur un bitDans cet exemple, on utilise la carte MSC1210 EValuation Module. On utilise un bouton poussoir et deux diodesélectroluminescentes (LED) dont le câblage est fixé comme suit :Tableau 10. Entrées/Sorties un bit MSC1210EVM

Type Désignation Broche microcontrôleur

Entrée Bouton poussoir SW2 P3.2

Sortie LED rouge P3.4

Sortie LED jaune P3.5

Exemple 15. Programme d'illustration des entrées/sorties logiques sur un bit

Voici un programme «minimaliste» d'illustration du fonctionnement des entrées/sorties sur un bit : sdcc_ttl_1bit.c. Àchaque appui sur le bouton poussoir, on allume la LED rouge. Tous les quatre appuis sur le même bouton poussoir,on allume la LED jaune.01: #include <stdio.h>02: #include <msc1210.h>03: #include "ser_msc1210.h"04: 05: __sbit __at (0xb2) IN_SW2; // p3.206: __sbit __at (0xb4) OUT_RED; // p3.407: __sbit __at (0xb5) OUT_YELLOW; // p3.508: 09: void putchar(char c) {10: ser_putc(c);11: }12: 13: bit antirebond() {14: unsigned char i = 0;15: unsigned int j = 0;16: bit sw_now = 1, sw_previous = 1;17: 18: while (i < 5) {19: sw_previous = IN_SW2;20: // Boucle de temporisation21: for(j = 0; j < 8000; j++)22: ;23: sw_now = IN_SW2;24: if (sw_now == sw_previous)25: i++;26: }27: 28: return sw_now;29: }30: 31: void main(void) {32: 33: unsigned char c, i = 0;34: bit sw;35: 36: /* Appuyer sur Entrée pour ajuster automatiquement37: * le débit sur la liaison série */38: autobaud();

Page 44: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 44

39: EA=1;40: 41: puts("Lecture SW2/Ecriture LED");42: putcr();43: while (1) {44: if (sw = antirebond())45: OUT_RED = 1;46: else {47: OUT_RED = 0;48: if (++i % 4)49: OUT_YELLOW = 1;50: else51: OUT_YELLOW = 0;52: }53: c = sw + 0x30;54: putchar(c);55: putchar('\r');56: }57: }

Adressage des entrées/sorties, lignes 5 à 7En fonction du tableau donné ci-dessus on affecte les noms d'entrées/sorties à l'aide des directives du compilateur.Ici, la directive __sbit __at (0xb2) IN_SW2; affecte le nom IN_SW2 au bit accessible à l'adresse 0xb2. Cetteadresse correspondant au troisième bit du port numéro 3 du microcontrôleur : P3.2.

Une fois ces affectations en place, on utilise les noms d'entrées/sorties de la même façon que des variables.

Comme avec n'importe quel type de variable, il faut respecter les espaces de représentation mémoire des entrées/sorties. Dans l'exemple, on a désigné des entrées/sorties de type bit. Il n'est donc pas question de placer le contenud'une variable qui occupe plus d'un bit sur une sortie de type bit. À l'inverse, le transtypage automatique offertpar le langage C permet très bien de stocker un bit dans une variable dont l'occupation mémoire est plus grande. Àla ligne ligne 53, on place le bit sw dans c qui est une variable de type character dont l'espace de représentationest l'octet. Voir la Section 7.3, « Types de représentation des données ».

Fonction antirebond(), lignes 13 à 29Comme l'exemple d'illustration propose de compter les appuis sur le bouton poussoir, il est nécessaire de sepréoccuper des «rebonds». Lors d'un appui manuel sur le contact électrique du bouton poussoir, une suited'impulsions transitoires est transmise. Ces impulsions parasites sont communément appelées rebonds.

La fonction présentée ici utilise une boucle de temporisation (lignes 20 à 22). L'emploi de ce type de boucle doitêtre évité au maximum mais le bouton poussoir de la carte MSC1210 EValuation Module a été câblé directementsur la broche P3.2 du microcontrôleur sans cellule RC de filtrage des rebonds.

Le compteur i sert à contrôler que l'on a lu 5 fois le même état entre chaque temporisation.

Programme principal, lignes 43 à 56La condition d'appel au corps de la boucle tant que while (1) est toujours vraie. Il s'agit donc d'une boucleinfinie. Seule la ré-initialisation du microcontrôleur peut interrompre le programme.

Sans appui sur le bouton poussoir, la fonction antirebond() renvoie un bit à 1. On éteint alors la LED rouge enenvoyant un niveau 1 sur la broche P3.4 du microcontrôleur : OUT_RED = 1;.

Lors d'un appui sur le bouton poussoir, la fonction antirebond() renvoie un bit à 0. On allume alors la LEDrouge en envoyant un niveau 0 : OUT_RED = 0;.

C'est aussi lors d'un appui sur le bouton poussoir que l'on incrémente le compteur i. On teste ensuite si le restede la division entière de i par 4 est nul. Si la condition est vérifiée, on allume la LED jaune. Ce codage permetd'allumer la LED jaune tous les quatre appuis sur le bouton poussoir.

L'évaluation des conditions des lignes 44 et 48 utilise directement les résultats numériques des expressions codéesavec l'instruction if-else. Si l'expression renvoie la valeur 0, c'est que le test est faux. Voir Une condition faussevaut toujours 0.

Page 45: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 45

Affichage de la valeur d'un bit, lignes 53 à 55Pour afficher l'état de l'appui sur le bouton poussoir sur la console du système de développement via la liaisonsérie, il est nécessaire de transformer le bit lu en un code ASCII. Sachant que le code ASCII du chiffre 0 est 0x30,il suffit d'ajouter la valeur du bit à ce code pour afficher les caractères '0' ou '1' sur la console.

Comme la scrutation de l'état du bouton poussoir est continue, on envoie le code ASCII de retour en début de ligne'\r' après chaque affichage de la valeur du bit d'état. De cette façon, on évite de remplir l'écran de la consoleet l'affichage est donc plus lisible.

11.2. Exemple d'entrées/sorties sur plusieurs bitsDans cet exemple, on utilise la carte du département Génie Électrique de l'IUT 'A' Paul Sabatier. Relativement à lacarte MSC1210 EValuation Module, cette carte offre une extension sur les entrées/sorties logiques.

L'utilisation du port P0 a été «étendue» en utilisant deux sorties du port P3 comme signaux de contrôles. Ces bits decontrôle servent à sélectionner un composant chacun : un pour les entrées et un pour les sorties. De plus, deux bitssupplémentaires des ports P3 et P1 ont été alloués comme entrées et sorties. Le schéma ci-dessous montre que l'ondispose de 10 entrées et 10 sorties logiques.

Schéma de principe extension port P028

Exemple 16. Programme d'illustration des entrées/sorties logiques sur plusieurs bits

Voici un programme d'illustration du fonctionnement des entrées/sorties sur plusieurs bits : sdcc_ttl_io_iut.c. Il proposeun menu qui permet de lire ou écrire 10 bits simultanément ainsi que la lecture ou l'écriture d'un bit individuel parmi 10.01: #include <stdio.h>02: #include <stdlib.h>03: #include <msc1210.h>04: #include "ser_msc1210.h"05: #include "iut_msc1210.h"06: 07: #define EOF 0x0408: #define MAXCHAR 409: 10: char getchar(void) {11: return ser_getc();12: }13: 14: void putchar(char c) {15: ser_putc(c);16: }

28 images/p0_ttl_extension.png

Page 46: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 46

17: 18: unsigned char menu(void) {19: 20: putcr();21: putcr();22: puts("------- Menu -------");23: putcr();24: puts("(a) : lecture des 10 entrees");25: putcr();26: puts("(b) : ecriture des 10 sorties");27: putcr();28: puts("(c) : saisie de la valeur a ecrire (< 1024)");29: putcr();30: puts("(d) : lecture bit individuel (0 <= b <= 9)");31: putcr();32: puts("(e) : ecriture bit individuel (0 <= b <= 9)");33: putcr();34: puts("(EOF) : taper CTRL D pour sortir");35: putcr();36: puts("--------------------");37: putcr();38: 39: return getchar();40: }41: 42: void main(void) {43: 44: unsigned int val = 0;45: unsigned char c, chaine[MAXCHAR], num;46: 47: /* Appuyer sur Entrée pour ajuster automatiquement48: * le débit sur la liaison série */49: autobaud();50: EA=1;51: 52: while ((c = menu()) != EOF) {53: switch (c) {54: case 'a':55: val = lecture_10bits();56: break;57: case 'b':58: ecriture_10bits(val);59: break;60: case 'c':61: puts("Valeur :");62: putcr();63: ser_gets_echo(chaine, MAXCHAR);64: val = atoi(chaine);65: putcr();66: break;67: case 'd':68: do {69: puts("Numero du bit :");70: putcr();71: ser_gets_echo(chaine, MAXCHAR);72: num = atoi(chaine);73: putcr();74: } while (num > 9);75: val = lecture_1bit(num);76: break;77: case 'e':78: do {

Page 47: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 47

79: puts("Numero du bit :");80: putcr();81: ser_gets_echo(chaine, MAXCHAR);82: num = atoi(chaine);83: putcr();84: } while (num > 9);85: do {86: puts("Valeur du bit :");87: putcr();88: ser_gets_echo(chaine, MAXCHAR);89: val = atoi(chaine);90: putcr();91: } while (val > 1);92: ecriture_1bit(num, val);93: break;94: default:95: puts("Option non reconnue");96: putcr();97: }98: printf ("/%03x/\n\r", val);99: putcr();100: }101: // Fin du programme102: puts("The End!");103: putcr();104:105: while(1);106:}

Page 48: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 48

12. Contraintes de temps sur les sorties numériquesMême si les microcontrôleurs de la famille MSC12xx ne peuvent rivaliser avec les composants logiques programmablesspécialisés (FPGAs, etc.), il est utile d'évaluer précisément les performances en fréquence que l'on peut obtenir surles sorties numériques.

Cette section traite de l'utilisation des ports «classiques» du microcontrôleur. Les périphériques spécialisés tels que lestimers ou le port SPI font l'objet de sections particulières.

On présente donc un exemple de programme qui permet d'évaluer les différents types de temporisations logicielles ainsique le temps d'exécution des différentes boucles du Langage C. Le code source du programme complet est disponiblesous le nom : sdcc_port_timings.c.

Pour chaque exemple de temporisation logicielle, on présente le code en Langage C, le code assembleur correspondantainsi que les mesures de temps pour un appel unique et pour une exécution supplémentaire.

Remarque importante : les mesures temps ont été réalisées à l'aide d'un microcontrôleur MSC1210Y5 cadencé à22.1184MHz.

12.1. Temps d'exécution d'une instruction nopL'instruction nop (acronyme de no operation) est une instruction assembleur dont le seul but est de gaspiller un cycled'horloge du microcontrôleur. En appelant cette instruction directement à partir du langage C on doit obtenir le pluspetit temps d'exécution possible.

• Codage en Langage C :#define nop() {_asm nop _endasm;}

TEST_PIN = 0;nop();TEST_PIN = 1;

• Code assembleur produit par le compilateur sdcc :; sdcc_port_timings.c:79: TEST_PIN = 0;clr _TEST_PIN; sdcc_port_timings.c:80: _asm nop _endasm;nop; sdcc_port_timings.c:81: TEST_PIN = 1;setb _TEST_PIN

• Temps mesuré à l'analyseur logique :

temps d'exécution d'une instruction nop29

12.2. Temps d'exécution d'une temporisation codée en assembleur en ligneAprès avoir mesuré le plus petit temps d'exécution, on utilise une boucle de type do-while codée en assembleur etinsérée dans le code source du programme en langage C. Cette technique, baptisée assembleur en ligne, est senséeoptimiser la compilation relativement au code généré par le compilateur. Si l'optimisation manuelle est efficace, letemps d'exécution sera plus réduit qu'avec un programme écrit en langage C.

• Codage en Langage C :

Page 49: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 49

void inline_delay (unsigned char n) __naked { n; _asm mov r0, dpl00001$: nop djnz r0, 00001$ ret _endasm;}

// dans le programme principal

ser_puts("Temporisation assembleur en ligne: ");ser_gets_echo(chaine, MAXCHAR);v = atoi(chaine);TEST_PIN = 0;inline_delay(v);TEST_PIN = 1;

• Code assembleur produit par le compilateur sdcc :

;------------------------------------------------------------;Allocation info for local variables in function 'inline_delay';------------------------------------------------------------;n Allocated to registers;------------------------------------------------------------; sdcc_port_timings.c:37: void inline_delay (unsigned char n) __naked {; -----------------------------------------; function inline_delay; -----------------------------------------_inline_delay:; sdcc_port_timings.c:44: _endasm;

mov r0, dpl 00001$: nop djnz r0, 00001$ ret; naked function: no epilogue.

// dans le programme principal

; sdcc_port_timings.c:98: TEST_PIN = 0; clr _TEST_PIN; sdcc_port_timings.c:99: inline_delay(v); lcall _inline_delay; sdcc_port_timings.c:100: TEST_PIN = 1; setb _TEST_PIN

• Temps mesuré à l'analyseur logique :

L'appel du sous-programme inline_delay(n) dure 2.890µs et l'incrémentation d'une unité de la variable n ajoute720ns au temps d'exécution du sous-programme.

temps d'exécution d'une temporisation écrite en assembleur en ligne avec le paramètre n = 130

Page 50: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 50

temps d'exécution d'une temporisation écrite en assembleur en ligne avec le paramètre n = 231

12.3. Temps d'exécution d'une temporisation basée sur une boucle tant-que

À partir de cette étape, on n'utilise plus d'artifice d'optimisation et on s'appuie entièrement sur le travail du compilateur.Une boucle while doit avoir un temps d'exécution plus court que les autres types de boucles sachant qu'elle utilisemoins d'opérations.

• Codage en Langage C :void while_delay (unsigned char n) { while (n--) ;}

// dans le programme principal

ser_puts("Temporisation boucle tantque: ");ser_gets_echo(chaine, MAXCHAR);v = atoi(chaine);TEST_PIN = 0;while_delay(v);TEST_PIN = 1;

• Code assembleur produit par le compilateur sdcc :;------------------------------------------------------------;Allocation info for local variables in function 'while_delay';------------------------------------------------------------;n Allocated to registers r2;------------------------------------------------------------; sdcc_port_timings.c:47: void while_delay (unsigned char n) {; -----------------------------------------; function while_delay; -----------------------------------------_while_delay: mov r2,dpl; sdcc_port_timings.c:48: while (n--)00101$: mov ar3,r2 dec r2 mov a,r3 jnz 00101$ ret

// dans le programme principal

; sdcc_port_timings.c:114: TEST_PIN = 0; clr _TEST_PIN; sdcc_port_timings.c:115: while_delay(v); mov dpl,r2 lcall _while_delay; sdcc_port_timings.c:116: TEST_PIN = 1; setb _TEST_PIN

Page 51: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 51

• Temps mesuré à l'analyseur logique :

L'appel du sous-programme while_delay(n) dure 5.040µs et l'incrémentation d'une unité de la variable n ajoute1.280µs au temps d'exécution du sous-programme.

temps d'exécution d'une temporisation basée sur une boucle tantque avec le paramètre n = 132

temps d'exécution d'une temporisation basée sur une boucle tantque avec le paramètre n = 233

12.4. Temps d'exécution d'une temporisation basée sur une boucle pour

Comme dans le cas précédent, on s'appuie entièrement sur le compilateur. Sachant qu'une boucle for effectuedavantage d'opérations relativement à la boucle while, le temps d'exécution doit être plus important que dans tousles cas précédents.

• Codage en Langage C :

void for_delay (unsigned char n) {

__idata unsigned char i;

for (i = 0; i < n; i++) ;}

// dans le programme principal

ser_puts("Temporisation boucle tantque: ");ser_gets_echo(chaine, MAXCHAR);v = atoi(chaine);TEST_PIN = 0;for_delay(v);TEST_PIN = 1;

• Code assembleur produit par le compilateur sdcc :

;------------------------------------------------------------;Allocation info for local variables in function 'for_delay';------------------------------------------------------------;i Allocated to registers r3;n Allocated to registers r2;------------------------------------------------------------; sdcc_port_timings.c:55: void for_delay (unsigned char n) {; -----------------------------------------; function for_delay; -----------------------------------------

Page 52: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 52

_for_delay: mov r2,dpl; sdcc_port_timings.c:59: for (i = 0; i < n; i++) mov r3,#0x0000101$: clr c mov a,r3 subb a,r2 jnc 00105$ inc r3 sjmp 00101$00105$: ret

// dans le programme principal

; sdcc_port_timings.c:136: TEST_PIN = 0; clr _TEST_PIN; sdcc_port_timings.c:137: for_delay(v); mov dpl,r2 lcall _for_delay; sdcc_port_timings.c:138: TEST_PIN = 1; setb _TEST_PIN

• Temps mesuré à l'analyseur logique :

L'appel du sous-programme for_delay(n) dure 5.790µs et l'incrémentation d'une unité de la variable n ajoute1.790µs au temps d'exécution du sous-programme.

temps d'exécution d'une temporisation basée sur une boucle pour avec le paramètre n = 134

temps d'exécution d'une temporisation basée sur une boucle pour avec le paramètre n = 235

12.5. Récapitulatif des temps d'exécutionTableau 11. Tableau récapitulatif des temps d'exécution

Instruction 1er appel Appel suivant

nop 540ns idem

Boucle do-while assembleur en ligne 2.890µs 720ns

Boucle while en langage C 5.040µs 1.280µs

Boucle for en langage C 5.790µs 1.790µs

Page 53: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 53

13. Outils de développementCette section rassemble les références sur les outils utilisés dans ce support. Ce «catalogue» ne prétend pas êtreexhaustif.

13.1. C/C++ sur Windows : Dev-Cpp

Dev-Cpp est une interface de développement intégrée (IDE ou Integrated Development Environment très connue surWindows. Elle permet d'utiliser les outils GNU : le compilateur gcc36, le debugger gdb37, make38, etc.

Dev-Cpp39 est téléchargeable à partir du site SourceForge40. Le fichier exécutable de la forme devcpp-x.x.x_x_setup.exe comprend l'interface graphique et tous les outils de développement. Il n'est pas nécessaired'installer d'outils supplémentaires pour commencer à développer en C/C++.

13.2. C/C++ sur GNU/linux

Les outils de la chaîne de développement C/C++ sont installés par défaut avec le système d'exploitation. On peut levérifier en interrogeant le gestionnaire de paquets APT.$ aptitude search gcc-4.1i gcc-4.1 - The GNU C compileri gcc-4.1-base - The GNU Compiler Collection (base package)p gcc-4.1-doc - documentation for the GNU compilers (gcc, gobjc, g++)i gcc-4.1-locales - The GNU C compiler (native language support files)i gcc-4.1-multilib - The GNU C compiler (multilib files)p gcc-4.1-source - Source of the GNU Compiler Collection

13.3. C sur MSC1210 : SDCC

SDCC est un compilateur C multi-cibles conforme à la norme ANSI. Il supporte les microcontrôleurs (MCUs) desfamilles Intel 8051, Maxim 80DS390, Zilog Z80, Motorola 68HC08, Microchip PIC16 et PIC18.

Ce compilateur est une alternative intéressante pour les microcontrôleurs qui ne sont pas directement supportés parla chaîne d'outils GNU.

Les composants Texas Instruments™ de la famille MSC1210 sont des convertisseurs analogiques/numériques (ADC)qui intègrent un microcontrôleur 8051 avec 2Ko de ROM contenant des fonctions de pilotage de périphériques et decontrôle. Ce type de composant entre donc bien dans les cibles du compilateur SDCC.

Sur Windows XPLe compilateur et ses bibliothèques sont téléchargeables à partir du site SourceForge41. Le fichier exécutable dela forme sdcc-2.6.0-setup.exe disponible à la rubrique sdcc-win3242 de la page de téléchargement du projet.

Cette installation ne comprend que les outils de compilation.

Copie d'écran version SDCC43

36 http://gcc.gnu.org/37 http://www.gnu.org/software/gdb/38 http://www.gnu.org/software/make/39 http://www.bloodshed.net/devcpp.html40 http://www.sourceforge.net/41 http://www.sourceforge.net/42 http://sourceforge.net/project/showfiles.php?group_id=59943 images/sdcc-version.png

Page 54: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 54

Sur Debian GNU/LinuxLe compilateur et ses bibliothèques sont disponibles sous forme de paquets dans la distribution Debian44. La listedes paquets utiles est obtenue en interrogeant le gestionnaire de paquets.$ aptitude search sdccp sdcc - Small Device C Compilerp sdcc-doc - Small Device C Compiler (documentation)p sdcc-libraries - Small Device C Compiler (libraries)p sdcc-ucsim - Micro-controller simulator for SDCC

Comme pour tout logiciel libre, les sources de la chaîne de développement sont disponibles à partir des pages Webdu projet SDCC - Small Device C Compiler45 sur SourceForge46. Pour bénéficier des toutes dernières avancées del'équipe de développement, il est possible de compiler la chaîne de développement.

Téléchargement des sources avec SubversionOn commence par créer une arborescence de stockage local des sources.phil@b0x:~$ mkdir -p SVN/sdccphil@b0x:~$ cd SVN/sdccphil@b0x:~/SVN/sdcc$

Le premier téléchargement se fait avec la commande svn checkout.phil@b0x:~/SVN/sdcc$ svn co https://svn.sourceforge.net/svnroot/sdcc/trunk/sdcc sdcc

Toutes les mises à jour suivantes se font avec la commande svn update.phil@b0x:~/SVN/sdcc$ svn updateÀ la révision 4788.

Compilation de la chaîne de développementLa compilation sur un système GNU/Linux utilise les outils classiques de la chaîne GNU. On retrouve les troisétapes rituelles : ./configure, make et make install• La commande ./configure recense les outils installés sur le poste de travail et les bibliothèques nécessaires à la

compilation. Si cette étape se passe correctement, on obtient un résultat du type :phil@b0x:~/SVN/sdcc$ ./configure<snipped/>

sdcc 2.7.2 is now configured for

Build: Host: Source directory: . C compiler: gcc CFLAGS: -pipe -ggdb -g -O2

ENABLED Ports: avr yes ds390 yes ds400 yes gbz80 yes hc08 yes mcs51 yes pic yes pic16 yes xa51 yes z80 yes

Disable packihx: 0

44 http://www.debian.org/45 http://sdcc.sf.net/46 http://www.sourceforge.net/

Page 55: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 55

Disable ucsim: 0 Disable device lib: 0 Disable sdcpp: 0 Disable sdcdb: 0 Enable documentation: 0 Enable libgc: 0

Install paths: binary files: ${prefix} include files: ${datarootdir}/sdcc/include library files: ${datarootdir}/sdcc/lib documentation: ${datarootdir}/doc/${PACKAGE_TARNAME}

prefix: /usr/local datadir: ${datarootdir} datarootdir: ${prefix}/share

Search paths (incomplete, see manual for all search paths): binary files: $SDCC_HOME/bin include files: /share/sdcc/include path(argv[0])/../share/sdcc/include /usr/local/share/sdcc/include library files: $SDCC_HOME/share/sdcc/lib/<model> path(argv[0])/../share/sdcc/lib/<model> /usr/local/share/sdcc/lib/<model>

• La commande make lance les opérations de compilation en fonction des cibles définies lors de l'étape précédente.

phil@b0x:~/SVN/sdcc$ makefor misc in debugger/mcs51 sim/ucsim; do make -C $misc ; donemake[1]: entrant dans le répertoire « /home/phil/SVN/sdcc/debugger/mcs51 »make[1]: quittant le répertoire « /home/phil/SVN/sdcc/debugger/mcs51 »make[1]: entrant dans le répertoire « /home/phil/SVN/sdcc/sim/ucsim »make -f main.mk allmake[2]: entrant dans le répertoire « /home/phil/SVN/sdcc/sim/ucsim »make[2]: quittant le répertoire « /home/phil/SVN/sdcc/sim/ucsim »<snipped/>

• La commande make install doit être exécutée avec les droits superutilisateur pour installer les binaires et lesbibliothèques dans l'arborescence /usr/local.

phil@b0x:~/SVN/sdcc$ suPassword:b0x:/home/phil/SVN/sdcc# make install<snipped/>mkdir -p /usr/local/share/sdcc/lib/srccp -u -r build/* /usr/local/share/sdcc/libcp -u -r small medium large ./mcs51 ./ds390 ./ds400 \ ./gbz80 ./z80 ./hc08 \ ./pic ./pic16 ./*.c /usr/local/share/sdcc/lib/src<snipped/>

• On peut enfin vérifier que la version active de la chaîne de développement correspond aux outils que l'on vientde compiler.

$ sdcc -vSDCC : mcs51/gbz80/z80/avr/ds390/pic16/pic14/TININative/xa51/ds400/hc08 2.7.2 #4851 (Jun 13 2007) (UNIX)

Activation du support des nombres réelsPar défaut, le support des nombres réels (type float) n'est activé que pour les microcontrôleurs de la familleDS390. Pour activer l'utilisation des nombres réels sur les microcontrôleurs de la famille MSC121x, il faut éditermanuellement le fichier device/lib/printf_large.c et procéder aux modifications suivantes :

phil@b0x:~/SVN/sdcc$ diff -uBb device/lib/printf_large.c.dist device/lib/printf_large.c

Page 56: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 56

--- device/lib/printf_large.c.dist 2006-05-22 23:27:38.868496000 +0200+++ device/lib/printf_large.c 2006-05-22 22:29:34.298724000 +0200@@ -24,9 +24,9 @@ what you give them. Help stamp out software-hoarding! -------------------------------------------------------------------------*/

-#if defined(__ds390)+//#if defined(__ds390)#define USE_FLOATS 1-#endif+//#endif

#include <stdarg.h>#include <string.h>

Il suffit ensuite de reprendre la compilation des outils de la chaîne de développement et leur installation commeprésentées ci-dessus pour bénéficier du support des nombres réels.

13.4. Logiciel de programmation de la mémoire Flash du MSC1210 via le portsérie

Texas Instruments™ fournit un logiciel pour Windows de pilotage de la liaison série entre le PC et le système embarqué.Ce logiciel sert aussi bien à la programmation du composant qu'aux communications lorsque le programme est encours d'exécution.

TIDownloader est disponible à l'adresse : Software for Programming the Flash Memory Using the Serial Port v1.3.4(Rev. C) (sbac018c.zip, 2381 KB )47

47 http://www.ti.com/litv/zip/sbac018c

Page 57: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 57

14. Codes sourceCette section liste les fichiers sources utilisés dans ce document. Ces fichiers sont téléchargeables à partir des liensdonnés ci-dessous.

14.1. Sources GNU/GCC

Ces exemples de programmes sont utilisables dans un environnement de développement avec système d'exploitation.Ils sont utilisés pour illustrer les différences avec le contexte de développement sur les systèmes embarqués industriels.

gcc_sizeof.c, gcc_sizeof.tar.bz248

Fichier source C du programme d'affichage des dimensions de représentation mémoire des types simples par lecompilateur GNU/GCC. Les résultats obtenus sont à comparer avec ceux du même programme exécuté sur unmicrocontrôleur. Voir le fichier source sdcc_sizeof.c pour le microcontrôleur MSC1210.

gcc_fibonacci_single.c, gcc_fibonacci_single.tar.bz249

Fichier source C du programme d'introduction aux éléments de la syntaxe du Langage C. Ce programme estexemple simple de calculs illustrant les limites de représentation des données sur les types entiers du Langage C.

gcc_fibonacci_iterative.c, gcc_fibonacci_iterative.tar.bz250

Fichier source C du programme d'illustration d'appel à un sous-programme en Langage C.

gcc_stdio.c, gcc_stdio.tar.bz251

Fichier source C du programme d'illustration de la gestion des entrées sorties sur les flux standards stdin etstdout. Ce programme utilise les fonctions fournies par la bibliothèque glibc.

gcc_printf.c, gcc_printf.tar.bz252

Fichier source C du programme d'illustration des formats d'affichages standards disponibles avec la fonctionprintf.

14.2. Sources MSC1210

msc1210.h, Lien vers le dépôt Subversion SDCC : msc1210.h53

Fichier d'en-tête contenant les définitions des registres de fonctions spécifiques (Special Functions Registers ousfr) et les définitions des bits spécifiques (Special Bits ou sbit) du microcontrôleur MSC1210.

Ce fichier est directement distribué avec la chaîne de développement SDCC.

rom1210.h, rom1210.h54

Fichier d'en-tête contenant les prototypes en Langage C des fonctions intégrées dans la mémoire ROM dumicrocontrôleur. La documentation sur ces fonctions est donnée par le constructeur du composant : MSC1210ROM Routines.

rom1210.asm, rom1210.asm55

Fichier source en assembleur asx8051 de définition des adresses d'appel des sous-programmes intégrés dans lamémoire ROM du microcontrôleur. Ce fichier est utilisé avec le fichier d'en-tête contenant les prototypes des sous-programmes en Langage C (rom1210.h). Lors de l'étape d'édition des liens, le compilateur fait correspondre lesappels de sous-programmes avec leurs adresses en mémoire ROM.

48 http://www.linux-france.org/prj/embedded/sources/gcc_sizeof.tar.bz249 http://www.linux-france.org/prj/embedded/sources/gcc_fibonacci_single.tar.bz250 http://www.linux-france.org/prj/embedded/sources/gcc_fibonacci_iterative.tar.bz251 http://www.linux-france.org/prj/embedded/sources/gcc_stdio.tar.bz252 http://www.linux-france.org/prj/embedded/sources/gcc_printf.tar.bz253 http://svn.sourceforge.net/viewvc/sdcc/trunk/sdcc/device/include/mcs51/msc1210.h?view=markup54 http://www.linux-france.org/prj/embedded/sources/rom1210.h55 http://www.linux-france.org/prj/embedded/sources/rom1210.asm

Page 58: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 58

La table d'adressage des sous-programmes est fournie par le constructeur du composant : MSC1210 ROM Routines.

ser_msc1210.h, ser_msc1210.h56

Fichier d'en-tête contenant les prototypes des sous-programmes de gestion de la liaison série entre le PC dedéveloppement et le système spécialisé.

lcd_msc1210.h, lcd_msc1210.h57

Fichier d'en-tête contenant les prototypes des sous-programmes de gestion d'un afficheur à cristaux liquides (LCD)standard de type HD44780U.

iut_msc1210.h, iut_msc1210.h58

Fichier d'en-tête contenant les prototypes des sous-programmes de gestion des entrées/sorties spécifiques à la cartemicrocontrôleur utilisée au département Génie Électrique & Informatique Industrielle de l'IUT 'A' Paul Sabatier.On y trouve notamment les sous-programmes utilisés dans l'exemple sdcc_ttl_io_iut.c.

hello_serial.c, hello_serial.c59

Fichier de démonstration de l'utilisation des sous-programmes intégrés dans la mémoire ROM du microcontrôleur.On peut l'utiliser comme patron pour démarrer un nouveau développement.

Makefile, Makefile.tpl60

Ce fichier est un patron de compilation pour les applications utilisateur. On peut l'utiliser comme modèle pourdémarrer un nouveau développement. Il suffit de renommer ce fichier en Makefile sans extension puis de l'éditeren désignant le fichier source C utilisateur avec la variable BASENAME.

sdcc_sizeof.c, sdcc_sizeof.tar.bz261

Fichier source C du programme d'affichage des dimensions de représentation mémoire des types simples par lecompilateur SDCC.

sdcc_fibonacci_single.c, sdcc_fibonacci_single.tar.bz262

Fichier source C du programme d'introduction aux éléments de la syntaxe du Langage C. Ce programme estexemple simple de calculs illustrant les limites de représentation des données sur les types entiers du Langage Cimplémentés dans la chaîne de développement SDCC.

sdcc_fibonacci_iterative.c, sdcc_fibonacci_iterative.tar.bz263

Fichier source C du programme d'introduction à l'utilisation de sous-programmes. Ce programme illustre aussi lepassage de paramètres lors de l'appel du sous-programme dans le programme principal.

sdcc_stdio.c, sdcc_stdio.tar.bz264

Fichier source C du programme d'illustration de la gestion des entrées sorties sur la liaison série de la cartemicrocontrôleur. Ce programme utilise les fonctions de base fournies par le moniteur du MSC1210.

sdcc_printf.c, sdcc_printf.tar.bz265

Fichier source C du programme d'illustration des formats d'affichages standards disponibles avec la fonctionprintf sur le microcontrôleur. Il montre les limites du support des formats standards sur un système embarquésimple.

hello_lcd.c, hello_lcd.tar.bz266

Fichier source C de démonstration de l'affichage sur écran à cristaux liquides (LCD). Ce programme est l'équivalentdu fichier hello_serial.c qui utilise une console via une liaison série.

56 http://www.linux-france.org/prj/embedded/sources/ser_msc1210.h57 http://www.linux-france.org/prj/embedded/sources/lcd_msc1210.h58 http://www.linux-france.org/prj/embedded/sources/iut_msc1210.h59 http://www.linux-france.org/prj/embedded/sources/hello_serial.tar.bz260 http://www.linux-france.org/prj/embedded/sources/Makefile.tpl61 http://www.linux-france.org/prj/embedded/sources/sdcc_sizeof.tar.bz262 http://www.linux-france.org/prj/embedded/sources/sdcc_fibonacci_single.tar.bz263 http://www.linux-france.org/prj/embedded/sources/sdcc_fibonacci_iterative.tar.bz264 http://www.linux-france.org/prj/embedded/sources/sdcc_stdio.tar.bz265 http://www.linux-france.org/prj/embedded/sources/sdcc_printf.tar.bz266 http://www.linux-france.org/prj/embedded/sources/hello_lcd.tar.bz2

Page 59: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 59

sdcc_lcd_set_xy.c, sdcc_lcd_set_xy.tar.bz267

Fichier source C de positionnement du curseur sur un écran à cristaux liquides (LCD). Ce programme illustrel'utilisation de «macro» qui permet de diminuer le volume de code exécutable en effectuant les traitements auniveau du préprocesseur.

sdcc_switch.c, sdcc_switch.tar.bz268

Fichier source C d'illustration de la syntaxe du test à choix multiple : switch. Ce programme donne un exemplede menu offrant plusieurs options à la console.

sdcc_ttl_1bit.c, sdcc_ttl_1bit.tar.bz269

Fichier source C d'illustration de la gestion des entrées/sorties sur un bit disponibles sur la carte MSC1210EValuation Module. Ce programme propose une solution logicielle de traitement anti-rebonds sur l'entrée boutonpoussoir.

sdcc_ttl_io_iut.c, sdcc_ttl_io_iut.tar.bz270

Fichier source C d'illustration de la gestion des entrées/sorties sur plusieurs bits disponibles sur la cartemicrocontrôleur du département Génie Électrique & Informatique Industrielle de l'IUT 'A' Paul Sabatier. Ceprogramme propose un menu permettant la lecture ou l'écriture de 10bits ou d'un bit parmi 10.

sdcc_port_timings.c, sdcc_port_timings.tar.bz271

Fichier source C permettant la mesure des temps d'exécution de différents types de temporisations logicielles.

67 http://www.linux-france.org/prj/embedded/sources/sdcc_lcd_set_xy.tar.bz268 http://www.linux-france.org/prj/embedded/sources/sdcc_switch.tar.bz269 http://www.linux-france.org/prj/embedded/sources/sdcc_ttl_1bit.tar.bz270 http://www.linux-france.org/prj/embedded/sources/sdcc_ttl_io_iut.tar.bz271 http://www.linux-france.org/prj/embedded/sources/sdcc_port_timings.tar.bz2

Page 60: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 60

15. Documentations de référenceCette section rassemble les références documentaires qui ont été utilisées pour construire ce support.

15.1. Système d'exploitation GNU/Linux

Linux - Base d'administration pour le superutilisateur, RUTELe livre Linux - Base d'administration pour le superutilisateur72 est une ressource essentielle pour l'apprentissagedes manipulations de base sur un système d'exploitation GNU/Linux. Il présente de façon détaillée les commandesutilisables sur la console du Shell ainsi que les opérations de séquencement entre les programmes (pipes,redirections, etc.).

La version originale du livre est aussi disponible sous forme de paquet Debian : rutebook. Une fois le paquetinstallé, les pages HTML du livre sont placées dans le répertoire /usr/share/doc/rutebook/html.

15.2. SDCC - Small Device C Compiler

SDCC Compiler User GuideLe manuel SDCC Compiler User Guide73 est une ressource essentielle pour l'utilisation des outils de la chaînede développement SDCC. Toutes les directives et les éléments de syntaxe y sont décrits en détails et mis à jourrégulièrement.

15.3. Microcontrôleurs MSC12xx

MSC121x User's Guide, Guide de l'utilisateur MSC121x, sbau101aLe document MSC121x User's Guide (Rev. A)74 regroupe les définitions des registres de fonctions spécifiques etdes exemples de programmation des différents types de périphériques intégrés dans le microcontrôleur.

MSC12xx Programming with SDCC: An Open-Source Alternative, Programmation des composants MSC12xx avecSDCC, sbaa109a

Le document MSC12xx Programming with SDCC75 a été publié en 2003 et révisé en 2006. Plusieurs remarquessont à faire sur l'utilisation du compilateur SDCC et les exemples proposés.• Il n'est plus nécessaire de compiler les outils SDCC manuellement à partir d'une distribution cygwin. Voir

Section 13.3, « C sur MSC1210 : SDCC ».• L'exemple de programme «Hello, World!» s'appuie sur les bibliothèques livrées avec SDCC. Ce sont des

bibliothèques génériques pour les microcontrôleurs de type 8051. En utilisant les sous-programmes fournisdirectement en ROM dans le composant, on optimise considérablement l'occupation mémoire et les tempsd'exécution.

• Toujours dans le même programme exemple, l'appel à la fonction autobaud() effectue bien l'ajustementautomatique du débit de la liaison série entre le terminal du PC et l'interface du MSC1210 mais l'appel suivantà la fonction ser_init() impose un débit de 19200 bauds par programmation du diviseur de fréquence. Il estdonc préférable de s'appuyer sur les fonctions intégrées du composant.

MSC1210 ROM Routines, Bibliothèque intégrée du MSC1210, sbaa085cLes composants de la famille MSC1210 intègrent 2Ko de ROM dans laquelle sont placés des sous-programmes depilotage du microcontrôleur. Le premier sous-programme utilisé dans ce support : autobaud(); permet d'ajusterautomatiquement le débit de la liaison série entre la console du PC de développement et le microcontrôleur. Ladocumentation sur ces sous-programmes est fournie par le constructeur Texas Instruments™ : MSC1210 ROMRoutines (Rev. C)76.

Pour utiliser les fonctions de la bibliothèque intégrée au composant avec SDCC, il faut procéder à quelquesadaptations.

72 http://www.loligrub.be/contrib/tlepoint/BASE/version-internet.html73 http://sdcc.sourceforge.net/doc/sdccman.pdf74 http://www.ti.com/litv/pdf/sbau101a75 http://www.ti.com/litv/pdf/sbaa109a76 http://www.ti.com/litv/pdf/sbaa085c

Page 61: Sdcc Course

Initiation au développement C sur microcontrôleur

Initiation au développement C sur microcontrôleur $Revision: 1153 $ 61

• Le fichier source d'adressage des sous-programmes ROM.A51 proposé en annexe du document doit être convertien un format compatible avec l'assembleur asx8051 ; voir rom1210.asm.

Le code objet correspondant à ce nouveau fichier source, le fichier rom1210.rel, est obtenu à l'aide de lacommande : asx8051 -losffgp rom1210.asm.

Ce code objet est ajouté à celui de l'application utilisateur lors de la phase d'édition des liens (voir Section 4,« Cycle de développement »). Avec l'exemple du premier programme hello.c, on utilise la commande :sdcc hello.rel rom1210.rel.

• Le fichier d'en-tête contenant les prototypes des fonctions de la bibliothèque doit aussi être modifié ; voirrom1210.h.

MSC1210 EValuation ModuleLe module d'évaluation MSC1210EVM est une carte complète fournie par le constructeur dont les caractéristiquessont décrites à la page : Full EVM for use with the MSC121077.

15.4. Bus I²C

THE I²C-BUS SPECIFICATIONLa documentation THE I²C-BUS SPECIFICATION VERSION 2.1 JANUARY 200078 contient l'ensemble desdéfinitions et des contraintes de communication sur un bus I²C. Le code I²C proposé dans ce document permet aumicrocontrôleur MSC1210 d'être le maître sur un bus I²C. Cette réalisation logicielle doit respecter les contraintesde temps sur les signaux de données (SDA) et d'horloge (SCL) définies dans ces spécifications. Le code I²C proposéest à vocation pédagogique. Dans le cas d'une exploitation industrielle, il est préférable d'utiliser des composantsspécialisés dans le contrôle du bus I²C dont le matériel garantit le respect des spécifications I²C.

A. En-tête ser_msc1210.hLe fichier d'en-tête ser_msc1210.h rassemble les sous-programmes de gestion de la liaison série entre le système dedéveloppement (c'est à dire le PC) et le système embarqué. Voici une description des prototypes de sous-programmes.

• Émission d'un caractère c sur la ligne série.void ser_putc(unsigned char c)

• Émission d'une chaîne de caractères s sur la ligne série.void ser_puts(char code * data s)

• Transmission au programme appelant d'un caractère reçu sur la ligne série.unsigned char ser_getc(void)

• Transmission au programme appelant d'un caractère reçu sur la ligne série avec echo.unsigned char ser_getc_echo(void)

• Réception d'une chaîne de caractères s sur la ligne série. La longueur maximum de la chaîne est limitée à lencaractères.void ser_gets(unsigned char *s, unsigned char len)

• Réception d'une chaîne de caractères s sur la ligne série avec echo. La longueur maximum de la chaîne est limitéeà len caractères.void ser_gets_echo(unsigned char *s, unsigned char len)

77 http://focus.ti.com/docs/toolsw/folders/print/msc1210evm.html78 http://www.nxp.com/acrobat_download/literature/9398/39340011.pdf