Atelier du 26 février 2008 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
La programmation c'est si simple : atelier 4 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
J'avais mentionné un peu plutôt, qu'un module bien conçu devrait conserver les valeurs des registres. Donc notre module SendLCD, devrait lui aussi conserver les registres et la valeur contenu dans l'accumulateur, avant d'effectuer sa fonction. A la fin juste avant le retour, il devrait les replacer à leurs états initiaux. Toutefois dans certains cas, on peut omettre cette étape si le changement ne pose aucun problème au déroulement normal du programme. Regardons maintenant le nouveau module DoDelay. Celui-ci utilisera l'accumulateur pour faire son travail, donc quand le module DoDelay termineras et qu'il redonne le contrôle au module "appelant", la valeur de l'accu- mulateur sera changé. Dans notre module SendLCD, à chaque fois que le délai est appelé, la valeur contenue dans l'accumulateur sera modifié, nous perdrons donc la valeur de notre commande ou la position des bits de contrôle RS et E! Ce n'est pas très intéressant en soi, mais comment peut-on donc sauvegarder notre valeur? Deux méthodes s'offrent à nous, la première sauvegarder la valeur de l'accumulateur avant d'appeler DoDelay et la recharger après DoDelay. Cette méthode nous demandera douze lignes de code, six sauvegardes et six rappels. La deuxième méthode sera incluse dans DoDelay, ce qui nous demandera seulement 2 lignes de code, une sauvegarde et un rappel. Voyons comment s'effectue cette opération. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Tableau 14 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Quel sera la longueur de ce délai? Pour
répondre à cette question il faudra savoir, quel est la vitesse du CPU et
le nombre de cycles utilisés pour chaque instruction. Supposons un PIC qui
utilise une horloge interne de un mégahertz, chaque impulsion d'horloge
dureras donc une microseconde. La plupart des instructions d'un pic,
s'effectue en un seul coup d'horloge, donc ce CPU à une capacité de un
million d'opérations par seconde (1 MIPS). Si nous effectuons un calcul
sommaire, nous obtiendrons, la longueur de notre module DoDelay.
Premièrement sauvegarder l'accumulateur (1), Charger l'accumulateur avec
248 (1), décrémenter l'accumulateur (247), vérifier sa valeur (247),
rétablir l'accumulateur (1), et le retour (2), pour un total de 499 coups
d'horloge. Cette routine prendra donc environ 499 microsecondes pour
s'effectuer. Elle sera donc très courte et dans certains cas, elle ne sera pas suffisante. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Supposons que nous ayons besoin d'un délai
plus important, comme cent millisecondes. Comment pouvons-nous améliorer
cette routine pour avoir un délai plus important? On pourrait imaginer appeler cette routine environ 200 fois pour créer notre délai requis. On pourrait aussi faire une autre routine qui accepterais une valeur dans une variable et qui répéterait DoDelay 200 fois!!! |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Tableau 15 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Ce mécanisme de modules intercalés, peut-être utilisé un certain nombre de fois. La grandeur de la pile ("stack") nous limiteras, quand à la quantité de boucles intercalées. Les CPU modernes nous offrent aussi, d'autres possibilités pour générer des délais, il s'agit des "timers". En effet plusieurs CPU possèdent des registres internes capables de compter au-delà de 256, car il utilisent des registres doubles et des modules diviseurs pour l'horloge ("pre-scaler"). Si vous posséder un tel registre, je vous recommande de vous en servir, votre programme sera plus léger, car l'utilisation de ces "timers" est très simple. De façon générale, vous choisissez une valeur pour le diviseur, vous précharger une valeur dans le timer en question et il ne vous reste qu'à vérifier un "flag" qui indique que l'opération est terminée! Il peut même vous l'indiquer en générant une interruption (IRQ), pendant que vous effectuer d'autre tâche. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Nous regarderons en détails, les mécanismes de ces registres, les méthodes d'interruptions et le fonctionnement interne du microcontrôleur, dans les chapitres qui suivent. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
8-Écrire le code, en suivant la syntaxe de l'interpréteur. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Une des dernières étapes
consiste à transformer nos ordinogrammes, en un code acceptable pour le
CPU que nous utiliserons. Pour ce faire nous nous servirons d'un
interpréteur. Cet outil agit comme un traducteur, et génère normalement du
code machine dans un fichier de type "HEX". Pour nommer quelques-uns de
ces outils, il y a l'assembleur, le langage "C" et le basic. Chacun de ces
traducteurs peuvent produire du code machine pour une multitude de CPU.
Ils feront usage de librairies, contenant la traduction elle-même, propre
à chaque CPU. Ces interpréteurs, en plus de traduire nos lignes de codes,
réserverons des cases mémoires pour nos variables déclarées et
s'occuperons des directives données au CPU dans ses registres de
configuration. Ces directives contrôleront la structure interne du CPU,
comme la source d'horloge interne ou externe, utilisation des
comparateurs, du voltage de référence, l'utilisation des "timers" et la programmation des ports d'entrée / sorties pour ne nommer que ceux-là. Dans le cas d'un PIC ™ il s'agit, entre autre, du "config word" (fuses). |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comme la plupart d'entre vous on suivi les présentations de Daniel VA2HDD, sur le PicBasic Pro de microEngineering Labs Inc, nous nous serviront de cet interpréteur pour poursuivre nos exercices. Le choix du PBP© est purement académique, tout autre interpréteur aurais été valide, mais vu sa simplicité, il devient donc le meilleur choix pour le groupe. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Le défi de la page blanche quand on commence un programme en PBP© est similaire à l'expérience que j'ai vécue en écrivant ce document, 22 pages plus tard, je dois avouer que le plus dur est passé. Par où commencer? Commencez donc par un commentaire, qui décriras le nom de votre programme, une description brève de ce qu'il effectue comme travail et votre nom, c'est comme le générique qui apparait au début d'un film, les noms les plus importants y sont présents! Ces commentaires doivent être précédés par une apostrophe ' pour être interprétés comme un tel. L'apostrophe indique le début du commentaire, jusqu'à la fin de la ligne, on doit donc en placer une au début de chaque ligne de commentaires. Dans d'autre interpréteur le caractère qui détermine le début d'un commentaire est différent, il faut consulter le manuel, ou la section d'aide du programme. Une des premières lignes indiquera à l'interpréteur, la configuration matérielle que nous utiliserons. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Cette ligne ressemblera à ceci: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@ DEVICE PIC16F628, INTRC_OSC_NOCLKOUT, WDT_OFF, MCLR_ON, PWRT_ON, BOD_ON, LVP_OFF, CPD_OFF, PROTECT_OFF | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Qu'est ce que c'est que ce charabia, me direz-vous? C'est la façon que nous devons utiliser pour que l'interpréteur génère le config word, ou fuses, si vous préférez et la syntaxe est définie dans un fichier "include" dans le programme de l'interpréteur. Regardons une partie du contenu de ce fichier, appelé M16F62X.inc (page suivante). Vous remarquerez que chacune des commandes de notre ligne de code sont clairement définies dans ce fichier. Voici leur signification: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@ DEVICE PIC16F628 Indique à l'interpréteur que nous avons choisis un PIC 16F628 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
INTRC_OSC_NOCLKOUT Un des 11 choix disponibles; Oscillateur interne et on utilise la pin RA6 comme un I/O régulier, donc on prend l'option "no clock output" | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
WDT_OFF Le Watch Dog Timer est inactif, cela nous permettra d'utiliser le timer 0. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
MCLR_ON La broche RA5 nous servira de Master Clear. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PWRT_ON Le Powerup Timer est on, retarde le début des opérations du CPU | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
BOD_ON Détecte une baisse dans l'alimentation VCC et génère un Reset. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
LVP_OFF La fonction de programmation à bas voltage en désactivée | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
CPD_OFF La protection du data est off, le data peut donc être lu du PIC™ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PROTECT_OFF La protection du code est off, il peut donc être lu du PIC™ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Tableau 16 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Grâce à cette seule ligne nous venons de faire plusieurs choix importants. Cette ligne sera pratique- ment toujours la même, pour tout les programmes que nous écrirons, dans cet environnement. Il est très important que les commandes soient écrites de la même façon qu'a l'intérieur du document INC, sinon quand l'interpréteur essaieras de compiler notre programme, il nous donnera un message d'erreur. Je vous conseille d'utiliser la commande Copier-coller pour prévenir les erreurs de frappe! | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
A l'intérieur du même fichier, nous retrouverons aussi, le nom déjà associé aux registres internes du PIC™, comme TMR0, PCL, STATUS, PORTA, PORTB, PCLATH et INTCON pour n'en nommer que quelques un. Donc si nous voulons faire référence au port d'entrée / sorties A, nous pouvons déjà l'appeler PORTA, car il est défini dans le fichier include. Quand nous décidons notre CPU il est préférable de voir les noms déjà attribués, dans le fichier include et d'utiliser les mêmes. Nous verrons comment on peut changer ces noms, quand nous regarderons les variables. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
À la suite de cette ligne, nous activerons ou désactiverons les modules internes du PIC ™ en fonction de nos besoins. Dans le cas du 16F628, pour le programme qui nous concerne, nous ne nous servirons pas des comparateurs, du voltage de référence et du Pulse Width Modulation. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Nous les désactiverons ces modules en ajoutant trois lignes de code: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
CMCON = 7 ' désactive les comparateurs. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
VRCON=0 ' désactive le voltage de référence | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
CCP1CON=0 ' désactive PWM | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||