[GUIDE] Introduction à la domotique : microcontrôleurs PIC

Retrouvez dans ce forum, tous les guides et tutoriels sur la culture cannabique.
Si t'es un MacGyver du bricolage ou un Einstein du cannabis, poste ton guide/tutoriel dans la section "Propositions de guides et tutoriels".

Votre PC dispose t'il d'un port Rs232 Série ?

Oui
12
48%
Non
13
52%
 
Nombre total de votes : 25

Message
Auteur
Super Koala

[GUIDE] Introduction à la domotique : microcontrôleurs PIC

#1 Message non lu par Super Koala »

  • 1. Introduction
    2. Les microcontrôleurs PIC Microchip
    • 1. Un micro bidule quoi ?
      2. A quoi ça sert ?
      • 1. Les organes de commande
        2. Les organes de « contrôle »
        3. Les organes de puissance
    3. Le PIC 16F628A
    • 1. Organisation de la mémoire
      • 1. La mémoire programme
        2. La mémoire EEPROM
        3. La mémoire RAM
      2. Les banques et les registres spéciaux
      • 1. Gros plan sur un registre
        2. Comment changer de banque
      3. Les périphériques internes
      • 1. Les ports A et B
        2. Les Timers
        3. Le module USART
        4. Le module Capture / Compare / PWM
      4. Le jeu d'instructions
    4. Ressources
    • 1. Les systèmes de numération
      • 1. Le système de numération décimal
        2. Le système de numération binaire
        3. Le système de numération hexadécimal
      2. Obtenir des composants gratuits chez Microchip
      3. Obtenir des composants gratuit chez Maxim
      4. Installer MPLAB
      5. Utiliser le programmateur de PIC
      6. Utiliser le simulateur
      7. Le fichier maquette du 16F628A
      8. Préparer l'alimentation pour nos montages
    5. Travaux pratiques
    • 1. Allumer des LED
      2. Utiliser TMR0 pour faire clignoter une LED
      3. Utiliser le Timer 1 pour faire clignoter une LED
      4. Utiliser le Timer 1 et une variable
Dernière modification par Super Koala le 24 janv. 2011, 22:13, modifié 27 fois.

Super Koala

Re: Introduction à la domotique : Les microcontrôleurs PIC

#2 Message non lu par Super Koala »

Introduction

Salut les F.C.F !

Un soir où je me baladais sur internet, je suis tombé sur un site de domotique. Le sujet bien sympathique sur l’économie d’énergie, la sécurité que ça apporte dans une habitation ou encore comment nous transformer en Américain type (^_^)

Une recherche en entrainant une autre, je suis tombé sur un excellent site qui parle de la programmation de microcontrôleurs PIC Microchip.

Il s’agit d’une petite puce noire avec plein de pattes qui cache bien son jeu !

Pour quelques euros, du temps et surtout beaucoup de patience, vous pouvez avoir un contrôle total sur votre box et même intégrer votre espace de culture dans un réseau informatique.

Je n’ai pas la prétention de réaliser un système complet clé en main et sur mesure si possible. Je ne suis pas un pro du microcontrôleur non plus et c’est la première fois que je vais proposer un tutoriel sérieux donc je m’excuse d’avance des différentes erreurs qui se glisseront dans ce tutoriel.


Les microcontrôleurs PIC Microchip
001.jpg
Un micro bidule quoi ?

Un microcontrôleur est une unité de traitement de l’information de type microprocesseur à laquelle on a ajouté des périphériques internes permettant de réaliser des montages sans nécessiter l’ajout de composants externes.

A partir d’un programme embarqué dans le microcontrôleur, vous pouvez utiliser les périphériques internes pour obtenir le comportement électrique que vous souhaitez dans votre box.

Il en existe de plusieurs marques, ici on va parler uniquement des PIC Microchip car on trouve beaucoup d’informations sur internet notamment sur l’excellent site de Mr Bigonoff.


A quoi ça sert ?

Imaginons quelqu’un qui souhaite installer de la lumière dans un bâtiment de 3 pièces.

Au plus simple il lui faut un interrupteur et une ampoule par pièce.

Si j’appuis sur l’interrupteur, la lampe s’allume comme dans toute installation classique.

Au bout de 3 jours, notre amis trouve ça chiant et décide de remplacer ses interrupteurs par des boutons poussoir et d’installer un télérupteur par pièce. Il faut donc acheter 3 télérupteurs puis modifier le câblage.

Si j’appuis sur le bouton poussoir, la lampe s’allume et reste allumée.
Si j’appuis une seconde fois, la lampe s’éteint

Pas très décidé, notre ami vire les télérupteurs pour installer des minuteries. Il faut donc acheter des minuteries et modifier le câblage.

Si j’appuis sur le bouton poussoir, la lampe s’allume et reste allumée pendant le temps programmé sur la minuterie.

Sur tous les systèmes cités ci-dessus, on peut distinguer 3 groupes :

Les organes de commande :

La commande représente vos moyens d’interagir avec votre montage, ça peut être des interrupteurs, des boutons poussoirs, votre ordinateur qui envoi une information ou encore un signal venant d’un autre composant du montage.

Les organes de « contrôle » :

Ce sont les appareils électriques qui vous permettent d’obtenir le comportement électrique que vous souhaitez par rapport à une information venant d’un organe de commande comme par exemple un contacteur, un télérupteur ou encore une minuterie.

Les organes de puissance :

Les organes de puissance sont les appareils contrôlés par les organes de « contrôle » comme par exemple une lampe, un chauffage, un ventilateur.

Attention : Nous allons utiliser du 5 volt continue pour notre montage, les contacts configurés en tant que sorties vont être en 5 volt aussi. On ne peut donc pas brancher un appareil directement sur la sortie du microcontrôleur !

On va utiliser des LED classiques pour simuler nos lampes ou autres appareils qui seront pilotés par le microcontrôleur.

Un microcontrôleur va nous permettre de brancher des organes de commande sur les broches configurées en tant qu’entrées, brancher nos LED sur les broches configurées en tant que sorties et de créer virtuellement les organes de « contrôle ».

On peut donc au maximum contrôler 18 sorties.

Si par exemple, j’ai besoin d’un bouton poussoir, je vais configurer une broche en tant qu’entrée, il me reste donc 17 sorties pour mes LED.

Suivant le programme envoyé dans le PIC, je peux émuler un télérupteur, une minuterie et bien d’autre chose sans modifier le câblage du montage. Il vous permet aussi de communiquer avec un ordinateur par exemple ou encore de moduler un signal pour utiliser un composant externe, etc…


Le PIC 16F628A

J’ai choisis ce modèle parce qu’il n’est pas spécialement compliqué et qu’il dispose de périphériques internes intéressants.

Avant de se lancer dans la programmation, il faut un peu de théorie. Au début ça parait super difficile mais je vous assure que ça vaut le coup !

Je souhaite juste vous faire partager ma passion et mes recherches et en aucun cas piquer le boulot de quelqu’un d’autre donc je vous conseille de lire le cours Partie 1 de Mr Bigonoff.

Je lui pique certains passages (ceux où il n’y a pas de fautes ^^), j’essaye de vérifier chaque information que je vous donne, j’ai pas mal avancé et je commence à être à l’aise avec le 16F628 mais je ne comprends pas tout non plus et je ne peux pas expliquer mieux que Mr Bigonoff.

Voyons un peu ce qui se cache dans les entrailles de cette petite puce ^^



Organisation de la mémoire

La mémoire du PIC 16F628A est divisée en trois parties.

La mémoire programme :

C’est cette mémoire qui va contenir votre programme. Elle est composée de 2048 mots de 14 bits, chaque mot est une instruction de votre programme. Si vous coupez l’alimentation de votre microcontrôleur, cette mémoire ne perd pas ses données.

La mémoire EEPROM :

La mémoire EEPROM (Electrical Erasable Programmable Read Only Memory), est constituée de 128 octets que vous pouvez lire et écrire depuis votre programme. Ces octets sont conservés après une coupure de courant et sont très utiles pour conserver des paramètres semi-permanents. Leur utilisation implique une procédure spéciale que nous verrons par la suite.

La mémoire RAM :

La mémoire RAM (Random Access Memory) est celle que nous allons sans cesse utiliser. Toutes les données qui y sont stockées sont perdues lors d’une coupure de courant.

La mémoire RAM est organisée en 4 banques pour le 16F628A. Dans chacune des banques nous allons trouver des « cases mémoires spéciales » appelées REGISTRES SPECIAUX et des cases mémoires « libres » dont vous pouvez vous servir à votre guise.

Pour le cas du 16F628A, vous disposerez de 224 octets libres dispatchés sur les quatre banques dont 16 octets communs pour faciliter certaines opérations.

Voici comment sont organisées nos quatre banques :
002.jpg
Sur le coté droit des bandes, on peut lire des adresses mémoire notées en hexadécimale. Chaque adresse correspond à une zone de 8 bits (un bit peut être à 1 ou à 0).

Les cases qui portent un nom comme par exemple TMR0, PCL, STATUS, … sont des espaces mémoire réservés pour le fonctionnement interne du microcontrôleur, pour récupérer une information ou encore piloter les périphériques internes.

On les appels les registres spéciaux.

On voit que certains registres sont dans les quatre banques et sur la même ligne comme par exemple PCL ou encore INTCON. Ce n’est pas un hasard, cela permet d’utiliser le registre en question à partir de n’importe quelle banque dans le but de simplifier la programmation.

Si mon programme utilise le registre PIR1, je dois être en banque 0.
Si je dois ensuite utiliser le registre PIE1, je dois d’abord passer en banque 1.
Si je dois ensuite utiliser le registre T1CON, je dois retourner en banque 0.
Si je dois ensuite utiliser le registre FSR, on ne se préoccupe pas de la banque car FSR est dans les quatre banques.


Tout en bas, on peut voir une zone de 16 octets commune aux quatre banques. Ici on va pouvoir stocker nos propres variables et les utiliser sans se préoccuper des banques.

Ensuite on dispose d’une zone de 80 octets en banque 0, 80 octets en banque 1 et 48 octets en banque 2. C’est la même chose, on va utiliser ces zones pour nos variables sauf que là il faut bien sélectionner la bonne banque avant d’utiliser notre variable.

Gros plan sur un registre

On a vu qu’un registre est un zone mémoire réservée de 8 bits qui porte un nom. Un bit ne peut avoir que 2 valeurs, soit 1, soit 0 donc un registre doit ressembler à ça :

0 0 0 0 0 0 0 0

Il faut lire de gauche à droite en commençant de b7 à b0. Ici des 0 c’est pas pratique donc voici un autre exemple :

0 1 1 0 1 1 1 0

Ici, il faut lire :

b7 = 0
b6 = 1
b5 = 1
b4 = 0
b3 = 1
b2 = 1
b1 = 1
b0 = 0

Pour certains registres spéciaux, il faut considérer chaque bit comme une information marche / arrêt.




Par exemple :

Si b7 = 1, l’option truc est activée
Si b6 = 1, l’option bidule est activée
Si b5 = 0, l’option chouette est désactivée
Etc…


Pour se simplifier la tache, chaque bit d’un registre porte un nom. Voici un extrait du datasheet :
003.jpg
004.jpg
005.jpg
006.jpg
Rassurez vous, on va en reparler plus bas ^^

D’autres registres comme par exemple TMR0 vont plutôt utiliser une valeur numérique plutôt que des bits de configuration. Comme nous disposons que de 8 bits dans un registre, la valeur maximale est :

1 1 1 1 1 1 1 1

Si on convertit cet octet en valeur décimale, on obtient 255. On verra pourquoi plus tard.

Comment changer de banque

Pour changer de banque et ainsi utiliser le registre que l’on a besoin, il faut jouer avec les bits RP0 et RP1 du registre STATUS qui est accessible à partir des quatre banques.

Si RP0 = 0 et RP1 = 0, nous sommes en BANK0
Si RP0 = 1 et RP1 = 0, nous sommes en BANK1
Si RP0 = 0 et RP1 = 1, nous sommes en BANK2
Si RP0 = 1 et RP1 = 1, nous sommes en BANK3

Pour placer le bit d’un registre à 0 on va utiliser l’instruction bcf comme ceci :

Bcf NOM_DU_REGISTRE, NOM_DU_BIT

Pour placer le bit d’un registre à 1 on va utiliser l’instruction bsf comme ceci :

Bsf NOM_DU_REGISTRE, NOM_DU_BIT


Il faut donc 2 opérations pour changer de banque, la première pour placer RP0 à 1 ou à 0 et la seconde pour placer RP à 1 ou à 0.

Pour se simplifier la tache, on va créer des macro pour changer de banque qui ressemble à ça :

Code : Tout sélectionner

BANK0 macro            ; Passer en banque0
      bcf   STATUS,RP0
      bcf   STATUS,RP1
      endm

BANK1 macro            ; Passer en banque1
      bsf   STATUS,RP0
      bcf   STATUS,RP1
      endm

BANK2 macro            ; Passer en banque2
      bcf   STATUS,RP0
      bsf   STATUS,RP1
      endm

BANK3 macro            ; Passer en banque3
      bsf   STATUS,RP0
      bsf   STATUS,RP1
      endm
On en reparlera au moment de créer notre premier programme.
Vous ne pouvez pas consulter les pièces jointes insérées à ce message.
Dernière modification par Super Koala le 21 janv. 2011, 20:53, modifié 12 fois.

Super Koala

Re: Introduction à la domotique : Les microcontrôleurs PIC

#3 Message non lu par Super Koala »

Les périphériques internes

Comme évoqué plus haut, un microcontrôleur dispose de périphériques internes.

Voici la liste de ce que j’ai pu traduire :

16 Entrées / Sorties configurables
Un Timer0 de 8 bits avec un pré-diviseur
Un Timer1 de 16 bits
Un Timer2 de 8 bits avec pré-diviseur et post-diviseur
Un module USART (Universal Synchronous/Asynchronous Receiver / Transmitter)
Un module Capture / Compare / PWM
012.jpg
Les ports A et B

Les ports A et B représentent les organes de commandes ainsi que les organes de puissances.
Il ne faut pas se dire que le A est la commande et le B la puissance, ça n'a rien à voir. Si il y a deux ports, c'est surement pour une raison électronique très compliquée.

Le port A dispose de 8 I/O, de RA0 à RA7.
Le port B dispose de 8 I/O, de RB0 à RB7.

C'est troublant car on voit que les pattes de ces I/O ont plusieurs noms, comme par exemple RA6 et RA7 qui portent aussi le nom de OSC1 et OSC2...

En fait, il faut se souvenir que ces pattes sont configurables via un registre et que leur fonction change suivant les périphériques internes que l'on utilise.

Sur ce montage, je vous fait utiliser un Quart 4Mhz qui se branche sur OSC1 et OSC2. Le Quartz introduit dans le montage une notion de temps et vous permet de cadencer un cycle (via le timer). Le fait d'utiliser la fonction Timer me retire donc la possibilité d'utiliser RA6 et RA7.

Pour résumer ça, il faut se dire qu'avec le montage le plus simple, nous disposons de 16 I/O (port A et B), plus nous utilisons de périphériques internes, moins nous disposons d'I/O pour le reste du montage.

Comment placer une I/O en mode O (Output / Sortie) ?

Prenons par exemple le port A qui contient 8 I/O (8 I/O, comme un octet?, oui c'est ça ^^)
Pour le configurer, nous devons utiliser le registre TRISA qui permet de choisir le mode I ou O d'une patte RA.

Le registre TRISA contient donc 8 bits comme le nombre d'I/O du port A, chaque bit représente l'état I ou O d'une patte RA. Si je met un bit à 1, la patte concernée va passer en mode I (Entrée pour la commande), si le bit concerné est à 0, la patte sera une sortie(Sortie pour la puissance)

Rappelez vous que le registre W est omniprésent.
La bonne marche à suivre pour assigner la fonction du port A doit ressembler à ça :

- Je met un octet dans W (par exemple 0 0 0 0 0 0 0 0)
- Je place le contenu de W dans TRISA

Ici, tous les bits sont à 0 donc, toutes les pattes du port A seront des sorties.

- Je met un octet dans W (par exemple 1 0 0 1 0 0 1 0)
- Je place le contenu de W dans TRISA

Ici, RA0 sera une sortie, RA1 sera une entrée, RA2, RA3 seront des sorties, RA4 sera une entrée, RA5 et RA6 seront des sorties et RA7 sera une entrée.

On commence à capter l'utilité d'un registre non ? Il faut car tout marche comme ça dans le monde des microcontrôleurs.

Voilà pour les ports A et B, ça sera plus concret quand vous allez allumer et éteindre vos 3 voyants en modifiant le registre TRISB (car sur mon schéma, les voyants sont sur RB1, RB2 et RB3)

- Je met un octet dans W (par exemple 1 1 1 1 0 0 0 1)
- Je place le contenu de W dans TRISB

Ici, RB1, RB2 et RB3 sont placés en mode Output.

- Je met un octet dans W (par exemple 0 0 0 0 0 0 0 0)
- Je place le contenu de W dans PORTB

Les 3 voyants sont éteints

- Je met un octet dans W (par exemple 0 0 0 0 1 0 1 0)
- Je place le contenu de W dans PORTB

Ici, RB1, RB2 et RB3 sont TOUJOURS en mode Output (puisque c'est TRISB qui gère ça)
Par contre, le voyant RB1 sera allumé, le voyant RB2 sera éteint, le voyant RB3 sera allumé.

En résumé, on utilise toujours le registre W pour manipuler quelque chose. Le registre TRISA et TRISB servent à définir le mode I ou O des pattes RA et RB. Le registre PORTA et PORTB servent à définir l'état (présence de tension ou absence de tension) des pattes RA et RB.

N’oubliez pas qu’il va falloir changer de banque car si on reprend le schéma de l’organisation de la mémoire, on voit que TRISA et TRISB sont en banque 1 et que PORTA et PORTB sont en banque 0.


Les Timers

Le Timer 0 est un compteur sur 8 bits. Il peut être utilisé en mode Compteur ou en mode Timer.

En premier lieu, vous pouvez compter les impulsions reçues sur la pin RA4/TOKI. Nous dirons dans ce cas que nous sommes en mode compteur.

Vous pouvez aussi décider de compter les cycles d’horloge du PIC® lui-même. Dans ce cas, comme l’horloge est fixe, nous compterons donc en réalité du temps. Donc, nous serons en mode « timer ».

La sélection d’un ou l’autre de ces deux modes de fonctionnement s’effectue par le bit 5 du registre OPTION : T0CS pour Tmr0 Clock Source select bit.

T0CS = 1 : Fonctionnement en mode compteur.
T0CS = 0 : Fonctionnement en mode timer.

Le Timer 1 est un compteur sur 16 bits, le Timer 2 est un compteur sur 8 bits. Chaque Timer possède des caractéristiques particulières mais on ne va pas les utiliser tout de suite.


Le module USART

USART signifie « Universal Synchronous Asynchronous Receiver Transmitter ». C’est donc un module qui permet d’envoyer et de recevoir des données en mode série, soit de façon synchrone, soit asynchrone. Dans certaines littératures, vous retrouverez également le terme générique de SCI pour « Serial Communications Interface ».

Il permet donc de communiquer avec d’autres composants de notre montage, pour notre application, on va utiliser un MAX232 ou un HIN232 pour relier notre montage à un ordinateur.

Voici un aperçu des quatre modes disponible :

- Mode asynchrone full duplex : émission sur TX et réception sur RX
- Mode asynchrone half-duplex sur 2 lignes (TX et RX) ou sur une ligne (TX/RX reliées)
- Mode synchrone maître : émission horloge sur CK et émission/réception données sur DT
- Mode synchrone esclave : réception horloge sur CK et émission/réception données sur DT


Le module Capture / Compare / PWM

Ici c’est encore un peu complexe pour moi, on va tenter d’utiliser le mode PWM pour moduler un signal et ainsi utiliser des composants externes qui acceptent ce signal comme par exemple certains petits extracteurs ou encore un driver LED.


Le jeu d'instructions

goto (Aller à) :
Cette instruction effectue ce qu’on appelle un saut inconditionnel, encore appelé rupture de séquence synchrone inconditionnelle.

incf (INCrement File) :
Cette instruction provoque l’incrémentation de l’emplacement spécifié (encore appelé File).

decf (DECrement File) :
Decrémente l’emplacement spécifié. Le fonctionnement est strictement identique à l’instruction précédente.

movlw (MOVe Literal to W) :
Cette instruction charge la valeur spécifiée (valeur littérale, ou encore valeur immédiate), dans le registre de travail W.

movf (MOVe File) :
Charge le contenu de l’emplacement spécifié dans la destination.

movwf (MOVe W to File) :
Permet de sauvegarder le contenu du registre de travail W dans un emplacement mémoire.

addlw (ADD Literal and W) :
Cette opération permet d’ajouter une valeur littérale (adressage immédiat) au contenu du registre de travail W.

addwf (ADD W and File) :
Ne pas confondre avec l’instruction précédente. Une nouvelle fois, il s’agit ici d’un ADRESSAGE DIRECT. Le CONTENU du registre W est ajouté au CONTENU du registre F.

sublw (SUBtract W from Literal) :
Attention, ici il y a un piège. L’instruction aurait du s’appeler SUBWL. En effet, on soustrait W de la valeur littérale, et pas l’inverse.

subwf (SUBtract W from File) :
Nous restons dans les soustractions, mais, cette fois, au lieu d’un adressage immédiat, nous avons un ADRESSAGE DIRECT.

andlw (AND Literal with W) :
Cette instruction effectue une opération « AND » BIT A BIT entre le contenu de W et la valeur littérale qui suit.

andwf (AND W with File) :
Maintenant, vous devriez avoir bien compris. De nouveau la même opération, mais en ADRESSAGE DIRECT. Je vais donc accélérer les explications.

iorlw (Inclusive OR Literal with W) :
Et oui, les mêmes instructions, mais pour le OU inclusif. Inclusif signifie simplement le contraire d’exclusif, c’est à dire que le bit de résultat vaudra 1 si un des bits, OU LES DEUX BITS, opérandes =1.

iorwf (Inclusive OR W with File) :
Effectue un OR entre (w) et l’emplacement spécifié. C’est donc une instruction en ADRESSAGE DIRECT.

xorlw (eXclusive OR Literal with W) :
Par opposition au ou inclusif, voici maintenant le OU EXCLUSIF. Sa table de vérité est la même que le ou inclusif, excepté que lorsque les 2 bits sont à 1, le résultat est 0.

xorwf (eXclusive OR W with File) :
C’est exactement la même opération que XORLW, mais en ADRESSAGE DIRECT.

bsf (Bit Set File) :
C’est une instruction qui permet tout simplement de forcer directement un bit d’un emplacement mémoire à 1.

bcf (Bit Clear File) :
C’est une instruction qui permet tout simplement de forcer directement un bit d’un emplacement mémoire à 0.

rlf (Rotate Left through carry to File) :
Rotation vers la gauche en utilisant le carry.Les opérations de décalage sont des opérations très souvent utilisées. Les PIC® ont la particularité de ne disposer que d’instructions de ROTATION. Vous allez voir qu’avec ces instructions, on peut très facilement réaliser des décalages.

L’opération de rotation effectue l’opération suivante : Le bit de carry C est mémorisé. Ensuite chaque bit de l’octet est déplacé vers la gauche. L’ancien bit 7 sort de l’octet par la gauche, et devient le nouveau carry. Le nouveau bit 0 devient l’ancien carry. Il s’agit donc d’une rotation sur 9 bits.

rrf (Rotate Right through carry to File) :
Rotation vers la droite en utilisant le carry. L’opération de rotation vers la droite effectue l’opération suivante : Le bit de carry « C » est mémorisé. Ensuite chaque bit de l’octet est déplacé vers la droite. L’ancien bit 0 sort de l’octet par la droite, et devient le nouveau carry. L’ancien carry devient le nouveau bit7. Il s’agit donc également d’une rotation sur 9 bits.

btfsc (Bit Test File, Skip if Clean) :
Traduit littéralement, cela donne : Teste le bit de l’emplacement mémoire et saute s’il vaut 0. Il s’agit ici de votre premier SAUT CONDITIONNEL, ou RUPTURE DE SEQUENCE SYNCHRONE CONDITIONNELLE .

btfss (Bit Test File, Skip if Set) :
Traduit littéralement, cela donne : Teste le bit de l’emplacement mémoire et saute s’il vaut 1. Toutes les remarques de l’instruction « BTFSC » restent valables.

decfsz (DECrement File, Skip if Zero) :
Nous poursuivons les sauts conditionnels avec une instruction très utilisée pour créer des boucles. Cette instruction décrémente un emplacement mémoire et saute l’instruction suivante si le résultat de la décrémentation donne une valeur nulle.

incfz (INCrement File, Skip if Zero) :
Je ne vais pas détailler cette instruction, car elle est strictement identique à la précédente, hormis le fait qu’on incrémente la variable au lieu de la décrémenter.

swapf (SWAP nibbles in File) :
Nous pouvons traduire cette instruction par «inverser les quartets dans F ». Cette opération inverse simplement le quartet (demi-octet) de poids faible avec celui de poids fort.

call (CALL subroutine) :
Cette opération effectue un saut inconditionnel vers un sous-programme.

Voyons ce qu’est un sous-programme. Et bien, il s’agit tout simplement d’une partie de programme qui peut être appelé depuis plusieurs endroits du programme dit « principal ».

Le point de départ est mémorisé automatiquement, de sorte qu’après l’exécution du sous-programme, le programme continue depuis l’endroit où il était arrivé. Cela paraît un peu ardu, mais c’est extrêmement simple.

return (RETURN from subroutine) :
Retour de sous-routine. Va toujours de pair avec une instruction call. Cette instruction indique la fin de la portion de programme considérée comme sous-routine (SR). Rappelez-vous que pour chaque instruction « call » rencontrée, votre programme devra rencontrer une instruction « return ».

retlw (RETurn with Literal to W) :
Retour de sous-routine avec valeur littérale dans W.
C’est une instruction très simple : elle équivaut à l’instruction return, mais permet de sortir d’une sous-routine avec une valeur spécifiée dans W.

retfie (RETurn From IntErrupt) :
Cette instruction indique un retour d’interruption (nous verrons ultérieurement ce que sont les interruptions). Cette instruction agit d’une manière identique à RETURN, excepté que les interruptions sont remises automatiquement en service au moment du retour au programme principal.

clrf (CLeaR File) :
Cette instruction efface l’emplacement mémoire spécifié.

clrw (CLeaR W) :
Cette instruction efface W.

clrwdt (CLeaR WatchDog Timer) :
Remet à 0 le chien de garde (watchdog) de votre programme. Nous aborderons la mise en oeuvre du watchdog ultérieurement. Sachez cependant que c’est un mécanisme très pratique qui permet de provoquer un reset automatique de votre PIC® en cas de plantage du programme (parasite par exemple).

comf (COMplemente File) :
Effectue le complément à 1 de l’emplacement mémoire spécifié. Donc, inverse tous les bits de l’octet désigné.

nop (No OPeration) :
Comme vous devez être fatigué, et moi aussi, je vous présente l’instruction qui ne fait rien, qui ne positionne rien, et qui ne modifie rien. On pourrait croire qu’elle ne sert à rien. En fait elle est surtout utilisée pour perdre du temps, par exemple pour attendre une ou deux instructions, le temps qu’une acquisition ai pu se faire, par exemple. Nous l’utiliserons donc à l’occasion.

sleep (Mise en sommeil) :
Place le PIC® en mode de sommeil. Il ne se réveillera que sous certaines conditions que nous verrons plus tard.
Vous ne pouvez pas consulter les pièces jointes insérées à ce message.
Dernière modification par Super Koala le 21 janv. 2011, 22:57, modifié 15 fois.

Super Koala

Re: Introduction à la domotique : Les microcontrôleurs PIC

#4 Message non lu par Super Koala »

Le matériel minimum pour commencer

Il vous faut :

- Une platine à essais
- Un programmateur de PIC
- Un petit tournevis plat
- Une pince coupante
- Un peu de câble de téléphone
- Un chargeur de téléphone portable se rapprochant le plus possible du 5V Continu

En option pour participer au développement :

- Un multimètre sur lequel on peut sacrifier les pointes pour souder un bout de fil de téléphone.
- Un oscilloscope (^_^)


La platine à essais :
007.jpg
J'ai une PLAQUE D ESSAI PROFI B (729) pour environ 28€, vous pouvez prendre plus petit mais mieux vaut avoir plus de place que d'utiliser 2 platines :)


Le programmateur de PIC :
008.jpg
Moi j'ai ce modèle, environ 50€, ils acceptent plusieurs types de PIC et quelques mémoire EEPROM externes.
Je vous déconseille vivement ce type de programmateur, déjà pour la rareté des ports rs232 sur nos PC, il est incompatible avec les PC portable, il coûte relativement chère pour ce que c'est, il faut acheter un câble dit "null modem" et une alimentation externe 12V continue.

Celà dit, moi je l'ai depuis longtemps et j'ai jamais eu de problème avec sauf sur mon PC portable donc je vire Madame de sa tour quand j'ai besoin de programmer un PIC.


Le programmateur haut de gamme PICkit™ 2 Starter Kit :
009.png
USB, normalement compatible avec les PC portables, il est recommandé par les pros sur les forums d'électronique mais je ne peux vous conseiller car j'ai jamais utiliser. Si quelqu'un est intéressé, il faut faire des recherches, poser des questions et tout feed back sera le bienvenue. On le trouve pour 37€ sur le site officiel Microchip mais les frais de port et les taxes piquent un peu. Si quelqu'un trouve son bonheur moins chère, merci de me le faire savoir pour mettre à jour ce tutoriel. On le trouve moins chère sur ebay mais attention à pas confondre avec la copie chinoise qui est très ressemblante mais qui n'est bien évidement pas marqué du logo Microchip :)


La copie chinoise :

La copie chinoise coûte environ 20€ sur ebay frais de port inclus. Une photo n'est pas nécessaire car c'est la même chose que le vrai PICKIT 2 mais sans le logo Microchip. Il y a de très bons feed back sur le net, je ne peut pas me prononcer car je n'en ai pas. Pareil que ci-dessus, tout commentaire est le bienvenue. Il semblerai que ce soit le modèle parfait pour nous car la seule chose qui lui manque, c'est le système de débogage sur circuit mais pour un début, on en a pas plus besoin que ça.

Le multimètre :
010.jpg
Environ 12€ dans tous bons supermarchés qui se respectent, on est pas obligé d'en avoir un pour réaliser les montages mais si vous voulez être autonome et partir à l'aventure, je vous le conseille vivement. N'hésitez pas à couper le bout des fils pour souder du fil de téléphone au bout, c'est très pratique pour faire ses mesures sur platines à essais.

L'oscilloscope numérique :
011.jpg
Loin d'être obligatoire, de par son prix. Il sert à "voir" le courant à certain endroits de votre montage comme par exemple les trames échangées entre votre PC et le montage, vérifier un signal d'horloge etc...
J'ai eu la chance de la payer 60€ chez cours vite :ange:


Ressources

Les systèmes de numération

Le système de numération décimal :

Le système que tout le monde connait et utilise, on dit que ce système est en BASE 10.
Pourquoi ? Simplement parce que nos ancêtres ont commencés à compter sur leurs 10 doigts ^^
Avec 10 chiffres (de 0 à 9), nous pouvons exprimer n'importe quel nombre.

Le système de numération binaire :

Ce système est en BASE 2. Si je veux exprimer un nombre en binaire, je suis obligé d'utiliser un 1 ou un 0.

Ce système a été conçu pour répondre à un problème physique lors de la création des premiers ordinateurs (si je dis pas de conneries ^^). Sur un circuit électronique, la seule chose qu'on peut échanger entre composants c'est bien l'électricité et du coup, on se retrouve qu'avec deux possibilités, présence de tension (0) ou absence de tension (1).

Le 1 ou le 0, ici on va appeler ça un "bit".

Reprenons notre système décimal à 10 chiffres. De 0 à 9, pas de problème, nous avons les chiffres qui vont bien mais comment aller plus loin que 9?

10, 125, 4215? Et bien c'est juste une histoire de normes, nos ancêtres ont mit au point des règles pour qu'on s'y retrouve et je vais pas passer trop de temps la dessus :)

Pour le binaire, c'est exactement la même chose. Nous avons décidé qu'une série de 8 bits forme un "octet".

Avant de se lancer dans les conversions, vous avez peut être déjà remarqué que votre adresse IP comporte une série de 4 nombres comprit entre 0 et 255. C'est étrange de pas pouvoir mettre 256 non ? Et bien non, en fait c'est très logique. Une adresse IP est codée sur 4 octets (actuellement car le protocole IP6 utilise 16 octets).

Ceci explique les 4 nombres mais pourquoi 255 max ?

Voici quelques octets et leur valeur décimale :
binaire_01.jpg
C'est étrange, il faut que j'explique ^^

En fait, il suffit de se souvenir qu'on est en BASE 2. On va donc se placer un petit repère au dessus de l'octet comme ceci :
binaire_02.jpg
Comme on peut le constater, le repère commence à 1 à partir de la droite, puis à chaque fois qu'on se décale d'un rang vers la gauche, on multiplie le repère par 2.

Quand on regarde, 32, 64, 128, ça fait penser aux barrettes de RAM, aux cartes graphiques etc.

Bha oui, c'est pour cette raison qu'on trouve pas de barrettes de RAM qui font par exemple 300Mo, c'est soit 256, soit 512.
binaire_03.jpg
Dans cet exemple, il faut additionner les repères qui sont à 1. On se retrouve donc avec 4+2+1 = 7

Voici un octet à sa valeur maximal :
binaire_04.jpg
Donc, 128+64+32+16+8+4+2+1 = 255 :lol:


Le système de numération hexadécimal :

Parfois on va vous parler d'hexadécimal, c'est la même chose mais en BASE 16 (moi j'aime pas donc je sort la calculette scientifique)
Wikipedia a écrit : Le système hexadécimal est un système de numération positionnel en base 16. Il utilise ainsi 16 symboles, en général les chiffres arabes pour les dix premiers chiffres et les lettres A à F pour les six suivants.

Le système hexadécimal est utilisé par les informaticiens car il est particulièrement commode et permet un compromis entre le code binaire des machines et une base de numération pratique à utiliser pour les ingénieurs. En effet, chaque chiffre hexadécimal correspond exactement à quatre chiffres binaires (ou bits), rendant les conversions très simples et fournissant une écriture plus compacte. L'hexadécimal a été utilisé la première fois en 1956 par les ingénieurs de l'ordinateur Bendix G-15.
Vous ne pouvez pas consulter les pièces jointes insérées à ce message.
Dernière modification par Super Koala le 21 janv. 2011, 23:54, modifié 14 fois.

Super Koala

Re: Introduction à la domotique : Les microcontrôleurs PIC

#5 Message non lu par Super Koala »

Obtenir des composants gratuits chez Microchip

Microchip nous permet d'obtenir des composants gratuitement dans le cadre d'un développement personnel, projets scolaires, test d'un composant dans le but de réaliser un tutoriel ou encore test avant de lancer une chaine de production et donc de leur acheter du matos plus tard ^^

Pour commencer, il vous faut une adresse mail sérieuse du genre mon-nom.prenom@entreprise_ou_ecole.fr

Évitez à tout prix hotmail, la poste, yahoo etc, leur site dispose d'un système qui filtre ce genre d'adresse et vous serez mit à la trappe directement.

Si vous êtes encore à l'école, en particulier dans les lycées techniques, demandez à un responsable si il peut vous créer une adresse mail temporaire en lui expliquant que vous voulez obtenir des échantillons gratuits de composants, souvent ça marche.
Votre adresse mail sera donc mon-nom.prenom@mon_lycee.fr

Personnellement je dispose d'un nom de domaine qui fait très pro donc j'ai pu créer mon adresse mail et c'est passé sans soucis.

Si vous n'avez aucun moyen d'obtenir ce genre d'adresse, je vous conseille de vous regrouper entre personnes de confiance et prendre un hébergement web chez 1&1 pour 1,90€ HT / mois. Ce compte va vous permettre de créer 5 adresses mail avec le nom de domaine que vous aurez choisit.

Rendez-vous ensuite sur cette page :
http://www.microchip.com/wwwregister/RegisterStep1.aspx

Inscrivez-vous avec les vrais informations bien entendu, ils posent parfois des questions embarrassantes comme par exemple le secteur d'activité, le pourquoi on fait la demande etc.
Si je me souviens bien, dans "Company Name" j'ai mis "None", dans "Occupation" j'ai mis "Student" (Étudient), "Industry" j'ai mis "Computing".

Une fois votre inscription validée, identifiez vous avec votre login/password.

Retournez sur la page d'accueil du site si vous n'y êtes pas, dans le menu en haut, survolez "Buy/Sample" puis cliquez sur "Sample".

On arrive sur une page avec 2 combo en haut et un tableau en page centrale.
Fichier(s) joint(s):
013.jpg
Dans le premier combo, sélectionnez toujours "8 bits PIC microcontrollers", dans le second, commencez par choisir 16F628A.

Vous aller voir un tableau avec tous leurs produits disponibles, si il y a un petit carré jaune dans la colonne "sample", c'est bon pour nous !

Dans les sample on va prendre le PIC16F628A-I/P.

Voili voilou, j'en ai profité pour prendre un PIC18F258-I/SP et un PIC16F887-I/P pour de futurs expériences.

Une fois vos courses terminées, cliquez sur "checkout" en haut à coté du panier

Il me semble qu'on a le droit de prendre 2 types de PIC / commande et de passer 2 commandes / mois.

Après le "checkout", on va vous poser des questions chiantes :

Dans "Industry" j'ai pris "Computing", dans "Application Category" j'ai pris "Computers", dans "Project Description" j'ai mis "Personal projet for school", dans "Production Target Date" j'ai mis le premier qui vient, dans "Current Design Stage" j'ai mis "Prototyping" et mettez ce que vous voulez pour les 2 dernières.

Cliquez ensuite sur "Proceed to Step 2".

Il reste plus qu'a suivre le déroulement classique d'une commande comme vous avez surement déjà fait sur d'autres sites et normalement ça roule ma poule !

On prend vite goût à ne pas payer hein ? En ces temps de crise ça le fait bien je trouve.

Commandé le 03/01, reçu le 24/01 par la poste dans une boite en carton.
DSC00582.jpg
Obtenir des composants gratuits chez Maxim

Rendez-vous sur cette page :
https://memcenter.maxim-ic.com/guest/register.mvp

Suivez l'inscription etc, j'abrège car c'est un peu la même chose que chez Microchip.
Si vous avez un problème avec l'anglais, une question qui vous empêche de vous inscrire, Uncle à ouvert un topic de discutions donc n'hésitez pas à demander de l'aide.

Une fois le compte validé et identifié, dans le menu de gauche, vous avez un lien "Order Sample".

On doit arriver sur cette page :
014.jpg
Dans la textbox, entrez la référence : DS1620

Cliquez sur le bouton "Sample now" à droite pour le modèle PDIP (le premier)

Toujours en PDIP si possible, si quelqu'un trouve un autre composant intéressant en sample, n'hésitez pas à me le faire savoir.

Une fois les courses terminées, cliquez sur le lien "Sample Cart" en haut de la page.
Dans "Annual Usage*" mettez "< 1000", je vous laisse choisir la quantité mais n'abusez pas, ça sert à rien.

Le reste de la procédure de validation est particulièrement simple, à la question "What is your application (what is the end product)? *" j'ai mis "Personal project for school" et roule ma poule ^^

Voilà, n'hésitez pas à partager vos feed back sur cette méthode.

Commandé le 03/01, reçu le 07/01 par UPS.
DSC00579.jpg
Vous ne pouvez pas consulter les pièces jointes insérées à ce message.
Dernière modification par Super Koala le 24 janv. 2011, 16:50, modifié 5 fois.

Super Koala

Re: Introduction à la domotique : Les microcontrôleurs PIC

#6 Message non lu par Super Koala »

Installer MPLAB

On va commencer par télecharger MPLAB sur le site de Microchip.

http://www.microchip.com/stellent/idcpl ... t=SW007002

Tout en bas de la page web, cliquez sur "MPLAB IDE v8.63" pour le télécharger.
017.jpg
Double clique sur le fichier "setup.exe" puis on clique sur "Suivant" comme un bourrin :guerrier:

Ça va installer pendant un petit moment puis il va demander si on veut installer "HI-TECH C Compiler".
Moi j'ai dis oui, je sais pas encore si on va en avoir besoin.

Voilà, après "Finish", ça va ouvrir une fenêtre "MPLAB IDE Document Select", on la ferme ^^

Pour lancer le programme, double clique sur le raccourci "MPLAB IDE v8.63" sur le bureau ou dans le menu "Démarrer".


Créer un nouveau projet avec MPLAB

motivation en cours...


Fichier maquette du 16F628A

motivation en cours...
Vous ne pouvez pas consulter les pièces jointes insérées à ce message.
Dernière modification par Super Koala le 24 janv. 2011, 23:20, modifié 20 fois.

Super Koala

Re: Introduction à la domotique : Les microcontrôleurs PIC

#7 Message non lu par Super Koala »

Utiliser un simulateur

motivation en cours...

Utiliser un programmateur de PIC

motivation en cours...

Préparer l'alimentation pour nos montages

Le microcontrôleur fonctionne avec une alimentation 5 volts continue. Si comme moi vous utilisez un vieux chargeur de téléphone portable, il vaut mieux réguler et stabiliser votre tension.

Dans un premier temps, il faut différencier le + et le - de votre chargeur de portable, utilisez un multimètre ou encore une LED.

Si quelqu'un a besoin d'explications pour brancher la LED, MP moi.

Voici le schéma qu'il faut réaliser :
schema_alimentation_stabilisee.jpg
D1 : Diode 1N7004 (2€20 les 40)
U1 : Régulateur de tension 5V (2.50€ les 5)
C1 : Condensateur 100µF (4€ les 25)
C2 : Condensateur 100nF (4€ les 50)

Je donne les prix avec les frais de port sur ebay, je choisis les vendeurs au hasard ou suivant leurs prix

Attention : C1 est polarisé !
DSC00577.jpg
Vous ne pouvez pas consulter les pièces jointes insérées à ce message.
Dernière modification par Super Koala le 24 janv. 2011, 23:15, modifié 10 fois.

Super Koala

Re: Introduction à la domotique : Les microcontrôleurs PIC

#8 Message non lu par Super Koala »

Espace réservé
Dernière modification par Super Koala le 22 janv. 2011, 00:47, modifié 5 fois.

Super Koala

Re: Introduction à la domotique : Les microcontrôleurs PIC

#9 Message non lu par Super Koala »

Travaux pratiques

Allumer des LED

Cet exercice a pour but de réaliser notre premier montage, de vérifier que tout va bien en allumant des LED et commencer à regarder comment est organisé un programme pour microcontrôleur.

Schéma
015.jpg
- PIC 16F628A (Gratuit chez Microchip)
- R1, R2, R3, R4 : Résistance 220 Ohms 1/4W (1.75€ les 20)
- D1, D2, D3, D4 : LED classiques (2.10€ les 20)

Je donne les prix avec les frais de port sur ebay, je choisis les vendeurs au hasard ou suivant leurs prix

Gardez toujours ce schéma sous la main :
012.jpg
Une petite photo du montage :
016.jpg
Projet
16f628_LED.rar
Explications complémentaires

Alors, on va regarder comment est organisé ce programme. L’organisation peut paraître étrange, rappelez vous que l’on n’utilise pas toutes les options du microcontrôleur dans cet exercice donc j’ai enlevé un peu de code pour simplifier la compréhension. Pour avoir un aperçu d’un programme complet, il faut regarder le fichier maquette du 16f628A dans les ressources un peu plus haut.

Tout ce qui commence par un point virgule est considéré comme commentaire par le compilateur. On est donc illimité en commentaires donc il ne faut pas hésiter à les utiliser. Commencez toujours un programme par une petite phrase qui résume ce que doit faire votre programme ainsi que quelques informations générales comme ceci :

Code : Tout sélectionner

	;*****************************************************************************
	; Allumer des LED
	; PIC 16F628A
	; Oscillateur externe 4Mhz
	;*****************************************************************************
Ensuite vous avez quelques lignes destinées au compilateur (le programme qui compile en fichier .HEX quand on appuis sur F10)

Code : Tout sélectionner

	LIST P=16F628A					  ; Définition du processeur
	#include "P16F628A.INC"  		; Définition du PIC16F628A
Ici on définit le processeur à utiliser, dans notre exemple on utilise un 16F628A. Si vous utilisez un 16F628, enlevez simplement le A.

Le fichier P16F628A.INC se trouve dans le dossier d’installation de MPLAB (Recherchez son nom dans votre dossier Program Files). C’est ce fichier qui fait la liaison entre les adresses mémoires à droite des bandes mémoires (banque) du schéma sur l’organisation de la mémoire.

Grâce à lui vous pouvez utiliser le nom des registres dans votre programme au lieu des adresses mémoires ^^

Code : Tout sélectionner

	errorlevel -302					 ; Supprime quelques Warning dans le compilateur (facultatif)
	errorlevel -207					 ; ``
	errorlevel -205					 ; ``
Ici se sont juste quelques lignes pour filtrer les messages retournées par le compilateur. Vous n’êtes pas obligé de les utiliser.

Code : Tout sélectionner

	; '__CONFIG' précise les paramètres encodés dans le processeur au moment de la programmation du processeur. 
	; Les définitions sont dans le fichier include.

	__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_OFF & _INTRC_OSC_NOCLKOUT & _LVP_OFF & DATA_CP_OFF & _BODEN_OFF & _MCLRE_OFF
	
	; Protection du programme
	; -----------------------
	; _CP_ALL						    Protection totale du programme
	; _CP_75 						    Protection du programme de 1000 à 1FFF
	; _CP_50						     Protection du programme de 1F00 à 1FFF
	; _CP_OFF						    Pas de protection programme
	
	; Watchdog
	; --------
	; _WDT_ON						    Watchdog en service
	; _WDT_OFF						   Watchdog hors service

	; Retard à la mise sous tension
	; -----------------------------
	; _PWRTE_OFF					    Démarrage rapide
	; _PWRTE_ON						  Démarrage temporisé
	
	; Oscillateur
	; -----------
	; _ER_OSC_CLKOUT 				  CLCKOUT sur RA6 resistance externe sur RA7 (38K-1M)             
	; _ER_OSC_NOCLKOUT				 I/O sur RA6 resistance externe sur RA7  (38K-1M)           
	; _INTRC_OSC_CLKOUT				Oscillateur interne clkout sur RA6 I/O sur RA7 (4MHz)    
	; _INTRC_OSC_NOCLKOUT			 Oscillateur interne I/O sur RA6 et RA7 (4MHz)        
	; _EXTCLK_OSC					   Signal clock fournit au pic sur RA7 I/O sur RA6                
	; _LP_OSC 						   Oscillateur basse vitesse (?<F<200Khz)        
	; _XT_OSC               		 Oscilateur moyenne vitesse (0,1MHz<F<4Mhz)     
	; _HS_OSC 						   Oscillateur haute vitesse (1Mhz<F<20Mhz)

	; Programmation sur circuit
	; -------------------------
	; _LVP_ON						    RB3 permet la programmation série de la PIC
	; _LVP_OFF						   RB3 en utilisation normale
	
	; Protection de l'EEprom
	; -----------------------
	; DATA_CP_ON					    Mémoire EEprom protégée
	; DATA_CP_OFF					   Mémoire EEprom déprotégée

	; Reset de la PIC si tension <4V
	; ------------------------------
	; _BODEN_ON						  Reset tension en service, valide PWRTE_ON automatiquement			
	; _BODEN_OFF					    Reset tension hors service
	
	; Utilisation de la pin MCLR
	; ------------------------------
	; _MCLRE_ON						  RA5/MCLR est utilise pour le reset
	; _MCLRE_OFF					    RA5/MCLR est utilise comme une entree/sortie
Ici beaucoup de commentaires pour une si petite ligne. Ce sont des réglages un peu particuliers qui fixent le fonctionnement du PIC. Pour l’instant on met de coté tout ceux qui sont à OFF et on reviendra dessus sur d’autres projets, j’expliquerai au fur et à mesure les options que j’utilise dans le projet concerné.

Dans notre projet, on utilise : _INTRC_OSC_NOCLKOUT.

_INTRC_OSC_NOCLKOUT indique que l’on va utiliser l’oscillateur interne du PIC en conservant les broches RA6 et RA7 en tant que entrée / sortie.

L’oscillateur (interne ou externe) se met à vibrer à une fréquence fixe quand il est traversé par un courant. C’est cette fréquence qui va rythmer votre PIC un peu comme le battement d’un cœur.

Le 16F628 contient un oscillateur interne de 4Mhz. Un cycle d’horloge correspond à 4 oscillations. Nous avons donc dans ce cas (4000000/4) = 1.000.000 de cycles par seconde. Chaque cycle d’horloge dure donc 1/1000000ème de seconde, soit 1μs.

Il y a des options pour utiliser un oscillateur externe entre 1Mhz et 20Mhz, voir même utiliser un oscillateur pour le PIC et un autre oscillateur pour les Timers de façon à obtenir la fréquence d’horloge qui vous convient le mieux suivant la précision que l’on souhaite obtenir dans les temporisations.

Code : Tout sélectionner

	;*****************************************************************************
	; ASSIGNATIONS SYSTEME                    
	;*****************************************************************************

	OPTIONVAL	EQU	B'10000000'
	INTCONVAL	EQU	B'00000000'
	CMCONVAL	 EQU	B'00000111'
	DIRPORTA	 EQU	B'11110000'		; De RA7 à RA4 en entrées et de RA3 à RA0 en sorties
	DIRPORTB	 EQU	B'11111111'		; De RB7 à RB0 en entrées
Ici ce sont des constantes qui représentent le contenu que l’on souhaite placer dans différents registre pour activer ou désactiver certaines options du PIC. Elles sont là pour regrouper la configuration en haut du programme, avec l’habitude vous trouverez ça pratique aussi ^^

On ne va pas trop s’attarder sur les trois premiers, on en reparlera plus tard. On va juste dire que configuré comme ça, le PIC va désactiver presque tout ses périphériques internes.

Le bit 7 d’OPTIONVAL est à 1 pour désactiver la résistance de rappel que l’on utilise pas dans notre projet.

Les bits 2, 1 et 0 de CMCONVAL sont à 1 pour désactiver les broches dédiées au module comparateur et ainsi les utiliser en tant que entrées / sorties classiques.

Nous allons nous intéresser ici à DIRPORTA et DIRPORTB.

Rappelez-vous qu’on lit de gauche à droite et que le premier bit à gauche est le bit 7.

Ici on va mettre tous le monde en tant qu’entrées (je préfère mettre les broches non utilisées en tant qu’entrées) sauf les broches RA3, RA2, RA1 et RA0 qu’on va placer en tant que sorties pour nos LED.

Code : Tout sélectionner

	;*****************************************************************************
	; DEFINE                                    
	;*****************************************************************************

	#DEFINE	LED1	PORTA, 0		; RA0 Sortie LED
	#DEFINE	LED2	PORTA, 1		; RA1 Sortie LED
	#DEFINE	LED3	PORTA, 2		; RA2 Sortie LED
	#DEFINE	LED4	PORTA, 3		; RA3 Sortie LED
Ici se sont encore des lignes pour nous simplifier la vie. Il s’agit de donner un nom utilisable dans notre programme à une broche du PIC. Si en évoluant mon projet je me rends compte que je vais devoir changer la broche d’une LED, j’ai juste à modifier ici et le programme principal ne devrait pas en être affecté.

Code : Tout sélectionner

	;*****************************************************************************
	; MACRO                                          
	;*****************************************************************************

BANK0 macro							; Passer en banque0
	bcf		STATUS,RP0
	bcf		STATUS,RP1
	endm

BANK1 macro							; Passer en banque1
	bsf		STATUS,RP0
	bcf		STATUS,RP1
	endm

BANK2 macro							; Passer en banque2
	bcf		STATUS,RP0
	bsf		STATUS,RP1
	endm

BANK3 macro							; Passer en banque3
	bsf		STATUS,RP0
	bsf		STATUS,RP1
	endm
Ici nous retrouvons nos macros qui vont nous éviter de manipuler le bit RP0 et RP1 du registre STATUS à chaque fois que l’on souhaite changer de banque. Il suffira par exemple d’utiliser le nom de la macro « BANK1 » pour passer RP à 1 et RP1 à 0.

Code : Tout sélectionner

	;*****************************************************************************
	; DEMARRAGE SUR RESET                                
	;*****************************************************************************

	org 	 0x000 					; Adresse de départ après reset
	goto    init				     ; Initialiser

Ici c’est une ligne système. A chaque reset, le PIC va aller exécuter l’instruction qui se trouve à l’adresse 0x000 de la mémoire programme. Juste après on va faire un saut, dans notre projet ça peut paraître étrange mais il y a une raison. En effet, l’adresse 0x004 est réservée pour les interruptions qu’on va étudier plus tard.

Code : Tout sélectionner

	; ////////////////////////////////////////////////////////////////////////////

	;                           P R O G R A M M E

	; ////////////////////////////////////////////////////////////////////////////

	;*****************************************************************************
	; INITIALISATIONS                                   
	;*****************************************************************************

Init
Le code qui va se trouver en dessous de l’étiquette « init » va être exécuté une seule fois au démarrage et à chaque reset.

Code : Tout sélectionner

	; Initialisation PORTS (banque 0 et 1)
	; ------------------------------------
	BANK0							  ; Passer en banque 0
	clrf	 PORTA					; Si le PORTA a des sorties, on les met au niveau 0 Volt
	clrf	 PORTB					; Si le PORTB a des sorties, on les met au niveau 0 Volt
	BANK1							  ; Passer en banque 1
	movlw	DIRPORTA				; Charge notre configuration du PORTA dans W
	movwf	TRISA					; Place le contenu de W dans le registre TRISA 
	movlw	DIRPORTB				; Charge notre configuration du PORTB dans W
	movwf	TRISB					; Place le contenu de W dans le registre TRISA
Ici on va appliquer notre configuration du début de programme au registre qui concernent PORTA et PORTB.

Le registre TRISA permet de configurer les broches RA7 à RA0 en tant que entrées ou sorties.
Le registre PORTA représente l’état des broches de RA7 à RA0.

Par sécurité, on va commencer par passer au niveau 0 volts toutes les broches qui sont peut être configurées en sorties. (On en sais encore rien ici).

On va commencer par s’assurer qu’on est bien en banque 0 grâce à notre macro « BANK0 »

Clrf permet de placer à 0 tous les bits d’un registre, donc on va placer le registre PORTA ainsi que le PORTB à 0.
On va ensuite passer en banque 1 pour configurer TRISA et TRISB.
(Voir le schéma sur l’organisation de la mémoire)

Pour plus d’informations sur le registre W, je vous laisse consulter le cours de Mr Bigonoff, on va gagner du temps ^^ Il faut juste savoir que c’est un registre qui nous permet de manipuler une donnée sur 8 bits.

On va donc placer notre configuration DIRPORTA dans le registre W grâce à l’instruction movlw.
On va ensuite initialiser le registre TRISA avec le contenu du registre W grâce à l’instruction movwf.

Même opération pour TRISB et PORTB.

Arrivé à cet endroits du programme, les broches RA7 à RA4 sont configurées en tant que entrées, les broches RA3 à RA0 sont configurées en tant que sorties et leur niveau actuel est 0 volt donc les LED sont éteintes.

Code : Tout sélectionner

	; Registre d'options (banque 1)
	; -----------------------------
	movlw	OPTIONVAL				; Charger notre masque de configuration dans W
	movwf	OPTION_REG			  ; Initialiser le registre OPTION

	; Registres interruptions (banque 1 et 0)
	; --------------------------------------
	movlw	INTCONVAL				; Charger notre masque contrôle interruptions standard dans W
	movwf	INTCON					; Initialiser le registre INTCON
	BANK0							   ; Passer en banque 0
	movlw	CMCONVAL				 ; Charger notre masque comparateurs dans W
	movwf	CMCON					 ; Initialiser le registre CMCON

Un peu pareil que pour PORTA et PORTB, ici il s’agit d’appliquer la configuration qu’on a définit au début du programme dans les registres qui vont bien. On profite d’être toujours en banque 1 après avoir configuré les directions des ports pour initialiser le registre OPTION_REG ainsi que le registre INTCON.

On retourne ensuite en banque 0 grâce à notre macro « BANK0 ».

On initialise le registre CMCON (principalement pour utiliser RA0 RA1 RA2 RA3 en tant que entrées ou sorties.

Code : Tout sélectionner

	bsf   LED1						; Allumer la LED sur RA0
	bsf   LED2						; Allumer la LED sur RA1
	bsf   LED3						; Allumer la LED sur RA2
	bsf   LED4						; Allumer la LED sur RA3

	goto  start					  ; Programme principal
Ici on va passer le bit correspondant à une de nos LED à l’état 1.
L’instruction Bsf NOM_DU_REGISTRE, NOM_DU_BIT nous permet de placer un bit précis à 1.
On peut par exemple utiliser bsf PORTA, 0 pour placer un niveau 5 volt sur la broche RA0.

En début de programme on a cette ligne :
#DEFINE LED1 PORTA, 0 ; RA0 Sortie LED

Ici on peut remplacer NOM_DU_REGISTRE, NOM_DU_BIT par notre « define » ce qui revient à utiliser :

bsf LED1 ; Allumer la LED sur RA0

Donc après avoir exécuté ce code, nos quatre LED doivent s’allumer.

Code : Tout sélectionner

	;*****************************************************************************
	; PROGRAMME PRINCIPAL                                  
	;*****************************************************************************

start
	goto  start					  ; Programme principal

END
Ici on arrive dans la boucle du programme principal. Il s’agit d’une boucle infinie qui permet de maintenir le PIC en état « d’alerte ».
END est la directive de fin de programme, tous ce qui suit cette instruction est ignoré par le compilateur.
Vous ne pouvez pas consulter les pièces jointes insérées à ce message.
Dernière modification par Super Koala le 27 janv. 2011, 23:46, modifié 37 fois.

Super Koala

Re: Introduction à la domotique : Les microcontrôleurs PIC

#10 Message non lu par Super Koala »

Utiliser le Timer 0 pour faire clignoter une LED

Cet exemple donne une première approche des temporisations et de l'utilité du pré-diviseur.

Schéma

On va utiliser le même schéma que pour le projet "Allumer des LED".

Projet
16f628_TMR0_sans_interruption.rar
Explications complémentaires

Le Timer 0 est un compteur sur 8 bits. On a vu que avec un oscillateur interne de 4Mhz on obtient un cycle d’horloge d’1µs.

Le registre TMR0 va donc s’incrémenter tous les cycles d’horloge. Au moment où il arrive à 255 (la valeur maximal sur 8 bits), il va placer le flag T0IF du registre INTCON à 1.

En surveillant ce flag, on peut donc obtenir des temporisations de 256µs avec un oscillateur de 4Mhz.

Si on fait clignoter une LED avec une temporisation de 256µs, on va avoir l’impression que la LED reste allumée alors qu’en fait elle clignote.

Il faut donc augmenter la temporisation pour observer le clignotement.

La solution la plus simple pour augmenter la temporisation est d’utiliser le pré-diviseur du timer0, il permet d’incrémenter TMR0 tous les X cycles d’horloge.

Code : Tout sélectionner

	;*****************************************************************************
	; ASSIGNATIONS SYSTEME                    
	;*****************************************************************************

	OPTIONVAL	EQU	B'10000111'
	INTCONVAL	EQU	B'00000000'
	CMCONVAL	 EQU	B'00000111'
	DIRPORTA	 EQU	B'11110000'		; De RA7 à RA4 en entrées et de RA3 à RA0 en sorties
	DIRPORTB	 EQU	B'11111111'		; De RB7 à RB0 en entrées
Le Timer 0 partage le pré-diviseur avec le Watchdog que l’on n’utilise pas ici. Si on ne souhaite pas utiliser le pré diviseur sur le Timer 0 et ainsi obtenir une temporisation de 256µs, il faut appliquer le pré-diviseur sur le watchdog grâce au bit PSA du registre OPTION_REG.

Ici on place le bit PSA à 0 donc on souhaite appliquer le pré-diviseur sur le Timer 0, la valeur du pré-diviseur est déterminée par les bits b2, b1 et b0 du registre OPTION_REG.

Dans notre exemple les bits b2, b1 et b0 sont tous à 1 donc on souhaite utiliser un pré-diviseur 1/256.

On obtient donc une incrémentation de TMR0 tout les (Pré-diviseur * 256µs) soit (256 * 256) = 65536µs.

Ensuite, on passe à la fin du programme car le reste est identique au projet « Allumer des LED ».

Code : Tout sélectionner

	;*****************************************************************************
	; PROGRAMME PRINCIPAL                                 
	;*****************************************************************************

start
	clrf 	TMR0 						    ; Effacer TMR0, début du comptage dans 2 cycles
	bcf 	 INTCON ,T0IF 				  ; Effacer le flag T0IF

loop
	btfss   INTCON ,T0IF 			     ; Si T0IF = 1, on saute la prochaine instruction
	goto 	loop					        ; T0IF = 0, on boucle sur l'étiquette "loop"
	btfss	LED1					        ; Si la LED1 (PORTA, 0) est à l'état 1 on saute la prochaine instruction
	goto	 allumer_led1			      ; Si la LED1 est à l'état 0, on saute à l'étiquette pour allumer LED1
	bcf	  LED1					        ; Si on arrive ici, on éteind LED1
	goto 	start					       ; Boucle vers le début du programme principal

allumer_led1						        ; Etiquette
	bsf	  LED1					        ; Passer LED1 à l'état haut
	goto	 start					       ; Boucle vers le début du programme principal

END
Ici il faut commencer par remettre à zéro le compteur TMR0 grâce à l'instruction clrf puis on doit placer le flag T0IF du registre INTCON à zéro grâce à bcf.

Si on regarde dans le jeu d'instructions du 16f628A, on voit que btfss veut dire Bit Test File, Skip if Set.
Associé avec une étiquette et un goto, on obtient une boucle : tant que T0IF n'est pas égal à 1 on boucle.

Une fois la temporisation de 65536µs écoulée, on va vérifier si la sortie RA0 est à 1. Si RA0 = 0 on va exécuter le goto allumer_led1, si RA0 = 1, on va sauter le goto pour aller exécuter le lot d'instructions suivantes.

Dans cet exemple on a pas besoin d'une grande précision, si c'était le cas il faudrait prendre en compte les 2 cycles d'instruction pour les sauts et un cycle par instruction pour allumer ou éteindre la LED, le tout multiplié par le pré-diviseur.
Vous ne pouvez pas consulter les pièces jointes insérées à ce message.
Dernière modification par Super Koala le 27 janv. 2011, 23:47, modifié 17 fois.

Super Koala

Re: Introduction à la domotique : Les microcontrôleurs PIC

#11 Message non lu par Super Koala »

Utiliser le Timer 1 pour faire clignoter une LED

Ici on va étudier une des particularités du Timer 1 pour faire clignoter une LED à une fréquence d'environ 0.5 Hz.

Schéma

On va utiliser le même schéma que pour le projet "Allumer des LED".

Projet
16f628_TMR1_sans_interruption.rar
Explications complémentaires

Ici on va utiliser le Timer 1 en mode timer sans interruptions.

On a vu plus haut que le Timer 1 est un compteur sur 16 bits donc sur deux registres. Le registre qui contient la valeur de poids faible est TMR1L et celui qui contient la valeur de poids fort est TMR1H.

La valeur maximum qu'on peut obtenir est (TMR1H * TMR1L) - 1 soit (256 * 256) - 1 soit 65535.

Avec un quartz de 4Mhz et le pré-diviseur interne on obtient une incrémentation du Timer 1 toutes les µs donc le Timer 1 va déborder tous les 65535µs.

Le Timer 1 dispose aussi d'un pré-diviseur qui se configure avec les bits T1CKPS1 et T1CKPS0 du registre T1CON.

Code : Tout sélectionner

	; REGISTRE T1CON (Timer 1)
	; ------------------------
	T1CONVAL	EQU B'00110001'

	; b7 : XXX						 Inutilisé
	; b6 : XXX						 Inutilisé
	; b5 : T1CKPS1					Pré-diviseur
	; b4 : T1CKPS0					Pré-diviseur
	;								    T1CKPS1 = 0 & T1CKPS0 = 0 : pré-diviseur = 1
	;								    T1CKPS1 = 0 & T1CKPS0 = 1 : pré-diviseur = 2
	;								    T1CKPS1 = 1 & T1CKPS0 = 0 : pré-diviseur = 4
	;								    T1CKPS1 = 1 & T1CKPS0 = 1 : pré-diviseur = 8
	; b3 : T1OSCEN					Met en service l'oscillateur interne
	; b2 : T1SYNC					 Mode synchrone ou asynchrone pour le mode compteur
	; b1 : TMR1CS					 0 = Mode Timer, 1 = Mode compteur
	; b0 : TMR1ON					 1 = Marche Tmr1, 0 = Arrêt Tmr1
Dans notre exemple, les bits T1CKPS1 et T1CKPS0 sont à 1 donc on utilise un pré-diviseur de 8.

Notre calcul devient donc Pré-diviseur * ((TMR1H * TMR1L) - 1) soit 8 * ((256 * 256) -1) soit 524288.

Code : Tout sélectionner

	; Initialisation Tmr1 (banque 0)
	; ------------------------------
	movlw	T1CONVAL				; Charger notre masque Timer 1 dans W
	movwf	T1CON					; Initialiser le registre T1CON
Ici on va placer notre masque définit en haut de programme dans W puis initialiser le registre T1CON avec le contenu de W.

A cet instant on indique au PIC que l'on souhaite utiliser un pré-diviseur de 8 (T1CKPS1 = 1 et T1CKPS0 = 1) mais aussi qu'on souhaite démarrer le Timer 1 (TMR1ON = 1).

Code : Tout sélectionner

	;*****************************************************************************
	; PROGRAMME PRINCIPAL                                 
	;*****************************************************************************

start
	clrf 	TMR1L 				  ; Effacer Timer 1, 8 lsb												
	clrf 	TMR1H 				  ; Effacer Timer 1, 8 msb
	bcf 	 PIR1 ,TMR1IF 		 ; Effacer le flag TMR1IF

loop
	btfss   PIR1 ,TMR1IF 		 ; Si TMR1IF = 1, on saute la prochaine instruction
	goto 	loop					 ; TMR1IF = 0, on boucle sur l'étiquette "loop"
	btfss	LED1					 ; Si la LED1 (PORTA, 0) est à l'état 1 on saute la prochaine instruction
	goto	 allumer_led1		  ; Si la LED1 est à l'état 0, on saute à l'étiquette pour allumer LED1
	bcf	  LED1					 ; Si on arrive ici, on éteind LED1
	goto 	start					; Boucle vers le début du programme principal

allumer_led1						 ; Étiquette
	bsf	  LED1					 ; Passer LED1 à l'état haut
	goto	 start					; Boucle vers le début du programme principal

END 
Ici c'est le même principe que pour le Timer 0.

On commence par remettre à zéro le registre de poids faible TMR1L puis celui de poids fort TMR1H.

On place le flag TMR1IF du registre PIR1 à zéro.

On crée ensuite une boucle "tant que TMR1IF = 0 boucle".

Une fois que le Timer 1 va déborder (quand il arrive à sa valeur maximum, ici 524 288), le flag TMR1IF va passer à 1.

On sort donc de la boucle et on inverse l'état de la LED avec le PORTA.

Ici la LED va clignoter avec un intervalle de 524 288µs soit environ 0.5 seconde.
Vous ne pouvez pas consulter les pièces jointes insérées à ce message.
Dernière modification par Super Koala le 27 janv. 2011, 23:47, modifié 26 fois.

Super Koala

Re: Introduction à la domotique : Les microcontrôleurs PIC

#12 Message non lu par Super Koala »

Utiliser Timer 1 et une variable

Ici le but est d'utiliser une variable accessible à partir de toutes les banques de manière à réaliser un clignotement approchant la minute.

Schéma

On va utiliser le même schéma que pour le projet "Allumer des LED".

Projet
16f628_TMR1_avec_une_variable.rar
Explications complémentaires

Ici on déclare un variable du nom de compteur_1 sur un octet.

Code : Tout sélectionner

	;*****************************************************************************
	; VARIABLES ZONE COMMUNE                                
	;*****************************************************************************

	; Zone de 16 bytes
	; ----------------
	CBLOCK 0x70						; Début de la zone (0x70 à 0x7F)
	compteur_1 : 1					; Compteur 1 pour obtenir un interval plus long avec le Timer 1
	ENDC
L'objectif ici est de créer une temporisation se rapprochant de la minute. On a vu plus haut que le Timer 1 déborde au bout de 524 288 µs avec un oscillateur de 4Mhz et un pré-diviseur de 8 sur le Timer1.

60 000 000 / 524 288 = 114.44

Il faut donc compter 114 débordements de Timer 1 dans notre configuration pour obtenir une temporisation qui se rapproche de la minute.

En réalité, notre LED va clignoter avec un intervalle de 59 768 832 µs. Pour être plus précis, il faut prendre en compte les cycles d'horloge consommées par nos goto, reset de compteurs ou encore allumer ou éteindre la LED puis boucler X fois pour retomber sur nos 60 000 000 µs.

Code : Tout sélectionner

start
	movlw	D'114'					; Placer 114 dans W
	movwf	compteur_1			  ; Initialiser compteur1 avec le contenu de W

timer
	clrf 	TMR1L 					; Effacer Timer 1, 8 lsb												
	clrf 	TMR1H 					; Effacer Timer 1, 8 msb
	bcf 	 PIR1, TMR1IF 		  ; Effacer le flag TMR1IF

loop
	btfss   PIR1, TMR1IF 		  ; Si TMR1IF = 1, on saute la prochaine instruction
	goto 	loop					  ; TMR1IF = 0, on boucle sur l'étiquette "loop"
	
	decfsz  compteur_1, f		  ; Décrémente compteur1, saute la prochaine instruction si compteur1 = 0
	goto 	timer					 ; Si compteur1 != 0 on relance le timer 1

	btfss	LED1					  ; Si la LED1 (PORTA, 0) est à l'état 1 on saute la prochaine instruction
	goto	 allumer_led1			; Si la LED1 est à l'état 0, on saute à l'étiquette pour allumer LED1
	bcf     LED1					  ; Si on arrive ici, on éteind LED1
	goto 	start					 ; Boucle vers le début du programme principal

allumer_led1						  ; Etiquette
	bsf     LED1					  ; Passer LED1 à l'état haut
	goto	 start					 ; Boucle vers le début du programme principal

END 
Donc on commence par placer le nombre 114 décimal dans le registre W puis on place le contenu de W dans compteur_1.

La suite est identique au projet ci-dessus, on reset les registres de Timer1, on reset le flag puis on lance une boucle.

Une fois que Timer 1 déborde, il place le flag à 1 ce qui va nous faire sortie de la boucle.

On va décrémenter notre variable compteur_1 (lui enlever 1).

Si notre variable n'est pas égal à zéro, on exécute le goto timer qui va reset le Timer 1 et continuer à décrémenter notre variable.

Si notre variable est égal à zéro, on aura donc obtenu 114 débordements de Timer 1 et on va sauter l'instruction goto timer pour aller inverser l'état de la LED.

Une fois l'état de la LED inversé, on va retourner au moment de placer 114 dans notre variable pour recommencer l'opération grâce à l'instruction goto start.
Vous ne pouvez pas consulter les pièces jointes insérées à ce message.
Dernière modification par Super Koala le 27 janv. 2011, 23:48, modifié 26 fois.

Super Koala

Re: Introduction à la domotique : Les microcontrôleurs PIC

#13 Message non lu par Super Koala »

Minuterie à enclenchement retardé

On va réaliser une minuterie à enclenchement retardé pour par exemple protéger une HPS des coupures de courant.

On va utiliser les interruptions du Timer 1 donc du coup j'en profite pour faire clignoter une LED avec Timer 0 pour indiquer que la minuterie est en marche.

Donc quand on alimente le montage, LED2 (qui représente la sortie HPS) doit s'allumer au bout de 3 minutes (réglable de 1 à 255 mn). Tant que LED2 est éteinte, LED1 clignote et dès que LED2 s'allume, LED1 va s'éteindre.

Schéma

On va utiliser le même schéma que pour le projet "Allumer des LED".

Projet
16f628_Exemple_minuterie_enclenchement_retarde.rar
Explications complémentaires

Code : Tout sélectionner

	; REGISTRE OPTION_REG (configuration)
	; -----------------------------------
	OPTIONVAL	EQU	B'10000111'

	; b7 : RBPU     			1 = Résistance de rappel +5V hors service
	; b6 : INTEDG   			1 = Interrupt sur flanc montant de RB0, 0 = Interrupt sur flanc descend de RB0
	; b5 : TOCS     			1 = Source clock = transition sur RA4, 0 = Horloge interne              
	; b4 : TOSE      		  1 = Sélection flanc montant RA4(si B5=1), 0 = Sélection flanc descendant RA4
	; b3 : PSA       		  1 = Assignation prédiviseur sur Watchdog, 0 = Assignation prédiviseur sur Tmr0
	; b2/b0 : PS2/PS0    	 Valeur du prédiviseur :
	; 							  000 =  1/1 (watchdog) ou 1/2 (tmr0)
	;								001 =  1/2               1/4
	; 							  010 =  1/4		     	 1/8
	; 							  011 =  1/8		     	 1/16
	;								100 =  1/16		     	1/32
	;								101 =  1/32		     	1/64
	;								110 =  1/64		     	1/128
	; 							  111 =  1/128	     	  1/256
On place RBPU à 1 uniquement parce qu'on utilise pas la résistance de rappel.

Ici on va s'intéresser à PSA et de PS2 à PS0 (pré-diviseur).

Donc PSA à 0 pour appliquer le pré-diviseur sur le Timer 0, Ps2 à PS0 à 1 pour indiquer que l'on souhaite utiliser un pré-diviseur de 256.

Rappelez vous que le Timer 0 est un compteur sur 8 bits donc avec un oscillateur de 4 Mhz et un pré-diviseur de 256 on obtient un débordement de Timer 0 tout les (Pré-diviseur * 256) - 1 = 65 535µs.

Code : Tout sélectionner

	; REGISTRE INTCON (contrôle interruptions standard)
	; -------------------------------------------------
	INTCONVAL	EQU	B'01000000'

	; b7 : GIE       			Masque autorisation générale interrupt, ne pas mettre ce bit à 1 ici
	; b6 : PEIE      			Masque autorisation générale périphériques
	; b5 : T0IE      			Masque interruption tmr0
	; b4 : INTE      			Masque interuption RB0/Int
	; b3 : RBIE      			Masque interruption RB4/RB7
	; b2 : T0IF      			Flag tmr0
	; b1 : INTF      			Flag RB0/Int
	; b0 : RBIF      			Flag interruption RB4/RB7
Ici on va placer PEIE à 1 pour autoriser les interruptions périphériques.
On placera le bit GIE à 1 à la fin de l'initialisation du PIC.

Code : Tout sélectionner

	; REGISTRE PIE1 (contrôle interruptions périphériques)
	; ----------------------------------------------------
	PIE1VAL		EQU	B'00000001'

	; b7 : EEIE				   Masque interrupt écriture EEPROM
	; b6 : CMIE				   Masque interrupt comparateur
	; b5 : RCIE				   Masque interrupt réception USART
	; b4 : TXIE				   Masque interrupt transmission USART
	; b3 : XXX				    Réservé, laisser à 0
	; b2 : CCP1IE			    Masque interrupt CCP1
	; b1 : TMR2IE			    Masque interrupt TMR2 = PR2
	; b0 : TMR1IE			    Masque interrupt débordement TMR1
Ici on place TMR1IE à 1 pour autoriser les interruptions du Timer 1.

Code : Tout sélectionner

	; REGISTRE T1CON (Timer 1)
	; ------------------------
	T1CONVAL	EQU B'00100000'

	; b7 : XXX					 Inutilisé
	; b6 : XXX					 Inutilisé
	; b5/b4 : T1CKPS1/T1CKPS0 Valeur du pré-diviseur
	;										00 = 1/1
	;										01 = 1/2
	;										10 = 1/4
	;										11 = 1/8
	; b3 : T1OSCEN				Met en service l'oscillateur interne
	; b2 : T1SYNC				 Mode synchrone ou asynchrone pour le mode compteur
	; b1 : TMR1CS				 0 = Mode Timer, 1 = Mode compteur
	; b0 : TMR1ON				 1 = Marche Tmr1, 0 = Arrêt Tmr1
Ici on va vérifier que TMR1CS est à 0 pour utiliser le Timer 1 en mode Timer.

On va placer TMR1ON à 1 pour activer le Timer 1 à la fin de l'initialisation du PIC.

Maintenant on va regarder le pré-diviseur utilisé, ici on à T1CKPS1 à 1 et T1CKPS0 à 0 donc on utilise un pré-diviseur de 4.

Le but ici est d'obtenir un évènement toutes les minutes.

Si on utilise un pré-diviseur de 8 pour obtenir le temps maximum avant débordement de Timer 1 :

(Pré-diviseur * 65535) soit 8 * 65535 = 524 280µs
(1 mn / 524 280) soit 60 000 000 / 524 280 = 114,44

Il faudra donc compter 114 débordements de Timer 1 pour approcher la minute avec une erreur de :

60 000 000 - (114 * 524 280) = 232 080µs de moins que prévu.

Si on utilise un pré-diviseur de 4 :

(Pré-diviseur * 65535) soit 4 * 65535 = 262 140µs
(1 mn / 262 140) soit 60 000 000 / 262 140 = 228.88 soit environ 229.

Il faudra donc compter 229 débordements de Timer 1 pour approcher la minute avec une erreur de :

229 * 262 140 = 60 030 060 soit 30 060µs de trop.

Je préfère avoir un peu trop, ce qui explique pourquoi j'ai utilisé un pré-diviseur de 4, puis pour notre montage on est pas à 30 millisecondes près / minute ^^

Code : Tout sélectionner

	; MINUTERIE LED2 (en minute)
	; --------------------------
	M1VAL		EQU D'3'			; Nombre de minutes pour Minuterie 1
On règle le nombre de minutes pour la protection HPS de 1 à 255.

Code : Tout sélectionner

;*****************************************************************************
; VARIABLES ZONE COMMUNE                         
;*****************************************************************************

	; Zone de 16 bytes
	; ----------------
	CBLOCK 0x70					  ; Début de la zone (0x70 à 0x7F)
	w_backup : 1					 ; Sauvegarde registre W
	status_backup : 1			  ; Sauvegarde registre STATUS
	compteur_tmr1 : 1			  ; Compteur pour Timer 1
	compteur_m1 : 1				 ; Nombre de minutes pour LED2
	ENDC
On va déclarer nos variables dans la zone accessible à partir des quatre banques.

w_backup va contenir une copie du registre W lors d'une interruption.
status_backup va contenir une copie de registre STATUS lors d'une interruption.
compteur_tmr1 est une variable pour toutes nos minuteries pour obtenir 229 débordements de Timer 1
compteur_m1 contient le nombre de minutes restantes avant d'allumer notre HPS.

Code : Tout sélectionner

;*****************************************************************************
; ROUTINE INTERRUPTION                                  
;*****************************************************************************

	; Sauvegarder registres	
	;----------------------
	org 0x004						; Adresse d'interruption
Alors ici c'est plus compliqué à comprendre, je ne saurai mieux expliquer que Mr Bigonoff donc je vous invite à lire son cours ^^

Pour faire simple, une interruption est un évènement extérieur qui permet de sortir temporairement de la boucle du programme principal pour aller exécuter un bout de code par exemple lors d'un appuis sur un bouton etc...

C'est pour cette raison que l'on va sauvegarder le registre W ainsi que le registre STATUS car à la fin de l'interruption, on retourne à l'endroit ou l'on était dans la boucle principale, on va donc restaurer ces deux registres pour ne pas perturber la suite du programme après interruption.

Il existe plusieurs interruptions qui commencent toutes à l'adresse 0x004, ici on va utiliser l'interruption du Timer 1 qui se produit à tous les débordements (262 140µs dans notre cas)

je vais pas me perdre dans les explications pour les interruptions car c'est pas très parlant quand il n'y en a qu'une (ici Timer 1) donc on va dire que la suite du code permet de :

- Sauvegarder le registre W et le registre STATUS dans des variables.
- Tester si les interruptions sont autorisées
- Tester si l'interruption Timer 1 est autorisée et est en cours
- Exécuter notre routine Timer 1
- Restaurer les registres W et STATUS

On détaillera un peu plus quand on va utiliser deux interruptions en même temps.

On va donc s'intéresser à la routine qui va être exécutée quand il y a une interruption Timer 1.

Code : Tout sélectionner

;*****************************************************************************
; INTERRUPTION TIMER 1                                   
;*****************************************************************************
int_tmr1
	decfsz compteur_tmr1, f	 ; Décrémente compteur_tmr1, saute la prochaine instruction si est égal à 0
	goto	end_int_tmr1		  ; Si compteur_tmr1 n'est pas egal à 0, on met fin à l'interruption
	
	movlw  D'229'			     ; Place 229 dans le registre W
	movwf  compteur_tmr1	    ; Place le contenu de W dans notre variable

	decfsz compteur_m1, f		; Décrémente compteur_m1, saute la prochaine instruction si égal à 0
	goto	end_int_tmr1		  ; Si compteur_tmr1 n'est pas egal à 0, on met fin à l'interruption

	bsf	 LED2				    ; Allume la LED 2
	bcf 	T1CON, TMR1ON		 ; Désactive le Timer 1		
end_int_tmr1
	return
Ici compteur_tmr1 = 229, cette variable sera initialisée plus bas dans le code.

On va commencer par décrémenter notre variable compteur_tmr1 (lui enlever 1).

Si compteur_tmr1 n'est pas égal à 0, on saute vers la fin d'interruption, quand elle sera égal à 0, on aura donc compté 229 débordements de 262 140µs.

On va donc réinitialiser la variable compteur_tmr1 à 229, puis on va décrémenter la variable compteur_m1 (qui contient le nombre de minutes avant d'allumer la HPS).

Si compteur_m1 n'est pas égal à 0, on saute vers la fin d'interruption.

Si compteur_m1 est égal à 0, on aura donc compté 3 x (229 x 262 140) soit 180 090 180µs soit 3 minutes et 90 millisecondes.

On va donc allumer la LED et stopper le Timer 1.

Code : Tout sélectionner

; Initialiser nos variables (banque 0)
	; ------------------------------------
	movlw	D'229'				 ; Place 229 dans le registre W
	movwf	compteur_tmr1		; Place le contenu de W dans notre variable
	movlw	M1VAL				  ; Place le nombre de minutes de la minuterie LED2 dans W
	movwf	compteur_m1		  ; Place le contenu de W dans notre variable	

	; Autoriser interruptions (banque 0)
	; ----------------------------------
	clrf	 PIR1				   ; Effacer flags 1
	bsf	  INTCON,GIE			; Valider interruptions

	goto	 start				  ; Programme principal
Dans l'initialisation on va placer 229 dans le registre W puis envoyer le contenu de W dans notre variable compteur_tmr1.

On va ensuite placer le nombre de minutes définit en haut de programme dans W puis envoyer le contenu de W dans notre variable compteur_m1.

Il reste plus qu'à autoriser les interruptions ^^
Vous ne pouvez pas consulter les pièces jointes insérées à ce message.
Dernière modification par Super Koala le 28 janv. 2011, 00:09, modifié 49 fois.

Super Koala

Re: Introduction à la domotique : Les microcontrôleurs PIC

#14 Message non lu par Super Koala »

17. Minuterie classique

Super Koala

Re: Introduction à la domotique : Les microcontrôleurs PIC

#15 Message non lu par Super Koala »

18. Minuterie à enclenchement retardé

Verrouillé