Tutorials - PIC

 

Come passare un programma Assembly scritto per 16F84 al 16F1827


Note

Ricordiamo che:

  1. Una comodità è data dal fatto che 16F1827 può lavorare senza quarzo da 31 kHz a 32 MHz, utilizzando un circuito interno, come peraltro in modo più limitato può fare anche 16F628
    Questo non è preciso come il cristallo esterno, ma per applicazioni in cui il tempo di clock non è determinante (ovvero la maggior parte...), permette di risparmiare componenti. 
     
  2. Gli Enhanced Mid-range hanno come tools di sviluppo e programmazione indicati PICkit3, ICD3 e REAL-ICE. Se usate altri tools o tools di terze parti, verificate che il PIC16F1827 sia supportato.
     
  3. Dato che 16F1827 dispone della possibilità di debug attraverso ISCP/ICD, il tools Microchip scelto avrà anche la possibilità di effettuare il debug in circuit. 16F84 e 16F628 non hanno questa possibilità.
     
  4. 16F1826 è la stessa cosa di 16F1827, ma con una quantità di memoria inferiore
  5. Le versioni LF sono previste per funzionare in un range di alimentazione tra 1.8 V e 3.6 V. Quindi attenzione alla tensione di alimentazione. 

"Accendi il LED"

Vediamo come il programma minimale "accendi il LED", scritto per il vecchio 16F84, possa essere passato al 16F1827 senza modifiche sensazionali, se non quelle relative alle diverse prestazioni dell' ambiente.

Per i test abbiamo usato la nostra 18-pini Mini Demo Board, che è estremamente pratica e comoda per questo genere di esercitazioni, anche per la possibilità di funzionare sia stand alone, sia inserita su una breadboard. Si potrà utilizzare anche una 18-pin Demo Board DM164120-4 di Microchip che è offerta proprio con il 16F1827 o qualsiasi altra soluzione. Anche perchè lo schema elettrico è minimale.

Sono necessari solo pochissimi componenti:

L' oscillatore è composto dal classico quarzo a 4MHz (limite del 16F84) e dai condensatori C1 e C2.
Una resistenza R2 è il pull-up del MCLR (sempre per i limiti del 16F84).
Il LED è collegato tra RA1 e la massa con una resistenza di limitazione R1.
Non dimenticare un condensatore sull' alimentazione (C3) vicino ai pin del chip.
La presa ISCP/ICD è necessaria per la programmazione on board. 

Inoltre l' intero circuito è alimentabile direttamente dal PICkit3.

  • C1-C2 18-27 pF
  • C3      100 nF
  • R1      330 ohm
  • R2      10 k
  • Q1       4 MHz

"Accendi il LED" - ver. 16F84

Per curiosità, iniziamo con una versione extra-skyfo del sorgente, giusto per avere ben chiaro quello che NON bisogna seguire come esempio:

   list p=16F84
    _CONFIG=3FF2H

 org 0x00

     bsf      0x03, 05

     movlw    0x00    
     movwf    TRISA
     bcf      0x03, 05     
     bsf      0x03, 1
     goto     $

  end
;--------------------------------------------
; al momento della programmazione scegliere:
; memory unprotected
; watchdog timer disabled
; standard crystal (4 MHz)
; power-up timer on

Davanti ad un aborto del genere, il consiglio è quello dantesco:"non ti curar di lor, ma guarda e passa...".
Però possiamo vedere i dettagli della versione "infernale" e come si trasforma in versione "paradisiaca".

manca completamente una testata di commento che spieghi, almeno superficialmente, cosa si voglia fare
  list p=16F84 definizione del processore
  org 0x00 locazione di partenza del programma (vettore di reset)
     bsf      0x03, 05
     movlw    0x00    
     movwf    0X85
     bcf      0x03, 05     
     bsf      0x05, 1
essendo utilizzati valori assoluti, il senso delle operazioni è remoto, anche perchè non c'è alcun commento esplicativo
     goto     $ l' uso del $ ha forti limitazioni sulla portabilità
  end fine programma
;--------------------------------------------
; sul programmatore scegliere:
; memory uprotected
; watchdog timer disabled
; standard crystal (4 MHz)
; power-up timer on
non ha alcun senso demandare ad una azione manuale sul programmatore quello che la linea __CONFIG farebbe automaticamente

Una scrittura minimale, ma più sensata, rende le cosa ben più semplici:

;---------------------------------------------------------------------
; FILE:  helloLed84.asm
; AUTH:  afg
; DATE:  04/05/20129
; DESC:  Accendi un LED con 16F84
; NOTE:  Verificato con PIC16F84-04/P su 18-pin Demo Board di Microchip. 
;
;----------------------------------------------------------------------
; definizione del processore

   list p=16F84
  #include "P16F84.inc"

;----------------------------------------------------------------------
; CONFIGURAZIONE
; memoria non protetta
; watchdog timer disabled
; power-up timer abilitato

; standard crystal (4 MHz)

 __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC

;----------------------------------------------------------------------
; uso dell' I/O
; definizione per il LED per utilizzarla nel sorgente

#define LED PORTA, 1   ; LED collegato tra PA0 e massa. 
                       ; Si accende con PA0=1

;----------------------------------------------------------------------
; inizio programma

 org 0x00                 ; vettore di reset

; al POR è puntato il Banco 0
start    clrf     PORTA   ; azzera il latch di PORTA (banco 0)
         
                banksel  TRISA   ; va al banco di TRISA (banco 1)
         movlw    0x00    
         movwf    TRISA   ; PORTA come uscita

       
  banksel  PORTA   ; va al banco di PORTA (banco 0)
         bsf      LED     ; accendi LED

lock     goto     lock    ; blocco

 end
;----------------------------------------------------------------------

Adesso le cose sono più chiare e, come vedremo, la scrittura è portabile facilmente, anche veramente minimale (d' altronde anche il programma lo è...).

 


"Accendi il LED" - ver. 16F628

Vediamo cosa dobbiamo fare per il 16F628.

;---------------------------------------------------------------------
; FILE: helloLed628.asm
; AUT :  afg
; DATE:  04/05/20129
; DESC:  Accendi un LED con 16F628
; NOTE:  Verificato con PIC16F628 su 18-pin Demo Board di Microchip. 
;

;----------------------------------------------------------------------
; definizione del processore

   list p=16F628
  #include "P16F628.inc"

;----------------------------------------------------------------------
; CONFIGURAZIONE

; memoria non protetta
; watchdog timer disabled
; power-up timer abilitato

; standard crystal (4 MHz)

 __CONFIG, _CP_OFF & _WDT_OFF & _PWRTE_ON &  _HS_OSC

; LVP disabilitato
; MCLR abilitato

 __CONFIG, _LVP_OFF & _MCLRE_ON

;----------------------------------------------------------------------
; uso dell' I/O
; definizione per il LED per utilizzarla nel sorgente

#define LED PORTA, 1   ; LED collegato tra PB0 e massa. 
                       ; Si accende con PB0=1

;----------------------------------------------------------------------
; inizio programma

 org 0x00

start
; la prima linea non è necessaria perchè al POR è puntato il Banco 0
      ;banksel  CMCON  ; va al banco di CMCON (banco 0)
       movlw    0x07    ; disabilita i comparatori da PORTA
       movwf    CMCON   ; CMCON è in Banco 0 
 
; anche PORTA è in Banco 0
      
clrf     PORTA   ; azzera il latch di PORTA (banco 0)
         
            banksel  TRISA   ; va al banco di TRISA (banco 1)
       movlw    0x00    
       movwf    TRISA   ; PORTA come uscita

       banksel  PORTA   ; va al banco di PORTA (banco 0)
       bsf      LED     ; accendi LED

lock   goto     lock    ; blocco

 end

;----------------------------------------------------------------------


E' stato necessario aggiungere solo due righe per disabilitare i comparatori che, al default del POR, si trovano abilitati ed impedirebbero l' uso del PORTA 0 in modo digitale.
Ovviamente il _CONFIG sarà differente, visto che si tratta di un chip con diverse prestazioni.
Le linee di configurazione, che solitamente sono una sola, qui sono scritte in due blocchi per rendere evidente come una serie di opzioni sia comune con il PIC16F84, mentre un' altra serie sia relativa solo al PIC più recente.


"Accendi il LED" - ver. 16F1827

Veniamo ora all' Enhanced Mid-range.

;---------------------------------------------------------------------
; FILE:  helloLed1827.asm
; AUT:   afg
; DATE:  04/05/20129
; DESC:  Accendi un LED con 16F1827
; NOTE:  Verificato con PIC16F1827 su 18-pin Demo Board di Microchip. 
;
;----------------------------------------------------------------------
; definizione del processore

   list p=16F1827
  #include "16F1827.inc"

;----------------------------------------------------------------------
; CONFIGURAZIONE

; memoria non protetta
; watchdog timer disabled
; power-up timer abilitato

; standard crystal (4 MHz)

 __CONFIG _CONFIG1, _CP_OFF & _CPD_OFF & _WDTE_OFF & _PWRTE_ON & _FOSC_HS 

; LVP disabilitato
; MCLR abilitato
; BOR disabilitato
; CLOCKOUT, IESO, FCMEN, PLL, STVREN, WRT disabilitati

 __CONFIG _CONFIG1, _LVP_OFF & _MCLRE_ON & _BOREN_OFF & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF

 __CONFIG _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_OFF

;----------------------------------------------------------------------
; uso dell' I/O
; definizione per il LED per utilizzarla nel sorgente

#define LED PORTA, 1   ; LED collegato tra PB0 e massa. 
                       ; Si accende con PB0=1

;----------------------------------------------------------------------
; inizio programma

 org 0x00

start  banksel  ANSELA  ; va al banco di ANSELA (banco3)
       clrf     ANSELA  ; disabilita la funzione analogica da PORTA

      
banksel  PORTA   ; va al banco di PORTA (banco 0)
              clrf     PORTA   ; azzera il latch di PORTA

              banksel  TRISA   ; va al banco di TRISA (banco 1)
       movlw    0x00    
       movwf    TRISA   ; PORTA come uscita

       banksel  PORTA   ; va al banco di PORTA (banco 0)
       bsf      LED     ; accendi LED

lock   goto     lock    ; blocco 

 end

;----------------------------------------------------------------------


E' stato necessario aggiungere solo due righe per disabilitare la funzione di ingresso dell' ADC che, al default del POR, si trova abilitata ed impedirebbe l' uso del PORTA 0 in modo digitale.
Disponendo il microcontroller di modo sleep, potrebbe essere elegante arrestarlo in questa condizione, che ha un consumo minore del loop chiuso.
Ovviamente pure questo _CONFIG sarà differente, visto che si tratta di un chip con diverse prestazioni e, come possiamo vedere, si sviluppa su due blocchi (CONFIG1 e CONFIG2). Anche qui le linee sono state divise per rendere evidente le parti comuni e quelle specifiche del chip.


CVD...

Vediamo comparate sole le parti principali del programma:

16F84 16F628 16F1827 Note
 __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC

 org 0x00  

start 

 
 __CONFIG, _CP_OFF  & _WDT_OFF & _PWRTE_ON & _LVP_OFF & _HS_OSC & _MCLRE_ON
 org 0x00  

start movlw    0x07
      movwf    CMCON
     
 
 __CONFIG _CONFIG1, _FOSC_HS & _WDTE_OFF & _PWRTE_ON & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF

 __CONFIG _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_OFF & _LVP_OFF

 org 0x00  

start banksel  ANSELA 
           clrf    ANSELA
      banksel
  PORTA
       
Area istruzioni necessarie ad adeguare l' hardware specifico del processore
          clrf     PORTA
      banksel  TRISA

      movlw    0x00    
      movwf    TRISA
      banksel
  PORTA
      bsf      LED 
lock  goto     lock 
end
           clrf     PORTA
      banksel  TRISA

      movlw    0x00    
      movwf    TRISA
      banksel
  PORTA
      bsf      LED 
lock  goto     lock 
end
         clrf     PORTA
      banksel  TRISA

      movlw    0x00    
      movwf    TRISA
      banksel
  PORTA
      bsf      LED 
lock  goto     lock 
end
Area istruzioni necessarie ad accendere il LED

Osserviamo che il "core" del programma è identico nelle tre versioni; quello che cambia è l' aggiunta iniziale di istruzioni per adeguare l' hardware specifico di ciascun processore. 16F84, che ha l' hardware con la minore complessità (meno funzioni, meno memoria, meno registri) sarà quello che richiede meno adeguamenti; ma il problema della programmazione sta solo relativamente negli adeguamenti della base hardware, che, una volta conosciuti, valgono per tutte le situazioni di compatibilità all' indietro e vengono riportati pari pari. La programmazione vera e propria sta da un' altra parte.

Così, qualsiasi programma o attività didattica si svolgerà molto più proficuamente sul chip più recente che su quello precedente e ancor più sensibile differenza si avrà utilizzando un C.
 

Come Volevasi Dimostrare

non esiste alcuna pregiudizale logica e sensata per non partire con il prodotto più recente piuttosto che con uno precedente, se non addirittura più "antico". 

Questo perchè:

  • la struttura del programma è identica: basta quel  minimo di adeguamento all' ambiente diverso, che, peraltro, deve essere applicato anche per il passaggio dal nonno 16F84 al nipote 16F628, dato che ogni chip ha le sue particolarità. 
     
  • ovvero, è possibile esercitare sul PIC più recente qualunque cosa funziona su quello più datato
     
  • ma, per contro, utilizzando il PIC più recente si avrà la possibilità di sperimentare un gran numero di funzioni, prestazioni e situazioni non possibili col suo predecessore
     
  • per di più spendendo meno !

E' evidente che chi sostiene la necessità per il principiante di partire dal "Momento della Creazione del Silicio" non ha minimamente le idee chiare.
 

Il concetto guida per l' uso di chip complessi e con data sheet di centinaia di pagine non è quello di ritenere più accessibili i componenti meno dotati, ma bensì quello di approcciare il componente complesso col l' idea della "Libreria".
Nella "Libreria" complessa e vasta del componente "dotato" inizierò a scegliere quali "libri" leggere, ovvero quali periferiche e funzioni utilizzare: le altre resteranno lì, inutilizzate, fino a che non mi serviranno. Le le pagine del foglio dati relative a queste parti non saranno neppure sfogliate.
Così il componente complesso, affrontato per gradi, non sarà niente di più che l' utilizzare gradualmente le possibilità della famiglia di microcontroller, potendo per di più scegliere quali parti considerare e quali no.

 


Nota:

Va però detto onestamente che ci sono da considerare alcuni presupposti:

  1. è necessario, sopratutto per il principiante assoluto, l' appoggio di un tutor adeguato. 
    Questo, ovviamente, è valido per qualsiasi approccio, dato che chi fa da sè fa per tre, ma chi parte con un valido aiuto arriva molto prima e molto più proficuamente, dato che l' apprendimento non sta nel procedere per errori e correzioni, ma nell' evitare di ripetere errori inutili con un adeguato studio o aiuto e concentrare gli sforzi sul risultato.
    Ovvero, con questo mini tutorial avete ora ben chiaro che accendere un LED sull' arcaico 16F84 o sul super performante 16F1827 è la stessa cosa; ma questo perchè avete seguito appunto un tutorial (che dovrebbe essere un mezzo per rendere l' apprendimento più efficace). Senza il tutorial, per i più arrivare alle stesse conclusione avrebbe richiesto un tempo ben più lungo che la lettura di queste pagine.
  2. la struttura di base è analoga tra il chip obsoleto e quello ultima generazione, e questo permette di utilizzare con ragionevole semplicità le vecchie applicazioni o corsi o tutorial. 
    Occorre però che queste esercitazioni e tutorial siano aggiornati
    : finchè si tiene buono quanto scritto 10 anni fa, il progresso difficilmente progredisce...
  3. Però, la conoscenza delle prestazioni addizionali del nuovo prodotto, delle sue caratteristiche specifiche, dell' uso delle periferiche enhanced è un lavoro del tutto nuovo e va affrontato di nuovo per ogni chip che appartenga ad una diversa famiglia rispetto a quello fino ad ora usato.
  4. E, fatto chiave, i microcontroller di una stessa area (PIC16, PIC18, PIC24) sono omologhi, ma NON sono tutti esattamente uguali. Questo è evidenziato dalle "trappole" in cui si cade passando da un chip ad un' altro, dove il cambio di una funzione o di un bit o di una modalità operativa arrestano lo sviluppatore per ore nel tentativo di venirne a capo. Fa storia il comparatore attivo al POR che impedisce su alcune porte l' uso digitale o la diversa gestione dei banchi o il pin open drain, ecc.
    Qui, il punto 1 può essere sostituito, con meno efficienza,  solo dall' accurata lettura del foglio dati (406 pagine in inglese...) e dalla consultazione di forum o documentazione varia.
     
  5. Si potrà giustamente sostenere che l' uso di linguaggi evoluti e di librerie adeguate rendono i sorgenti molto meno dipendenti dall' hardware di quanto sia possibile con il "semplice" Assembly, anche se questo è ineguagliabile in alcune situazioni. 

Una nota extra.

Per chi rimane impressionato dall' estensione del __CONFIG completo del 16F1827, va detto che l'impostazione di tutte le opzioni possibili non è strettamente necessaria; da un punto di vista funzionale basterebbe accertarsi di avere fissato le opzioni indispensabili al funzionamento del programma, trascurando completamente le altre. Se, negli esempi precedenti, ci limitassimo alle opzioni minime, il CONFIG avrebbe lo stesso aspetto.

All' atto pratico, però, è buona cosa inserire una versione completa:

  • una volta scritta, copia e incolla; non si perde tempo. Al massimo si varieranno quelle opzioni necessarie al nuovo progetto
  • in ogni caso, scrivendo alcune opzioni nei registri di CONFIG, questi registri vengono modificati. Tanto vale essere sicuri di avere una base di configurazione ben definita piuttosto che ritrovarsi con qualche spiacevole bit fuori posto. 
     
  • infine, dal punto di vista didattico, e non solo, conoscere tutte le possibilità del componente che si sta usando è l' unico modo per usarlo al meglio. 

Per ultimo, la configurazione va fatta attraverso il sorgente e non manualmente sul dispositivo di programmazione: questa pratica è inutilmente astrusa, fonte di errori e non portabile.
L' uso delle direttive di configurazione è chiaro, portabile e il risultato è automatico.


 

 

Copyright © afg. Tutti i diritti riservati.
Aggiornato il 17/05/12.