samedi 31 mars 2012

outil de dévellopement

afficheur binaire

Dans la chronique précédente j'ai fait mention de l'afficheur binaire d'un octet que je me suis fabriqué comme outil de dévellopement. Il s'agit en fait du circuit très simple qui utilise un registre à décalage de 8bits SN74HC164 avec 8 DEL de 3mm branchées sur les sorties Qx. en série avec chaque DEL il y a une résistance de 1Kohm. Les spécifications d'alimentation du SN74HC164 sont de 2 à 6Volt et il peut fournir un courant de 4ma sur chaque sortie Qx.

Une routine très simple (11 instructions) permet d'y envoyer l'octet à afficher.

#define DISP_CLK EQU GPIO, GP0 ; à redéfinir en fonction de l'usage
#define DISP_DAT EQU GPIO, GP1

;;;;; display ;;;;;;;;;;;;;;
;;; affiche une valeur en binaire sur le dbg_display
;;; entrée: display_val contient la valeur à afficher
display
movlw 8
movwf bit_cntr ; compteur de boucle
display01
bcf DISP_CLK
bcf DISP_DAT
rlf display_val,F
skpnc
bsf DISP_DAT
bsf DISP_CLK
decfsz bit_cntr
goto display01
return


lecture d'un clavier sur entrée en logique TTL

Suite au résultat positif de lecture de plusieurs boutons sur une 1 entrée en logique TTL, (voir projet PocketSimon), J'ai décidé de vérifier s'il était possible de lire un keypad de 16 touches avec cette méthode. J'ai donc fait le montage suivant

Ce qu'on aperçoit à gauche du montage est un affichage binaire de 1 octet que je me suis fait. C'est un petit outil de dévellopement utile qui n'utilise que 2 sortie TTL du MCU, 1 DATA et 1 CLOCK et une très courte routine d'affichage. Dans ce cas ci je m'en suis servis pour afficher la valeur du compte de délais de charge du condensateur pour chaque touches du clavier.
Ce projet n'est alimenté que par le 5Volt fournis par le PICKIT 2.

résultat des tests

Voici le schémas du circuit et le code utilisé.

; test le principe de lecture de plusieurs boutons par la mesure
; du temps de charge d'un condensateur.
#include <P10F202.INC>
__CONFIG _WDTE_OFF & _CP_OFF & _MCLRE_OFF

#define DISP_CLK GPIO, GP1
#define DISP_DAT GPIO, GP0
#define BTN_INP GPIO, GP2

;;;;;;;;;;; constantes ;;;;;;;;;;;

OPTION_CFG EQU B'01000001'
TMR0_CNT EQU ~.250

;;;;;;;;;;;;;;;; macros ;;;;;;;;;;;;;;;;;

clamp_on macro ;; court-circuite le condensateur sur GP1
movlw B'1000'
TRIS GPIO
bcf BTN_INP
endm

clamp_off macro ;; enlève le court-circuit et met GP1 en mot input
movlw B'1100'
TRIS GPIO
endm

cpr macro r1, r2 ; copie le registre r1 dans r2
movfw r1
movwf r2
endm

ldr macro reg, const ; initialise le registre avec une constante
if const==0
clrf reg
else
movlw const
movwf reg
endif
endm

init_delay_cntr macro msec
ldr delay_cntr, low (~msec)
ldr delay_cntr+1, high (~msec)
endm


;;;;;;;;;;;; variables ;;;;;;;;;;;;;;;
cblock 8
charge_delay : 1 ; compteur du délais de charge du condensateur
delay_cntr : 2 ; compteur pour la routine delay_ms
display_val : 1 ; valeur à afficher
bit_cntr : 1 ; compteur de bit pour display
endc

;;; début du code ;;;;;;;;;
org 0
movlw OSCCAL
goto initialization

;;;; delay_ms ;;;;;;;;;
;; delais en milisecondes
;; entrée: delay_cntr = nombre de millisecondes
delay_ms
ldr TMR0, TMR0_CNT
movlw OPTION_CFG
option
movfw TMR0
skpz
goto $-2
incfsz delay_cntr
goto delay_ms
incfsz delay_cntr+1
goto delay_ms
return

;;;;; display ;;;;;;;;;;;;;;
;;; affiche une valeur en binaire sur le dbg_display
;;; entrée: display_val contient la valeur à afficher
display
ldr bit_cntr, 8
display01
bcf DISP_CLK
bcf DISP_DAT
rlf display_val,F
skpnc
bsf DISP_DAT
bsf DISP_CLK
decfsz bit_cntr
goto display01
return

;;;;;;;;;;;; read_buttons ;;;;;;;;
;;; lecture des boutons
;;; sortie: charge_delay contient le compte
read_buttons
clrf charge_delay
clamp_off
btfsc BTN_INP
goto sortie
incfsz charge_delay
goto $-3
sortie
clamp_on
return


initialization
movlw OPTION_CFG
bcf OSCCAL, 0
option
clamp_off

main
init_delay_cntr .500
call delay_ms ; attend 20 milliseconde entre chaque lecture
call read_buttons ; lecture des boutons
cpr charge_delay, display_val ; copie la valeur pour affichage
call display ; affiche la value
goto main
end


résultats
boutonlecture
14
28
312
A16
417
521
625
B28
730
834
938
C41
*43
047
#50
D54
Il n'y a qu'un digit de différence entre la lecture de A et de 4. Pour que cette méthode soit fiable il faut une alimentation régulé et stable et il serait préférable que les résistances R5 à R7 soit de 12Kohm plutôt que 10Kohm pour augmenter l'écart entre les boutons A et4.

jeudi 29 mars 2012

délais

implémentations des délais en assembleur
Dans presque tous les projets on a besoin de créer un délais entre 2 opérations. Par exemple dans hello DEL il fallait attendre 0,5 seconde entre chaque changement d'état du DEL. Dépendant de la tâche à accomplir le délais peut-être aussi bref qu'un Tcy ou encore duré plusieurs secondes ou même minutes.

Ajourd'hui je vais exposer une méthode pour implémenter un délais en assembleur sur PIC.

délais courts
Pour attendre un seul Tcy l'instruction NOP est idéale. Pour 2 Tcy il y a mieux que 2 NOP consécutifs, GOTO $+1 va s'exécuter en 2 Tcy en utilisant qu'une seule instruction. En utilisant une macro on peut grandement facilité la tâche de la façon suivante


delais_us macro usec ; délais en micro-secondes 0<=usec<=3*255+4
local q,r
q=(usec-4) / 3
if q==0
r=usec
else
r=(usec-4) % 3
endif
if q>0
movlw ~q
movwf delay_cntr
incfsz delay_cntr
goto $-1
endif
while r>1
goto $+1
r -= 2
endw
if r==1
nop
endif
endm


Ici on utilise la directive d'assemblage conditionnelle if pour générer du code assembleur qui sera différent dépendant de la constante qu'on passe en argument. Si usec=0 aucun code n'est généré, si 1<usec<7 seule la boucle while et le if qui suit génèreront du code. Ce code varira d'un simple NOP lorsque r=1 à 3 GOTO $+1 lorsque r=6. Si usec est plus grand que 6 la variable delay_cntr sera utilisée et le code pour une boucle incrémentielle sera généré.
cette macro peut générer un délais entre 0 et 769*Tcy soit dans le cas d'un PIC10F2xx 769usec.

délais plus long
pour des délais plus long 2 techniques ont été données en exemple dans la chronique retour sur hello DEL

dimanche 25 mars 2012

Pocket Simon avec PIC10F202

Depuis un certain temps je m'amuse à explorer les possibilités du plus simple des microcontrolleurs vendu par Microochip soit le PIC10F202. La seule différence avec le PIC10F200 est la quantité de mémoire programme et le nombre de registres pour les variables. le 200 a 256 mots programme et 16 registres pour les variables. Le 202 a 512 mots programme et 24 registres de variables. Ce processeur n'a que 33 instructions assembleur. Son faible coût, 54cent/10 chez digikey.ca la simplicité de ses périphériques et de son jeux d'instructions en font un MCU idéal pour quelqu'un qui veut s'initier à la programmation des microcontrolleurs en assembleur.

caractéristiques principales du PIC10F202

  • 512 mots programmes
  • 24 registes de variables
  • 1 seul timer 8 bits
  • 3 E/S binaire programmable en entré ou sortie GP0,GP1,GP2
  • 1 entrée binaire GP3 qui peut-être programmé comme MCLR

On pourrait difficilement faire plus simple au point ou certains questionnent l'utilité d'un MCU si limité. Mon objectif est justement d'explorer les possibilités de ce MCU. Le jeux pocket Simon utilise 5 sorties: 4 DEL et 1 haut-parleur ainsi que 4 entrées boutons. Comment peut-on contrôler tout ça avec un MCU qui ne possède que 3-1/2 E/S?

Le jeux simon

Simon est un jeux qui a été mis en marché en 1978 par Milton Bradley. Ce jeux a 3 modes mais ma version pocket Simon ne reproduit que le premier mode. Une séquence aléatoire de notes est entendue et le joueur doit répéter la séquence. la séquence rallonge d'une note à chaque succès. Il y a 4 notes associée chacune à une couleur DEL et au bouton correspondant pour rejouer la séquence. Après un succès de 6 notes une petite mélodie se fait entendre à titre de félicitation. A 12 notes la mélodie se répète mais plus longue ainsi de suite. Le nombre maximum de notes est de 32 et la mélodie au complet est jouée si le joueur se rends jusque là.

J'ai ajouté une petite touche personnelle au jeux. Puisque dans le montage que j'ai fait les DELs sont alignées plutôt qu'en cercle, j'ai décidé de les utiliser comme un affichage binaire à 4 bits. Donc avant de jouer une séquence le programme affiche en binaire le nombre de notes qui sera jouées. si le nombre de notes dépasse 15 l'affichage se fait en 2 passes, la partie haute de l'octet ensuite la partie basse (high nibble, low nibble).

A la mise sous tension une routine POST Power On Self Test est exécutée. Cette routine consiste à faire entendre les 4 notes en allumant la DEL correspondante. Après le POST les DELs sont allumées séquentiellement l'une après l'autre en boucle jusqu'à ce que le joueur enfonce un bouton pour débuter la partie.

Le schéma du circuit

Examinons le schéma du circuit.
Notons d'abord que le circuit est conçu pour une alimentation 3.3volt contrôlé par le régulateur de tension U2. Il y a 2 raisons pour utiliser ce régulateur de tension, la première est que si on alimente le circuit avec une tension de plus 3.3volt les DELs seront allumées en permanances car elles sont branchées en série par 2 entre les rails de l'alimentation. D1 en série avec D2 et D3 en série avec D4. Ce montage permet de contrôler 2 DELs avec une seule sortie du MCU. GP0 contrôle la jaune et la bleu et GP1 contrôle la verte et la rouge. Si on place une sortie à 0 le DEL dont l'anode est branchée sur Vdd allume mais si on met la sortie à 1 c'est celle avec la cathode est à Vss qui s'allume. pour éteindre les 2 DEL on place la broche E/S en mode entrée haute impédance. De cette façon le seul chemin de parcour du courant est entre Vdd et Vss via les 2 DEL en série. Mais comme le voltage est inférieure à la tension de seuil des 2 jonctions en séries le courant qui circule est trop faible pour faire briller les DEL.

J'ai monté ce projet pour vérifier une idée, c'est à dire comment lire plusieurs boutons avec une seule entrée numérique lorsqu'il n'y a pas de convertisseur analogue/numérique? La réponse à cette question est de mesurer le temps de charge d'un condensateur. Le transistor Q1 maintient le condensateur C3 en court-circuit la majorité du temps. Lorsqu'on veut faire une lecture des boutons en enlève le court-circuit. Si un bouton est enfoncé le condensateur va se chargé à travers les résistances R4 à R7. Le nombre de résistances en série détermine le temps de charge. Le principe est simple, on libère le court-circuit et on commence à compter le temps que ça prends pour que l'entrée GP3 passe au niveau 1. Le temps le plus court est obtenu lorsque SW4 est enfoncé et le plus long lorsque SW1 est enfoncé. la sortie GP2 controle le transistor Q1 mais aussi le Q2 qui est la sortie audio. Ce partage a été nécessaire du au nombre limité de sorties. Il en résulte un petit inconvénient. Lorsque la routine de lecture des boutons est appellée en boucle on entend un son basse-fréquence dans le haut-parleur du à la commande ouverture/fermeture répétitive du transistor Q1.
Q1 ne serait pas nécessaire si GP3 pouvait être programmé en mode sortie, mais ce n'est pas le cas. Avec un controlleur PIC12F508 qui possède 5 E/S on pourrait se passer de Q1 et avoir une sortie audio indépendante. Remarquez que Q2 est un Transistor PNP monté en emitter-follower. L'objectif ici est d'éviter qu'un courant circule dans le haut-parleur lorsque la sortie audio est inactive. En effet la majorité du temps GP2 est gardé à 1 pour conserver Q1 en saturation donc Q2 est en blocage à ce moment là. Au départ je n'avais pas mis de commutateur ON/OFF SW5. Je croyais que en mettant le MCU en mode sleep serait suffisant pour réduire le courant de drainage de la pile à un niveau négligeable. Je n'avais pas pensé que les 2 jonctions base-émetteur de Q1 et Q2 étant en série un courant circule entre Vdd et Vss via ces 2 jonctions. Conséquence lorsque le MCU était en mode sleep un courant de 8MA circulait à travers le transistor Q2 et le haut-parleur, drainant ainsi la batterie. Je croyais corrigé le problème en ajoutant les diodes D5 et D6 mais c'était insuffisant pour mettre Q1 et Q2 complètement en cut-off. Je me suis résigné à ajouter SW5 et à modifier le logiciel pour ne plus utiliser le mode sleep.

Le logiciel

Examinons maintenant le code source du logiciel.
algorithme
  1. Au démarrage exécution du POST
  2. Allumer les DELs séquentiellement en attente d'un bouton pressé.
  3. Générer une nouvelle note au hazard
  4. Afficher le nombre de notes en binaire
  5. Jouer la séquence
  6. Lecture des boutons
  7. si aucun bouton pressé dans un délais de 2 secondes on va à ERREUR
  8. Si le joueur joue la mauvaise note on va a ERREUR.
  9. Est-ce que le joueur à complété toute la séquence?
  10. NON! on retourne à 6
  11. OUI! quel est la longueur de la séquence?
  12. a chaque multiple de 6 notes faire entendre la mélodie CONGRATULATION
  13. on retourne à 3
  14. ERREUR: Fait entendre un son aigu et réinitilise les variables et retourne à 2
  15. CONGRATULATION: on joue une mélodie. Le nombre de notes jouées dépend de la longueur de la séquence. Si longueur <32 on retourne à 3 sinon réinitialise le jeux à 2.

Le montage

J'ai monté le circuit sur une plaquette de prototypage Droids modèle 990.101 disponible chez robotshop. J'ai monté la plaquette dans la boite de plastique dans laquelle mon iPod Nano m'a été livré. Les boutons monté sur le circuit sont de type miniatures et j'ai du trouvé un moyen pour fabriquer des extensions. Pour ce faire j'ai utilisé des push-pin pour tableau d'affichage. Elles sont en acrylique transparent et s'apparient bien avec le boitier. Je les ai coupé juste au dessus de l'aiguille.


alimentation: 2xAAA en série


Dans ce projet j'ai utilisé le repurposing de 3 façons:
  1. Réaffectation du boitier de iPod
  2. Réaffectation de push-pin
  3. Réaffection du connecteur d'une pile de 9volt que j'ai désassemblée et que j'ai soudé à 2 piles AAA connectées en série qui servent d'alimentation au pocket simon
Le repurposing est un jeux qui me plait, car ça fait appel à l'imagination.

mise à jour 2017-01-02

J'ai revisité ce projet ces derniers jours pour le présenter au défi Hackaday 1KB challenge. J'ai modifié légèrement le circuit et fabriqué un nouveau montage. Toute l'information sur de nouveau projet est sur https://github.com/picatout/pocketsimon.

retour sur hello DEL

Voici quelques explications supplémentaires sur la sous-routine minuterie du programme hello-del.asm présenté dans la chronique précédente.

J'ai expliqué comment calculer la valeur de la constante pour déterminer la durée du délais. On se base sur la durée du cycle d'instruction Tcy. Dans les micro-controlleurs PIC un cycle d'instruction dure 4 cycles d'oscillateur. Comme l'oscillateur interne du PIC10F202 fonctionne a 4Mhz ça donne un Tcy de 1usec (micro-seconde). Donc on a 500 000 Tcy par 1/2 secondes. Pour créer un délais on initialise une variable compteur ensuite on la décrémente jusqu'à zéro. Du moins c'est la première idée qui vient a l'esprit.


NBRE_ITERATION EQU 0
;initialisation du compteur
movlw low NBRE_ITERATION
movwf compteur
; boucle de délais
boucle
decfsz compteur,F ; 1 Tcy ou 2Tcy si la condition est vrai
goto boucle ; 2 Tcy


Mais que ce passe-t-il si on charge le compteur avec la valeur zéro?
la variable compteur est décrémentée et tombe à la valeur 255
le test si compteur = 0 saute la prochaine instruction échoue et l'instruction goto boucle est exécutée. Normalement on ne veut pas bouclé puisqu'on a indiqué une valeur de délais nulle. Mais dans ce cas on va en fait bouclé 255 fois! Esssayons autre chose.


NBRE_ITERATION EQU 0
;initialisation du compteur
movlw ~NBRE_ITERATION ; ~ signifit complément de 1
movwf compteur ; compteur = 0xFF - NBRE_ITERATION
boucle
incfsz compteur,F
goto boucle


Dans cette version si la constante NBRE_ITERATION=0 son complément à 1 est 0xFF (255). Le compteur est incrémenté et tombe à la valeur zéro et on saute par dessus le goto qui suit. On obtient donc l'effet escompté. C'est à dire que si on initialise le compteur avec la valeur zéro il n'y a pas de bouclage et le délais est minimal, il est de 4 Tcy, 2 Tcy pour l'initialisation et 2 pour l'instruction incfsz compteur,F car cette instruction prend 2Tcy lorsque la condition de test est vraie et qu'il y a un saut. Si la valeur de NBRE_ITERATION valait 1 sont complément serait 0xFE (254) et on bouclerais exactement 1 fois, etc. Cet algorithme fonctionne tel qu'attendu.

autre méthode pour minuterie

Les ressources du PIC10F202 étant très limitées on essaie de les économiser le plus possible. la sous-routine minuterie utilisé dans le programme de la chronique hello DEL utilise 3 registres de variables et la routine minuterie utilise 13 instructions. En utilisant le périphérique TIMER0 du MCU on peut faire mieux.



NBRE_ITERATION EQU .245 ;
minuterie
;initialisation du compteur
movlw ~NBRE_ITERIATION
movwf compteur
;initalisation du TIMER0
init_tmr0
movlw 1
movwf TMR0
movlw B'10000010' ; pré-division par 8
option ; W -> OPTION
boucle
movfw TMR0 ; TMR0 -> W
skpz ; si W==0 on saute le "goto boucle"
goto boucle
incfsz compteur,F ; incrémente le compteur de délais
goto init_tmr0 ; cette instruction est sauté si compteur==0
return ; on retourne à la procédure appelante.

TIMER0 est une minuterie 8bit interne du MCU qui est allimenté par la fréquence de l'oscillateur interne divisé par 4 (Fosc/4). Mais il y a aussi dans le MCU un diviseur de fréquence binaire programmable (prescaler) qui peut-être inséré entre l'oscillateur et l'entrée du TIMER0. Dans notre exemple on branche le diviseur et on le programme pour une division par 8. Donc le TIMER0 reçoit une impulsion qui le fait incrémenté à toute les 8 micro-secondes. On initialise le TIMER0 avec la valeur 1 on attend qu'il revienne à zéro. Pour revenir à zéro il doit recevoir 255 impulsions. Donc ça prend 8*255= 2040uSec. NBRE_ITERATION= 500000uSec/2040uSec=245

Remarquez que cette méthode nécessite 12 instructions, on gagne 1 seule instruction par contre on sauve 2 registres de variables. Considérant que le PIC10F202 n'en a que 24 cette méthode est aventageuse si on manque de variables. Mais ce n'est pas la seule raison pour laquelle l'utilisation d'un TIMER est avantageuse. Il y a aussi le fait que pendant que ce dernier compte le MCU peut effectuer une autre tâche car le TIMER n'a pas besoins d'instructions pour être incrémenté.

samedi 24 mars 2012

hello DEL

Avant de passer au projets dont je parlais dans le message précédent je vais présenter quelque chose de très simple. Si vous avez déjà fait de la programmation vous connaissez le fameux hello world que tous les débutants en informatique ont probablement programmé un jour. En language C ça donne quelque chose d'aussi simple que:


#include <stdio.h>
void main(){
puts("hello world");
}


Dans le monde de la programmation de MCU l'équivalent de hello world consiste à faire clignoter une DEL1. Le code est un peut plus long mais ça demeure simple.
Voici ce que ça donne en MPASM pour le PIC10F202

explication du code

Les programmeurs C remarqueront certaines similitudes, d'abord la directive #include et les directives #define. Elle sont utilisées de la même façon qu'en C.

__CONFIG

les controlleurs PIC possèdent des registres d'options de configuration qui déterminent certains paramètres de fonctionnement du MCU qui généralement ne sont pas modifiables au moment de l'exécution (runtime). Dans l'exemple ci-haut le watchdog timer (WDT_OFF) , la protection du code (CP_OFF) et le master clear sur GP3 (MCLRE_OFF> sont désactivés.

macros de substitution

Comme en C le pré-processeur substitue le premier symbole par les symboles qui suivent dans le texte source du programme. Par exemple chaque fois que le pré-processeur rencontre le mot DEL dans le code source il le remplace par GPIO, GP2.

macros d'assembleur

MPASM est un macro assembleur, c'est à dire qu'on peut créer des macros avec arguments que l'assembleur va substituer dans le code source dans la première phase de l'assemblage. Il s'agit d'un language de programmation en lui-même qui est beaucoup plus puissant que les macros de substitution du pré-processeur. On peut y définir des variables locales, des conditions d'assemblage et même des boucles de contrôle. Les 2 exemples montrés ici sont des plus simples et pourrait-être définit par des macros de substitution. Les macros d'assemblage permettent en quelque sortent de créer des sous-routines in-line.

les variables

Les variables sont des noms symboliques donnés à des adresses de mémoire qui vont contenir des valeurs qui seront modifiées en cours d'exécution. En MPASM il y a plusieurs façon de définir des variables, la directive cblock est une de ces méthodes. Le chiffre 8 qui apparait après la directive est la première adresse mémoire occupé par ce bloque de variables. Donc la variable compteur se trouve à l'adresse 8. Mais cette variable réserve 3 octets. Elle se termine donc à l'adresse 10. En réalité le symbole compteur sera remplacé par le chiffre 8 par l'assembleur, donc si je veux lire ou écrire dans le deuxième octet de compteur je peux écrire compteur+1 dans le code pour aller à l'adresse 9 (voir sous-routine minuterie à ce sujet).

le segment de code

la directive org indique que les instructions de code qui suivent commence à l'adresse indiquée après la directive. Dans ce cas à l'adresse 0 qui est l'adresse pointé par le compteur ordinal après une réinitialisation du mcu.

le code programme lui-même

Pour faire clignoter une DEL c'est très simple:

  • Allumer la DEL
  • partir la minuterie et attendre qu'elle revienne à zéro
  • Eteindre la DEL
  • partir la minuterie et attendre qu'elle revienne à zéro
  • retourner à la première étape et recommencer
Mais avant d'exécuter cette boucle il faut initialiser certains paramètres de fonctionnement
du MCU. Le PIC10F202 utilise un oscillateur interne de 4Mhz calibré en usine avec une précision de 1%. La valeur de calibration est conservée dans la dernière adresse de l'espace programme sous la forme d'une instruction RETLW xx. Où xx est la valeur de calibration qui sera retournée dans le registre W lors de la réinitialisaton du MCU. Donc si on veut que l'oscillateur fonctionne à la fréquence de calibration d'usine la première instruction à exécuter est movlw OSCCAL qui copie cette valeur dans le registre spécial de calibration de l'oscillateur appellé OSCCAL. Ensuite on utilise l'instruction goto initialisation pour déplacer le compteur ordinal à la première instruction après l'étiquette initialisation. Lorsque cette initialisation est complétée on tombe directement dans la procédure principale. Contrairement au C il n'y a aucune obligation de nommer cette procédure main, je l'ai baptisé ainsi par habitude.

Comme on peut le voir la boucle de la procédure principale mime exactement l'algorithme décris ci-haut. Contrairement au C où il suffit de nommer une fonction pour l'appeller, en assembleur MPASM il faut utiliser l'instruction call suivit du nom de la fonction.

la sous-routine minuterie

Le code le plus complexe de ce petit programme est dans cette routine. Mais c'est en fait assé simple. On inscris la valeur constante DEMI_PERIODE dans la variable compteur ensuite on entre dans une boucle qui incrémente cette variable jusqu'à ce qu'elle retourne à la valeur 0. La complexité viens du fait qu'il y a 3 boucles imbriquées car une variable de 24 bits (3 octets) est utilisée pour obtenir un compte assé long pour un délais de 1/2 seconde. La DEL clignote donc à une fréquence de 1hz. La boucle intérieure est celle qui s'éxécute le plus souvent et qui détermine principalement la durée du délais. Pour calculer la valeur de la constante DEMI_PERIODE, j'ai divisé 0,5 seconde par le temps d'exécution d'une seule itération de la boucle intérieure (celle qui incrémente l'octet faible du compteur). Soit Tcy le temps d'exécution d'un cycle d'instruction qui est de 1usec. la boucle dure 3*Tcy, 1 Tcy pour l'instruction incfsz compteur et 2 Tcy pour l'instruction goto boucle. On obtient donc qu'il faut 166667 itérations de cette boucle pour une durée de 0,5 secondes. Puisque j'incrémente le compteur plutôt que de le décrémenter la valeur réelle utilisée est DEMI_PERIODE=0xFFFFFF-0x28B0B. Les 2 boucles extérieures n'ont pas d'influence significatives sur la durée car elles s'exécutent trop rarement par rapport à la bouche intérieure, l'erreur induite par celles-ci est inférieure à 0,5%.

Pourquoi pas 'Hello World!'

En fait pour créer Hello World! sur un micro-controlleur il suffit d'envoyer le message à l'ordinateur qui va se charger de l'afficher. On envoie le message en protocol UART sur un port sériel (COM) de l'ordinateur. Sur l'ordinateur il suffit d'ouvrir un programme émulateur de terminal et le message va s'imprimer dans la console. Voici le montage à faire sur la platine sans soudure.

GP2 est utilisé comme sortie UART. La DEL est branchée anode au +5Volt de sorte qu'elle n'allume que lorsqu'il y a envoie d'un caractère car autrement GP2 est gardé au niveau 5volt.

hello-led-3.asm

Cette version est réécrite à partir de zéro donc c'est différent de la précédente. On a 2 routines de délais _delais_usec qui est une macro pour les délais courts, moins de 1023 usec. _delais_msec est une macro pour les délais plus longs en millisecondes (jusqu'à 65 535 msec). Cette macro prépare le compteur_delais et appelle la sous-routine delais_msec qui fait le gros du travail. Cette sous-routine utilise la macro _delais_usec pour créer un délais de 1msec de sorte que compteur_delais est décrémenté à toutes les millisecondes jusqu'à zéro.

La sous-routine uart_send est responsable d'envoyer le caractère vers l'ordinateur. Elle utilise les variables carac et compteur_bits ainsi que la macro _delais_usec pour le délais de bit. l'envoie se fait à 9600 BAUD, 8 bits, pas de parité et 1 stop bit. Il n'y a pas de contrôle flux. Sous linux on peut utiliser picocom pour recevoir le message:
exemple: picocom -b 9600 -d 8 -f n /dev/ttyS0
Utilisez le port qui convient à votre installation.
Sous windows 7 l'application terminal peut-être utilisée.

La table message est créée dans dans la mémoire programme avec le contenu: "Hello World!\r\n",0. La procédure main ne fait que lire les caractères dans cette table en l'indexant avec la variable idx_carac et appelle uart_send. Lorsque le zéro terminal est rencontré l'envoie se termine et un saut vers pause est effectué. Après un délais 1 seconde le programme boucle vers main et le message est renvoyé.





notes

1) Diode Électro-Luminescente, abréviation anglophone LED

Outils de dévellopement

Logiciels

Microchip fournis gratuitement un environnement de dévellopement appellé MPLAB et depuis peut MPLABX. L'intérêt de ce dernier est qu'il fonctionne aussi bien sous GNU/Linux que windows. C'est celui que j'utilise car je travaille sous GNU/Linux. Avec MPLABX vous pouvez aussi télécharger des compilateurs C gratuits en version allégé. Personnellement, étant donné la simplicité de mes projets, je travaille en assembleur en utilisant MPASM qui est fournir avec l'IDE MPLAB(X).

matériel

En plus des outils usuels d'un technicien en électronique, vous devez posséder un programmeur. Ajourd'hui les MCU utilisent de la mémoire FLASH pour conserver le programme. C'est très pratique car ça permet un cycle de programmation rapide lors du développement. Dans certains cas on peut-même laissé le pragrammeur branché en permanence au circuit durant la phase de développement. Pour ma part j'utilise le PicKit 31 qui en plus d'être un programmeur est un débogueur en-circuit pour les micro-controlleurs qui le supporte2. A 45US$ le Pickit 3 est abordable pour utilisation de loisir mais il y a encore moins couteux comme le pickit 2 (35US$) et on peut aussi trouver des schémas de clones de pickit 2 dans l'internet. IL faut faire attention cependant de vérifier quels sont les micro-controlleurs supportés par tel programmeur avant d'acheter.

À venir

Depuis un certains temps J'explore les possibilités du plus simple et petit micro-controlleur de Microchip, soit le PIC10F200/PIC10F202. Seulement 3 broches programmables en entrées ou sorties binaire et une broche en entrée binaire seulement qui sert aussi de master clear. A venir donc la présentation de 2 petits projets utilisant le PIC10F202.

  • Une lampe de poche programmable
  • Un jeux de mémoire appellé pocket Simon



notes

1) J'ai aussi un pickit 2 qui a été mon premier programmeur.

2) Ce ne sont pas tous les micro-controlleurs qui peuvent-être débogué en ciruit à moins d'utiliser un outil spécial et plus coûteux comme le ICD-3

À propos de ce blog

Je suis technicien en électronique et en informatique et dans mes loisirs j'aimes bien explorer les micro-controlleurs en créant de petits projets les utilisants. Jusqu'à maintenant je me suis limité au micro-controlleurs PIC de Microchip. Il y a une grande variété de micro-contolleurs sur le marché dont les AVR de Atmel popularisé par le projet Arduino. Mais comme chaque type de micro-controlleur a besoin d'un programmeur et d'un environnement de dévelloppement spécifique, celà implique des coûts et du temps investis dans un nouvel apprentissage chaque fois qu'on change de famille de micro-controlleur. Pour le moment j'ai donc décidé de me limiter aux MCU de Microchip.

Je n'ai pas inventé la roue, ni le bouton 4 trous. Tout ce que je sais je l'ai appris des autres. Des autres ont reçoit la connaissance et aux autres on doit la retransmettre. L'internet est un outil formidable de diffusion de la connaissance. Comme mes champs de compétances sont l'électronique et l'informatique, mon intention est de partager un partie de mes connaissances.

Si vous avez des connaissances de bases en électronique et en programmation et que vous être curieux de découvrir les possibilités des micro-controlleurs, ce blogue peut vous intéressé. Je vais y présenté des projets simples avec une description détaillé du circuit et du logiciel écris en assembleur.