Atelier du 11 mars 2008
La programmation c'est si simple : atelier 5
Si nous omettons ces lignes de codes, ces modules prendront le contrôle de certaines lignes d'entrées / sorties et affecteras donc le fonctionnement de notre programme. La ligne suivant définiras la vitesse de l'horloge interne, c.-à-d. quelle ne change pas la vitesse réelle de l'horloge mais elle spécifiera à l'interpréteur quelle en est sa valeur, pour des fins de calculs. DEFINE OSC 4 ' fréquence de l'horloge interne du PIC™ Vous remarquerez qu'à chaque ligne de code que j'ai entré en fin de ligne un commentaire pour nous indiquer ce que fait réellement cette ligne. L'interpréteur ne considère pas les caractères qui suivent l'apostrophe, donc on peut écrire ce que bon nous semble, ces commentaires ne seront lus que par nous, pour notre compréhension.
La majeure partie de l'initialisation est maintenant terminée. Il nous reste seulement qu'à définir nos variables. Il est important de définir nos variables au début du programme, car l'interpréteur réserveras des cases mémoires dans la mémoire vive du CPU et il associera les noms de nos variables avec la case mémoire appropriées. Ces cases mémoires débute dans un 16F628 à partir de l'adresse $0020, mais nous n'avons besoin de le savoir car l'interpréteur le sais lui, grâce à son fichier INC et il fera la distribution de ces cases RAM pour nous. Si nous écrivons un programme en code machine, sans utiliser un interpréteur, nous devrons connaître ces adresses. La grosseur de la mémoire RAM disponible dans le PIC™, détermineras le nombre et le type de variables que nous pourrons utiliser. Dans le cas d'un 16F628, on dispose de 224 bytes de RAM. On pourrait donc avoir 224 variables de type BYTE (octet) avant que l'interpréteur nous signale une erreur. La commande utiliser pour définir nos variables s'appelle VAR et s'utilise comme suit;
NOM VAR TYPE ' Nom de la variable, VAR, TYPE de variable; BIT, BYTE, WORD
Le nom choisis pour notre variable doit respecter certains critères, ils doivent commencer par une lettre et ne peuvent dépasser 31 caractères. Le nom des variables ne sont pas "case sensitive", Donc NOM, nom et Nom représenteront tous la même variable. Nous pouvons aussi utiliser des chiffres ou la barre de soulignement (underscore _), dans le nom de notre variable, mais pas au début! Des variables appelées Score_31, Radio26 et b23 sont valides, mais pas 123abc. Certains nom sont réservés par l'interpréteur et ne peuvent être utilisés pour nos variables. Parmi ces noms réservés, on retrouve le nom des commandes elles-mêmes comme ABS, ADCIN, AND… La liste des noms réservés est fournie dans la documentation de l'interpréteur. (Appendix C, PBP). Les nom des registres inclus dans le fichier INC, sont aussi réservés et ne peuvent être utilisés.
Le TYPE de variable doit aussi être indiqué. Ces TYPE sont BIT, BYTE ou WORD. Le premier type BIT réservera, comme le nom le dit, une seule bit. L'interpréteur pourra emmagasiner jusqu'à huit de ces variables dans un seul octet, donc la première variable de type BIT réserveras un byte et les sept autres variables de type BIT iront se loger dans le même byte. Comme nous l'avons vu précédemment, une variable de type BIT ne pourras prendre que deux valeurs 0 ou 1. Le deuxième type est le byte, il pourrait prendre les valeurs de 0 à 255. (ou -128 à 127) Le troisième type est le word, ce dernier réservera deux octets et les valeurs de 0 à 65535. (ou -32768 à +32767). La représentation d'un chiffre négatif place le MSB à 1.
Regardons maintenant les variables que nous utiliseront dans notre programme de traduction.
NEW VAR BYTE ' Conserve l'état des commutateurs inversés ( lecture 0 = commutateurs ON)
OLD VAR BYTE ' Conserve l'état des commutateurs précédents ( lecture 0 = commutateurs ON)
NEWBIN VAR BYTE ' Conserve la valeur du code entrée ***BIN est un nom réservé ***
NEWDEC VAR BYTE ' Conserve la valeur du code entrée ***DEC est un nom réservé ***
NEWHEX VAR BYTE ' Conserve la valeur du code entrée
TEMPA VAR BYTE ' Conserve la valeur de l'accumulateur
COUNTER VAR BYTE ' Utilisée par la routine Delay. ***COUNT est un nom réservé ***
DATABIT VAR BIT ' Utilisée par la routine SendLCD
COMMAND VAR BYTE ' Utilisée par la routine SendLCD
Vous remarquerez que j'ai du changer certain noms de variables, que nous avions choisis en établissant notre ordinogramme, car ces noms sont réservés par l'interpréteur que nous avons choisi d'utiliser. Nous utilisons aussi le port A pour contrôler notre afficheur LCD, certains des bits du port A auront une fonction spécifique. RA7 serviras de RS et RA6 pour le clock E. Nous pouvons définir des ALIAS que nous permettrons d'accéder à ces bits du port A en utilisant des noms plus familiers. Le bit 7 (RA7) peut être appelé directement PORTA.7 et de même le bit 6 (RA6) s'appelle PORTA.6, en se servant de ces informations, nous pouvons écrire:
LCD_RS VAR PORTA.7 ' Pointe le bit 7 du port A, LCD Register Select pin
LCD_E VAR PORTA.6 ' Pointe le bit 6 du port A, LCD Clock pin
Les CPU étant des outils très versatiles, nous devons aussi préciser ce que nous voulons leur faire exécuter. On doit donc prendre soin de contrôler chacun des registres du CPU pour nous garantir un fonctionnement interne qui sera compatible avec notre programme. Ces registres sont initialisés lors d'un reset du CPU, il est donc important de voir si ces valeurs initiales devront être changées. La documentation du manufacturier est nécessaire pour comprendre les valeurs de ces registres. Un de ceux-ci est le registre INTCON, il contrôle le mécanisme d'interruption, il est placé à 00 lors de l'initialisation, ce qui à pour effet de désactiver tous les interruptions. Dans notre cas, nous n'utiliseront pas les interruptions, donc la valeur de ce registre doit rester à zéro. Deux autres registres appelé TRISA et TRISB détermine si les ports A et B seront en entrées ou en sorties. Après un reset ils sont tous configurés en entrées (valeur 1, pour chaque bit en entrée)
Dans notre programme nous désirons utiliser le port A principalement en sortie et le port B en entrée. Il ne sera donc pas nécessaire de donner l'information TRISB = %11111111 (% indique le binaire) car c'est une des fonctions déjà implémentée dans le processus de reset. Nous pouvons quand même l'inscrire dans notre liste de commande, ce qui nous servira de "pense-bête", soit comme un commentaire, soit comme une commande. Pour le port A qui est présentement en mode "input", nous devrons obligatoirement inscrire une ligne TRISA. Voici comment déterminer la valeur à inscrire, en partant du MSB (RA7) inscrivez si le bit doit être en entrée (In=1), ou en sorties (Out=0). Dans notre cas tous les bits seront en sorties sauf RA5 qui sert de Reset. Donc la valeur que l'on doit donner à TRISA sera %00100000 ($20 en hex, identifié par $) Inscrivons donc;
TRISA = %00100000 ' port A en sortie sauf RA5, reset
TRISB = $FF ' port B en entrée.
Les deux notations binaire (%) et hex ($) sont valide, mais le binaire nous indique directement qui est en entrée et qui est en sortie, en un seul coup d'œil!
La dernière chose à faire est d'activer les résistances "pullups" du PORT B, pour ce faire nous devrons inscrire le bit RBPU à zéro. Ce bit de contrôle est à la position 7 du registre OPTION_REG. Nous pouvons donc déclarer directement OPTION_REG.7 = 0 et les pullups seront activés L'initialisation complétée nous pouvons commencer à écrire les lignes de codes qui effectueront le travail souhaité. Si on se rapporte à notre ordinogramme de la page 16, la première tâche à effectuer est l'initialisation du LCD. Le fabricant du LCD nous recommande d'attendre au moins 15 mS avant de donner des commandes au module LCD, après la mise sous tension. Notre PIC ™ ne commence à travailler que 72mS après la mise sous tension, à cause de la commande PWRT_ON donc la première condition est respectée sans problème. Par la suite le fabricant nous indique que l'on doit faire l'initialisation du LCD, en lui envoyant une certaine séquence de code, tout en respectant des délais pour permettre à l'afficheur de les accepter. Cette séquence tient compte
que nous pourrons l'initialiser, même en utilisant une interface de 4 bits seulement, car toutes les commandes d'initialisation sont acceptées, grâce au lignes RS, E, DB7, DB6, DB5 et DB4.
Cette séquence est celle-ci:
La méthode que l'on va utiliser sera la suivante, puisque durant les quatre premières commandes on de doit que transmettre un nibble et que notre routine SendLCD accepte un octet, nous combi- neront ces commandes. Donc un fixe le délai à au moins 4 mS, et on envoie $33 et $32. Par la suite on ajuste le délai à 500 uS et on envoie les commandes $28, $08, $0C et $06. Durant toutes ces commandes il faudra s'assurer que DATABIT sera à zéro, pour indiquer à notre routine SendLCD qu'il s'agit bien de commande.
Quand nous préparons un programme pour l'interpréteur, il est très important de suivre sa syntaxe. Les lignes importantes de notre liste devront posséder des étiquettes (labels) qui permettront à l'interpréteur de comprendre, ou est le début du programme principal et ou est le début de nos routines. Dans le cas de MicroCode Studio, les étiquettes doivent être au début de la ligne et suivie par : Les commandes suivent ensuite, ces commandes peuvent être écrites en utilisant les majuscules ou les minuscules, l'interpréteur choisi n'en fait aucun cas. Par contre si nous écrivons pour le langage "C", il faudra en tenir compte, surtout pour les noms de variables. Par la suite, vous pouvez inscrire un commentaire, précédé par l'apostrophe '. Je vous suggère encore une fois, de ne pas négliger les commentaires, ils vous rendront de très bon service.
Voici donc le début de notre programme: