Vous êtes sur la page 1sur 41

découvrir créer partager

cours intensif
d’assembleur
(1)

le premier programme

Miroslav Cina (Allemagne), miroslav.cina@t-online.de

De nos jours doit-on encore parler


« assembleur » ? Notre réponse est un oui (franc
et massif), car pour les microcontrôleurs à 8 bits
en particulier, optimiser la longueur du code et
la rapidité d’exécution peut s’avérer utile. Notre
cours intensif autour d’un petit µC PIC allie comme
d’habitude théorie et pratique.

L’assembleur est un langage de pro- déroulement d’une routine en assembleur. Le logiciel utilisé est mis à disposition
grammation très proche du matériel, L’assembleur est aussi le meilleur moyen gratuitement. Sous Windows, nous pou-
ce qui présente des avantages et des de découvrir le matériel dans le détail. Les vons utiliser un éditeur de texte (Note-
inconvénients. langages de haut niveau cachent (plus ou pad) pour saisir le code source, pour l’as-
Avec un langage de programmation de moins) aux yeux du programmeur ce qui sembler ensuite, c.-à-d. le traduire en
haut niveau, c’est du compilateur que se passe dans les registres & Co. langage machine, à l’aide du programme
dépend l’efficacité de la compilation du Cependant, en assembleur, tout est vrai- MPASM.exe (inclus dans la Suite MPASM
code source. En assembleur, pour obte- ment à faire soi-même – la simple mul- de Microchip). La Suite MPASM fait par-
nir un résultat optimal, il faut s’occuper tiplication de deux petits nombres peut tie de l’IDE (Integrated Development
soi-même tant de la taille du code que requérir une certaine réflexion. Environment) MPLAB. On pourra télé-
de la vitesse d’exécution. La conversion charger l’IDE MPLAB gratuitement chez
de l’assembleur en langage machine (ou Matériel et logiciel Microchip [2].
code hexadécimal) est en effet parfaite- Comme je travaille depuis longtemps Finalement, le logiciel du PICkit2 assure le
ment définie. avec les µC PIC de Microchip, j’ai opté « transport » vers le µC du fichier hexa-
La longueur du programme est un aspect ici pour l’un des plus petits d’entre eux, décimal résultant de l’assemblage. Voilà,
très important en cas d’utilisation d’un le PIC12F675 [1]. Ce µC d’un euro ou c’est tout.
petit µC (un PIC10F200 par ex. n’a que moins fait parfaitement l’affaire pour de
256 mots de mémoire de programme). nombreuses applications simples. Les registres
La performance peut jouer un rôle impor- Pour les expériences proposées, j’ai utilisé Commençons par découvrir notre µC et
tant dans les calculs complexes là où un un programmateur PICkit2 et une petite apprendre quelques instructions d’as-
compilateur C est capable parfois de pro- carte d’expérimentation (l’ensemble est sembleur. Pas de panique – le premier
duire des inepties. Dans de tels cas, il est souvent vendu sous le nom de PICkit2 paquet de théorie n’est pas très compli-
alors logique de programmer directement Starter Kit). Dans la prochaine partie qué ; ensuite nous pourrons démarrer
en assembleur les parties de programme du cours, nous verrons comment réali- dans la foulée.
critiques. Autre avantage : pour les opé- ser soi-même une carte d’expérimenta- Le PIC12F675 est un µC à 8 bits de la
rations à la chronologie critique, on peut tion simple. Rien n’interdit bien entendu famille midrange (milieu de gamme)
calculer exactement le nombre de cycles d’utiliser pour ce cours le programmateur de Microchip. Ce µC est proposé entre
d’horloge (c.-à-d. la durée) nécessaire au PICkit3 plus récent. autres en boîtier PDIP-8 (Plastic Dual

18 juillet/août 2015 www.elektormagazine.fr


q&r cours banc d’essai trucs & astuces logiciel

Inline Package). Six des huit pattes sont endroit, est le bit n° 5 (RP0), le Regis- Premières instructions
des broches de port numérique d’usage ter Bank Select Bit. Il est utilisé pour Il est temps maintenant de découvrir
général (GP0 à GP5). GP3 ne peut être la sélection entre les deux banques de quelques instructions d’assembleur (les
utilisée qu’en entrée, les cinq autres bro- mémoire ; le bit doit être mis à 1 (levé) instructions de base en quelque sorte).
ches peuvent l’être soit en entrée, soit en ou à 0 (effacé) avant que l’on ne puisse Le PIC12F675 fait partie des µC RISC
sortie. Le PIC dispose de 1 024 mots de donner une adresse comme paramètre à (Reduced Instruction Set = à jeu d’ins-
mémoire de programme flash, ainsi que une instruction subséquente. Nous avons tructions réduit) – il n’y a que 35 instruc-
de 64 octets de SRAM utilisables libre- accès aux emplacements de mémoire 80h tions à apprendre.
ment et de 128 octets d’EEPROM. à FFh lorsque le bit est levé ; si RP0 = 0,
nous avons accès aux emplacements de
Lorsque l’on programme en assembleur, il mémoire 00h à 7Fh.
faut travailler avec des registres ; ce sont, L’écriture du registre Config se fait lors du
ici, des unités de mémoire de 1 octet qui flashage du µC (cf. ci-dessous). Il définit
ont une fonction logique spécifique. Cer- par ex. l’utilisation (ou non) de l’oscilla-
tains registres font partie du noyau ; ils teur interne du µC.
peuvent, par ex. lors de calculs, stocker
des valeurs de 8 bits ou donner des infor- Pour le moment, laissons de côté le
mations quant à l’état du µC. D’autres registre des options. Maintenant nous
registres sont responsables des blocs allons nous intéresser brièvement à trois
périphériques du µC, le registre GPIO autres registres qui, à la différence de
qui donne l’état des entrées/sorties par ceux qui ont précédé, s’occupent des
exemple. périphériques.

Pour les PIC, il y a toujours au moins TRISIO, GPIO et ANSEL


quatre registres dans le noyau : Les registres TRISIO, GPIO et ANSEL
servent à commander les E/S. Pour le
• Le registre W registre ANSEL, pour le moment il faut
• Le registre de configuration juste retenir que nous devons le mettre
(__CONFIG) à 00h pour les premières expériences – ce
• Le registre des options qui désactive les fonctions analogiques.
(OPTION_REG) Le registre TRISIO commande le sens
• Le registre d’état (STATUS) de la communication. Les bits corres-
pondants du registre TRISIO définissent
La mémoire SRAM de 64 octets utili- l’utilisation d’une broche de port soit en
sable librement, mais aussi la plupart des entrée, soit en sortie. La valeur 0 en fait
registres, sont accessibles à des adresses une sortie, un 1 une entrée. Si par ex.
de mémoire bien définies. Une adresse le premier bit est à zéro (on écrit TRI-
sur 8 bits permet d’accéder à 256 empla- SIO<0> = 0), la broche GP0 est utilisée
cements de mémoire. Un coup d’œil à en sortie.
la cartographie de la mémoire (memory
map) (fig. 1) nous apprend que l’on n’a La seule exception est, nous le disions
pas réellement 256 emplacements de plus haut, la broche de port GP3 (qui rem-
mémoire à disposition ; le registre d’état plit également la fonction MCLR - Master
par ex. est accessible aux adresses 03h Clear) ; elle ne peut être utilisée qu’en
et 83h. entrée. Le bit correspondant du registre
La cartographie montre que le registre TRISIO est donc toujours à 1.
GPIO (nous l’utiliserons bientôt) se trouve Le registre GPIO nous permet de com-
à l’emplacement 05h ; nous voyons aussi mander directement les entrées/sor-
que nous pouvons accéder à la mémoire ties. Toute écriture dans le registre GPIO
d’application (64 octets) sous les adresses affecte directement les broches configu-
de mémoire comprises entre 20h et 5Fh. rées en sortie, les entrées pouvant quant Figure 1. La cartographie de la mémoire donne
Les registres sans emplacement de à elles être interrogées par une lecture les adresses des registres et des emplacements
mémoire, comme le registre des options du registre GPIO. de mémoire utilisables librement.
et le registre W, sont des exceptions.
Le registre W (W = Work, travail) est le
registre principal du µC. Toutes les opé-
rations arithmétiques par ex. se font par
le biais du registre W.
Le registre d’état est subdivisé en bits
individuels (cf. fig. 2). L’important, à cet Figure 2. Les bits du registre d‘état (status).

www.elektormagazine.fr juillet/août 2015 19


découvrir créer partager

D’ailleurs, la casse (écriture en majus- à l’emplacement de mémoire 20h.


MOVLW et MOVWF cules ou minuscules) des instructions en
L’instruction MOVLW charge une valeur assembleur est sans importance, nous Pour résumer, l’exemple suivant reprend
à 8 bits dans le registre W. La valeur elle- pouvons donc également écrire : les instructions MOVLW, MOVWF et CLRF :
même peut être représentée en binaire,
hexadécimal ou décimal. MOVLW k movlw H’9E’
La syntaxe de la commande est la movwf H’20’
suivante : Les exemples ci-après montrent com- clrf H’20’
ment écrire la valeur sous forme binaire
movlw k (préfixe B), hexadécimale (H) et déci- La figure 3 montre l’effet sur les empla-
male (D) : cements de mémoire (au départ, nous ne
où k est une valeur se trouvant dans connaissons pas les valeurs qu’avaient
l’intervalle compris entre 00h et FFh movlw B’10011110’ le registre W et l’emplacement de
(1 octet). movlw H’9E’ mémoire 20h).
movlw D’158’
BSF et BCF
Les trois instructions sont identiques, elles Contrairement aux instructions précé-
chargent la valeur 9Eh dans le registre W. dentes qui travaillent toujours avec des
octets, les instructions BSF et BCF opèrent
L’instruction MOVWF copie le contenu du sur des bits. BSF est l’abréviation de Bit
registre W vers un emplacement de Set f et, par analogie, BCF l’abréviation
mémoire : de Bit Clear f où f représente l’adresse
d’un emplacement mémoire. La syntaxe
movwf f est la suivante :

où f est une valeur entre 00h et 7Fh qui bsf f, d


représente l’adresse-cible (comme nous bcf f, d
Figure 3. Mode opératoire des instructions
MOVLW, MOVWF et CLRF.
le disions plus haut, il faudra aupara-
vant, selon le cas, lever ou effacer le 5e bit où f est une valeur entre 00h et 7Fh et
du registre d’état, pour commuter d’une d un chiffre entre 0 et 7.
banque de mémoire à l’autre).
Il s’agit d’instructions qui mettent à un
Si nous voulons par ex. écrire la (bsf) ou effacent (bcf) un seul bit d’un
valeur 9Eh à l’adresse 20h, la séquence octet se trouvant à un emplacement de
des instructions pourrait être : mémoire indiqué. Un exemple :

movlw H’9E’ bsf H’03’, H’05’


movwf H’20’
Cette instruction met à 1 le bit 5 (d =
La première instruction charge la 05h) de l’emplacement de mémoire 03h
Figure 4. DECFSZ permet de réaliser des
boucles.
valeur 9Eh dans le registre W et la (f = 03h).
seconde écrit le contenu du registre W à
l’emplacement de mémoire 20h. GOTO
Tout comme avec bien d’autres langages
CLRF de programmation, GOTO permet d’inter-
L’instruction met le contenu d’un empla- rompre le déroulement linéaire du pro-
cement de mémoire à 00h (CLRF = Clear gramme pour le faire se poursuivre à un
f). autre endroit – spécifié dans l’instruction.
La syntaxe de l’instruction est : La syntaxe de l’instruction est :

clrf f goto k

où f est une valeur entre 00h et 7Fh qui où k est une adresse de la mémoire de
représente l’adresse-cible. programme. En fait, k peut prendre une
valeur entre 000h et 7FFh, mais comme
Un exemple : notre µC ne possède que 1 024 mots
de mémoire de programme, les valeurs
clrf H’20’ au-delà de 3FFh sont hors des limites.
On pourra, au lieu de k, également spéci-
Figure 5. CALL sert à appeler un sous- se traduit par l’écriture de la valeur 00h fier une étiquette (label), c’est-à-dire un
programme.

20 juillet/août 2015 www.elektormagazine.fr


q&r cours banc d’essai trucs & astuces logiciel

STATUS EQU H’0003’


nom attribué à un emplacement particu- tion d’un 1 et réécriture en 20h. La valeur
lier de la mémoire de programme. Cette actuelle diminue ainsi et passe à FEh, et Nous n’avons plus besoin, plus loin dans
étiquette doit être définie ailleurs dans ainsi de suite. le code, d’indiquer explicitement l’empla-
le code assembleur ; il suffit de l’inter- Nous avons donc créé une boucle exé- cement auquel peut être trouvé le registre
caler juste avant l’instruction à partir de cutée 256 fois dans notre exemple. Si la d’état et écrire par exemple :
laquelle doit se poursuivre le programme. valeur en 20h atteint finalement 00h, on
Ici, il faut tenir compte de la casse ! a saut de l’instruction goto ; nous sortons bsf STATUS,H’05’
de la boucle. À noter que nous n’avons
DECFSZ pas utilisé le registre W ici. au lieu de
Cette instruction est une abréviation de On peut ainsi utiliser une boucle lorsque,
DECrement F and Skip if Zero (décré- par ex., on souhaite intégrer une tem- bsf H’0003’,H’05’
menter F et sauter si zéro) ; nous pour- porisation dans le déroulement du pro-
rions également la nommer « Instruction gramme (pour faire clignoter une LED pour mettre à un le 5e bit du registre
de boucle » (loop instruction). Elle est par ex.). d’état. Ne faisons pas les choses à moitié
chargée de l’exécution conditionnelle de et convenons aussi que
l’instruction qui suit. On commence par CALL / RETURN
décrémenter (diminuer de 1) la valeur de Tout comme nous l’avons vu avec d’autres RP0 EQU H’05’
l’emplacement de mémoire f pour ensuite langages de programmation, call sert à
exécuter soit l’instruction suivante (si le appeler un sous-programme et return à Nous pouvons dès lors, par
résultat est différent de zéro), soit sau- terminer le sous-programme et reprendre
ter ladite instruction et exécuter celle qui le programme principal. bsf STATUS,RP0
suit immédiatement après (si le résultat La syntaxe de l’instruction est très proche
est égal à zéro). de celle de goto : et
La syntaxe est la suivante :
call k bcf STATUS,RP0
decfsz f,d
où k est ici aussi une adresse de la mettre à un et effacer le 5 e  bit du
où f est l’adresse d’un emplacement mémoire de programme ; elle peut aller registre d’état et ainsi commuter entre
mémoire et d définit où doit être enregis- de 000h à 3FFh. les banques de mémoire.
tré le résultat de l’opération (décrémen- Ici à nouveau il va de soi qu’il est possible Le code se laisse également plus facile-
tation). Si d = 0, le résultat est stocké d’attribuer une étiquette. Nous préférons ment porter d’un type de µC à un autre
dans le registre W et l’emplacement de donner un nom explicite à notre sous-pro- (passage par ex. d’un petit PIC à un PIC
mémoire n’est pas modifié ; si d = 1, gramme, Delay par exemple. plus grand). Le registre d’état peut, avec
le résultat est écrit à l’emplacement de un autre type de µC, se trouver à un autre
mémoire (le registre W reste inchangé). return ne comporte pas de paramètre emplacement de mémoire ; il nous suffit
La figure 4 montre comment cette ins- additionnel : dans ce cas de changer la définition des
truction permet de réaliser une boucle. constantes, le reste du code est conservé.
Dans la première ligne, nous mettons return
à 00h le contenu de l’emplacement de __CONFIG
mémoire 20h. Immédiatement après on L’instruction call permet d’appeler le Cette commande (appelée directive) n’est
a exécution de l’instruction DECFSZ suivie même sous-programme depuis différents pas, à l’inverse des instructions mention-
d’un 1 – le résultat écrase le contenu de points dans le programme (cf. fig. 5). nées précédemment, convertie en code
l’emplacement 20h. Lors du premier pas- Une fois le traitement terminé et le return machine exécuté lors du déroulement du
sage, nous soustrayons un 1 de 00h ; le exécuté, le déroulement du programme programme. Elle est utilisée pour fixer le
résultat est FFh, vu que nous calculons continue toujours avec l’instruction qui contenu du registre Config. Le registre
avec des octets non signés. Ensuite, le suit le call en question. de configuration est l’un des (très rares)
µC regarde si le résultat est égal à 00h. registres, dans lequel on ne peut pas
Ce n’est pas le cas ici, on a donc exé- NOP écrire à une adresse de la mémoire. La
cution de l’instruction suivante. Notons Même ça, ça existe : cette instruction ne définition de la valeur du registre de confi-
que la décision de savoir si le résultat est fait vraiment rien ; on pourra l’utiliser guration se fait dès le flashage du µC.
égal à zéro ou non est prise sur l’examen pour une temporisation. Nous nous en
du bit dit zéro du registre d’état. Ce bit servirons dans notre exemple pratique. En général, nous retrouvons la directive
serait à 1 si le résultat de la soustraction __CONFIG au début du code source, par
avait été 00h. Définitions de constantes exemple :
En assembleur, on peut utiliser le mot-
Comme nous le montre la figure 4, la clé EQU pour définir des constantes afin __CONFIG B’00000110000100’
deuxième ligne est identifiée par une éti- d’améliorer la lisibilité du code et sa por-
quette l_loop. À la ligne suivante, goto tabilité. Si au début du code nous conve- Ces bits permettent de paramétrer l’utili-
l_loop permet de revenir à l’instruction nons par ex. que : sation de l’oscillateur interne sans quartz
decfsz. Ici on a à nouveau une soustrac- externe, la non-activation de la protec-

www.elektormagazine.fr juillet/août 2015 21


découvrir créer partager

Code source
À quoi doit ressembler le programme
IC1 1 en assembleur ? Que faut-il faire au
BT2 VCC
minimum pour écrire un programme
4 7
AA GP3/MCLR GP0/AN0 exécutable ?
1V2 6
GP1/AN1 Comme nous le disions plus haut, nous
5
GP2/AN2
2 3 LED1 pouvons utiliser pour notre exemple un
BT1 GP5/CLKIN GP4/AN3
simple éditeur de texte tel que Notepad,
GND
AA y saisir le code et enregistrer le fichier.
1V2 8 PIC12F675P
L’extension doit toujours être .asm (il fau-
dra peut-être, après enregistrement, la
modifier manuellement). Nous utiliserons
Figure 6. Difficile de faire plus simple pour Figure 7. Le circuit peut être réalisé sur une comme nom de fichier : 01_LED_v_1p03.
obtenir le clignotement d‘une LED. plaque d‘essais. asm. Vous pouvez télécharger un fichier
tout fait sur la page de projet de cet
article [3].
tion des données ou de la mémoire de faut pour créer une application simple.
programme, la désactivation de la fonc- Allons-y. La figure 8 reprend le début du code.
tion de chien de garde (watchdog), etc. Notre tâche est (relativement) facile. Pour augmenter la lisibilité du programme
Nous retrouvons, comme d’habitude, la Nous allons, pour commencer, connec- et le rendre plus facile à comprendre par
description de chacun de ces bits dans ter une LED à la broche GP0 et la faire d’autres utilisateurs, nous l’avons doté de
la feuille de caractéristiques, souvent au clignoter. nombreux commentaires. Nous voulons
chapitre « Special Features of the CPU / En termes de matériel, la solution est de plus travailler avec des constantes.
Configuration Bits » (les fiches en fran- d’une mise en œuvre ultrasimple. Nous Des définitions telles que
çais sont rarissimes). utiliserons l’oscillateur d’horloge interne
(4 MHz) et n’aurons pas besoin de quartz STATUS EQU H’03’
Commentaire externe. La LED sera connectée directe-
Un commentaire commence toujours par ment à GP0 (même sans résistance) – le rendront le code plus portable si nous
un point-virgule (;). Tout ce qui suit le µC limite lui-même le courant de sortie voulons plus tard nous essayer à un PIC
point-virgule (jusqu’à la fin de ligne - End à environ 20 mA (alimentation de 5 V) un peu plus grand.
of Line) est ignoré par le compilateur et par le biais de la résistance interne du Heureusement il est inutile de réécrire à
considéré comme commentaire. port (fig. 6). chaque fois ces définitions de constantes
Si la ligne commence par un point-vir- Le circuit peut être réalisé sur une plaque dans notre code. On retrouve, dans le
gule, toute la ligne est traitée comme un d’essais (fig. 7). La source d’alimenta- fichier P12F675.INC, qui fait partie de la
commentaire. tion pourra par ex. être constituée de Suite MPASM, toutes les définitions essen-
deux piles de 1,2 V ; mais aussi n’importe tielles (adresses de registres, positions de
Application « Hello World » quelle autre source qui peut fournir au bits, etc.) pour notre type de µC.
Nous savons maintenant tout ce qu’il moins 20 mA sous 2 à 5 V. Nous incluons ce fichier tout au début

Figure 8. Les commentaires sont importants, même en assembleur. Figure 9. Définitions des registres dans le fichier
Include.

22 juillet/août 2015 www.elektormagazine.fr


q&r cours banc d’essai trucs & astuces logiciel

Liens
[1] www.microchip.com/wwwproducts/Devices.aspx?product=PIC12F675
[2] www.microchip.com/pagehandler/en-us/family/mplabx
[3] www.elektor-magazine.fr/130483

de notre code par une directive INCLUDE. Le petit sous-programme delay_r intro-
Cela fonctionne exactement comme avec duit une temporisation. Vous voyez peut-
tous les autres langages de programma- être immédiatement comment cela fonc-
tion « classiques » ; le résultat est le tionne ? Note : on se trouve en présence Figure 11. Capture d‘écran de l‘assembleur
même que si nous avions tout simplement de deux boucles imbriquées. MPASM qui convertit le code en fichier Hex.
copié, par un copier-coller, le code du Tout à la fin du fichier on doit impérati-
fichier à inclure dans notre programme. vement trouver la directive END.
La figure 9 nous montre le contenu
du fichier comportant les définitions de Assembler
constantes typiques au µC. Une fois le programme saisi, nous pou-
vons assembler le code. Pour cela, nous
La figure 8 nous apprend que nous avons appelons le programme MPASM.EXE (par-
en outre défini deux variables de type tie de l’IDE MPLAB).
octet (c.-à-d. des emplacements de Après le démarrage du programme
mémoire en SRAM), à savoir TIMER1 et (fig. 11), nous sélectionnons notre fichier
TIMER2. Nous les utiliserons dans notre texte (dans le champ Source File Name).
boucle de temporisation. Dans le champ Processor, il faut sélec-
tionner le type de notre µC. Le reste peut
La figure 10 montre le reste du pro- être laissé avec les valeurs par défaut.
gramme. Nous n’y utilisons que des Presser sur le bouton Assemble déclenche
instructions dont il a été question plus la compilation du fichier ASM.
haut. L’illustration montre les différents Ce processus produit alors un fichier hex
registres avec tous leurs bits. Un point (et quelques autres fichiers que nous pou-
d’interrogation noir à la place du bit signi- vons ignorer pour l’instant).
fie que sa valeur est sans importance ici.
Dans la boucle Main on voit un petit rond Le PICkit2 est accompagné du pro- Figure 12. Le logiciel de programmation du
rouge ; il signale le moment d’allumage gramme PICkit2V2.exe. Avant le lan- PICkit nous permet de flasher le programme
de la LED. Le rond gris identifie l’instruc- cement du programme, le kit doit être dans le µC.
tion qui éteint la LED. Les flèches repré- connecté à l’ordinateur via USB et le µC
sentent les sauts. doit se trouver dans le support de pro-
grammation de la carte d’expérimenta-
tion. Lors du démarrage de PICkit2V2.
exe, il y a détection automatique du µC
(cf. fig. 12).
Ensuite, le point du menu File – Import
Hex permet de charger le fichier hex et
enfin le bouton Write de le flasher dans
le µC.

C’est tout pour aujourd’hui – j’espère


que vous avez apprécié vos premiers pas
en assembleur. Dans le prochain article
nous passerons en revue l’ensemble du
jeu d’instructions du PIC12F675. Notre
exercice pratique se matérialisera sous
la forme d’un dé électronique.

(130483 – version française : Guy Raedersdorf)

Figure 10. Pour la temporisation, nous utilisons un sous-programme.

www.elektormagazine.fr juillet/août 2015 23


découvrir créer partager

cours intensif d’assembleur


(2) mini-carte de développement et dé électronique
Miroslav Cina (Allemagne) miroslav.cina@t-online.de

Dans la 1ère partie, nous avons abordé les bases


de la programmation en assembleur et les aspects
matériels du contrôleur PIC utilisé. Nous continuons
avec une mini-carte de développement faite
maison et de nouvelles instructions d’assembleur.
Notre application de « démonstration » prendra la
forme d’un dé (électronique).

reste utile. La figure 2 montre comment raccorder la platine


d’adaptation terminée au programmateur.

Zoom sur les registres


La réalisation d’une mini-carte Avant de découvrir d’autres instructions d’assembleur utilisées
d’adaptation pour le programmateur PICkit2 dans notre application de « démo », jetons un rapide coup
prend quelques minutes. Ce type de carte facilite énor- d’œil aux registres les plus importants.
mément la programmation du microcontrôleur (µC) correspon-
dant : enficher le µC, connecter la carte au programmateur, Registre de configuration (Config)
lancer le logiciel de programmation, transférer par son biais le Si la plupart des registres du µC se trouvent en SRAM, le registre
micrologiciel (firmware) assemblé et l’affaire est réglée. Sans de configuration fait exception. Le registre possède 14 bits,
gros efforts, il est possible de fabriquer des cartes d’adaptation mais, pour l’instant, seuls quatre de ces bits sont pertinents.
pour des µC avec différents nombres de broches ; chaque µC de Les trois LSB (Least Significant Bit = bit de poids faible) FOS-
Microchip comporte les broches de programmation requises : C2:FOSC0 servent à la configuration de l’oscillateur. Dans le
Vpp, ICSPDAT et ICSPCLK. Il faut donc, avec ces cartes d’adap- cours, nous utilisons les deux paramétrages suivants de ces
tation, relier lesdites broches (sans oublier Vcc et GND) aux trois bits :
broches de même nom du programmateur PICkit. 010 : oscillateur HF piloté par quartz. Dans ce mode, on
Pour notre µC PIC12F675 à huit broches, on réalisera une utilise l’oscillateur externe. La fréquence est définie par un
variante à huit broches comme celle de la figure 1. Convaincu ? quartz externe entre les broches 2 (GP4) et 3 (GP5). On
Simplissime. Un mini-morceau de platine à trous, un support peut ainsi pousser la fréquence d’horloge jusqu’à 20 MHz
pour circuit intégré à huit broches et une embase à six bro- maximum. Le quartz occupe deux broches, seules quatre
ches, c’est tout. On pourra, le cas échéant, supprimer la LED des six E/S potentielles restent disponibles.
et sa résistance-série, mais le témoin d’alimentation du µC 100 : oscillateur interne. Par ce mode, on active l’oscillateur

IC1 1 K1
VCC 1
VPP/MCLR
LED1 7 2
GP0/AN0 VCC
6 3
VREF/GP1/AN1 GND
5 4
GP2/AN2 ICSPDAT/PGD
R1 4 5
GP3/MCLR ICSPCLK/PGC
3 6
270R

GP4/AN3 AUX
2
GP5/CLKIN

GND
8
PIC12F675P

Figure 1. Schéma de la carte d‘adaptation, une carte de développement en Figure 2. Carte d’adaptation terminée, connectée au programmateur
version minimale. PICkit2.

16 septembre 2015 www.elektormagazine.fr


cours q&r trucs & astuces logiciel

Figure 3. Signification des bits du registre d‘état (Status Register).

interne de 4 MHz. La fréquence d’horloge est moins pré- La mémoire de données regroupe tous les registres spécifiques
cise qu’avec un pilotage par quartz, mais, avec sa tolé- au processeur et à l’application. Hormis les registres du pro-
rance de ±1%, elle suffit à de nombreuses applications. cesseur préparamétrés, le contenu de la mémoire de données
Son gros avantage : permettre de se passer de composants est indéfini à la mise sous alimentation. Elle perd son contenu
additionnels, GP4 et GP5 restent disponibles comme E/S à la disparition de l’alimentation – il s’agit de SRAM volatile.
d’usage général. Contrairement à la mémoire de programme, la mémoire de
données est, classiquement, organisée en octets (8 bits cha-
Le bit 5 (MCLRE) du registre de configuration commande la cun). La fiche de caractéristiques [1] (p. 9 sqq) donne une des-
fonction de la broche 4. Si MCLRE = 1, la broche 4 sert de cription détaillée de la cartographie de la mémoire. À retenir :
Master Clear – c.-à-d. de broche de réinitialisation (reset). Si les 64 octets de mémoire de l’application se trouvent dans la
MCLRE = 0, la broche 4 peut être utilisée comme entrée, avec plage d’adresses entre 20h et 5Fh.
en corolaire la perte de la fonction de réinitialisation. Par logiciel, on pourra, stocker dans l’EEPROM, mémoire non
volatile organisée en octets elle aussi, des valeurs qui « sur-
Registre d’état (Status) vivent » à une réinitialisation ou à un redémarrage. Cependant,
Le registre d’état contient des informations relatives à des opé- il faut éviter les écritures trop fréquentes.
rations arithmétiques terminées. La figure 3 donne la signi-
fication des différents bits du registre. Autres instructions
Les deux MSB (Most Significant Bit = bit de poids fort) IRP et Passons aux instructions dont, outre celles déjà évoquées dans
RP1 sont réservés et doivent toujours être à 0 en écriture. Ils la 1ère partie de cours, nous aurons besoin pour notre pro-
ne sont pas utilisés avec le PIC12F675. jet de « démo ». À noter que la fiche de caractéristiques de
Le bit 5, RP0, est le Register Bank Select Bit. Il sert (cf. 1ère tout µC de Microchip donne une liste exhaustive de toutes les
partie du cours) à la sélection de la banque de mémoire. S’il est instructions [1].
à 0, toutes les instructions qui suivent accèdent aux emplace- Notre description commence par un complément d’informa-
ments de mémoire 00h à 7Fh – sinon, s’il est à 1, aux empla- tions sur une instruction déjà utilisée dans la première partie.
cements 80h à FFh.
Les deux bits TO et PD révèlent l’origine de la dernière réini- DECFSZ
tialisation (cf. fiche de caractéristiques [1]). Dans la 1ère partie, nous avons parlé de la fonction de l’ins-
Le bit 2 Z (= Zero) est activé si le résultat de la dernière opé- truction DECFSZ (= DECrement F and Skip if Zero) pour les
ration est égal à zéro – il n’est pas impératif qu’il ait s’agit boucles. En dehors des boucles, cette instruction permet aussi
d’une opération arithmétique. de procéder à des branchements généraux lors de l’exécution
Les deux LSB indiquent les débordements suite à une addition du programme (une boucle n’est qu’un type de branchement
ou une soustraction (états Carry). spécifique). La figure 4 montre l’ordinogramme.
Supposons qu’il y a, à l’emplacement de mémoire 20h, une
Registre des options (Option) variable X. Un branchement complet requiert trois instructions
Le registre des options permet d’activer d’autres paramètres. (cf. fig. 5). En utilisant l’argument « 0 » avec DECFSZ, le résultat
Notre application de « démo » (cf. plus loin) donne un exemple : de la soustraction (valeur dans « X » moins 1) est écrit dans
l’effacement du bit 7 active la fonction de polarisation haute le registre W. Si le résultat est 00h, on saute l’instruction sui-
(pull-up) des entrées. vante et la troisième instruction goto branche_B est exécutée.

Cartographie de la mémoire
Pour programmer en assembleur, il faut connaître la cartogra-
phie de la mémoire du microcontrôleur utilisé. Généralement
(et donc ici), la mémoire est divisée en trois zones :
• La mémoire de programme (Flash)
• La mémoire de données (SRAM)
• L’EEPROM
La mémoire de programme est utilisée, en règle générale – et
même exclusivement avec le PIC12F675 – pour y stocker le
logiciel. La largeur d’un mot y est de 14 bits. Si cette informa-
tion n’a pas grande importance en programmation, elle nous
apprend que la mémoire de programme d’un PIC12F1675 ne
comporte pas 1024 octets (de 8 bits chacun), mais 1024 mots Figure 4. Ordinogramme d‘un branchement conditionnel.
(de 14 bits chacun).

www.elektormagazine.fr septembre 2015 17


découvrir créer partager

Figure 5. Exemple de code d‘un branchement conditionnel. Figure 6. Exemple de boucle avec les instructions BTFSS / BTFSC.

Cela n’a lieu que si la valeur de X est, avant décrémentation, est un nombre entre 00h et 07h ; il définit le bit à tester. Ces
de 01h. Dans tous les autres cas, on se retrouve à branche_A. instructions ne modifient ni le contenu du registre W, ni celui
de l’emplacement de mémoire.
INCFSZ Dans l’exemple de la figure 6, l’emplacement de mémoire
Vous savez tout de l’instruction DECFSZ. INCFSZ est identique à 20h a la valeur 98h (= 10011000b). À gauche l’instruction
ceci près qu’il faut lire incrémentation au lieu de décrémentation. BTFSS vérifie si la valeur du bit 00h est de 1. Si oui, on saute
l’instruction suivante goto branche_A. Cependant, comme la
BTFSS et BTFSC valeur du bit 0 est 0, ce saut n’a pas lieu et l’instruction goto
Pour les deux instructions BTFSS (= Bit Test F and Skip if Set) branche_A est alors exécutée.
et BTFSC (= Bit Test F and Skip if Clear), il s’agit aussi de bran- À droite on voit l’effet de l’instruction BTFSC. Ici on effectue un
chements. Elles permettent de vérifier l’état des différents bits saut si le bit 00h a la valeur 0 – ce qui est le cas pour la valeur
d’un emplacement de mémoire et d’effectuer le branchement de l’emplacement de mémoire 20h. On saute donc l’instruction
correspondant. goto branche_A et le programme poursuit avec l’instruction
La syntaxe est : goto branche_B.

btfss f,b ADDWF


Cette instruction ajoute le contenu du registre W à celui d’un
ou emplacement de mémoire.
La syntaxe est :
btfsc f,b
addwf f,d
L’argument f a une valeur comprise entre 00h et 7Fh et repré-
sente l’adresse de l’emplacement de mémoire. L’argument b L’argument f désigne l’adresse-cible et a une valeur comprise

Figure 7. Exemple de code ADDWF : résultat dans le registre W. Figure 8. Exemple de code ADDWF : résultat en SRAM.

18 septembre 2015 www.elektormagazine.fr


cours q&r trucs & astuces logiciel

Figure 9. Addition d‘une constante au (contenu du) registre W. Figure 10. Prototype du dé électronique.

entre 00h et 7Fh. L’argument d peut être à 0 ou 1 ; il défi- clrw
nit l’endroit de stockage du résultat. Si d = 0, le résultat est
stocké dans le registre W et l’emplacement de mémoire reste INCF et DECF
inchangé. Si d = 1, le contenu de l’emplacement est remplacé Ces instructions nous permettent d’incrémenter (INCF ; +1)
par le résultat. ou de décrémenter (DECF ; -1). La syntaxe est :
Dans l’exemple ci-après, nous allons calculer la somme de
3 + 16 (en décimal). On stocke tout d’abord 3 dans l’empla- incf f,d
cement de mémoire 20h ; on écrit ensuite 16 (10h) dans le
registre W et on effectue ensuite l’addition. Le résultat est écrit ou
soit dans le registre W (fig. 7), soit en 20h (fig. 8).
decf f,d
ANDWF
Pour ce qui est de ses syntaxe et utilisation, cette instruction Les arguments f et d ont la même signification que dans le cas
est identique à ADDWF. C’est la fonction qui diffère : ANDWF effec- de l’instruction ADDWF. En fonction de d, le résultat est écrit
tue l’opération logique ET (AND), bit par bit. dans le registre W ou à l’emplacement de mémoire d’origine.

ADDLW Dé électronique
À l’image de l’instruction ADDWF, ADDLW effectue elle aussi une La réalisation d’un dé électronique n’est pas bien plus com-
addition. ADDWF ajoute quant à elle une valeur de mémoire au pliquée que l’incontournable clignotement de LED. Comme le
registre W tandis qu’ADDLW ajoute une constante au registre W. circuit est, pour le simplifier au maximum, alimenté par un
La syntaxe est : port USB d’un PC, la figure 10 comporte un port USB. Sinon,
le dé n’a rien à faire avec l’interface USB, on pourrait tout
addlw k autant l’alimenter avec un adaptateur secteur, ou trois piles
(rechargeables) en série.
L’argument k a une valeur comprise entre 00h et FFh ; il s’agit Si vous examinez un vrai dé, vous constaterez que les points
de la constante additionnée (au contenu) du registre W. Le se trouvent à sept positions différentes. La figure 11 illustre
résultat est enregistré dans le registre W. la représentation de chacun des chiffres. Il nous faut, pour tra-
duire ces points par des LED, exactement quatre sorties d’un
Dans l’exemple de la figure 9, on commence par charger µC. Si cela vous étonne, en voici le pourquoi : les paires de
la valeur 03h dans le registre W, on additionne ensuite la LED 6 et 7, 2 et 3 ainsi que 4 et 5 ne sont toujours allumées
constante 10h. ou éteintes qu’ensemble. Chaque paire est donc pilotée par
sa propre broche de port GPIO. La LED1 a sa propre ligne de
ANDLW commande. Pour éviter que LED1 ne soit plus claire que les
Cette instruction est identique à ADDLW à ceci près que l’opé- autres, elle est dotée d’une résistance-série, R1. Bien que la
ration ET (AND) remplace l’addition. connexion directe de LED aux broches GPIO (cf. le schéma de
la figure 12) ne soit pas vraiment conforme aux règles, les
CLRF et CLRW
Nous avons déjà rencontré l’instruction CLRF dans la partie 1
(un emplacement mémoire donné est mis à 00h). De façon
similaire, l’instruction CLRW met le registre W à 00h.
La syntaxe est :

clrf f

ou Figure 11. Représentation des chiffres sur un dé.

www.elektormagazine.fr septembre 2015 19


découvrir créer partager

-- En cas d’action sur S1, les valeurs 1 à 6 s’affichent


successivement très rapidement. En raison de la
R1
D1 100R persistance rétinienne, on voit le chiffre 7 (toutes les LED
allumées).
1N4004
-- Le comptage rapide se termine au lâcher de S1. L’état
LED4 LED6
USB IC1 1 instantané du compteur s’affiche définitivement.
1 VCC
+5V 7
D–
2 GP0/AN0
6
Allons-y.
3 VREF/GP1/AN1
D+
4 GP2/AN2
5 LED2 LED1 LED3 Le micrologiciel du dé comporte deux parties : lancement du
GND 4
GP3/MCLR
3
dé et affichage. Il faut commencer par définir certains para-
GP4/AN3
GP5/CLKIN
2 mètres après réinitialisation ou redémarrage.
LED7 LED5
GND Dans le code de la figure 13, le repère 1 identifie cette confi-
PIC12F675P 8 S1
guration. On commence par la sélection de l’oscillateur interne
et le paramétrage de GP3 en entrée – sans MCLR ensuite.
Au repère 2, on attribue les emplacements de mémoire 20h
et 21h aux variables TIMER1 et TIMER2.
Aux repères 3 et 4, on travaille avec la banque de mémoire 1
Figure 12. Schéma du dé électronique.
puisque le bit RP0 du registre d’état est à un.
Au repère 3, les deux premières instructions (movlw B’11001100’
et movwf TRSIO) font que GP0, GP1 GP4 et GP5, se trouvent
faibles courants mis en jeu ne posent pas de problème réel. configurées en sorties par mise à zéro des bits correspondants
Aux fins d’économiser de l’énergie, le 5 V du port USB peut du registre TRISIO. Les LED sont connectées à ces quatre bro-
être diminué de 0,7 V environ par D1 et ramené à 4,3 V. En cas ches. Comme elle sert à la lecture de l’état du bouton, GP2 est
d’alimentation par trois piles NiMH, soit 3 x 1,2 V, on pourra configurée en entrée. Le bit 2 du registre TRISIO est donc mis
supprimer la diode. Pour lancer le dé, on appuie brièvement à un. L’instruction clrf ANSEL désactive la fonction analogique.
sur le bouton S1. Au repère 4, on contourne l’implantation d’une résistance de
Petite note : en raison de leur tension directe plus élevée, on polarisation haute externe pour le bouton. Le µC PIC12F675
ne pourra pas utiliser de LED bleues ou blanches dans ce circuit. comporte en effet sur toutes les broches GPIO configurées en
entrée (hormis GP3), des résistances de polarisation haute
Micrologiciel du dé dites « molles » (weak pull-up). Pour cela, le bit 7 du registre
Avant de se lancer dans la programmation, il est bon de bien des options doit être mis à zéro. Dans le programme, c’est
spécifier les fonctions du logiciel de commande. Voici le cahier l’instruction bcf OPTION_REG,D’007’ qui le fait. Ensuite, avec
des charges du dé : les bits du registre WPU, on définit pour lesquelles des broches
• Après la mise en fonction (reset) mettre le dé en démo. Celle- les résistances de polarisation internes doivent être activées.
ci consiste à faire défiler tous les chiffres (1 à 6) jusqu’à une Si le bit x du registre WPU est mis à un, la résistance de pola-
action sur le bouton S1. risation haute de la broche GPx correspondante est active.
• L’implémentation de la logique du dé prend la forme d’une En principe, les résistances de polarisation haute internes ne
boucle sans fin : sont pas actives car elles peuvent augmenter la consomma-
tion de courant jusqu’à 400 µA. Si c’est vraiment important,
on implantera une résistance de polarisation haute externe
de forte valeur ou si nécessaire une résistance de polarisation
basse externe.
Après l’initialisation, le programme entre dans la boucle de
« démo » (fig. 14). L’implémentation à ce niveau est facile –
tout se passe dans le sous-programme start_effect, auquel il
est tout simplement fait appel ici. Une action sur S1 termine
la partie de « démo ».

La routine de « démo »
La routine de « démo » illustrée en figure 15 est parlante.
On y reconnaît six parties de programme similaires, une par
chiffre. La représentation des chiffres se fait par un sous-pro-
gramme : disp_1 se charge d’allumer la LED du chiffre 1. disp_2
provoque l’allumage du chiffre 2 et ainsi de suite.
Après l’affichage d’un chiffre donné, le logiciel attend avant le
chiffre suivant. C’est la fonction de delay_routine – une routine
déjà utilisée dans la 1ère partie du cours. L’instruction btfss
GPIO,D’002’ mérite le détour. Elle sert, bouton ouvert, à sauter
par-dessus l’instruction return et ainsi à produire l’affichage
du chiffre suivant. En cas d’action sur le bouton, ce saut n’est
Figure 13. Code du dé électronique : initialisations. plus effectué puisque l’entrée fournit un 0. Le programme

20 septembre 2015 www.elektormagazine.fr


cours q&r trucs & astuces logiciel

continue depuis ce return. Ceci termine le sous-programme


start_effect et donc la démo. Dès lors on retrouve l’exécution
du programme principal.
Venons-en aux routines d’affichage : le code de cette partie
(fig. 16) est étonnamment simple. On y retrouve six routines. Figure 14. Code du dé électronique : saut vers la routine de « démo ».
Dans chacune d’entre elles, la première instruction movlw déter-
mine par le biais d’une constante quelles sont les LED allumées
ou éteintes. Dans les constantes binaires, un « 0 » correspond
aux LED éteintes et un « 1 » aux LED allumées. L’instruction
movwf GPIO envoie ces informations au port. On attend ensuite
un court instant (sous-programme dr2) avant de terminer la
routine d’affichage. Dans la partie de « démo », cette courte
attente n’aurait pas lieu d’être, mais elle ne gêne en rien.

Programme principal
La structure de cette partie est similaire à la routine de
« démo ». Dans la figure 17, la partie étiquetée main_loop1
fait en sorte que, bouton relâché, il y ait affichage ininterrompu
du chiffre en cours. Comme dans la routine de « démo », on a
aussi, dans le programme principal, interrogation de la valeur
actuelle de l’entrée GP2 et en cas d’action sur le bouton pour-
suite du comptage avec affichage de la valeur actuelle. Tout
va si vite qu’on a l’impression que le chiffre « 7 » est affiché. Figure 15. Code du dé électronique : production des chiffres dans la routine
Après relâchement du bouton, l’instruction goto b_released de « démo ».
est exécutée ; le comptage s’arrête – l’état (du compteur) à
cet instant reste affiché. Ce chiffre est le résultat du (lancer
de) dé. Depuis l’étiquette b_release, on ressaute à main_loop1
qui arrête l’exécution du programme. On aurait aussi pu sau-
ter directement à main_loop1 ; pour rendre le programme
plus vivant, on pourrait ajouter des effets sous l’étiquette b_
release, par exemple, faire s’éteindre le comptage progressi-
vement ou faire clignoter le résultat et ne passer qu’ensuite
à l’affichage statique. Figure 16. Code du dé électronique : routine d‘affichage.
Dans le sous-programme dr2, on détermine la vitesse de chan-
gement des chiffres. En fait, on pourrait aussi s’en passer.
Essayez de ralentir l’exécution du programme au point de voir
les chiffres changer.
Comme à l’accoutumée, le logiciel est téléchargeable depuis
le site Elektor [4].

Perspectives
Nous voici arrivés à la fin de la 2e partie de ce cours d’as-
sembleur. Nous y avons décrit de nouvelles instructions et vu
comment réaliser à peu de frais (et d’efforts) un dé électro-
nique fonctionnel. On pourra, selon le même modèle, réaliser
des applications sensiblement plus complexes. Vous avez pu
constater ainsi que la programmation en assembleur est plus
facile qu’on ne le pense au premier abord.

J’ose espérer que cela vous a plu ! Dans le prochain épi-


sode, nous verrons comment utiliser un µC simple tel que le
PIC12F675 pour remplacer le temporisateur NE555. Figure 17. Code du dé électronique : le programme principal.
(150274 – version française : Guy Raedersdorf)

Liens
[1]  PIC12F675 : www.microchip.com/wwwproducts/Devices.aspx?product=PIC12F675
[2]  MPLAB IDE : www.microchip.com/pagehandler/en-us/family/mplabx
[3]  Première partie du cours: www.elektormagazine.fr/130483
[4] Logiciel : www.elektormagazine.fr/150274

www.elektormagazine.fr septembre 2015 21


découvrir créer partager

cours intensif d’assembleur


(3) remplacez un 555 par un PIC
Miroslav Cina miroslav.cina@t-online.de

La première partie de cet article était consacrée aux bases de la programmation en assembleur et
aux aspects matériels du contrôleur PIC utilisé. Dans la deuxième partie, nous avons conçu un dé
électronique. Dans cette dernière partie, nous vous montrons comment simuler un circuit intégré (CI)
standard comme le célèbre temporisateur NE555 à l’aide d’un microcontrôleur moderne.

Ne perdons pas notre temps à parler du temporisateur NE555 loge du contrôleur. Comme le montre la figure 1, le circuit ne
lui-même. Ce circuit intégré est produit depuis 1972 et détient peut pas être plus simple.
aujourd’hui encore le record du nombre de pièces vendues Le programme nécessaire ne s’occupe que du pilotage de la
alors qu’il n’est même pas « numérique ». Il est non seule- sortie. Pour un signal rectangulaire avec un rapport impulsion/
ment capable de fonctionner comme générateur de signaux pause de 50 %, on atteint la fréquence la plus élevée avec le
rectangulaires ou monostable, mais sa mise en œuvre est en code suivant en assembleur :
plus incroyablement souple.
La version normale bipolaire permet des signaux jusqu’à output_1 bsf GPIO,D’001’ ;1us @ 4 MHz
500 kHz, et ses successeurs plus modernes comme le LMC555 nop ;1us @ 4 MHz
de TI atteignent même des fréquences jusqu’à 3 MHz. On peut nop ;1us @ 4 MHz
très bien produire des signaux rectangulaires et autres avec des bcf GPIO,D’001’ ;1us @ 4 MHz
circuits intégrés polyvalents comme les microcontrôleurs. Nous
goto output_1 ;2us @ 4 MHz
vous montrons ci-dessous comment utiliser un PIC12F675 pour
remplacer un 555. Nous nous intéresserons essentiellement La première instruction met la sortie GP1 à 1 (logique). Le com-
à la fonction d’oscillateur rectangulaire. Les autres fonctions, mentaire de cette instruction indique la durée de l’instruction :
par ex. monostable…, peuvent très bien être réalisées par logi- une µs pour une horloge à 4 MHz. On attend ensuite deux µs
ciel ; nous vous encourageons à faire preuve d’imagination ! du fait de deux instructions nop, jusqu’à ce que la sortie soit de
nouveau mise à 0 (logique). Cette attente est nécessaire pour
Étape 1 : oscillateur minimal obtenir la symétrie ; en effet, le retour au début de la boucle
Pour notre premier programme, nous n’aurons besoin que d’un avec la commande goto dure 2 µs. Cette boucle sans fin crée
microcontrôleur et de quelques lignes de code – et c’est tout. La pour une cadence de l’oscillateur interne de 4 MHz une fré-
fréquence du signal rectangulaire produit peut être définie dans quence de sortie à env. 166 kHz. L’oscillogramme de la figure 2
le code, d’une valeur très faible à environ 166 kHz. Le micro- prouve la bonne qualité du signal rectangulaire ainsi obtenu.
contrôleur montre sa supériorité pour les basses fréquences Pour des fréquences plus basses, il suffit d’intégrer des pauses
parce qu’il peut produire de manière stable des périodes ou plus longues. Vous avez pour ce faire deux possibilités : pour
des impulsions avec une durée d’un jour, d’un mois ou plus la gamme des kHz, il suffit d’ajouter le nombre correct de nop
encore. La fréquence maximale dépend de la fréquence d’hor- supplémentaires. Pour les signaux plus lents, il vaut mieux

IC1 1
VDD
7
GP0/AN0
6
J1 VREF/GP1/AN1 J2
1 5
+5V GP2/AN2
4 1
GND GP3/MCLR
3
POWER GP4/AN3 OUT
2
GP5/T1CKI/OSC1
GND
8
PIC12F675P

Figure 1. La variante la plus simple du substitut au 555 se passe de Figure 2. Oscillogramme du signal de l’étape 1 : un bon 166 kHz pour un
composants externes. rapport cyclique de 50 %.

10 octobre 2015 www.elektormagazine.fr


cours q&r trucs & astuces logiciel

créer une boucle d’attente à part entière qui démarre dans la de huit cycles d’horloge et donc d’un temps d’exécution deux
boucle principale. Pour un rapport cyclique de 0,5, les pauses fois plus long.
doivent être symétriques. L’exemple suivant met en évidence Vous devez savoir que l’horloge interne calibrée en usine avec
le double appel de la routine wait_1: une précision de ±1 % peut également être manipulée. En cas
de besoin, il est possible de modifier la valeur de calibrage stoc-
output_1 bsf GPIO,D’001’ ;1us @ 4 MHz kée dans la puce. C’est ce que fait justement le code suivant :
nop ;1us @ 4 MHz
nop ;1us @ 4 MHz bsf STATUS,RP0
call wait_1 ;predefined delay call H’3FF’
bcf GPIO,D’001’ ;1us @ 4 MHz movwf
OSCCAL
call wait_1 ;predefined delay bcf STATUS,RP0
goto output_1 ;2us @ 4 MHz
Bien sûr, on peut enregistrer dans le registre OSCCAL une
valeur personnelle et ainsi changer le cycle d’horloge réel.
Un appel via la commande call dure déjà 4 µs (call elle-même Maintenant que ce principe est clair, voyez le listage 1, le
a besoin de 2 µs et le return dure 2 µs). On définit dans la code complet grâce auquel on va transformer un PIC12F675
routine wait_1 le temps d’attente nécessaire. en un générateur rectangulaire à 166 kHz, avec un rapport
Si on a besoin d’un rapport cyclique asymétrique, on intègre cyclique de 0,5.
des pauses asymétriques. C’est ce que fait le code suivant
avec nop : Tout d’abord, le contrôleur utilisé est défini et configuré à par-
tir de _U002. Ce faisant, l’oscillateur interne est activé avec
output_1 bsf GPIO,D’001’ ;1us @ 4 MHz la valeur « 100 » dans les trois bits de poids faible ; la broche
nop ;1us @ 4 MHz MCLR est réglée pour servir d’entrée et non de RAZ. Les quatre
nop ;1us @ 4 MHz instructions suivantes (de bsf à clrf) désactivent les fonctions
;additional delay – additional 4 µs --------- analogiques inutiles et mettent la broche GP1 en sortie. Les
trois instructions suivantes de call à bcf étalonnent l’oscilla-
nop
teur interne comme on l’a vu plus haut. La boucle principale
nop
finale de bsf jusqu’à goto ne compte que cinq instructions.
nop
nop Étape 2 : réglage de la fréquence
;-------------------------------------------- Le circuit de la figure 4 comprend en plus le potentiomètre P1,
bcf GPIO,D’001’ ;1us @ 4 MHz qui permet de régler la fréquence de sortie d’environ 885 kHz
goto output_1 ;2us @ 4 MHz à 1,45 MHz. La création du signal se fait cependant d’une tout
autre manière que dans le premier exemple. Ici, vous allez
Les 4 µs supplémentaires réduisent la fréquence à environ voir l’application de la fonction CLKOUT ainsi que l’utilisation
100 kHz. Comme la phase à 1 dure maintenant 7 µs et que la du convertisseur A/N intégré.
phase à 0 seulement 3 µs, le résultat donne un rapport cycli-
que de 70 % visible sur la figure 3. Jusqu’ici, le signal rectangulaire était créé par la mise à 1 et
la mise à 0 de la broche de sortie. Faisons maintenant travail-
Encore une chose à propos du minutage : normalement, toutes ler le matériel à notre place. Le PIC12F675 offre la possibilité
les instructions ont besoin de quatre cycles d’horloge. La durée d’appliquer directement sur une sortie la fréquence d’horloge
d’exécution est donc tout naturellement t = 4 / fréquence d’hor- divisée par 4. Si on met les trois bits de poids faible du registre
loge. Les exceptions sont par exemple goto, call ou return, de configuration à « 101 » au lieu de « 100 », la broche GP4
qui manipulent le compteur d’instructions ; elles ont besoin est utilisée comme CLKOUT. Avec une horloge à 4 MHz, c’est un

IC1 1
VDD
7 P1
GP0/AN0
6
J1 VREF/GP1/AN1 10k
1 5
+5V GP2/AN2
4
GND GP3/MCLR J2
3
POWER GP4/AN3
2 1
GP5/T1CKI/OSC1

GND OUT
8
PIC12F675P

Figure 3. Avec quatre autres instructions nop, la fréquence baisse Figure 4. Un potentiomètre supplémentaire suffit pour pouvoir régler la
à 100 kHz avec un rapport cyclique de 70 % non symétrique. fréquence.

www.elektormagazine.fr octobre 2015 11


découvrir créer partager

Tableau 1. Registre ADCON0


Signification ADFM VCFG - - CHS1 CHS0 GO/DONE ADON
Bit 7 6 5 4 3 2 1 0

signal de 1 MHz qui est créé et le rapport cyclique est de 50 %. dont seuls 10 bits sont significatifs. Les six autres bits ont la
Pour pouvoir changer la fréquence, on va détourner de sa valeur 0. La valeur d’ADFM définit la position des bits superflus.
fonction le calibrage de l’oscillateur interne cité précédem- Si ADFM = 0, le résultat est aligné à gauche, c’est-à-dire que
ment (en donnant d’autres valeurs au registre OSCCAL). La les six bits de poids faible du registre ADRESL sont mis à 0.
plage de valeurs du registre sur 8 bits va de 00h à FFh. L’os- Par conséquent, les huit bits de poids fort du résultat sont mis
cillateur interne se laisse habituellement régler sur une plage dans le registre ADRESH. Les deux bits de poids faible (LSB)
de 3 à 5,8 MHz. Un quart de cette valeur donne la gamme déjà restants par contre sont dans les deux bits de poids fort (MSB)
citée de la fréquence de sortie. d’ADRESL. Si ADFM = 1, c’est exactement l’inverse, le résultat
Pour que le microcontrôleur puisse détecter la position du est alors aligné à droite.
potentiomètre via le CA/N, il faut écrire encore un peu de code. VCFG choisit la tension de référence du CA/N. Si VCFG = 1,
Dans ce but, trois registres sont importants : alors c’est la broche Vref (GP1) qui est utilisée. Si VCFG = 0,
c’est VDD, tout simplement la tension d’alimentation qui sert
• ADCON0 : configuration du CA/N de référence.
• ADRESH, ADRESL : octets de poids fort et faible du résul- Les deux bits CHS1 et CHS0 choisissent la broche qui servira
tat sur 16 bits du CA/N d’entrée au CA/N. Si les deux sont à 0, le canal AN0 est sélec-
• ANSEL : Analog Select Register – fixe la vitesse d’échan- tionné, et ainsi la broche GP0.
tillonnage et détermine la broche qui sera une entrée Go/Done lance une conversion A/N, lorsqu’on l’a mis à 1.
analogique Ensuite, on peut tester si la conversion est achevée. Le bit a
alors la valeur 0.
Voyez la signification des bits du registre ADCON0 dans le Avec ADON = 0, on peut ensuite désactiver complètement
tableau 1. Le bit 7 est ce que l’on appelle A/D Result Formed l’unité A/N (pour économiser le courant) et la réactiver avec
Select Bit (ADFM). Le CA/N intégré a une résolution de 10 bits, ADON = 1.
le résultat est stocké dans deux registres de 8 bits (= 16 bits), Les registres ADRESH et ADRESL contiennent comme on l’a

Listage 1.

;************************************************** movwf
TRISIO
;* NE555 Replacement - Example 1 * clrf ANSEL ;GPIO are digital I/O’s
;* v 1.00 - 19.06.2015 * ;--------------------------------------------------
;************************************************** ;oscillator calibration
;* Microcontroller: PIC12F675 * call H’3FF’
;* Oscillator: internal * movwf
OSCCAL
;************************************************** bcf STATUS,RP0 ;switch back to Bank 0
;Pin connections:
;GP0 --> N/C ;--------------------------------------------------
;GP1 --> Output ;Main Loop
;GP2 --> N/C ;--------------------------------------------------
;GP3 --> N/C output_1 bsf GPIO,D’001’ ;1us @ 4 MHz
;GP4 --> N/C nop ;1us @ 4 MHz
;GP5 --> N/C nop ;1us @ 4 MHz
;-------------------------------------------------- ;additional delay - additional 4 us ---------------
;Chip configuration: nop
INCLUDE «P12F675.INC» nop
_U002 EQU B’00000110000100’ nop
;MCLR = input/internal osc. nop
__CONFIG U002 ;--------------------------------------------------
;-------------------------------------------------- bcf GPIO,D’001’ ;1us @ 4 MHz
;analog functions off, GP1 = output goto output_1 ;2us @ 4 MHz
bsf STATUS,RP0 ;switch to regist. bank 1 ;--------------------------------------------------
movlw
B’11111101’ END
;GP1 = output; GP0; GP2 - GP5 = input

12 octobre 2015 www.elektormagazine.fr


cours q&r trucs & astuces logiciel

Listage 2.

;************************************************** ; ADON = 1 --> switch the module ON


;* NE555 Replacement - Example 2 with P1 * movwf ADCON0
;* v 1.00 - 19.06.2015 * ;Samplerate, GP0 = analog input
;************************************************** ; movlw B’00010001’
;* Microcontroller: PIC12F675 * ; ADCS<2:0> = 001 --> ADC clock = FOSC/8
;* Oscillator: internal * ; ANS3 = 0
;************************************************** ; ANS2 = 0
; ANS1 = 0
;Pin connections: ; ANS0 = 1 --> analog input on AN0 (GP0)
;GP0 --> Poti
;GP1 --> N/C bsf STATUS,RP0
;GP2 --> N/C movwf
ANSEL
;GP3 --> N/C bcf STATUS,RP0
;GP4 --> CLKOUT ;--------------------------------------------------
;GP5 --> N/C ;Main Loop
;-------------------------------------------------- ;--------------------------------------------------
;Chip configuration: ;start A/D conversion ------
INCLUDE “P12F675.INC” main_loop bsf ADCON0,D’001’
w_adc btfsc
ADCON0,D’001’
_U005 EQU B’00000110000101’ goto w_adc
;MCLR = input / internal osc. + CLKOUT
__CONFIG _U005 ;modify clock ------
;-------------------------------------------------- movf ADRESH,0
;setup ADC ------ bsf STATUS,RP0
;Result left adjusted, VDD = reference, GP0 = input, movwf
OSCCAL
activate ADC bcf STATUS,RP0
movlw B’00000001’ nop
; ADFM = 0 --> result is left justified nop
; VCFG = 0 --> Vdd = voltage reference goto main_loop
; CHS1:CHS0 = 00 --> Channnel 00 (GP0) ;--------------------------------------------------
; GO = 0 --> no start now END

vu le résultat de la conversion A/N. plus d’efforts). Vous n’échapperez pas aux interruptions ni au


La signification d’ANSEL se trouve dans le listage 2. recours à un temporisateur/compteur. Le circuit de la figure 5
La première modification par rapport au listage 1 est la valeur montre les composants supplémentaires nécessaires : un quartz
« 101 » pour les trois bits de poids faible du registre de confi- et ses deux condensateurs.
guration. Du coup, la broche GP4 est soumise à un quart de
la fréquence d’horloge.
La section suivante va nous aider à configurer le CA/N. Tout
d’abord, le résultat est calé à gauche. Si l’on n’utilise qu’ADRESH IC1 1
P1

en ignorant ADRESL, on a un résultat formaté sur 8 bits. En VDD


10k
7
GP0/AN0
outre, VDD sert de référence et GP0 d’entrée de mesure. 6
J1 VREF/GP1/AN1
Nous allons ensuite régler la fréquence du CA/N à un huitième +5V
1
GP2/AN2
5
J2
4
de la fréquence de l’horloge et mettre GP0 en entrée analo- GND GP3/MCLR
3 1
POWER GP4/AN3
gique. Cette action met fin à l’initialisation. 2
GP5/T1CKI/OSC1 OUT
Dans la boucle principale, une conversion A/N est lancée et le GND
résultat mis en mémoire. Dans l’étape suivante, la fréquence X1
8
PIC12F675P
de l’oscillateur interne dépendant du résultat du CA/N ou de
20MHz
la position du curseur du potentiomètre est réglée avec une C1 C2

résolution de 256 pas. 22p 22p

Étape 3 : interruptions et temporisateur


Si vous voulez disposer d’une fréquence réglable, mais sta- Figure 5. Grâce au quartz, le générateur rectangulaire est beaucoup
bilisée par quartz, il faut procéder autrement (cela demande plus stable.

www.elektormagazine.fr octobre 2015 13


découvrir créer partager

Tableau 2. Registre INTCON


Signification GIE PEIE T01E INTE GPIE T0IF INTF GPIF
Bit 7 6 5 4 3 2 1 0

Le programme devra exécuter deux tâches. D’une part, il doit produit alors le signal de sortie proprement dit. Voilà comment
comme précédemment détecter la position du potentiomètre, cela se passe :
mais aussi délivrer un signal rectangulaire précis qui ne pourra au début, une valeur est chargée dans le registre du temporisa-
pas être perturbé par un changement de la fréquence. C’est teur TMR0. À partir de là, cette valeur est incrémentée jusqu’à
pour cette raison qu’il y a deux parties dans le code. Inutile ce qu’elle atteigne FFh. Comme il s’agit d’un registre à huit
de rappeler comment acquérir la position du potentiomètre. bits, il s’ensuit un dépassement à l’incrémentation suivante et
Pour produire le signal de sortie, deux nouvelles fonctions du le registre contient alors la valeur 00h. Le dépassement est un
microcontrôleur sont utilisées : Timer0 et Interrupts. évènement qui déclenche une interruption. On peut alors créer
le signal à délivrer dans la routine d’interruption.
La fonction Timer0 peut être utilisée en temporisateur ou comp-
teur. En temporisateur, le registre correspondant est incré- La manipulation de Timer0 et de son registre TMR0 n’est vrai-
menté périodiquement par l’horloge. En compteur, ce sont ment pas compliquée. Quand on met le bit T0CS à 0, Timer0
des évènements externes par exemple qui sont comptés. Pour sert de temporisateur. À partir de là, TMR0 est incrémenté à
simuler le 555, il faut le mode temporisateur. Le temporisateur chaque cycle d’instructions (horloge / 4).

Listage 3.

;************************************************** ;--------------------------------------------------
;* NE555 Replacement - Example 3 with Xtal * ;ISR
;* v 3.07 - 05.07.2015 * ;Save status register ------
;************************************************** int_main movwf w_save0 ;save content of W-reg.
;* Microcontroller: PIC12F675 * ;could be Bank0 or Bank1
;* Oscillator: internal * swapf STATUS,0
;move content of Status to W
;************************************************** bcf STATUS,RP0 ;switch to Bank0
;GP0 --> Poti movwf stat_save
;GP1 --> Output ;save original content of Status
;GP2 --> N/C ;GPIO toggle ------
;GP3 --> N/C movf v_value,0
;GP4 --> Xtal movwf GPIO
;GP5 --> Xtal incf v_value,1
;-------------------------------------------------- ;Store ADC value in TMR0 ------
;Chip configuration: movf v_delay,0
INCLUDE “P12F675.INC” movwf TMR0
_U003 EQU B’00000110000010’ bcf INTCON,T0IF
;MCLR = external xtal up to 20 MHz ;Restore status register ------
__CONFIG U003 swapf stat_save,0 ;restore old Status to W
;================================================== movwf STATUS
;Variable definitions ;push content to Status register
w_save0 EQU H’20’ ;select old Bank
w_save1 EQU H’A0’ swapf w_save0,1 ;rebuild content of W-reg.
stat_save EQU H’21’ swapf w_save0,0 ;restore W register
v_delay EQU H’22’ retfie
v_value EQU H’23’ ;--------------------------------------------------
v_tmp EQU H’24’ ;ISR
;================================================== rst_main
;Set adress of subroutines ...
ORG H’000’ ;missing code
goto rst_main ...
ORG H’004’ ;--------------------------------------------------
goto int_main END

14 octobre 2015 www.elektormagazine.fr


cours q&r trucs & astuces logiciel

Quelques mots encore sur les interruptions : toutes les proprié- des interruptions doivent toujours être 000h et 004h.
tés importantes sont pilotées par le registre INTCON. Voyez la Avant d’arriver à l’ISR (Interrupt Service Routine) int_main, il
signification de ses bits dans le tableau 2. Pour notre projet, faut bien savoir ce qu’est une interruption. En principe, l’exé-
seuls trois bits sont importants : cution du programme est interrompue par l’apparition d’un
• GIE : Global Interrupt Enable. GIE = 1 active et GIE = 0 évènement déterminé et une routine d’interruption (ISR) s’exé-
désactive les interruptions. cute. Une fois l’ISR terminée, le programme principal revient
• T0IE : Timer0 Interrupt Enable. Seulement si T0IE = 1, un à l’emplacement où il se trouvait et il continue. C’est la même
dépassement de TMR0 provoque une interruption. chose que l’appel d’un sous-programme, simplement cet appel
• T0IF : Timer0 Overflow Indicator. En cas de dépassement peut se passer à n’importe quel endroit du programme. Il est
de TMR0, T0IF = 1. On peut consulter le bit et le code doit tout à fait possible que le programme ait exécuté une opéra-
le remettre à « 0 ». tion arithmétique, ait positionné les bits du registre d’état et
qu’une interruption survienne avant l’instruction BTFSS suivante.
Point important encore, la routine d’interruption doit tou- Comme l’ISR ne peut gêner le déroulement du programme
jours commencer à l’emplacement de mémoire 004h du pro- principal, elle doit sauvegarder avant sa tâche le contenu du
gramme. Pour les interruptions, il y a encore deux instructions registre d’état et ensuite le rétablir (avant le saut de retour).
à connaître : C’est pourquoi l’ISR se plante plus souvent que l’on ne pour-
rait le supposer.
SWAPF
Cette instruction échange les deux quartets (nibbles) d’un L’instruction SWAPF s’avère ici importante, elle va nous per-
registre. Une valeur de E4h devient après l’échange 4Eh. Pour mettre de sauvegarder le contenu d’un emplacement mémoire
les interruptions, il est en outre important que le registre d’état dans le registre W. Au début de l’ISR, les registres W et d’état
reste inchangé pendant l’exécution de cette instruction. La sont sauvegardés. La première instruction movwf w_save0 sau-
syntaxe est : vegarde le registre W à l’emplacement mémoire w_save0.
Comme nous ne savons pas si le programme principal travail-
swapf
f,d lait au lancement de l’interruption avec la banque 0 ou 1, il
est très important que w_save0 (ici 20h) et w_save1 (ici A0h)
L’adresse de registre « f » peut comporter des valeurs entre restent libres. L’instruction movwf laisse d’ailleurs inchangé le
00h et 7Fh et « d » peut être soit 0, soit 1. Pour d = 0, le contenu du registre d’état. Les trois instructions suivantes
résultat est sauvegardé dans le registre W. Si d = 1, c’est de sauvegardent le contenu du registre d’état à l’emplacement
nouveau le résultat qui s’inscrit dans le registre. mémoire prévu stat_save (21h) dans la banque 0. Ainsi tout
ce qu’il faudra restaurer plus tard est sauvegardé.
RETFIE C’est ici que commence vraiment le travail de l’ISR : la variable
RTFIE est l’acronyme de RETurn From IntErrupt. Cette ins- v_value est fournie au port GPI0 à chaque interruption. La
truction met fin à la routine d’interruption et le programme variable est ensuite incrémentée. Comme la broche GP0 délivre
principal reprend son cours. Avec RETFIE, il ne faut donner le signal de sortie (dont le niveau est déterminé par le bit de
aucun paramètre (comme avec RETURN). La syntaxe est : poids faible de la variable), il y a un changement de niveau à
chaque interruption. Maintenant, il reste à copier la variable v_
retfie delay dans le registre TMR0. Comme la valeur de ces variables
correspond à la position du curseur du potentiomètre, la fré-
Au démarrage d’une interruption, le bit GIE du registre INTCON quence de sortie est ainsi définie.
est mis à 0, ce qui arrête les autres interruptions. L’instruction Il reste encore à restaurer les valeurs originales du registre
RETFIE remet le bit GIE à 1. W et du registre d’état, ensuite l’ISR peut se terminer avec
l’instruction retfie.
Les gammes de fréquences que l’on peut couvrir avec ce code
Voyons le code du listage 3 : on remarque d’abord qu’ici CLK- et ce circuit dépendent de la fréquence du quartz et sont pré-
OUT n’est pas employé. En outre, les trois bits de poids faible sentées dans le tableau 3.
du registre de configuration sont mis à « 010 », ce qui permet
l’utilisation d’un quartz de haute fréquence. La description de la partie manquante du listage nous en emmè-
Suit une section avec la déclaration des variables. On définit nerait trop loin. Vous pouvez bien sûr télécharger gratuitement
ici les variables principales v_delay, v_value et v_tmp ainsi en  [4] cet exemple complet ainsi que les autres listages de
que w_save0, w_save1 et stat_save pour le traitement des cet article, pour les examiner tranquillement.
interruptions.
Dans la section suivante, la directive ORG fixe les adresses
de démarrage de deux sous-routines. Vous ne connaissez pas Tableau 3. Fréquences de sortie avec la fréquence du
encore cette directive, mais sa fonction est facile à expliquer : quartz comme paramètre
ORG fixe l’adresse de l’instruction qui suit. Dans notre cas, Fréquence du quartz fsortie min. fsortie max.
rst_main est verrouillé à l’adresse 000h et int_main à 004h.
2 MHz 237 Hz 4,63 kHz
Comme l’instruction goto n’occupe qu’un octet, les adresses
4 MHz 474 Hz 9,26 kHz
001h à 003h restent inoccupées. Nous faisons appel à cette
directive parce que les vecteurs (adresses cibles) de la RAZ et 20 MHz 2.370 Hz 46,30 kHz

www.elektormagazine.fr octobre 2015 15


découvrir créer partager

MEMORY USAGE MAP (‘X’ = Used, ‘-’ = Unused)

2000 : -------X-------- ---------------- -------------


IC1 1
--- ----------------
VDD
7
GP0/AN0
6
J1 VREF/GP1/AN1
All other memory blocks unused.
1 5
+5V GP2/AN2
P1 4
GND GP3/MCLR J2
3
POWER
2
GP4/AN3
1
Program Memory Words Used: 0
GP5/T1CKI/OSC1
100k Program Memory Words Free: 1024
GND OUT
8
PIC12F675P
Le fichier LST est créé par un passage de l’assembleur sur le
code source. Il contient le code lui-même et des informations
de l’assembleur (par exemple la quantité de mémoire du pro-
Figure 6. Dans la variante sans code, il suffit d’un potentiomètre pour
gramme occupée par le code).
régler la fréquence.
Perspective
Avec un exemple sans code, le cours intensif d’assembleur est
Étape 4 : PIC sans logiciel arrivé à son apogée et en même temps à sa fin. Nous espérons
Un microcontrôleur sans logiciel, ça fait quoi ? En fait, le cir- que ce cours vous a plu ! Peut-être allez-vous vous procurer un
cuit de la figure 6 comporte uniquement un potentiomètre PICKit3 ou PICKit2 et essayer d’améliorer ou d’enrichir l’un ou
comme composant supplémentaire et on peut quand même l’autre exemple. Je me ferai un plaisir de répondre à vos ques-
régler sa fréquence de 170 kHz à 3,5 MHz sans bits ni octets. tions envoyées à mon adresse miroslav.cina@t-online.de.
Quand la précision n’est pas essentielle, vous pouvez régler (150393 – version française : Eric Dusart)
l’oscillateur interne en « mode RC » sans quartz. Comme à
l’étape 2, la broche GP4 est utilisée comme sortie CLKOUT. Une
résistance sur GP5 définit la fréquence. Comme la fréquence
de l’oscillateur dépend directement de la résistance, aucun
Liens
code n’est nécessaire.
Plus la résistance sur GP5 est faible, plus la fréquence est éle- [1] PIC12F675: www.microchip.com/wwwproducts/
vée. Quand cette résistance descend sous environ 3 kΩ, l’oscil- Devices.aspx?product=PIC12F675
lateur s’arrête. Peu avant, la fréquence maximale est à 3,5 MHz. [2] Première partie du cours : www.elektormagazine.fr/130483
Avec la résistance maximale de P1, 100 kΩ, la fréquence est [3] Seconde partie du cours : www.elektormagazine.fr/150274
à environ 170 kHz. On peut aller encore plus loin : avec une
[4] Troisième partie du cours : www.elektormagazine.fr/150393
résistance de 10 MΩ la fréquence baisse à environ 2,1 kHz.

Pour être précis, il faut quand même un mot pour configurer


correctement le circuit, et donc un peu de code. Le listage 4
correspondant est cependant très court. À part pour la confi-
guration, il n’y a rien à faire. Un extrait du fichier LST corres-
pondant montre que la longueur du programme est exacte-
ment de 0 :

Listage 4.

;************************************************** ;GP3 --> N/C


;* NE555 Replacement - Example 4 w/o code * ;GP4 --> Output
;* v 1.00 - 19.06.2015 * ;GP5 --> Poti
;************************************************** ;--------------------------------------------------
;* Microcontroller: PIC12F675 * ;Chip configuration:
;* Oscillator: internal, RC mode with external R * INCLUDE “P12F675.INC”
;**************************************************
_U004 EQU B’00000110000111’
;Pin connections: ;MCLR = input, RC mode, GP4 = CLKOUT
;GP0 --> N/C __CONFIG _U004
;GP1 --> N/C ;--------------------------------------------------
;GP2 --> N/C END

16 octobre 2015 www.elektormagazine.fr


découvrir créer partager

cours intensif
d’assembleur 2.1
(1)
interruption pour commander
un afficheur à LED

L’an dernier, nous avons publié un cours intensif d’assembleur pour microcontrôleurs PIC. Nous y
abordions, en trois articles, la théorie et la pratique de la programmation de µC la plus proche possible du
matériel. Dans cette seconde série, nous approfondissons le sujet. Commençons par les interruptions.

Miroslav Cina Chaque banque de mémoire a 128 emplacements avec les


adresses 00h à 7Fh. On doit ce maximum de 128 positions à
l’adressage sur 7 bits des instructions.
D’abord nous vous présenterons une famille intéressante de Chaque banque comporte quatre sections différentes : les
µC PIC. Pour les exemples du cours intensif initial, nous avions 12 premiers octets sont réservés aux registres de base ou
utilisé un PIC12F675 (Microchip). Bien que ces µC offrent beau- noyaux (Core) et occupent les adresses 00h à 0Bh. Ces registres
coup de possibilités, il semblerait, refrain connu, que le mieux influent de façon cruciale sur l’exécution du programme, car ils
soit l’ennemi du bien. Le tableau 1 répertorie les µC d’une contiennent des fonctions importantes telles que le compteur
famille baptisée « Flash Microcontrollers with nanoWatt XLP d’instructions (PC), le registre d’état, etc.
Technology ». Plus polyvalents, leur programmation s’en voit Les 20 octets suivants sont prévus pour des registres à fonctions
sensiblement simplifiée. spéciales. On peut, par leur biais, accéder aux ports d’E/S ou
commander certaines autres fonctions du µC (compteurs, confi-
La famille comporte dix membres. Le plus petit des µC se guration des interruptions, etc.). Ce bloc de registres occupe
« contente » de huit broches. Six d’entre elles sont des E/S les emplacements de mémoire 0Ch à 1Fh, sachant que cha-
– un peu comme le PIC12F675 de la première série. Les plus cune des banques abrite des registres différents.
grands en ont 20 dont pas moins de 18 E/S. Comme le montre Après la position 1Fh on trouve, dans la plage d’adresses 20h
le tableau 1, la famille connaît des µC avec 2 à 8 Kmots de à 7Fh, la zone de mémoire à usage libre. Mais ne nous réjouis-
mémoire programme, 256 octets d’EEPROM et entre 128 et sons pas trop vite : non homogène, elle est subdivisée en
1 024 octets de RAM. Et, cependant, un PIC12F1840 coûte à deux zones :
peine quinze centimes de plus qu’un PIC12F675 – un inves-
tissement souvent rentable. • RAM d’Usage Général. Cette mémoire de 80 octets
utilisables sans restrictions par l’utilisateur occupe les
Cartographie de la mémoire adresses 20h à 6Fh.
Dans un premier temps, il faut se familiariser avec l’organisation • RAM Commune. La partie restante d’une banque sise aux
de la mémoire de ces « Enhanced Mid-Range PICs ». La carto- adresses 70h à 7Fh est également utilisable librement,
graphie de la mémoire de données, avec ses 128 à 1024 octets mais d’une manière très spéciale : ces 16 octets sont
de RAM est, de par sa taille, quelque peu différente de celle identiques pour toutes les banques. Si l’on souhaite définir
du PIC12F675. Elle se subdivise en 32 banques de 128 octets. des variables à utiliser souvent, et indépendamment de la
Erreur de calcul ? 32 x 128 octets permettraient d’adresser banque de mémoire spécifique, c’est pour ce domaine pré-
jusqu’à 4 Ko, mais même les exemplaires haut de gamme n’ont cisément qu’il faudra opter.
que 1 Ko de RAM – les petits n’ont d’ailleurs que 128 octets.
Pour comprendre le principe, il faut avoir saisi le fin mot de En fait, on ne dispose vraiment, dans chaque banque, que de
l’organisation des banques. 80 octets de RAM. La totalité de RAM disponible dépend, bien

14 juin 2016 www.elektormagazine.fr


notions de base cours q&r trucs & astuces logiciel

Tableau 1. Types des familles PIC12F1822 / 1840 / PIC16F182X / 1847

temporisateurs
µC mémoire prog. EEPROM RAM E/S CA/N comparateurs MSSP I2C / SPI
8/16bits

PIC12F1822 2K 256 128 6 4 1 2/1 1

PIC12F1840 4K 256 256 6 4 1 2/1 1

PIC16F1823 2K 256 128 12 8 2 2/1 1

PIC16F1824 4K 256 256 12 8 2 4/1 1

PIC16F1825 8K 256 1024 12 8 2 4/1 1

PIC16F1826 2K 256 256 16 12 2 2/1 1

PIC16F1827 4K 256 384 16 12 2 4/1 2

PIC16F1828 4K 256 256 18 12 2 4/1 1

PIC16F1829 8K 256 1024 18 12 2 4/1 2

PIC16F1847 8K 256 1024 16 12 2 4/1 2

sûr, du type de µC. Sur un PIC12F1822, le programmeur pourra la déclaration dans Step 1 une valeur dans v_tmp, la position
utiliser 80 octets sur les 128 octets de RAM de la BANK 0, mais réelle de cette variable dépend non seulement des 7 bits de
seulement 32 octets de la BANK 1. Pourquoi donc ? Du total de l’adresse attribuée, mais aussi du contenu du BSR. Si, comme
128 octets, il faut encore déduire la RAM Commune avec ses dans Step 2, on sélectionne la BANK 1, la valeur 28h « n’atter-
16 octets. Il n’y a donc plus la moindre RAM pour les BANK 2 rit » pas à l’adresse 230h, mais en B0h, qui est l’adresse définie
à BANK 32. Si on lit la RAM d’Usage Général non disponible (à par la somme de 30h et de la valeur de début de la BANK 1 =
partir de l’adresse 20h dans la BANK 1 et tout pour les BANK 2 80h. On obtient l’adresse correcte pour v_tmp, à savoir 230h
à BANK 32), on obtient toujours la valeur 00h. si, cf. Step 3, on paramètre BSR à 04h pour la BANK 4 (bien
La figure 1 compare la cartographie de la BANK 0 des PIC entendu, le type de µC utilisé doit avoir de la RAM à cet endroit
des types PIC12F1822 et PIC16F1847. Elle est pratiquement – il faut donc un µC avec au moins 512 octets de RAM).
identique pour les différents types de cette famille. Les dif-
férences sont dues à des caractéristiques spécifiques : pour
le PIC16F1847, le registre PORTB occupe l’adresse 0Dh, mais
dans le cas du PIC12F1822 cet espace est inoccupé en rai-
son de l’absence de PORTB. Les fiches techniques correspon-
dantes [1] donnent les détails des banques de mémoire pour
chaque type de µC.

Adressage direct via BSR


L’accès à la mémoire se fait de deux façons. L’adressage direct
utilise le BSR (Bank Select Register = registre de sélection de
banque). Nous parlerons de l’autre possibilité plus loin.

Grâce au BSR, l’adressage est assez simple. Il suffit, pour accé-


der aux différentes banques, d’écrire dans le BSR le numéro
de la banque concernée. Pour accéder à la BANK 0, on utilise
le BSR de la manière suivante :

v_tmp EQU H'30'


;
movlw H'00'
movwf BSR ;select BANK 0
movlw H'28' ;28h
movwf v_tmp

On voit ici que la déclaration de variable à elle seule ne définit


pas de manière univoque l’emplacement utilisé. Prenons un
autre exemple : la variable v_tmp est initialisée avec l’adresse Figure 1. Comparaison de la BANK 0 des PIC de types PIC12F1822
230h : si, dans le listage 1, on écrit immédiatement après et PIC16F1847.

www.elektormagazine.fr juin 2016 15


découvrir créer partager

S1

19 VDD 16 R1 A
RA0 RC0 1k2
18 15 R2 B
RA1 RC1 1k2
17
IC1 14 R3 C
RA2 RC2 1k2
4 7 R4 D
RA3/MCLR RC3 1k2
3 6 R5 E
RA4 RC4 1k2
BT1 2 PIC16F1829 5 R6 F
RA5 RC5 1k2
RC6
8 R7
1k2
G LD0 SC08-11 LD1 SC08-11 LD2 SC08-11 LD3 SC08-11
9 R8 DP A 1
A
A 1
A
A 1
A
A 1
A
RC7 1k2
B 14 B 14 B 14 B 14
B B B B
13 10 C 12 C 12 C 12 C 12
RB4/SDA1 RB7/SCL2 C C C C
12 11 D 10 D 10 D 10 D 10
RB5/SDA2 RB6/SCL1 D D D D
VSS E 4 E 4 E 4 E 4
E E E E
20 F 2 F 2 F 2 F 2
F F F F
G 13 G 13 G 13 G 13
G G G G
DP 9 DP 9 DP 9 DP 9
DP DP DP DP
CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC
3 5 11 16 3 5 11 16 3 5 11 16 3 5 11 16

150518 - 11

Figure 2. Le circuit complet de notre exemple se résume essentiellement au µC épaulé par huit résistances et quatre afficheurs à LED (à 7 segments).

Afficheur à LED commandé avec une interruption ces LED requièrent en général quelque 10 mA de courant, il
Après les bases de l’adressage de la mémoire, passons aux est judicieux, en mode « piles » (4,5 V par trois AA ou AAA, p.
choses sérieuses : l’utilisation d’interruptions à l’aide d’un ex.), de prévoir un interrupteur, S1. Autres composants : le µC
exemple concret, la commande d’un afficheur à LED à quatre PIC16F1829 (avec ses vingt broches, il dispose de suffisam-
chiffres. Nous verrons ainsi combien la programmation est ment d’E/S et a assez de mémoire), huit résistances-série et
simplifiée par rapport à des µC moins puissants tels que le quatre afficheurs à LED à sept segments. On voit en figure 3
PIC12F675. notre prototype.

L’électronique Il est important que chacune des huit sorties de segment du


La commande statique de quatre afficheurs à LED, à sept seg- µC (RC0 à RC7) attaque, au travers d’une résistance-série, les
ments, requiert, dit Adam Riese, 4 x 8 lignes de commande. quatre segments identiques des quatre afficheurs. Un exemple :
Sur ces afficheurs, les huit LED sont accompagnées d’un point le µC pilote, par sa sortie RC0 et la résistance R1, tous les seg-
décimal. Un total de 32 adresses d’E/S pour une tâche aussi ments « A » des quatre afficheurs. S’agissant ici d’afficheurs à
simple nous paraît exagéré. De tels afficheurs n’ont que rare- cathode commune, ces quatre cathodes sont pilotées par les
ment une commande statique, ils sont pratiquement toujours quatre sorties RA0/1/4/5 du µC. Il faudrait, pour une luminosité
pilotés en mode multiplexé dynamique. La commande multi- maximale, que les quatre sorties du µC reliées aux cathodes
plexée classique se résume en fait à une commande commune soient amplifiées par un transistor, etc. vu qu’il circule ici le
de tous les segments des quatre afficheurs et, parallèlement, à courant combiné de jusqu’à huit segments. Pour des essais,
une alimentation cyclique très rapide des quatre afficheurs par et à l’intérieur, une luminosité plus faible est convient. Aux
un découpage chronologique. Si la fréquence de multiplexage valeurs de résistances données, le courant de cathode est de
est bonne, l’œil humain n’y voit que du feu... une luminosité l’ordre de 20 mA. Peu de risque donc que ce courant endom-
constante. Avec 8 + 4 = 12 lignes de commande, le matériel mage les sorties du µC vu qu’elles supportent jusqu’à 25 mA.
de la variante dynamique est nettement moins complexe. Le Le fonctionnement d’une commande multiplexée est relati-
processus de multiplexage devra être réalisé par le microlo- vement élémentaire en fait : avec niveau « bas », les quatre
giciel du µC. afficheurs sont, tour à tour et pendant un court laps de temps,
La figure 2 montre le schéma fonctionnel complet d’un affi- alimentés par le biais de la cathode correspondante. Simul-
cheur à LED à quatre chiffres à commande dynamique. Comme tanément, les anodes des segments qui doivent s’allumer

Listage 1 movlw H'28' ; 28h


movwf v_tmp
;Step 1
;
v_tmp EQU H'230' ; déclaration
;Step 3
;
movlw H'04'
;Step 2
movwf BSR ; sélection de la BANK 4
movlw H'01'
movlw H'28' ; 28h
movwf BSR ; sélection de la BANK 1
movwf v_tmp

16 juin 2016 www.elektormagazine.fr


notions de base cours q&r trucs & astuces logiciel

Figure 3. Le prototype du montage trouvera facilement place sur un petit Figure 4. Commande cyclique d‘un afficheur à LED à sept segments, à
morceau de platine à trous. quatre chiffres, en mode multiplexé avec pseudo-code.

sur l’afficheur actif à ce moment-là sont forcées au niveau sateurs 0, 1, 2, 4 et 6, le µC utilisé en a même plusieurs. Nous
« haut » par le µC. Il faut bien sûr veiller à ce qu’il n’y ait allons œuvrer avec le temporisateur 2. À chaque passage par
qu’une seule cathode d’activée à la fois, on aurait sinon des la routine d’interruption, il faut activer la position suivante de
affichages indéfinis. l’afficheur et la laisser allumée jusqu’à la prochaine interruption.
Le temporisateur 2 remplit diverses fonctions. La figure 5 nous
Le logiciel apprend que le module de temporisation est constitué de trois
Pour un affichage dynamique, le logiciel doit faire s’allumer compteurs montés en série :
brièvement d’abord l’afficheur LD0 puis LD1, LD2 et pour finir • Un prédiviseur (prescaler). Attaqué avec la fréquence de
LD3 – et ce de façon cyclique. La figure 4 montre le principe l’oscillateur divisée par quatre, il est paramétrable pour
avec son pseudo-code. une seconde division par 1, 4, 16 ou 64, avant déclenche-
La fréquence d’exécution du cycle complet doit être supérieure ment d’une impulsion d’horloge.
à que ce que l’on appelle la fréquence de clignotement de l’œil • TMRx. Dans le cas du temporisateur 2 il s’agit de TMR2.
humain, sinon l’afficheur scintille. Aux fréquences vraiment trop Chaque impulsion d’horloge du prédiviseur incrémente
faibles, il clignotera et sera illisible. Pour une luminosité uni- le registre TMR2. À chaque changement, il y a compa-
forme des quatre afficheurs, leurs durées d’activation doivent raison entre le contenu de TMR2 et le registre PR2 et
être identiques. en cas d’égalité, le postdiviseur (postscaler) délivre une
impulsion.
Si c’était tout ce que le µC a à faire, il suffirait d’une boucle • Un postdiviseur (postscaler). Dernier compteur de la
sans fin exécutant ce dont nous venons de parler ; un afficheur chaîne, il est paramétrable pour compter jusqu’à 1, 2...16.
qui fonctionne, mais sans contenu, ne sert pas à grand-chose. Tout dépassement provoque la mise à un de l’indicateur
Le µC peut produire des données lui-même (l’heure, p. ex.) ou TMR2IF – qui, si activé, déclenche une interruption.
en traiter (lecture de capteurs, p. ex.). Ces tâches prennent Pour la commande de l’afficheur, il y a quatre registres à obser-
du temps de calcul. Dans le cas d’une commande d’affichage
dans une boucle sans fin, il faudra que la tâche additionnelle
soit intercalée quelque part entre la commande des différentes
positions. Selon les conditions, il se peut que la fréquence de
multiplexage varie un peu, ainsi que les périodes actives des
quatre afficheurs les unes par rapport aux autres, il faut éviter
ces deux situations. Une technique plus satisfaisante et très
utilisée est de faire appel à des interruptions.

Affichage commandé par une interruption


Des interruptions interrompent l’exécution normale du pro-
gramme et l’aiguillent vers une routine d’interruption. Si on
déclenche une interruption à intervalles réguliers, on peut y
exécuter la commande de l’affichage. Pour cela, le temporisa- Figure 5. Structure d‘un module temporisateur (timer) dans le cas du µC
teur (timer) d’un µC convient parfaitement. Avec ses tempori- PIC16F1829.

www.elektormagazine.fr juin 2016 17


découvrir créer partager

ver. Le registre T2CON en est un. Le tableau 2 décrit l’affec- Step 2 concerne la configuration de l’interruption. Le paramé-
tation des différents bits. On voit que les deux bits de poids trage à « 1 » de TMR2IE du registre PIE1 active l’interruption
faible du registre T2CON définissent le diviseur du prédiviseur. du temporisateur 2. Il ne reste plus maintenant qu’à activer
Le tableau 3 donne des informations de configuration. Le bit un commutateur d’interruption globale par la mise à « 1 » des
TMR2ON active ou désactive le temporisateur 2. Les quatre bits 6 et 7 du registre INTCON.
bits restants de T2OUTPS définissent le diviseur du postdivi- On a, dans Step 3, comme dernière étape de l’initialisation, le
seur (cf. tab. 4). démarrage de TIMER2.

Le code du micrologiciel explicite l’usage des trois derniers Intéressons-nous maintenant à l’ISR (Interrupt Service Rou-
registres requis. L’initialisation de l’interruption et du tem- tine = routine de service d’interruption) du listage 3 : il est
porisateur 2 se fait de la façon suivante : dans Step 1 du lis- évident qu’il est inutile, au début, de sauvegarder les registres
tage 2, le prédiviseur est paramétré à 1:64 (T2CKPS<1:0> = (ni W, STATUS ou tout autre). La 3e partie du premier cours
11), le postdiviseur à 1:1 (T2OUTPS<3:0> = 0000). TMR2 est intensif [2] décrivait la sauvegarde des registres W et STA-
ensuite mis à « 0 », d’où un comptage incrémentiel. Ensuite TUS du µC PIC12F675. Ici c’est inutile, vu que chaque µC de
on écrit la valeur 02h dans le registre PR2, ce qui provoque cette famille se charge automatiquement de la sauvegarde
une interruption lorsque TMR2 atteint cette valeur. Le choix du contexte. Lors d’une interruption, le matériel se charge de
d’un postdiviseur égal à 1 le désactive de fait. sauvegarder les contenus des registres W, STATUS, BSR et FSR

Tableau 2. T2CON : registre de commande de Timer 2


bit 7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0
U-0 R/W-0/0 R/W-0/0 R/W-0/0 R/W-0/0 R/W-0/0 R/W-0/0 R/W-0/0
– T2OUTPS<3:0> TMR2ON T2CKPS<1:0>

Listage 2 banksel PIE1


clrf PIE1
;Step 1: paramétrage du temporisateur
clrf PIE2
timer2_init movlw B'00000011'
bsf PIE1,TMR2IE ; activer l'interruption TMR2
;T2CON, TMR2 et PR2 sont dans BANK 0
clrf BSR ; sélection de la BANK 0
=> pas besoin de sélection de banque
movlw B'11000000'
movwf T2CON
movwf INTCON
clrf TMR2
;
movlw D'002'
;Step 3: démarrer TIMER2
movwf PR2 ; dépassement après 2 impulsions
bsf T2CON,D'002' ; démarrer TIMER2
;
return
;Step 2: paramétrage de l'interruption

Listage 3 btfsc STATUS,Z


call ishow_digit2 ; LD2 actif
;-------------------------
;
;Routine de service d'interruption
movf v_curr_p,0
;-------------------------
xorlw D'003'
;Step 1
btfsc STATUS,Z
ir_main clrf BSR
call ishow_digit3 ; LD3 actif
;effacement du bit GIE de INTCON dans HW
;
;
;Step 3
;Step 2
irs_fin_prep incf v_curr_p,1
movf v_curr_p,0
movf v_curr_p,0
xorlw D'000'
xorlw D'004'
btfsc STATUS,Z
btfsc STATUS,Z
call ishow_digit0 ; LD0 actif
clrf v_curr_p ; démarrer nouveau cycle
;
;
movf v_curr_p,0
;Step 4: terminer la routine de service
xorlw D'001'
d'interruption
btfsc STATUS,Z
irs_fin clrf TMR2
call ishow_digit1 ; LD1 actif
bcf PIR1,TMR2IF ; effacer la source
;
d'interruption
movf v_curr_p,0
retfie ; positionner aussi bit GIE de INTCON
xorlw D'002'

18 juin 2016 www.elektormagazine.fr


notions de base cours q&r trucs & astuces logiciel

(à décrire ultérieurement) dans des « registres fantômes ».


Lors de l’exécution de l’instruction de retour d’interruption
« retfie » (return from interrupt), les contenus d’origine sont
automatiquement restaurés. C’est une bonne chose !

Dans Step 1 du traitement de l’ISR, le registre BSR est mis à


zéro ; on accède ainsi aux registres de BANK 0.

Step 2 comporte quatre sections de code quasiment iden-


tiques. On y vérifie quelle position de l’afficheur doit être acti-
vée, information trouvée dans la variable v_curr_p. Les quatre
instructions par section comparent, avec une fonction EXOR,
la valeur du moment de v_curr_p, 0, 1, 2 ou 3. Si, p. ex. on
a 2, après exécution de l’instruction xorlw D‘002‘ le bit Z du
registre d’état est mis à « 0 » (une opération EXOR sur deux
opérandes égaux a pour résultat 0) et donc il y a exécution
de l’instruction suivante, call ishow_digit2.

Dans Step 3, la variable v_curr_p est incrémenté de sorte que


lors de la prochaine interruption c’est la position suivant de
l’afficheur qui se verra désignée.
On vérifie ensuite si v_curr_p est égale à 4. Dans ce cas, il y
a eu un dépassement de ce compteur de position, raison pour
laquelle v_curr_p est remise à « 0 » ; ainsi, lors du cycle sui-
vant, on redémarre à la première position de l’afficheur.

Step 4 n’est en fait rien de plus que quelques opérations de celle de la section Path2, etc. (cf. listage 4).
clôture. Le registre W commence par se voir affecter la valeur 02h,
l’instruction BRW est ensuite exécutée. Puisque l’on a addi-
BRW tion de la valeur de W au CO, l’instruction suivante à exécuter
Le PIC de type 12F675 « connaît » 35 instructions. La nouvelle n’est pas goto path1, mais goto path3. De ce fait, on saute à
famille plus récente et utilisée ici, avec les 49 instructions du la section de code de Path3.
« Enhanced Instruction Set », en a encore plus. L’instruction
BRW est l’une d’entre elles : elle permet, dans une ISR, d’éco- BRW permet donc de simplifier sensiblement le code de l’ISR.
nomiser bien du temps et beaucoup de mémoire de programme. On peut, par son biais, réaliser un branchement élégant, en
BRW (relative BRanch with W) est en fait une instruction de fonction de v_curr_p, vers l’une des quatre sous-routines ishow_
saut sans paramètre additionnel. D’où sa syntaxe ultra simple : digitx. Dans le listage 5 il n’y a, logiquement, rien de changé
dans Step 1, 3 et 4. Step 2 au contraire a été subdivisé : dans
brw Step 2a, on fait appel à une nouvelle technique de décision.
Dans Step 2b, on utilise l’instruction BRW et on a, en fonction
L’instruction ajoute le contenu du registre W au compteur
d’instructions (PC pour Program Counter). Ainsi, l’exécution
du programme est interrompue et reprise à un autre endroit. Listage 4
La distance de l’endroit est donnée par le registre W. On peut
movlw B'00000010' ; W = 02h
utiliser l’instruction à chaque fois que l’on veut introduire un
brw
branchement multiple qui soit fonction d’une variable dans le
goto path1
déroulement du code. Elle permet, p. ex., d’exécuter quatre sec-
goto path2
tions de code différentes en fonction du contenu du registre W.
goto path3
Si W = 0, on aura exécution de la section Path1 et pour W = 1
goto path4
;
;autre code ici...
Tableau 3. configuration Tableau 4. configuration
;
du prédiviseur du postdiviseur
path1 nop
T2CKPS<1:0> diviseur T2OUTPS<3:0> diviseur
;
00 1 0000 1 path2 nop
0001 2 ;
01 4
0010 3 path3 nop
10 16 ;
… …
11 64 1111 16 path4 nop

www.elektormagazine.fr juin 2016 19


découvrir créer partager

du contenu de v_curr_p, branchement vers l’une des quatre correspondant. Dans le programme d’exemple, onze caractères
routines pour la position d’afficheur concernée. Si v_curr_p = différents ont été définis : 0 à 9 et « - », ce dernier caractère
0, on a exécution de ishow_digit0 et, dans le cas d’une valeur est codé 0Ah.
de 1, ishow_digit1 et ainsi de suite. Au lieu de 4 x 4 instruc-
tions, il n’en faut plus que sept au total. Pour que le pilote d’affichage affiche le caractère correct, il reste
encore à définir une sorte de « jeu de caractères » sous forme
Les sous-routines ishow_digit0 à ishow_digit3 sont presque d’un tableau. Pour un « 1 » par ex., il faudra activer les seg-
identiques, la seule différence est la sortie (RB4 à RB7) qui ments « B » et « C ». Pour cela, sur le circuit, les sorties RC1
présentera un « 0 » logique et activera donc la position de l’af- et RC2 doivent être mises à « 1 », RC0 et RC3 à RC7 à « 0 ».
ficheur correspondante. Les sous-routines s’expliquent d’elles- L’instruction BRW convient également fort bien pour mettre
mêmes. Signalons l’utilisation ici d’une sorte de mémoire vidéo. en place ce tableau. Il nous faut encore un petit complément
Il y a quatre emplacements de mémoire (variables v_pos0 fourni par l’instruction du paragraphe qui suit.
à v_pos3) pour stocker les données à afficher. Ces quatre
variables servent d’interface entre l’application principale et RETLW
le pilote d’affichage qui se cache dans l’ISR décrite. L’applica- RETLW est en fait une variante de l’instruction RETURN. Cette
tion principale stocke les données à afficher dans la mémoire dernière est utilisée pour quitter une sous-routine et revenir
vidéo. Le pilote d’affichage les lit et les affiche. Pour éviter que au programme d’appel. RETLW (RETurn with Literal in W) est
l’application n’ait à se soucier du codage des caractères, il faut similaire à RETURN, à ceci près que l’on peut la doter d’un
effectuer une conversion des valeurs numériques en segments paramètre. Ce paramètre représente une constante qui, lors
de LED à allumer. Si l’une des variables de la mémoire vidéo du saut de retour, est stockée dans le registre W.
contient la valeur 00h, il apparaîtra un « 0 » à l’emplacement Sa syntaxe est :

Listage 5 xorlw D'004'


btfsc STATUS,Z
;--------------------
clrf v_curr_p ; démarrer nouveau cycle
;ISR avec instruction bwr
;
;--------------------
;Step 4: finalize ISR
;Step 1
irs_fin clrf TMR2
ir_main clrf BSR
bcf PIR1,TMR2IF ; effacer la source
;effacement du bit GIE de INTCON dans HW
d'interruption
;
retfie ; positionner aussi bit GIE de INTCON
;Step 2a
;
movf v_curr_p,0
;Step 2b
call ishow_digits
ishow_digits brw
;
goto ishow_digit0
;Step 3
goto ishow_digit1
irs_fin_prep incf v_curr_p,1
goto ishow_digit2
movf v_curr_p,0
goto ishow_digit3

Listage 6 retlw B'01011011' ; "2" retlw B'00100111' ; "7"


retlw B'01001111' ; "3" retlw B'01111111' ; "8"
wm_char_set brw
retlw B'01100110' ; "4" retlw B'01101111' ; "9"
retlw B'00111111' ; "0"
retlw B'01101101' ; "5" retlw B'01000000' ; "-"
retlw B'00000110' ; "1"
retlw B'01111101' ; "6"

Listage 7 movf v_pos2,0 ;


xorlw H'0A' clrf v_pos1
demo_loop nop
btfss STATUS,Z incf v_pos0,1
call dr2
goto demo_loop movf v_pos0,0
incf v_pos3,1
; xorlw H'0A'
movf v_pos3,0
clrf v_pos2 btfss STATUS,Z
xorlw H'0A'
incf v_pos1,1 goto demo_loop
btfss STATUS,Z
movf v_pos1,0 ;
goto demo_loop
xorlw H'0A' clrf v_pos0
;
btfss STATUS,Z goto demo_loop
clrf v_pos3
goto demo_loop
incf v_pos2,1

20 juin 2016 www.elektormagazine.fr


notions de base cours q&r trucs & astuces logiciel

quences. Ralentir Timer 2 p. ex. pour voir l’effet produit sur


retlw k l’affichage. Si, p. ex. on fait passer la valeur du postdiviseur
de 1 à 16 et que l’on initialise le registre PR2 non pas avec 02h,
Comme le montre le listage 6, il est extrêmement facile de mais avec FFh, on voit très bien l’activation lente et successive
réaliser un « jeu de caractères » avec une combinaison BRW + des différents chiffres.
RETLW. Lorsqu’on appelle la sous-routine wm_char_set et que
le registre W contient alors la valeur 07h, l’exécution du code Perspectives
se poursuit, par le biais de l’instruction BRW, avec la ligne qui Cet exemple clôture le premier article de la seconde série de
définit le caractère « 7 ». On a ainsi, renvoi de la séquence de notre cours intensif d’assembleur. Le code complet est dis-
bits du caractère concerné. ponible au téléchargement sur la page de cet article [3]. Le
prochain épisode traitera de l’adressage indirect. Il vous pro-
Compteur de 0000 à 9999 posera bien entendu un autre exemple pratique.
Il est temps maintenant de tester la théorie par un exemple
pratique simple. Nous avons tout pour visualiser le contenu de En cas de question concernant le code et cet exemple, voici
la mémoire vidéo. Pour ce test, nous allons écrire une applica- mon courriel : miroslav.cina@t-online.de.
tion principale simple qui produit des données sous la forme (150518 – version française : Guy Raedersdorf)
d’un compteur qui s’incrémente de 0000 à 9999 et qui redé-
marre ensuite à 0000. Le pilote d’affichage décrit affiche alors
l’état actuel du compteur.
Liens

L’application principale prend la forme d’une boucle sans fin [1] PIC1XF18XX: http://ww1.microchip.com/downloads/en/
qui crée ce compteur et écrit l’état actuel du compteur dans DeviceDoc/40001413E.pdf
les quatre variables de mémoire vidéo. La boucle sans fin [2] Troisième partie du premier cours :
demo_loop du listage 7 contient le compteur incrémental. www.elektormagazine.fr/150393
Chaque changement du compteur est suivi d’une petite pause [3] Téléchargement du logiciel : www.elektormagazine.fr/150518
(call dr2), pour éviter que le compteur n’aille trop vite. On
pourra, pour étudier le comportement du pilote d’affichage,
effectuer de petites modifications et en observer les consé-

Publicité

EXPÉRIENCE, COMPÉTENCE, IDÉES, TALENT & ENVIES


Vous avez de l’expérience, des compétences, des idées, du talent et des
envies d’aller de l’avant dans la jungle des réseaux et des protocoles ?

Les fauves et les moustiques appelés LoRa, SigFox, Neul, Qowisio, ThingSpeak,
Brillo, Nest Weave, Thread… ne vous effrayent pas ?
Ce ne sont pas ces quelques réseaux à bas débit sur
longue distance qui vous font perdre le nord ?

Pour vous orienter dans le monde de l’Internet des


Objets, vous avez déjà pratiqué une ou plusieurs cartes
d’expérimentation : Elektor vous invite à partager vos connaissances
maintenant en publiant
votre livre !

Forts de notre expérience d’éditeur, nous vous


accompagnerons dans l’écriture de votre ouvrage
et nous chargerons de la mise en page, de
l’impression, de la commercialisation en librairie
et bien sûr sur l’internet (notamment chez Amazon).

La relation éditeur-auteur est encadrée par un contrat d’édition qui stipule vos
droits d’auteur sous la forme d’un pourcentage déterminé du prix de vente.

Présentez-nous votre projet en nous envoyant une description et un projet de


sommaire par courriel à redaction@elektor.fr.

www.elektormagazine.fr juin 2016 21


découvrir créer partager

cours intensif
d’assembleur 2.1
(2)
adressage indirect

Dans l’article précédent de notre cours intensif d’assembleur [1], nous avons traité de la commande
multiplexée d’un afficheur à LED. L’utilisation d’un microcontrôleur (µC) récent aux modes d’adressage
sophistiqués a permis de simplifier sensiblement la programmation. Dans ce second article, vous
découvrirez l’adressage indirect.

Miroslav Cina (miroslav.cina@t-online.de) deux autres registres spéciaux qui permettent un accès linéaire
à la mémoire de travail : INDF0 et INDF1. Mieux, ils auto-
risent même un accès linéaire à la mémoire de programme.
La famille plus moderne des µC PIC1xF18xx met à disposition Avec cette méthode d’accès, toute la mémoire, RAM + Flash
une fonction très pratique : l’adressage indirect. Son princi- (mais hors EEPROM), du µC se présente sous la forme d’un
pal avantage est que l’on peut accéder à la mémoire de façon seul bloc de 64 Ko.
totalement linéaire, ce qui permet de contourner le traitement Qui dit espace d’adressage de 64 Ko, dit adresses de 16 bits.
parfois complexe inhérent aux blocs segmentés. Ainsi, ces µC C’est ce type d’adresses que contiennent les paires de registres
redeviennent faciles à manipuler, à l’image de ce que permet- FSR0 (FSR0H | FSR0L) et FSR1 (FSR1H | FSR1L), dont nous
taient les « vrais » microprocesseurs à 8 bits tel le populaire avons déjà parlé comme membre des registres noyaux (Core).
Z80 (Zilog) des années 80. Il nous faut maintenant, pour l’adressage indirect, deux ins-
tructions additionnelles de l’assembleur. Nous verrons alors à
Registres INDFx quoi peuvent servir les registres INDF0 et INDF1.
Dans l’article précédent, nous avons vu l’adressage direct via La RAM se retrouve en double dans l’espace d’adressage
le registre BSR. Tous les µC de la série PIC1xF18xx comportent de 64 Ko. En premier lieu, dans la plage 0000h à 0FFFh, comme
mémoire de travail conventionnelle. L’accès à ces adresses
par le biais de FSRx correspond en grande partie à l’adres-
sage direct via BSR. La RAM est à nouveau disponible dans la
plage d’adresses 2000h à 29AFh – mais en linéaire cette fois.
Ceci est pertinent si l’on veut, par exemple, accéder élégam-
ment à une matrice de données, un tableau par exemple. Mais
pourquoi donc la plage d’adresses s’arrête-t-elle à 29AF et pas
à 2FFF ? Dans cet espace de mémoire, les blocs sont, à raison
de 80 octets, un miroir des banques de mémoire individuelles.
La banque BANK 0 sise dans la plage d’adresses 020h à 06Fh
se trouve ici dans la plage 2000h à 204Fh, BANK 1 entre 2050h
et 20AFh, etc. La dernière banque en miroir (BANK 30) se ter-
mine donc à l’adresse 29AFh.
L’accès à la mémoire de programme Flash se fait par les
adresses 8000h à FFFFh. Il est évident qu’il n’y a pas occu-
pation effective de tous les emplacements de mémoire. Par
exemple, la Flash de 8 Kmots du PIC16F1829 se trouve dans
la plage 8000h à 9FFFh. Les 2 Kmots du PIC12F1822 se situent
eux dans la plage 8000h à 87FFh. Le reste inutilisé est bien
adressable, mais inutile.
Caractéristique typique de ces µC PIC, des cellules de RAM
Figure 1. Cartographie de la mémoire des µC de la série PIC12F18xx. de 8 bits de large, bien que la mémoire de programme soit

14 juillet/août 2016 www.elektormagazine.fr


notions de base cours q&r trucs & astuces logiciel

organisée en mots de 14 bits. La question se pose : comment Tableau 1.


ces mots de 14 bits ont-ils été compactés dans l’espace d’adres-
syntaxe signification
sage. La solution est simple : on ne peut accéder directement
pré-incrémentation
à l’octet qu’avec les huit LSB (bits de poids faible). Avant que moviw ++FSRn
incrémentation avant accès en lecture
nous passions à la description de l’instruction MOVIW, exami-
pré-décrémentation
nez l’organisation de la mémoire à la figure 1. On y voit que moviw --FSRn
décrémentation avant accès en lecture
la mémoire de programme a une largeur de 14 bits ; on n’a
post-incrémentation
pas accès aux six bits de poids fort, c’est pourquoi cette zone moviw FSRn++
incrémentation après accès en lecture
a été grisée. La commande MOVIW recopie le contenu de la
post-décrémentation
cellule de mémoire dont l’adresse se trouve dans la paire de moviw FSRn--
décrémentation après accès en lecture
registres FSR0 ou FSR1 dans le registre W. Seuls les huit bits
de poids faible sont alors copiés.

MOVIW
Cette instruction est principalement destinée au transfert du
contenu du registre INDFn dans le registre W (MOVE Indfn
to W). INDFn peut être soit INDF0 soit INDF1. Maintenant,
l’astuce : le registre INDFn n’existe pas. Lors de l’accès à
Figure 2. Affichage d‘un octet sous forme hexadécimale sur l‘afficheur à
INDF0, on accède toujours à l’emplacement de mémoire dont
LED du premier article.
l’adresse se trouve dans FSR0 (pour INDF1 ce sera évidem-
ment l’adresse de FRS1).
Il existe deux variantes d’utilisation : pour l’une, on a ajuste- vant. La lecture de la valeur de FFh de la mémoire signale la
ment du pointeur (incrémenté ou décrémenté) et pour l’autre fin de la boucle. Tout repart alors à l’adresse 1000h.
pas d’ajustement. Il s’agit ici de la première variante, car sou- Comme il s’agit d’octets, la représentation requiert des carac-
vent utilisée lors de l’accès à des champs de données. tères numériques ordinaires, mais aussi hexadécimaux. L’affi-
La première variante connaît en outre quatre sous-types cf. le chage d’un octet de format hexadécimal ne nécessite que deux
tableau 1, qui se différencient par le moment de changement positions d’afficheur. Nous utilisons pour cela les deux positions
du pointeur, avant ou après l’accès, et la fonction, incrémen- gauches de l’affichage, LD0 et LD1. LD2 reste vide et la qua-
tation ou décrémentation ; « n » peut en outre avoir la valeur trième position, LD3, affiche un « h » en permanence. La valeur
« 0 » ou « 1 » (registre FSR0 ou FSR1). décimale 122 s’affiche alors comme « 7A h », cf. la figure 2.
Parallèlement à l’instruction MOVIW décrite ici, il existe, avec
MOVWI, son inverse : cette instruction écrit le contenu du Modification du pilote d’affichage
registre W dans la cellule de mémoire adressée correspondante. Nous le disions, l’affichage doit maintenant pouvoir représen-
Ceci ne fonctionne bien entendu que dans la zone où il existe ter des caractères hexadécimaux. Contrairement au code du
de la RAM. Il faudra, pour modifier le contenu de la mémoire 1er article, il ne suffit plus de pouvoir afficher uniquement les
Flash, opter pour une autre technique. Tout cela est à utiliser chiffres « 0 » à « 9 » et le signe « - », il nous faut maintenant
avec prudence : du code qui peut se modifier lui-même pré- les lettres « A » à « F », l’espace et le « h » minuscule, d’où
sente des pièges. modification du pilote d’affichage. Il devient possible alors de
représenter en hexadécimal toutes les valeurs décimales 0 à 255.
Affichage de la mémoire de programme Le générateur de police de la routine « wm_char_set » va gon-
Vu que l’on dispose déjà, avec l’afficheur à LED de l’article pré- fler un peu. Les différences entre l’ancienne version décimale
cédent, du matériel requis pour afficher des valeurs, il nous du listage 1 et la nouvelle version hexadécimale du listage 2
servira à afficher en boucle le contenu de la mémoire Flash à restent limitées. Cet exemple montre combien il est facile,
partir de l’adresse 1000h. Il suffit de modifier le programme si besoin était, d’étendre le pilote d’affichage. Un caractère
principal du logiciel du µC. Hormis cela, on réutilise le pilote est défini dans une ligne d’assembleur. Ainsi les modifications
d’affichage de l’article précédent légèrement modifié. Il n’y a nécessaires pour l’affichage sont simples et rapides.
pas cette fois de compteur dans la routine principale, mais le
code qui sert à lire les données de la mémoire de programme. Programme principal
Le principe : une boucle lit les données de la mémoire de pro- Passons au programme principal ; il est composé de trois
gramme et les affiche. Pour cela, le programme extrait les parties :
données octet par octet à partir de l’adresse 1000h. Chaque • Lecture des données de la mémoire Flash par le sous-
octet lu est affiché un court instant, on passe ensuite au sui- programme f_get_data.

Listage 1. retlw B'00111111' ;00h -> 0 retlw B'01111101' ;06h -> 6


retlw B'00000110' ;01h -> 1 retlw B'00100111' ;07h -> 7
;-------------------------
retlw B'01011011' ;02h -> 2 retlw B'01111111' ;08h -> 8
; ancien jeu de caractères décimaux
retlw B'01001111' ;03h -> 3 retlw B'01101111' ;09h -> 9
;-------------------------
retlw B'01100110' ;04h -> 4 retlw B'01000000' ;0Ah -> moins
wm_char_set brw
retlw B'01101101' ;05h -> 5

www.elektormagazine.fr juillet/août 2016 15


découvrir créer partager

• Conversion des octets au format hexadécimal à deux mémoire de programme peuvent contenir jusqu’à 14 bits. Ainsi,
chiffres avec le sous-programme calc_hex_disp. une déclaration H’AB’ est identique à H’00AB’. De ce fait, une
• Structure de la boucle principale, sans fin. telle déclaration écrase donc deux octets – d’où deux messages.
La première partie du mot ne peut prendre que des valeurs
Lecture de la Flash allant de 00h à 3Fh, mais comme, avec cette méthode, il est
Dans cette partie, nous découvrons l’utilisation de l’adressage de toute façon impossible d’accéder aux six premiers bits, on
indirect. La déclaration complète des constantes comme don- peut ici faire une déclaration abrégée.
nées pour la mémoire Flash et l’accès en lecture correspondant On aurait pu totalement oublier la directive ORG 1000, les
sont faciles à implémenter, cf. le listage 3. données auraient cependant été stockées dans la mémoire
Les données à lire doivent être stockées dans la mémoire de Flash juste après le sous-programme f_get_data. Il peut être
programme à partir de l’adresse 1000h. Ceci est obtenu par la important, à l’occasion, de connaître l’emplacement de mémoire
directive ORG 1000 (cf. step 3). En outre, le début des don- exact, car en l’absence de directive ORG la position change
nées est indiqué sous la forme de « c_data1 ». En principe, avec le code.
l’utilisation d’autres zones de mémoire est possible, mais avec La routine f_get_data (step 2) lit un octet de la mémoire Flash ;
deux restrictions : la zone de mémoire doit, pour le µC utilisé, elle ne requiert que quatre lignes de code. Comme déjà dit,
correspondre à de la mémoire Flash physique et la déclara- l’instruction MOVIW copie la valeur dans le registre W. Ensuite
tion ne doit pas entrer en conflit « accidentel » avec le code la valeur est sauvegardée dans la variable-tampon v_value
de programme proprement dit. Le µC PIC16F1829 utilisé ici pour une utilisation ultérieure ; et voilà. Comme ici on utilise
possède 8 Kmots de mémoire de programme ; la cellule de la variante post-incrémentation de l’instruction, le pointeur
la mémoire la plus haute se situe donc à l’adresse 1FFFh. Si correspondant est incrémenté après lecture. Lors du pro-
l’on utilisait à tort l’adresse 2000h, l’accès se ferait à l’adresse chain appel du sous-programme, il y a automatiquement lec-
0000h, ce qui n’est pas très malin. ture de l’octet suivant.
Avec la directive ORG, si vous déclarez la zone de mémoire des Un mot au sujet de l’initialisation du pointeur – dans ce cas,
données à une adresse trop basse, l’exécution de l’assembleur la paire de registres FSR1 : pour lire les données à partir de
produira des messages d’erreur. Cela dépendra de l’endroit l’endroit correct, il faut qu’il s’y trouve l’adresse correspon-
où l’on « débarque » dans la mémoire de programme. Pour dante. C’est la fonction du sous-programme f_get_add (step 1).
chaque octet écrasé par erreur, deux messages d’erreur sont L’adresse est divisée par les directives « LOW » et « HIGH » et
affichés, cf. l’exemple ci-après : écrite dans les moitiés de registre appropriées. La ligne

Error[118] C:\...\05_TEST.ASM 339 : movlw LOW c_data1


Overwriting previous address contents (0051)
Error[118] C:\...\05_TEST.ASM 339 : commence par copier l’octet de poids faible de l’adresse de
Overwriting previous address contents (0051) c_data1 vers le registre W – ici, la valeur 00h (de 1000h).

Pourquoi deux messages par octet ? Parce que les mots de Ensuite, la ligne

Listage 2. retlw B'01011011' ;02h -> 2 retlw B'01111100' ;0Bh -> b


retlw B'01001111' ;03h -> 3 retlw B'00111001' ;0Ch -> C
;-----------------------------
retlw B'01100110' ;04h -> 4 retlw B'01011110' ;0Dh -> d
; nouveau jeu
retlw B'01101101' ;05h -> 5 retlw B'01111001' ;0Eh -> E
; de caractères hexadécimaux
retlw B'01111101' ;06h -> 6 retlw B'01110001' ;0Fh -> F
;-----------------------------
retlw B'00100111' ;07h -> 7 retlw B'01000000' ;10h -> moins
wm_char_set brw
retlw B'01111111' ;08h -> 8 retlw B'00000000' ;11h -> espace
retlw B'00111111' ;00h -> 0
retlw B'01101111' ;09h -> 9 retlw B'01110100' ;12h -> h
retlw B'00000110' ;01h -> 1
retlw B'01110111' ;0Ah -> A

Listage 3. ;
;step 2
;---------------------
f_get_data clrf BSR
; déclaration et lecture des données
moviw FSR1++
;---------------------
movwf v_value
;step 1
return
f_get_add clrf BSR
;
movlw LOW c_data1
;step 3
movwf FSR1L
ORG 1000
movlw HIGH c_data1
c_data1 da H'01', H'02', H'03', H'04'
movwf FSR1H
da H'AB', H'CD', H'EF'
return
da H'FF'

16 juillet/août 2016 www.elektormagazine.fr


notions de base cours q&r trucs & astuces logiciel

movlw HIGH c_data1

copie l’octet de poids fort 10h (de 1000h) dans le registre W.


0 register f C
En fait, ce n’est pas tout à fait exact ; en raison de l’adressage
indirect, la mémoire Flash ne se trouve maintenant qu’à partir
Figure 3. Les opérations lors du décalage de bits par l‘instruction
de l’adresse 8000h. L’emplacement 0000h se trouve lui dans
assembleur LSRF.
l’espace d’adressage FSR à l’adresse 8000h. c_data1 pointe
donc sur l’adresse 9000h. C’est pourquoi pour la ligne de code
précédente, c’est la valeur 90h qui atterrit dans le registre W
et non pas 10h.

1 octet dans 2 quartets


Cette routine n’a rien à voir avec l’adressage indirect, mais
est nécessaire si l’on veut avoir sortie d’un octet en hexadé-
cimal. Pour mieux comprendre, nous allons décrire une nou-
velle instruction : LSRF (Logical Shift Right). Elle appartient Figure 4. Décalage vers la droite des bits (Bit-Shifting) avec l’instruction
à la catégorie « Byte-Oriented File Register Operations » et LSRF. Le bit de poids faible précédent fini dans le registre d‘état et à
se contente de décaler tous les bits du registre vers la droite. gauche on ajoute un « 0 » comme bit de poids fort.
La syntaxe est :

lsrf f

où « f » identifie le registre traité. Le bit tout à droite, de poids


le plus faible, finit dans les limbes ; il est ici représenté par le
bit de retenue (Carry Bit) du registre d’état, puisque supprimé.
Tout à gauche c’est un « 0 » binaire qui entre dans le registre
comme bit de poids fort (MSB). La figure 3 montre ce qui se
passe. Si, initialement, on a la valeur 7Ah dans le registre F,
elle devient, par l’application de LSRF, 3Dh (cf. fig. 4). Notons
qu’il existe une instruction produisant l’effet inverse, LSLF.
Le listage 4 donne le code de division d’un octet en deux quar-
tets de poids fort et faible (4 bits = 1 quartet = 1/2 octet).
L’octet lu commence par être copié dans le registre W (step 1) ;
l’instruction AND avec 00001111b met à 0 les quatre bits de
poids forts (MSB). Le résultat est écrit dans une variable v_lsb.
Figure 5. Division d‘un octet en deux quartets, ensuite affichés au format
L’octet lu est à nouveau copié dans le registre W (step 2) ; une
hexadécimal.
quadruple exécution de l’instruction de décalage LSRF permet
de supprimer les quatre bits de poids faible (LSB). Les quatre
bits LSB qui en découlent contiennent alors la valeur des quatre
bits MSB précédents (variable v_msb). La figure 5 traduit le
comportement de ce morceau de code. Les deux variables
Liens
v_lsb et v_msb contiennent alors les valeurs utilisables telles
quelles pour l’affichage des octets sous forme hexadécimale. [1] Cours intensif d’assembleur 2.1 (1), Elektor 06/2016 :
www.elektormagazine.fr/150518
Perspectives [2] Page de cet article : www.elektormagazine.fr/160018
La lecture d’un octet et la préparation de son affichage hexa-
décimal terminent ce second article de la deuxième mouture
du cours intensif d’assembleur. Le code complet est disponible
au téléchargement sur la page Web de cet article [2]. Dans le
prochain article, nous aborderons la communication série via Listage 4.
I2C ou SPI, qui prend une importance particulière dans le cas ;step 2
des µC et de leurs puces périphériques. Ensuite, nous verrons ;-----------------
movf v_value,0
comment, par le biais d’une telle interface série, commander ; octet -> 2 quartets
movwf v_msb
très simplement un expanseur de port. En outre, nous utili- ;-----------------
lsrf v_msb,1
serons l’affichage à LED pour réaliser une horloge ou un mul- ;step 1
lsrf v_msb,1
timètre U/I, applications qui nécessitent chacune une puce calc_hex_disp
lsrf v_msb,1
externe et un rien de micrologiciel. movf v_value,0
lsrf v_msb,1
Pour toute question concernant le code et cet exemple, voici andlw B'00001111'
return
mon courriel : miroslav.cina@t-online.de. movwf v_lsb
(160018 – version française : Guy Raedersdorf)

www.elektormagazine.fr juillet/août 2016 17


découvrir créer partager

cours intensif
d’assembleur 2.1
(3)
communication I2C et SPI

Dans les deux premiers articles de ce second cours intensif d’assembleur, nous avons abordé la
commande multiplexée d’un afficheur à LED et parlé de l’adressage indirect. Ce troisième et dernier article
s’intéresse à la communication série via les interfaces I2C et SPI.

Miroslav Cina (Allemagne) miroslav.cina@t-online.de (Maître) est particulièrement intéressante, car cette fonction
permet, lorsqu’il faut utiliser le port série en « maître », d’éco-
nomiser énormément de temps et beaucoup de mémoire de
Les microcontrôleurs (µC) modernes peuvent non seulement, programme.
comme leurs « ancêtres », échanger « de façon normale » des
données en série avec d’autres périphériques — à cet effet ils I2C
disposent généralement d’un UART (Universal Asynchronous Le protocole I2C et son bus virent le jour en 1982 (Philips
Receiver Transmitter), mais ils prennent aussi en charge des Semiconductors, NXP depuis pour ce segment) pour les TV
systèmes de bus rapides tels qu’I2C (Inter-Integrated Circuit) « smart » de l’époque. Ce bus permet de réaliser une com-
ou SPI (Serial Peripheral Interface). Les deux systèmes sont munication simple au cœur d’un appareil. Dans la pratique, un
très utilisés, car ils ne requièrent que peu de matériel et de µC communique sériellement avec d’autres circuits intégrés
logiciel et savent se « débrouiller » avec les niveaux de ten- ou d’autres µC, généralement un maître et plusieurs esclaves
sion tels que les connaissent les µC. Il existe nombre de puces dans ce cas-là. Atmel a repris ce système de bus, vu sa sim-
périphériques, des capteurs par ex., équipées de l’un au moins plicité, l’a rebaptisé TWI (Two Wire Interface) ; il ne comporte
de ces deux modes de communication. Nous allons voir ici, que deux lignes de données (plus la masse). Aujourd’hui, plus
comment les traiter en assembleur. de 50 fabricants le prennent en charge.
I2C offre une communication synchrone et bidirectionnelle,
MSSP mais en semi-duplex. Pour communiquer avec des puces indivi-
Chaque membre de la famille PIC utilisé, même le plus petit, duelles, les esclaves sont à l’écoute sur le bus par leur adresse
possède au moins une unité MSSP, certains en ont même deux. et répondent aux appels du maître. SDA est la ligne de don-
Son acronyme (Master Synchronous Serial Port) dévoile la nées et SCK la ligne d’horloge. Il ne peut, à un moment donné,
raison d’être d’un MSSP. Cas majeurs de mise en œuvre d’un circuler qu’un seul paquet de données sur le bus. Les taux
MSSP : de transmission vont de 100 kbits/s jusqu’aux modes haute
vitesse de 5 Mbits/s, les vitesses de 100, 400 et 1000 kbits/s
• Besoin d’un grand nombre de ports d’E/S (plus que le µC étant les plus fréquemment adoptées.
n’en a lui-même),
• Besoin de commander des puces périphériques spéciales SPI
(CA/N, CN/A, horloge en temps réel, capteurs, etc.), C’est à Motorola, en 1979, que l’on doit le bus SPI, protocole
• Besoin d’échanger facilement des données entre plusieurs développé pour l’introduction d’une CPU légendaire, la célèbre
puces et/ou 68K. SPI est une interface série synchrone, mais full duplex
• Échange de données à (« grande ») distance (plusieurs cette fois. Le bus en devient un peu plus complexe, car il lui
mètres souvent). faut, pour la communication bidirectionnelle, outre la ligne
d’horloge SCLK et deux lignes de données MOSI (Master Out-
Un MSSP connaît plusieurs modes. Sa configuration en tant put, Slave Input) ou SDO (Serial Data Out) et MISO (Master
qu’interface I2C ou SPI revêt une importance particulière. Avec Input, Slave Output) ou SDI (Serial Data In), au moins une
des PIC, la configuration en tant qu’esclave ou maître est pos- ligne SS (Slave Select) plus la masse. En fait chaque esclave
sible dans les deux modes. a besoin de sa propre ligne SS (parfois appelée CS pour Chip
De nombreux µC offrent un module SSP ; mais la lettre « M » Select) avec un numéro unique.

10 octobre 2016 www.elektormagazine.fr


notions de base cours q&r trucs & astuces logiciel

Cependant, la complexité plus grande et l’utilisation d’étages


Tableau 1.
d’attaque push-pull (par rapport à la conception à collecteur
MSSP n0 Signal Port Broche n0
ouvert d’I2C) permettent des débits bien plus élevés ; le cou-
SDA1 RB4 13
rant de service est aussi plus faible. Seul inconvénient, la lon- 1
gueur de câble est limitée, proche des restrictions en RS-232. SCL1 RB6 11
Comme la vitesse peut aller jusqu’à 80 Mbits/s, SPI convient SDA2 RB5 12
2
plus particulièrement à la connexion de puces connaissant des SCL2 RB7 10
volumes de données élevés tels que les CA/N rapides ou les
puces Flash externes. Tableau 2.
Certains µC prennent même les deux protocoles en charge
MSSP n0 Signal Port Broche n0
simultanément (par ex. MSSP1 comme maître I2C et MSSP2
SDO1 RC7 9
comme maître SPI), d’où une très grande flexibilité.
SDI1 RB4 13
1
Erreur de conception SCK1 RB6 11
Lorsqu’on utilise un µC en mode MSSP maître, certaines bro- SDO2 RA5/RC1 2/15
ches spécifiées assurent la communication. On retrouvera, dans SDI2 RB5 12
2
les tableaux 1 et 2, ces broches dans le cas du PIC16F1829 SCK2 RB7 10
pour les communications I2C et SPI. Avec SPI, la sélection des
broches CS est libre, elles ne sont pas pilotées par le matériel
MSSP, mais par le micrologiciel. Le tableau 2 montre qu’avec dernière cathode).
SPI et MSSP2, la ligne SDO peut être reliée à la broche RA5 • Dans le sous-programme disp_off (désactivation de
ou RC1. toutes les cathodes).
• À ces trois endroits il faudra modifier de la façon
Remarque : vous allez me dire que depuis le premier article de suivante :
cette série, les broches RA5, RC1 et RC7 sont monopolisées par -- bsf PORTA,D’005’ devient : bsf PORTA,D’002’
la commande de l’afficheur. Pas de problème pour I2C vu que ou
seules les broches de port RB4 et RB7 sont requises. Toutefois -- bcf PORTA,D’005’ devient : bcf PORTA,D’002’
pour disposer d’au moins un port SPI à des fins d’expérience,
il faut libérer l’une des trois broches de port RA5, RC1 ou RC7. Communication I2C
Cet accident de parcours permettra de montrer combien une Ayant à peu près vu à quoi peut servir un MSSP, entrons main-
telle réaffectation, y compris la réactualisation du logiciel, est tenant dans les détails de la communication I2C.
relativement simple à réaliser. Si l’on veut utiliser MSSP2 pour
expérimenter, il vaut mieux confier la commande de la cathode PIC16F1829 en maître I2C
de LD3 à RA2 plutôt qu’à RA5. Pour cela, il suffit de cou- Comme nous l’avons dit, un µC utilisé en maître peut comman-
per la connexion d’origine et de relier maintenant la cathode der très simplement nombre de puces intéressantes. Pour utili-
à RA2. Il reste ensuite à effectuer une petite modification du ser les fonctions MSSP, il suffit de savoir utiliser trois registres
micrologiciel : et d’écrire les quelques lignes de code requises.

Dans la routine init_main, on configure maintenant RA2 en Le premier s’appelle SSPxCON1. Un « 1 » ou un « 2 » au lieu
sortie. À cet effet, le bit 2 du registre TRISA est mis à 0 au du « x » indique que cela concerne MSSP1 ou MSSP2. Les gros
lieu de 1. µC disposent des deux registres SSP1CON1 et SSP2CON1,
movlw B’11001100’ les plus petits n’ont qu’un seul MSSP, donc SSP1CON1. Le
movwf TRISA tableau 3 montre l’organisation du registre. Pour l’instant,
devient de ce fait : seuls les quatre bits de poids faible SSPM<3:0> et le bit SSPEN
movlw B’11001000’ présentent un intérêt.
movwf TRISA
SSPM<3:0> permet de configurer le module MSSP. Sans entrer
Là où l’on accédait auparavant à PORTA,D’005’, il doit main- dans le détail, indiquons que la valeur 1000b correspond au
tenant y avoir PORTA,D’002’. Il s’agit des endroits suivants : fonctionnement en maître I2C. Le taux de transmission, dérivé
de l’horloge du système, répond à la formule :
• À la fin de la routine init_main (désactivation de toutes I2C Clock Speed = Fosc / (4 * (SSPxADD+1))
les cathodes). Le bit SSPEN permet d’activer (=1) le MSSP ou de le désac-
• Dans le sous-programme ishow_digit3 (activation de la tiver (=0).

Tableau 3.
Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
R/C/HS R/W R/W R/W R/W R/W R/W R/W
WCOL SSPOV SSPEN CK SSPM<3:0>

www.elektormagazine.fr octobre 2016 11


découvrir créer partager

Listage 1. ; step 2
movlw B'00101000' ; voir fiche de carac. pg 277
;---------------------------------------------------
; bit 3-0 SSPM<3:0> = 1000
; Paramétrer MSSP2 pour la communication par bus I2C
; 1000 = maître I2C,
; (le PIC est le maître)
; horloge = FOSC/(4*(SSPADD+1))
;---------------------------------------------------
movwf SSP2CON1
;
;
; step 1
; step 3, paramétrer vitesse I2C
i2c_init nop
movlw B'00111111'
banksel TRISB
movwf SSP2ADD
bsf TRISB,D'007' ; SCL
clrf SSP2STAT
bsf TRISB,D'005' ; SDA
clrf BSR ; sélection de BANK 0
movlw H'04'
return
movwf BSR ; sélection de BANK 4
;

SSPxADD est le second registre important. Pour le mode maître En fait, il suffit de mettre à 1 le bit SEN du registre SSP2CON2.
I2C, on se contente d’y placer une valeur de division. Soyons Le sous-programme d55, tout simple, produit la pause à la fin
exhaustifs : en mode esclave I2C, on y trouve l’adresse I2C. de l’étape de communication :
Dernier registre, SSPxSTAT. Pour des expériences avec I2C, il
suffit de veiller est à ce que tous les bits soient mis à 1. d55 movlw D’255’
movwf TIMER2
Une routine d’initialisation I2C en assembleur ressemble au d55_loop decfsz TIMER2,F
code du listage 1. Premier pas, on paramètre les deux ports goto d55_loop
d’entrée (step 1) – condition sine qua non de leur utilisation return
potentielle en mode I2C.
On procède ensuite au paramétrage de SSP2CON1 (step 2) : Dans d55, on a 256 fois l’exécution d’une boucle vide. À une
la valeur 1000b règle le mode MSSP en maître. Simultanément, fréquence d’horloge de 16 MHz, cette temporisation est suf-
le MSSP est activé par la mise à 1 du bit 5 (SSPEN). fisante, avec le taux de transmission sélectionné, pour toutes
Pour terminer, on fixe la vitesse de transmission et on initialise les étapes de communication I2C.
le registre d’état (step 3). Dans notre exemple de code, on Chaque communication I2C est clôturée par une Stop Condi-
obtient 62,5 kHz (Fosc = 16 MHz, SSP2ADD = 63). Le µC est tion. Comme dans le cas de la condition de début, son implé-
maintenant prêt à fonctionner en maître I2C. mentation en assembleur est un jeu d’enfant :

Routines de communication I2C i2c_stop bsf BSR,D’002’


La communication via I2C requiert certaines connaissances rudi- bsf SSP2CON2, PEN
mentaires. Nous supposons que vous connaissez au moins les bcf BSR,D’002’
aspects fondamentaux de la communication I2C. Si ce n’était call d55
pas le cas : Google vous proposera instantanément différentes return
descriptions.
La communication prend du temps. Le suivi du registre SSPS- On voit que le vrai travail est l’affaire du matériel MSSP, vu
TAT permet de déterminer l’instant où se termine le processus qu’il suffit de mettre à 1 le bit PEN du registre SSP2CON2.
de communication en cours. Pour les expériences initiales et la Il ne reste plus, pour effectuer un transfert de données concret,
plupart des applications, il suffit, après chaque étape de com- qu’à savoir comment écrire et lire des données. La routine
munication, d’attendre tout simplement un bref instant et de ci-après permet à un maître d’envoyer un octet à l’esclave :
supposer purement et simplement qu’après la pause, tout est
paré. Le micrologiciel devient d’une simplicité déconcertante. ; transfert du contenu (octet) depuis le registre W
Ce processus décrit ci-après convient parfaitement à condition i2c_send bsf BSR,D’002’
que la vitesse de transmission ne soit pas un facteur important. movwf SSP2BUF
Toute transmission I2C commence par ce que l’on appelle une bcf BSR,D’002’
Start Condition, initiée par le maître. Cette condition de début call d55 ;pause
peut très facilement être produite en assembleur en utilisant return
le MSSP :
L’envoi d’un octet est lui aussi très simple. Il suffit d’écrire dans
i2c_start bsf BSR,D’002’ ; sélection de BANK 4 le registre SSP2BUF les données à transmettre. Ensuite, le maté-
bsf SSP2CON2, SEN riel MSSP se recharge du vrai travail et l’octet du registre W
bcf BSR,D’002’ ; sélection de BANK 0 se retrouve, sous forme série, sur le bus I2C.
call d55 La routine de réception, qui lit un octet venant de l’esclave,
return

12 octobre 2016 www.elektormagazine.fr


notions de base cours q&r trucs & astuces logiciel

est un peu plus complexe : i2c_not_ack bsf BSR,D’002’


bsf SSP2CON2, ACKDT ;NACK
; mémorisation octet reçu dans registre W bsf SSP2CON2, ACKEN
; step 1 bcf BSR,D’002’
i2c_receive bsf BSR,D’002’ call d55
bsf SSP2CON2, RCEN return
bcf BSR,D’002’
call d55 Il reste la routine i2c_restart (redémarrage I2C) pour avoir
; step 2 tous les blocs de code. Un redémarrage I2C est nécessaire en cas
bsf BSR,D’002’ de modification du sens de la communication avec un esclave.
movf SSP2BUF,0 Le sous-programme i2c_restart pourra ressembler à ceci :
bcf BSR,D’002’
return i2c_restart bsf BSR,D’002’
bsf SSP2CON2, RSEN
Tout d’abord, le bit RCEN du registre SSP2CON2 est mis à 1 bcf BSR,D’002’
(step 1). Le matériel MSSP sait ainsi qu’il s’agit de recevoir call d55
un octet. On a ensuite une pause brève, ensuite l’octet reçu return
doit se trouver dans le registre SSP2BUF. Cet octet est lu et Comme vous l’avez sans doute déjà pressenti, il suffit de mettre
transféré dans le registre W (step 2). à 1 un seul bit (RSEN) du registre SSP2CON2.
Encore une remarque : tous les sous-programmes imposent
Les trois blocs de code qui suivent ne sont pas nécessaires dans qu’avant leur appel, le registre BSR pointe vers BANK 0 (BSR =
les exemples cités, mais comme il s’agit d’éléments importants 00h). Si cela ne devait pas être le cas, il faudra, avant chaque
de la communication I2C, prenons le temps d’en parler. instruction bsf BSR,D’002’, insérer un clrf BSR.
Après que le maître a reçu un octet venant d’un esclave, il
enverra généralement un ACK (ACKnowledge) ou un NACK Extension de port par PCF8574N
(Not ACKnowledge) à l’esclave, pour l’informer de la réussite Après avoir décrit les blocs de code pour la communication
(on non) du transfert. Un sous-programme ACK peut ressem- I2C, nous pouvons maintenant passer à la pratique. Pour les
bler à ce qui suit : expériences initiales, le plus utile serait une puce où l’on voit
immédiatement ce qui se passe grâce à une simple commande
i2c_ack bsf BSR,D’002’ de LED. Le PCF8574N de Texas Instruments (ou de NXP) est
bcf SSP2CON2, ACKDT ;ACK exactement ce dont nous avons besoin. Il s’agit d’un expan-
bsf SSP2CON2, ACKEN seur de port d’E/S pour 8 bits avec interface I2C, disponible
bcf BSR,D’002’ aussi en boîtier DIP-16.
call d55 Ses huit broches d’E/S sont commutables en entrées ou en
return sorties. Si les charges à connecter sont considérables, il faudra
les relier entre VDD et les sorties, sans oublier de tenir compte
Si le bit ACKEN est mis à 1, le matériel MSSP lance une séquence du courant maximal par sortie (25 mA) et de la puissance
ACK (accusé de réception) : le bit ACKDT est mis sur le bus. totale maximale de la puce (100 mA).
Si ce bit est à 0, on a envoi d’un ACK.
Un 1 signifie NACK. Par conséquent, le sous-programme NOT_ On commence par attaquer les huit LED avant de lire ensuite
ACK est presque identique, puisque seul le bit ACKDT du registre le niveau d’entrée sur les huit broches. La figure 1 montre
SSP2CON2 est mis à 1 : le schéma pour nos premières expériences avec I2C. Sur la

Publicité

www.elektormagazine.fr octobre 2016 13


découvrir créer partager

figure 2, on voit à quoi ressemble l’afficheur du premier article l’afficheur à LED, mais sont aussi visibles sous forme binaire
de ce cours doté cette fois de ports I2C et SPI après son mon- via le PCF8574N et ses huit LED. À cause de leur mode de
tage sur un morceau de platine à trous. On trouve en bas à connexion, les huit LED s’allument avec un « zéro » et sont
droite de la figure 1, l’extension de port avec huit LED autour éteintes avec un « un ». Il est facile, si on le souhaite, d’in-
d’IC2. Si on la réalise sur un morceau de platine à trous distinct verser cela dans le code.
pour en faire un module autonome, on devrait avoir quelque
chose ressemblant à la figure 3. La seule modification dans la boucle principale de l’application de
démo est l’appel du sous-programme additionnel PCF8574_send,
Les étages de sortie du PCF8574N sont connectés dans une avant l’envoi des données vers l’afficheur à LED. Comme son
configuration à drain ouvert. Cela permet, « sans risque de nom le laisse supposer, il envoie un octet via I2C au PCF8574N :
destruction », de connecter aux sorties, en plus des LED, des
boutons vers la masse. En cas d’action sur un bouton, la LED ;step 1
correspondante s’allume indépendamment de l’état du CI. Pour PCF8574_send call i2c_start
nous simplifier la vie, nous avons, dans la figure 3, remplacé movlw B‘01000000‘
les boutons par un octuple interrupteur DIP. call i2c_send
Le schéma de la figure 1 s’est vu en outre doté des deux résis- ;step 2
tances de polarisation haute, R9 et R10, sachant qu’un bus movf v_value,0
I2C est un système à collecteur ouvert ou à drain ouvert sans call i2c_send
sorties push-pull – et par conséquent une communication sans ;step 3
résistances de polarisation haute est impossible. call i2c_stop
return
Expérience 1 : écriture I2C
La première expérience consiste à envoyer des données à Le sous-programme est presque trivial grâce aux blocs de code
l’extension de port par PCF8574N. À cette fin, seule la der- I2C déjà décrits. On commence par produire la condition de
nière application de démonstration du second article a été début (step 1) pour ensuite adresser l’esclave (PCF8574N).
légèrement étoffée. Cette fois, les données lues à partir de la Dans l’exemple, l’adresse I2C de la puce est 0100000b. En
mémoire flash s’affichent non seulement en hexadécimal sur fait, l’adresse n’a que 7 bits – le dernier « zéro » indique une

1
VDD 16 R1 A
RC0 270R
19 15 R2 B
RA0 RC1 270R
18 IC1 14 R3 C
S1 RA1 RC2 270R
17 7 R4 D
RA2 RC3 270R
4 6 R5 E
RA3/MCLR RC4 270R LD1 SC08-11 LD2 SC08-11 LD3 SC08-11 LD4 SC08-11
3 5 R6 F
RA4 RC5 270R A 1 A 1 A 1 A 1
2 8 R7 G A A A A
RA5 RC6 270R B 14 B 14 B 14 B 14
9 R8 DP B B B B
RC7 270R C 12 C 12 C 12 C 12
C C C C
PIC16F1829 D 10 D 10 D 10 D 10
13 D D D D S2
RB4/SDA1 E 4 E 4 E 4 E 4
12 E E E E
BT1 RB5/SDA2 F 2 F 2 F 2 F 2
11 F F F F R11 LED1
RB6/SCL1 G 13 G 13 G 13 G 13
10 G G G G 270R
RB7/SCL2 DP 9 DP 9 DP 9 DP 9
VSS DP DP DP DP S3
20 CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC
3 5 11 16 3 5 11 16 3 5 11 16 3 5 11 16 R12 LED2
270R

S4

R13 LED3
16 270R
VDD S5
14 4
SCL P0
J1 J3 15 5 R14 LED4
5 5 SDA P1
VCC 13 IC2 6 270R
4 4 INT P2
R9 GND 7 S6
3 3 P3
4k7 SCL 9
2 2 P4
R10 N/C 1 10 R15 LED5
1 1 A0 PCF8574P P5
4k7 SDA 2 11 270R
A1 P6
3 12 S7
I2C I2C-Bus A2 P7

VSS R16 LED6


8 270R

S8

I2C Address: 0100 000


R17 LED7
270R

S9

R18 LED8
270R

R19 LED9
270R

160037 - 11

Figure 1. L‘afficheur à LED doté d‘un expanseur de port avec huit LED.

14 octobre 2016 www.elektormagazine.fr


notions de base cours q&r trucs & astuces logiciel

Publicité
Plus de
Figure 2. Si l‘on dote l‘afficheur à LED d‘une interface I2C ou SPI, le schéma
nouveaux produits
en stock que
qui résulte pourrait ressembler à ceci.

n'importe quel
autre distributeur.
C

CM

MY

CY

CMY

Figure 3. Prototype de l‘expanseur de port avec huit LED en tant que


module distinct sur un morceau de platine à trous.

écriture. Ensuite, l’octet à envoyer est transmis au PCF8574N


(step 2). Immédiatement après sa réception, les LED devraient
s’allumer en fonction de son contenu. Finalement, on a clos la
communication avec la condition d’arrêt (step 3).

Expérience 2 : lecture I2C


Cet exemple montre comment demander des données à un
esclave (PCF8574N) et les recevoir. Pour cela, la boucle prin-
cipale est modifiée de façon à ce que ce ne soient pas les don-
nées en provenance de la mémoire flash qui s’affichent sur
l’afficheur, mais l’octet venant du PCF8574N :
;step 1
PCF8574_read call i2c_start
Commandez dès maintenant sur
movlw B‘01000001‘
call i2c_send
mouser.fr

www.elektormagazine.fr octobre 2016 15


découvrir créer partager

;step 2 Communication SPI


call i2c_receive En principe, la communication via SPI est beaucoup plus simple
movwf v_value que par I2C. La configuration du PIC en tant que maître SPI
;step 3 est, cependant, très similaire à ce que connaît I2C. Comme
call i2c_not_ack le montre le listage 2, on utilise les mêmes registres MSSP.
call i2c_stop Avec deux lignes de données plus l’horloge, plus au moins une
return ligne de sélection de puce, il faut en SPI bien plus de lignes
qu’en I2C. De ce fait, il est normal que l’initialisation (step 1)
Au début de la routine, on envoie à nouveau la condition de soit un peu plus complexe. Comme RB5 doit ici être utilisée
début (step 1) avant d’adresser immédiatement le PCF8574N en SDI (Serial Data Input), cette broche doit donc être défi-
– mais en mode de lecture cette fois. D’où le « un » du dernier nie comme entrée. Les lignes restantes (SDO, CLK et CS) sont
bit de l’adresse. L’esclave sait maintenant qu’il doit envoyer toutes des sorties.
un octet, le CI esclave place le contenu du port sur le bus I2C. On en arrive maintenant aux réglages nécessaires du registre
Ensuite, on a appel du sous-programme i2c_receive (step 2) SSP2CON1 (step 2). Les bits 0 à 3 servent à configurer MSSP2
pour la lecture de cet octet et son transfert dans le registre W. en maître SPI. Comme SDO de MSSP2 peut être sur la bro-
L’octet reçu est en outre stocké dans la variable v_value pour che RA5 ou RC1, il faut commencer par la définir. Comme
une utilisation ultérieure. cela devrait être RA5, le bit SDO2SEL du registre APFCON1
Il reste à clôturer la communication (step 3). Il y a d’abord est mis à 1.
envoi d’un NACK vers l’esclave qui signale la fin de la lecture. En outre, il faut configurer le mode dit SPI de telle sorte que
Pour finir, il reste la condition d’arrêt. l’esclave connecté puisse s’y retrouver. Les différents modes

Listage 2. sur RC1)


banksel SSP2CON1
;---------------------------------------------------
movlw B'00000010' ; voir fiche de carac. pg 260
; Paramétrer MSSP2 pour communication par bus SPI
; bit 7 = 0 -> N/A
; (le PIC est le maître)
; bit 6 = 0 -> N/A
;---------------------------------------------------
; bit 5 = 0 -> désactiver MSSP2
; bit 4 = 0 -> état idle pour l'horloge =
; initialisation SPI du MSSP2
niveau bas
; RB7 = SCK2
; bit 3-0 = 0010 -> mode maître SPI, horloge =
; RB5 = SDI2
FOSC/64
; RA5 = SDO2
movwf SSP2CON1
;
clrf SSP2STAT
; step 1
;
spi_init nop
; step 3
banksel TRISB
; bit 7 = 0 -> données d'entrée échantillonnées
bsf TRISB,D'005' ; SDI2 (RB5 -- entrée)
; au centre de la fenêtre de sortie de données
bcf TRISA,D'005' ; SDO2 (RA5 -- sortie)
; bit 6 = 0 -> transmettre à la transition de idle
bcf TRISB,D'007' ; SCK2 (RB7 -- sortie)
; -> état actif de l'horloge
bcf TRISB,D'006' ; CS (RB6 -- sortie)
bsf SSP2CON1,D'005' ; activer SPI sur MSSP2
;
clrf BSR
; step 2
bcf PORTB,D'006' ; CS = 0 --> inactif
banksel APFCON1
return
bsf APFCON1,SDO2SEL ; SDO2 est sur RA5 (pas

Listage 3. ; step 2
movwf SSP2BUF
;-------------------------
spil2 btfss SSP2STAT,BF
; émission et réception de données SPI
goto spil2
;-------------------------
;
;
; step 3
; step 1
movf SSP2BUF,0
spi_send nop
clrf BSR
banksel SSP2CON1
movwf v_spi_buffi
bcf SSP2CON1,SSPOV ; pour la sécurité...
return
bcf SSP2STAT,BF ; pour la sécurité...
;

16 octobre 2016 www.elektormagazine.fr


notions de base cours q&r trucs & astuces logiciel

SPI se différencient par deux caractéristiques combinables à les deux sens. Mais cela n’est utilisé que rarement. Si le maître
volonté : veut uniquement recevoir, il envoie quand même un « octet
factice » à l’esclave, de sorte que la ligne d’horloge cadence.
• Idle Clock level : le bit 4 du registre SSP2CON1 détermine Le sous-programme spi_send s’attend à retrouver l’octet à
quel niveau sur la ligne SCK doit être considéré comme envoyer dans le registre W. Au début (step 1), on a remis
inactif (« zéro » ou « un »). à 0 des bits de dépassement, ceci pour la sécurité, au cas où
• SPI Clock Edge Select : le bit 6 du registre SSPSTAT définit il y aurait eu maldonne lors du dernier transfert de données.
à quel moment (par rapport à SCK) se fait l’échange de Ensuite (step 2) on a écriture de l’octet à transmettre dans le
données sur la ligne SDO. registre SSP2BUF, ce qui a pour effet de démarrer le matériel
MSSP et de pousser le contenu de SSP2BUF sur le bus via la
En règle générale, le niveau inactif du signal CS est un « un » ligne SDO. Le micrologiciel attend dans la boucle jusqu’à la fin
et, avec un « zéro », CS est activé – dans le cas de l’horloge en de la transmission. Il la détecte par le bit BF du registre SSPS-
temps réel (Real Time Clock) DS1306 utilisée ici, c’est l’inverse. TAT qui est mis à 1 à la fin de la communication.
Ici, le mode SPI est configuré pour que SCK à 0 soit inactif, et En raison de la bidirectionnalité, on a simultanément interro-
que l’échange de données se fasse au front montant de l’hor- gation de la ligne SDI et écriture dans le registre SSP2BUF de
loge (passage de « zéro » à « un »). Avec d’autres puces SPI l’information reçue à la fin du transfert.
esclaves, il faudra jeter un œil à la fiche de caractéristiques. Pour finir (step 3), on a lecture du registre SSP2BUF, son
À la fin de l’initialisation (step 3), on a activation de MSSP2 contenu est stocké à l’emplacement de mémoire v_spi_buffi
et mise du signal CS à 0 de sorte que la communication soit pour une utilisation ultérieure.
inactive au départ.
Connexion de l’horloge en temps réel DS1306
Pour la communication via le bus SPI, il suffit d’un seul module La connexion de l’horloge en temps réel (RTC) DS1306 via
de code. On en retrouve le code dans le listage 3 ; il est éga- SPI n’a rien de bien compliqué. On retrouve en figure 4 notre
lement utilisé pour la réception de données. Avec SPI il est en schéma SPI. Si l’on monte la RTC (en bas à droite) sur un
effet possible de transférer des données simultanément dans morceau de platine à trous pour obtenir un module distinct,

1
VDD 16 R1 A
RC0 270R
19 15 R2 B
RA0 RC1 270R
18 IC1 14 R3 C
S1 RA1 RC2 270R
17 7 R4 D
RA2 RC3 270R
4 6 R5 E
RA3/MCLR RC4 270R LD1 SC08-11 LD2 SC08-11 LD3 SC08-11 LD4 SC08-11
3 5 R6 F
RA4 RC5 270R A 1 A 1 A 1 A 1
2 8 R7 G A A A A
RA5 RC6 270R B 14 B 14 B 14 B 14
9 R8 DP B B B B
RC7 270R C 12 C 12 C 12 C 12
C C C C
PIC16F1829 D 10 D 10 D 10 D 10
13 D D D D
RB4/SDA1 E 4 E 4 E 4 E 4
12 E E E E
BT1 RB5/SDA2 F 2 F 2 F 2 F 2
11 F F F F
RB6/SCL1 G 13 G 13 G 13 G 13
10 G G G G
RB7/SCL2 DP 9 DP 9 DP 9 DP 9
VSS DP DP DP DP
20 CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC
3 5 11 16 3 5 11 16 3 5 11 16 3 5 11 16

16
VCC1
14 9
VCCIF SERMODE
2 10
J5 J1 VBAT CE
SCK 7 8 VCC SCK 7 8 VCC 13
IC2 SDO
SDI 5 6 GND SDI 5 6 GND 3 12
X1 SDI
SDO 3 4 SDO 3 4 X1 11
SCK
CS0 1 2 CS0 1 2 5 R9
INT0
BT2 4 DS1306DIP 6
SPI SPI X2 INT1
10k

32.768kHz 15
6p 32KHZ
1 7
VCC2 1HZ
SDI = input for PIC / output Device
GND
SDO = output for PIC / input Device CR2032H
8
160037 - 12

Figure 4. Le circuit de l‘afficheur à LED avec une horloge en temps réel connectée via SPI.

www.elektormagazine.fr octobre 2016 17


découvrir créer partager

on envoie maintenant comme adresse non pas 01h mais


81h, le DS1306 attend une valeur à écrire à l’« adresse
des minutes ».
Le listage 4 donne une routine de lecture, qui lit les heures,
les minutes et les secondes du DS1306. On commence par
activer le signal CS (step 1), par sa mise à 1. L’esclave est
alors à l’écoute du bus. Immédiatement après la RTC attend
l’adresse du registre à lire. Ainsi, on met, par le biais du
sous-programme spi_send la valeur 00h sur le bus (step 2).
Le DS1306 sait maintenant que l’on attend le contenu du
registre des secondes.
Pour récupérer la valeur des secondes, on fait à nouveau
appel à la routine spi_send (step 3), sans spécifier expli-
citement un octet à envoyer sachant que, pour la lecture,
son contenu est sans importance. L’esclave ne traite pas
même cet octet, mais envoie sur l’autre ligne de données
Figure 5. Prototype de l’horloge en temps réel en tant que module distinct la valeur de l’adresse 00h. On retrouve alors la valeur des
sur un morceau de platine à trous. secondes dans le registre W. Celle-ci est stockée à l’empla-
cement de mémoire v_sec. On a ensuite, un nouvel appel
à la routine spi_send. Grâce à la fonction d’auto-incrémen-
tation du DS1306, on obtient maintenant le contenu du
le résultat devrait ressembler à ce que montre la figure 5. registre des minutes. Avec le dernier appel, on obtient la
Attention ! Pour que le module RTC connecté à l’interface SPI valeur de l’heure.
de la carte de base (celle avec l’afficheur) fonctionne correc- Pour cette expérience, les autres registres du DS1306 sont
tement, il faut que les lignes SDI et SDO soient croisées, car sans intérêt. La communication est donc clôturée par la
ce qui est la sortie pour le maître est l’entrée pour l’esclave désactivation du signal CS (step 4).
et vice versa. SDI et SDO se référèrent donc toujours au cir- Nous disposons maintenant de l’heure actuelle dans les
cuit intégré concerné. La ligne RB6 fait office de CS. Une RTC variables v_hrs, v_min et v_sec pour une utilisation ulté-
requiert un quartz horloger, bien souvent de 32,768 kHz. Pour rieure. L’affichage de l’heure fournie par le DS1306 n’a
le circuit intégré sélectionné, il faudra utiliser un quartz conçu requis qu’un quadruple appel de la routine spi_send, avec
pour une capacité de charge de 6 pF. la transmission d’un octet à l’esclave et une triple lecture
d’octets en provenance de l’esclave. Il ne reste plus qu’à
Expérience 3 : horloge avec afficheur à LED afficher ces données sous forme d’heure.
Pour transformer l’afficheur à LED en horloge, il faut encore
un zeste de code approprié, plus simple qu’on ne pourrait Ce n’est pas très difficile, sachant que l’on dispose des valeurs
le penser. Ce dont on a besoin est, principalement, un au format BCD et qu’il existe déjà une routine pour l’affi-
sous-programme qui puisse extraire les informations de chage de données HEX. Le listage 5 est le code de l’applica-
temps du DS1306. Il faut donc connaître les spécificités tion principale. La routine Main_Appl affiche un court instant
du DS1306. « --.-- » (step 1), avant d’appeler l’initialisation SPI (step 2).

Le circuit de la RTC possède 128 emplacements de mémoire


adressables. Les sept premiers sont réservés à l’horloge La boucle principale clock_loop (step 3) attend brièvement
proprement dite ; on trouve à l’adresse 00h les secondes, et, par le biais du sous-programme spi_read_time, extrait
à 01h les minutes et à 02h les heures. Pas besoin de plus l’information de temps du DS1306. Ensuite, comme décrit
pour une horloge. Les valeurs individuelles sont stockées dans l’article précédent, les données BCD sont subdivisées
au format BCD. Pour 14:32:56, on lirait donc les valeurs en deux quartets et le résultat est transmis aux « variables
suivantes : de la mémoire vidéo » v_pos0 à v_pos3 (step 4). Et voilà,
fin du travail.
• Adresse 00h (secondes) = 56h Les secondes ne sont pas utilisées puisque l’afficheur ne
• Adresse 01h (minutes) = 32h comporte que quatre chiffres. Si on le voulait, on pourrait
• Adresse 02h (heures) = 14h utiliser dans step 4a la variable v_min et dans step 4b la
variable v_sec pour afficher les minutes et les secondes.
À chaque communication, un DS1306 s’attend d’abord à Il y a une petite extension de la routine d’affichage, qui sert
recevoir une adresse, il met ensuite à disposition les don- uniquement à faire clignoter le point au milieu. Pour des
nées demandées. Si le signal CS n’est pas désactivé, on raisons de place, nous en avons omis la description, mais
a incrémentation du compteur d’adresses après chaque elle n’a rien de sorcier et est facilement compréhensible
accès en lecture. Il est donc très facile de lire plusieurs dans le code source téléchargeable en [1].
octets successifs.
Dans le cas d’une adresse modulo 80h, le module d’horloge Absent également, le code qui permettrait de régler l’horloge
suppose qu’il ne s’agit pas de lire, mais d’écrire. Si donc sur une certaine heure. Avec tout ce que vous avez appris

18 octobre 2016 www.elektormagazine.fr


notions de base cours q&r trucs & astuces logiciel

tout au long de ce cours, cela ne devrait pas poser de gros Perspectives


problèmes. Nous avons vu plus haut comment écrire de nou- Nous en sommes arrivés la fin de ce deuxième cours intensif
velles données dans le DS1306. Mais même sans ce code, il d’assembleur. Nous espérons que vous l’aurez apprécié et que
est possible d’avoir l’heure exacte. Il suffit de rester debout vous y aurez découvert d’intéressantes suggestions.
un peu plus longtemps et d’appliquer la tension d’alimentation
lorsqu’il sera exactement 00:00. Il n’y a pas besoin d’autres Je me ferai un plaisir de répondre par courriel
configurations. En standard, l’horloge travaille au format 24h. (miroslav.cina@t-online.de) à vos questions sur ce sujet.

Autres expériences (160037 – version française : Guy Raedersdorf)


Comme nous le disions, il est possible, grâce aux interfaces I2C
ou SPI, de connecter de façon simple nombre de puces d’in-
terface. Googlisez « I2C IC » ou « SPI IC » et vous tomberez Lien
des nues : il n’y a presque rien qui ne soit pas là.
[1] Page de l’article : www.elektormagazine.fr/160037
On pourrait, par ex., grâce au circuit intégré INA219, faire de
l’afficheur à LED un multimètre (V/A). Outre ladite puce, il ne
nous faut qu’un rien de code et, dans le cas d’une mesure de
courant, un shunt bien sûr. Le µC peut aisément commander
le CI de mesure INA219, basculer d’un mode à l’autre, enre-
gistrer et afficher les valeurs mesurées.
Il est tout aussi facile d’utiliser l’afficheur à LED en tant que
thermomètre. On pourra fort bien utiliser alors, par ex., les
capteurs de température intégrés TCN75 de Microchip, TMP100
de TI ou ADP7410 d’Analog Devices. Ces thermomètres numé-
riques sont faciles à utiliser, car ils ne requièrent pratiquement
pas de composant externe. Les puces fournissent, à peu de frais
et facilement via l’interface I2C, la température du moment.

Listage 4. movf v_spi_buffi,0


movwf v_sec
;-----------------------------
call spi_send ; lecture des minutes
; lecture de l'heure du DS1306 via SPI
movf v_spi_buffi,0
;-----------------------------
movwf v_min
;
call spi_send ; lecture des heures
; step 1
movf v_spi_buffi,0
spi_read_time bsf PORTB,D'006' ; activer CS
movwf v_hrs
;
;
; step 2
; step 4
movlw H'00'
bcf PORTB,D'006' ; désactiver CS
call spi_send ; envoi de l'adresse
return
;
; step 3
call spi_send ; lecture des secondes

Listage 5. ; movwf v_pos0


; step 2 movf v_lsb,0
;-------------------------------
call spi_init movwf v_pos1
; application principale -
; ;
; horloge DS1306
; step 3 ; step 4b
;-------------------------------
clock_loop call dr2 movf v_min,0
;
call spi_read_time movwf v_value
; step 1
; call calc_hex_disp
Main_Appl movlw H'10'
; step 4a movf v_msb,0
movwf v_pos0
movf v_hrs,0 movwf v_pos2
movwf v_pos1
movwf v_value movf v_lsb,0
movwf v_pos2
call calc_hex_disp movwf v_pos3
movwf v_pos3
movf v_msb,0 goto clock_loop

www.elektormagazine.fr octobre 2016 19