Vai al precedente POST della serie
La cosa più semplice che possiamo fare con un PIC è sicuramente quella di accendere un LED collegato ad un pin di una porta digitale.
Questo nel mondo dei microcontrollori corrisponde al classico HelloWorld dell'universo della programmazione.
Riservandoci più avanti di scrivere anche noi un vero e proprio "Hello World !!!" su un display LCD per il momento ci accontentiamo di pilotare un LED per parlare di una tra le più importanti risorse dei PIC: i TIMER.
Un PIC può disporre di uno o più TIMER e per questo vengono numerati. Ogni TIMER ha le sue peculiarità, illustrate nel datasheet, ma tutti svolgono lo stesso compito: incrementare un contatore di uno con una determinata frequenza.
Quando il contatore raggiunge il suo OVERFLOW, ciòè ricomincia da 0 in quanto ha superato il valore massimo rappresentabile, viene generato un particolare interrupt (l'esecuzione del programma salta al vettore di interrupt).
Noi possiamo quindi scegliere il TIMER che più ci aggrada e configurarlo in modo da stabilire:
- la frequenza di incremento
- il numero di incrementi prima di raggiungere l'OVERFLOW
- se controllare ciclicamente l'avvenuto OVERFLOW oppure abiilitare l'interrupt per far eseguire in automatico un particolare blocco di codice
Ora proviamo a far lampeggiare (to blink che diventa blinkare !) il nostro LED con una frequenza di un secondo utilizzando un TIMER per ottenere un intervallo di lampeggio molto preciso.
Datasheet alla mano vediamo che il TIMER0 del 4431 fa proprio al caso nostro in quanto:
- può lavorare con un contatore a 16 bit permettendoci di impostare fino a 65536 incrementi
- dispone di uno specifico interrupt
- dispone di un prescaler programmabile fino a 1:256
Per chi non sapesse nulla sui prescaler (e postscaler) basti pensare a dei semplici divisori di frequenza: una sorta di riduttori del numero di impulsi generati dal clock principale del PIC.
Senza il prescaler abilitato il TIMER è infatti connesso direttamente al clock interno FOSC/4 quello cioè che produce un numero di impulsi pari alla frequenza dell'oscillatore divisa per 4.
Se ad esempio utilizziamo un quarzo da 8 MHZ avremo il TIMER0 che si incrementerà con una frequenza pari a FOSC HZ/4 = 8.000.000/4 = 2.000.000 = 2 MHZ.
Ogni incremento avverrà quindi con un intervallo di tempo in secondi di 1/HZ = 1/2.000.000 = 0,0000005 secondi = 0,5 uSec.
Troppo veloce per il nostro scopo: anche impostando il numero massimo di incrementi pari a 65536 il TIMER scatenerà l'interrupt ogni: 65536 * 0,5 uSec = 32768 uSec = 32,768 mSec = 0,032768 secondi.
A noi serve un interrupt ogni secondo cioè ogni 1000 mSec (1.000.000 di uSec).
In nostro aiuto arriva quindi il prescaler del TIMER0 che ridurrà ulteriormente la frequenza di clock e quindi ci permetterà di impostare un numero di incrementi nel range dei 16 bit disponibili:
OSC 8 MHZ | ||
---|---|---|
Prescaler | FOSC/4 al TIMER | Intervallo incremento TIMER |
1:1 (disabilitato) | 2.000.000 HZ | 0,5 uSec |
1:2 | 1.000.000 HZ | 1 uSec |
1:4 | 500.000 HZ | 2 uSec |
1:8 | 250.000 HZ | 4 uSec |
1:16 | 125.000 HZ | 8 uSec |
1:32 | 62.500 HZ | 16 uSec |
1:64 | 31.250 HZ | 32 uSec |
1:128 | 15.625 HZ | 64 uSec |
1:256 | 7.812,5 HZ | 128 uSec |
Per ottenere un secondo di intervallo possiamo utilizzare una tra le seguenti combinazioni di valori tra prescaler e numero di incrementi:
Prescaler | Intervallo incremento TIMER | Incrementi | Intervallo totale | Errore |
---|---|---|---|---|
1:32 | 16 uSec | 62500 | 1 Sec | 0 |
1:64 | 32 uSec | 31250 | 1 Sec | 0 |
1:128 | 64 uSec | 15625 | 1 Sec | 0 |
1:256 | 128 uSec | 7812 | 0,999936 Sec | -64 uSec |
1:256 | 128 uSec | 7813 | 1,000064 Sec | +64 uSec |
La scelta è ampia considerando che l'errore che otteniamo è nullo per ben 3 opzioni.
Possiamo quindi scegliere la 1:128 con 15625 incrementi: procediamo dunque!
Se non lo abbiamo ancora fatto è il momento di installare il tool di sviluppo (IDE) MPLAB-X scaricabile liberamente dal sito della microchip.
Aggiungiamo allo schema di base: un LED, una resistenza da 330 e cambiamo il quarzo con uno da 8 MHZ:
NB: il 4431 può fornire al massimo 25 mA di corrente da un singolo pin e 300 mA di corrente totale prelevabile da tutte le porte. Superare i valori raccomandati nel datasheet significa mettere fuori uso il PIC.
Non è bene connettere carichi che non siano altri dispositivi digitali alle porte del PIC: qui facciamo uno strappo alla regola connettendo direttamente un LED al pin RD1 della PORTD e limitando la corrente a 10mA circa con la R2.
Avviamo MPLAB-X, creiamo un nuovo progetto standalone seguendo il wizard e copiamo in un nuovo file sorgente asm il seguente codice:
; Copyright 2013 padnest@gmail.com ; Licensed under the Apache License, Version 2.0 (the "License"); ; you may not use this file except in compliance with the License. ; You may obtain a copy of the License at ; ; http://www.apache.org/licenses/LICENSE-2.0 ; ; Unless required by applicable law or agreed to in writing, software ; distributed under the License is distributed on an "AS IS" BASIS, ; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ; See the License for the specific language governing permissions and ; limitations under the License. LIST p=18F4431 #include <p18f4431.inc> ; configs CONFIG OSC = HS CONFIG IESO = OFF CONFIG FCMEN = OFF CONFIG PWRTEN = ON CONFIG WDTEN = OFF CONFIG BOREN = OFF CONFIG MCLRE = ON CONFIG LVP = OFF CONFIG DEBUG = OFF CONFIG STVREN = ON #define LED LATD, RD1 ; reset vector ORG 0x0000 goto main ; interrupt vector in compatibility mode ORG 0x0008 interrupt: btg LED bcf INTCON, TMR0IF movlw 0xC2 ; set 15625 increments in TIMER0: 65536-15625 = 49911 (C2F7) movwf TMR0H movlw 0xF7 movwf TMR0L retfie FAST main: ; init PORTD clrf PORTD clrf TRISD ; init interrupts bcf RCON, IPEN ; disable high priority interrupts mode movlw b'10100000' ; GIE + TMR0 enabled movwf INTCON ; init TIMER0 movlw 0xFF ; set 1 increment in TIMER0 movwf TMR0H movwf TMR0L movlw b'10000110' ; starting TIMER0 + 16bit mode + prescaler enabled (0) at 1:128 (110) movwf T0CON loop8: ; infinite loop goto loop8 END
Compiliamo ed eseguiamo il programma nel PIC (clccando sull'apposita icona in MPLAB-X) e vedremo lampeggiare il led con l'intervallo voluto: 1 secondo acceso e un secondo spento.
Variante: volendo adesso raddoppiare la velocità di lampeggio in modo che il led resti acceso per 0,5 secondi e spento per altri 0,5 secondi come ci conviene intervenire sul programma?
Provate a modificare il valore del prescaler da 1:128 a 1:64, cambiando quindi la linea:
movlw b'10000110' ; starting TIMER0 + 16bit mode + prescaler enabled (0) at 1:128 (110)
in
movlw b'10000101' ; starting TIMER0 + 16bit mode + prescaler enabled (0) at 1:64 (101)
Stay tuned!
ap
Vai al successivo POST della serie
NB: l'autore non risponde di eventuali danni causati da omissioni, inesattezze o errori eventualmente presenti nell'articolo pubblicato.
Prego, segnalare suggerimenti e migliorie commentando questo post o inviando una email a padnest@gmail.com.
Nessun commento :
Posta un commento