Comment démarrer avec un PIC16F84
Un livre de Wikibooks.
| Programmation Assembleur | |
| Retour au livre Programmation |
|
Un livre appartenant à la série Programmation du Département informatique |
Sections |
[modifier] Introduction
Le but de ce petit manuel est d’arriver simplement à prendre un microprocesseur en main, ici un microcontroleur PIC16F84, en ayant un minimum d’informations utiles et quelques exemples concrets utilisables rapidement.
En un mot, réduire le temps de mise en route du premier projet lorsque l’on pratique déjà un autre type de processeur.
En effet, il n’est pas rare de devoir lire, relire et feuilleter des kilos de documentation pour trouver une information aussi simple que la description d’un registre ou la fonction d’un bit de ce registre. Pour plus de détail, il faudra se reporter à la documentation constructeur.
[modifier] Architecture, Horloge, Mémoire de Données et de Programme
[modifier] Architecture interne du PIC 16F84:
Les Mémoire Données et Mémoire Programme ont deux bus internes séparés en architecture Harvard, ce qui permet ici à l’UC d’accéder à chaque bloc dans le même cycle d’horloge. Ce modèle d’architecture permet également de ne pas mélanger le code et par exemple les données utilisateur, ce qui ne simplifiera pas forcement la programmation, mais assure un degré d’intégrité des données supérieur au modèle Von Neumann (données et code cohabitant dans le même espace mémoire).
[modifier] Horloge:
Le cycle d’horloge interne est donné pour 1/4 de la fréquence nominale du quartz, soit:
Quartz de 4MHz => 4 MHz / 4 = 1 MHz interne => 1/1MHz = 1 µS de temps de cycle
Quartz de 10MHz => 10 MHz / 4 = 2,5 MHz interne => 1/2,5MHz = 400 nS de temps de cycle
Le PIC utilisé ici est un 16F84-04P, avec un quartz de 4MHz.
Le PIC ayant une structure interne de type RISC (Reduced Instruction Set Computer), la plupart des instructions s’exécutent en un seul cycle d’horloge. Chaque instruction va donc s’exécuter en un temps record. Par contre, le peu d’instructions disponibles engendrera quelquefois une programmation tortueuse demandant un grand nombre d’instructions simples, et donc aussi un temps de traitement rallongé.
Il faudra en tenir compte lors du choix du µC, sachant que son espace mémoire programme est limité à 1K.
[modifier] Mémoire de Données :
Les SFR (Registres internes à Fonctions Spéciales) sont répartis en deux banques: de 00h à 0Bh en Bank0 de 80h à 8Bh en Bank1.
Certains registres sont accessibles en Bank0, d’autres en Bank1 alors que d’autres sont communs aux deux banques (ils sont remappés). Il est donc nécessaire de changer de Bank avant d’accéder à un registre particulier, ce changement de Bank s’effectuant à l’aide des bits RP1:RP0 du registre STATUS.
La RAM GPR (RAM utilisateur d’usage Général ou encore General Purpose Registers) de 68 octets va de 0Ch à 4Fh, soient 68 octets disponibles pour les variables du programme.
Cette RAM est remappée en Bank0 et Bank1, il s’agit donc des mêmes emplacements mémoires qui sont accessibles par les deux Banks à deux adresses différentes. Ceci permet d’éviter d’avoir à changer de bank avant d’accéder à une variable ou à une autre.
La mémoire EEPROM est indirectement mappée dans la zone de données et est donc accessible par un pointeur d’adresse indirect. Ces 64 octets d’ EEPROM se situe de 00h à 3Fh.
La pile est un stack hard à 8 niveaux, sans contrôle de débordement. Seuls huit niveaux de sous programmes sont donc utilisables, IT comprises.
[modifier] Mémoire de Programme :
La mémoire programme Flash contenant le programme a une capacité de 1K x 14 bits et se situe aux adresses 0000h à 03FFh.
[modifier] Vecteurs
Le Reset se situe à l’adresse 0000h,
L’ Interrupt se situe à l’adresse 0004h.
Il ne s’agit pas à proprement parler de vecteurs.
En effet, le PIC va démarrer son programme à l’adresse 0000h, et non pas à l’adresse contenue en 0000h comme dans un micro avec reset vectorisé.
De ce fait, l’instruction qui sera placée à l’adresse 0000h sera très souvent un GOTO xxxxh mais peut être une instruction quelconque faisant partie du corps du programme si l’interruption n’est pas utilisée.
INCORPORER TABLE VECTEUR
[modifier] Registres internes
Les SFR (Registres internes à Fonction Spéciale) vont de 00h à 0Bh en Bank0 et de 80h à 8Ch en Bank1.
Bank 0
00h INDF Utilisé en adressage indirect avec FSR, il ne s’agit pas d’un registre physique 01h TMR0 Timer/Compteur 8 bits 02h PCL Poids faible du compteur programme (PC) 03h STATUS Registre d’état dont les bits sont : IRP RP1 RP0 TO PD Z DC C 04h FSR Pointeur d’adresse en adressage indirect. 05h PORTA Port d’Entrée/Sortie A dont les bits sont : x x x RA4/T0CKI RA3 RA2 RA1 RA0 06h PORTB Port d’Entrée/Sortie B dont les bits sont: RB7 RB6 RB5 RB4 RB3 RB2 RB1 RB0/INT 07h Pas utilisé 08h EEDATA Registre de données de l’ Eeprom 09h EEADR Registre d’adresses de l’ Eeprom 0Ah PCLATH 5 bits de poids fort du compteur programme 0Bh INTCON Registre des Interruptions dont les bits sont: GIE EEIE T0IE INTE RBIE T0IF INTF RBIF
Bank 1
80h INDF Utilisé en adressage indirect avec FSR, il ne s’agit pas d’un registre physique
81h OPTION_REG Registre d’options, bits : RBPU INTEDG T0CS T0SE PSA PS2 PS1 PS0
82h PCL Poids faible du compteur programme (PC)
83h STATUS Registre d’état dont les bits sont : IRP RP1 RP0 TO PD Z DC C
84h FSR Pointeur d’adresse en adressage indirect.
85h TRISA Registre de Direction du Port A
86h TRISB Registre de Direction du Port B
87h Pas utilisé
88h EECON1 Registre de Contrôle n°1 de l’ Eeprom : x x x EEIF WRERR WREN WR RD
89h EECON2 Registre de contrôle n°2 de l’ Eeprom (il ne s’agit pas d’un registre physique)
0Ah PCLATH 5 bits de poids fort du compteur programme
0Bh INTCON Registre des ITs dont les bits sont: GIE EEIE T0IE INTE RBIE T0IF INTF RBIF
Certains registres sont accessibles en Bank0 et également en Bank1 (ils sont remappés).
Le changement de Bank s’effectue à l’aide de RP1:RP0 du registre STATUS:
00 pour la sélection Bank0
01 pour la Bank1
(RP1 est utilisé pour la compatibilité avec d’autres PICS de la famille et restera à 0 sur le 16F84.)
[modifier] Détail des registres internes
[modifier] STATUS (Bank 0 en 03h et Bank 1 en 83h)
Voici les bits du registre STATUS qui reflètent le status de l’ALU du PIC, le status du reset et permet également de changer de Bank de registres.
b7: IRP non utilisé dans le 16F84
b6-5: RP1 RP0 Sélection de la bank de registres active
00: Bank0
01: Bank1
10: non utilisé sur le 16F84
11: non utilisé sur le 16F84
b4: TO\ Time Out du watch dog
1: après un démarrage, CLRWDT ou SLEEP.
0: après un time-out du watch dog
b3: PD\ Power down bit
1: après un démarrage ou après l’instruction CLRWDT
0: après l’exécution de l’instruction SLEEP
b2: Z bit Zero
1: Résultat de l’opération précédente nul
0: Résultat de l’opération non nul
b1: DC Digital carry / borrow\
1: Débordement du 4° bit du résultat de l’opération précédente
0: Pas de débordement
b0: C Carry / borrow\
1: Débordement bit du résultat de l’opération précédente
0: Pas de débordement
[modifier] OPTION_REG (Bank 1 en 81h)
Permet de configurer les résistances de rappel internes du PortB, et aussi l’INT externe, le Timer0 et le prescaler du Timer0 ou du watch-dog
b7: RBPU\ Résistances de rappel des entrées du PortB
1: Les résistances sont désactivées
0: Les résistances du PortB sont activées
b6: INTEDG Sélection du front actif de l’INT externe
1: Interruption sur le front montant de RB0/INT
0: Interruption sur le front descendant de RB0/INT
b5: TOCS Source de l’horloge du Timer0
1: Comptage sur la pin RA4/TOCKI
0: Comptage sur l’horloge interne CLKOUT
b4: TOCE Sélection du front actif pour le comptage sur RA4/TOCKI
1: Comptage sur front descendant
0: Comptage sur front montant
b3: PSA Assignation du Prescaler
1: Prescaler assigné au chien de garde WDT
0: Assigné au Timer TMR0
b2-b1-b0: PS2:PS1:PS0 Valeur du Prescaler du TMR0 ou du WDT
Valeurs du prescaler
PS2:PS1:PS0 Prescaler TMR0 Prescaler WDT
000 1/2 1/1
001 1/4 1/2
010 1/8 1/4
011 1/16 1/8
100 1/32 1/16
101 1/64 1/32
110 1/128 1/64
111 1/256 1/128
[modifier] INTCON (Bank 0 en 0Bh et Bank 1 en 8Bh)
Bits d’autorisation et Flags d’interruptions
b7: GIE Autorisation Globale des Interruptions
1: Autorise toutes les interruptions
0: Interdit toutes les interruptions
b6: EEIE Autorisation de l’interruption de fin d’écriture en Eeprom
1: Autorise l’interruption de fin d’écriture en Eeprom
0: Interdit l’interruption de fin d’écriture en Eeprom
b5: TOIE Autorisation de l’interruption de débordement de TMR0
1: Autorise l’interruption de TMR0
0: Interdit l’interruption de TMR0
b4: INTE Autorisation de l’interruption sur RB0/INT
1: Autorise l’interruption sur RB0/INT
0: Interdit l’interruption sur RB0/INT
b3: RBIE Autorisation de l’interruption lors d’un changement d’état sur le PortB
1: Autorise l’interruption sur RB7:RB4
0: Interdit l’interruption sur RB7:RB4
b2: TOIF Flag de débordement de TMR0
1: Le TMR0 a débordé (à effacer par programme)
0: Le TMR0 n’a pas débordé
b1: INTF Flag d’interruption sur RB0/INT
1: Il y a eu une demande d’interruption sur RB0/INT
0: Il n’y a pas d’interruption sur RB0/INT
b0: RBIF Flag d’interruption sur le PortB
1: Au moins une pin RB7:RB4 a changé d’état (doit être effacé par programme)
0: Il n’y a pas de changement d’état sur RB7:RB4
[modifier] Brochage
Le brochage du PIC 16F84A en boitier DIL est le suivant :
Liste des broches, classées par catégories:
OSC1/CLKIN (pin 16) Quartz ou entrée de l’horloge externe
OSC2/CLKOUT (pin 15) Quartz en mode cristal ou sortie d’horloge à 1/4 de la fréquence en mode RC
MCLR\ (pin 4) Master Clear (Reset) ou tension de programmation. (Reset actif à l’état bas).
Port A :
RA0 (pin 17) Port A I/O TTL
RA1 (pin 18) Port A I/O TTL
RA2 (pin 1) Port A I/O TTL
RA3 (pin 2) Port A I/O TTL
RA4/T0CKI (pin 3) Port A I/O Entrée Trigger, sortie Drain ouvert. Entrée de comptage TMR0
Port B : peut être programmé pour avoir des résistances de pull-up internes sur ses entrées.
RB0/INT (pin 6) Port B I/O TTL en I/O et Entrée d’Interruption avec Trigger
RB1 (pin 7) Port B I/O TTL
RB2 (pin 8) Port B I/O TTL
RB3 (pin 9) Port B I/O TTL
RB4 (pin 10) Port B I/O TTL avec Interruption sur changement d’état de l’entrée
RB5 (pin 11) Port B I/O TTL avec Interruption sur changement d’état de l’entrée
RB6 (pin 12) Port B I/O TTL avec Interruption sur changement d’état de l’entrée.
Serial programming clock avec entrée Trigger.
RB7 (pin 13) Port B I/O TTL avec Interruption sur changement d’état de l’entrée.
Serial programming data avec entrée Trigger.
VSS (pin 5) Masse
VDD (pin 14) Alimentation positive
[modifier] Schémas de base
Un système minimum peut être le suivant, avec simplement une alimentation 5Vdc, un quartz 4MHz de type AT (pas de quartz série), deux condensateurs 27pF céramique et un PIC 16F84 4MHz.
Dans ce cas, l’entrée de reset MCLR\ est connectée à l’alimentation positive +5V pour un reset de type POR (Power On Reset : reset à la mise sous tension) interne au PIC.
Ce circuit de reset est utilisable seulement dans le cas d’un oscillateur grande vitesse, et dans le cas d’une alimentation à excursion rapide (le niveau 5V doit être atteint rapidement, avec une pente raide). De plus, il ne permet pas un redémarrage du système à chaud (sans couper l’alimentation).
Pour obtenir un reset à chaud, il suffirait dans ce cas de connecter MCLR\ à un circuit RC (résistance de 22Ko et condensateur de 100nF) qui assurerait le POR, et permettrait d’effectuer le reset à chaud avec un bouton poussoir relié à la masse :
La résistance de 470 ohms est recommandée par Microchip pour limiter le courant de décharge du condensateur dans MCLR\.
Une diode de type 1N4148 peut être mise en parallèle sur la résistance de rappel de 22K afin de décharger le condensateur plus rapidement en cas de coupure d’alimentation.
Ceci permettra au PIC de redémarrer plus sûrement après une coupure d’alimentation brève.
[modifier] Les Ports d'entrées/sorties
[modifier] Le PORT A: RA0 … RA4
Le PORT A est un des deux Ports du PIC 16F84, et comprend 5 lignes Entrées/Sorties. Sa configuration et sa programmation passent par l’utilisation de deux registres qui sont PORTA et TRISA.
Le registre PORTA (Bank 0) est une copie des lignes RA0..RA4, tant en entrée qu’en sortie. En effet, lire le PORTA revient à lire l’état des pins alors qu’une écriture place le niveau correspondant sur les pins qui auront été configurées en sorties (dans une séquence interne au PIC de Read-modify-write).
Les lignes RA0 .. RA3 sont des entrées à niveaux compatibles TTL et des sorties CMOS standards. La ligne RA4 est une entrée à Trigger de Schmitt et une sortie à drain ouvert qui est multiplexée avec l’entrée de Timer TMR0.
Le registre TRISA (Bank 1) est le registre qui permettra de placer les pins indépendamment en entrée ou en sortie.
Mettre un bit de TRISA à 1 placera la pin correspondante en entrée (et le circuit de sortie correspondant en haute impédance).
Mettre un bit de TRISA à 0 placera la pin correspondante du PORTA en sortie.
Exemple de configuration du PORTA:
BSF STATUS, RP0 ; Acces Bank1
MOVLW 0xFB ; TRISA.b2 à 0 pour RA2 en sortie (% 1111.1011)
MOVWF TRISA
BCF STATUS, RP0 ; Acces Bank0
…
…
BCF STATUS, RP0 ; Acces Bank0
BSF PORTA, RA2 ; Allume la Led connectée à la ligne RA2
[modifier] Utilisation du PORT A: Allumage d’une Led
Un premier exemple d’utilisation du Port A est de faire clignoter une Led connectée à RA2 par l’intermédiaire d’une résistance de 1 Kohms.
-
-
- SCHEMA***
-
Exemple de code:
; Clignotement d'une Led sur RA2
;;;;;;; *** Configuration
LIST p=16F84A ; Processeur 16F84A
#INCLUDE <p16F84A.inc> ; Définition des registre internes du 16F84
__CONFIG _CP_OFF & _WDT_OFF & _HS_OSC ; Option de programmation
;;;;;;; *** Définitions
RA2 EQU 0x02 ; PortA, sortie RA2
;;;;;;; *** Variables
CBLOCK 0x0C
vTempo1, vTempo2;
ENDC
;;;;;;; *** Vecteurs
ORG H'0000' ; Déclaration du Reset
GOTO Start
; * Tempo de clignotement qui utilise deux variables pour obtenir une tempo longue
Tempo MOVLW 0xFF ; Charge W avec 0xFF
MOVWF vTempo2 ; pour charge la vTempo2
_Tempo2 MOVWF vTempo1 ; et la vTempo1
_Tempo1 DECFSZ vTempo1, f ; Décrémente vTempo et met le résultat dans vTempo
GOTO _Tempo1 ; puis saute l'instruction suivante si 0.
DECFSZ vTempo2, f
GOTO _Tempo2
RETURN
; * Programme principal
Start BSF STATUS, RP0 ; Acces Bank1
MOVLW 0xFB ; TRISA.b2 à 0 pour RA2 en sortie
MOVWF TRISA
BCF STATUS, RP0 ; Acces Bank0
BSF PORTA, RA2 ; Allume la Led
CALL Tempo
BCF PORTA, RA2 ; Eteint la Led
CALL Tempo
GOTO Start ; Reboucle au départ
END
La temporisation utilisée peut être améliorée de la sorte, afin d’obtenir des temps calibrés:
CBLOCK 0x0C
vWait1, vWait2, vWait3;
ENDC
; * Tempo 500µS 1+1+165*(1+2)+1+2=500µS
T_500us MOVLW 0xA5 ; 1 cy
MOVWF vWait1 ; 1 cy
_T1 DECFSZ vWait1, f ; 1 cy
GOTO _T1 ; 2 cy
NOP ; 1 cy
RETURN ; 2 cy
; * Tempo 100ms 1+1+198*(2+500µS+1+2)+6+2=100'000µS = 100 mS
T_100ms MOVLW 0xC6 ; 1 cy
MOVWF vWait2 ; 1 cy
_T2 CALL T_500us ; 2 cy + 500µS
DECFSZ vWait2, f ; 1 cy
GOTO _T2 ; 2 cy
NOP ;
NOP ;
NOP ;
NOP ;
NOP ;
NOP ; 6 cy
RETURN ; 2 cy
; * Tempo 1 S 1+1+10*(2+100'000µS+1+2)+2= 1,000054 secondes
T_1s MOVLW 0x0A ; 1 cy
MOVWF vWait3 ; 1 cy
_T3 CALL T_100ms ; 2 cy + 100mS
DECFSZ vWait3, f ; 1 cy
GOTO _T3 ; 2 cy
RETURN ; 2 cy
L’appel se fera donc par CALL T_1s pour une temporisation de 1 seconde.
[modifier] Déclarations et Définitions principales sous MPLAB
MPLAB est l'environnement de développement intégré Assembleur gratuit de Microchip.
Voici les principales déclarations les plus utiles:
[modifier] ORG
Défini l’adresse de l’instruction qui va suivre, utilisé pour le Reset et l’Interruption.
Le Reset se situe à l’adresse 0x0000 et se déclare de la façon suivante :
ORG 0x0000 ; Déclaration du Reset GOTO Start
Start MOVLW … … ; Programme principal
Si on utilise l’ Interruption, elle se déclarera de la façon suivante à la suite du Reset:
ORG 0x0000 ; Déclaration du Reset GOTO Start
ORG 0x0004 ; Déclaration de l’IT MOVLW 0x01 MOVWF var RETFIE
Start MOVLW … …. ; Programme principal
Si l’IT n’est pas utilisée, la place mémoire ainsi libérée par sa non utilisation au niveau du vecteur sera utilisée par le code du programme lui-même.
[modifier] INCLUDE
Permet à l’assembleur d’inclure le texte d’un autre fichier dans le fichier source en cours.
#include <p16F84A.inc >; définition du type de processeur
[modifier] EQU
Assignation de constante qui peut se déclarer de la façon suivante :
MaValeur EQU 0x05 ; La variable MaValeur vaut 0x05
Une variable peut également se déclarer de la façon suivante :
MaVariable EQU 0x0C ; MaVariable se trouve à l’adresse 0x0C MOVLW 0x12 ; W=0x12 MOVWF MaVariable ; W est stocké dans MaVariable
[modifier] CBLOCK …. ENDC :
On peut aussi déclarer des zones de plusieurs variables à l’aide de la directive CBLOCK …. ENDC
Ainsi,
CBLOCK 0x00C ; début du bloc des variables Mavariable : 1 ; 1 octet pour Mavariable Latempo : 2 ; 2 octet pour Latempo Truc, Muche ; 1 octet pour Truc et 1 octet pour Muche ENDC
défini plusieurs variables d’adresses consécutives: Mavariable à l’adresse 0x0C et La tempo à l’adresse 0x0D.
[modifier] CONFIG :
Permet de configurer les « fusibles » internes du PIC à activer par le programmateur.
__CONFIG _CP_OFF &_WDT_ON
Demande de ne pas positionner le fusible de protection en lecture et d’activer le WatchDog.
[modifier] Liste des bits du mot de Configuration:
_CP_ON ou_CP_OFF : Code Protection bit _PWRTE_ON ou_PWRTE_OFF : Power-up Timer enable _WDT_ON ou_WDT_OFF : Watch dog Timer enable _LP_OSC : Oscillateur LP (low power) _XT_OSC : Oscillateur XT (quartz) _HS_OSC : Oscillateur HighSpeed _RC_OSC : Oscillateur RC
[modifier] #DEFINE
Permet de définir une chaîne de substitution :
#define BitLED PORTA, 2
[modifier] LIST
Liste des directives à l’attention du pré-processeur.
LIST p=16F84A ; Le PIC utilisé est un 16F84A
[modifier] END
Défini la fin du programme.

