Lezione 8 di 43

Lezione 07

🎓 PIC16 — From Zero to Hero · Lezione 07

Il registro STATUS 🗺️

Otto bit, tre missioni: aritmetica, bank switching, diagnostica power.
Capire STATUS è capire come il PIC “ricorda” cosa è appena successo.

🎯 Cosa impari in questa lezione

  • La mappa completa degli 8 bit di STATUS e il loro ruolo
  • C, DC, Z — già noti, ora formalizziamo le regole esatte
  • RP0, RP1 — bank switching: come accedere a TRISA, TRISB e OPTION_REG
  • IRP — bank select per l’indirizzamento indiretto
  • TO, PD — i flag di diagnostica: cosa dicono al reset
  • Il valore di reset 0x18 e perché TO e PD sono già a 1 all’avvio
  • La trappola del bank switching: i bug più comuni

📋 Scheda lezione

Modulo1 — Assembly Base
Lezione07 di 42
Livello⭐⭐ Principiante+
Tempo~30 minuti
RegistroSTATUS (0x03)
Reset value0x18 — TO=1, PD=1

🗺️ La mappa completa — STATUS bit per bit

STATUS è all’indirizzo 0x03, visibile da entrambi i banchi (registro mirrored). Ogni bit ha un nome, una posizione fissa e una funzione precisa. Impararli a memoria è essenziale: ogni programma PIC non banale li usa tutti.

STATUS — 0x03 — Reset value: 0x18 = 0001 1000 bit 7 IRP Indirect Bank Sel. reset = 0 bit 6 RP1 Bank Select (non usato F84A) reset = 0 bit 5 RP0 Bank Select 0=Bank0 1=Bank1 reset = 0 bit 4 TO Time-Out WDT overflow reset = 1 ✓ bit 3 PD Power-Down SLEEP flag reset = 1 ✓ bit 2 Z Zero flag risultato = 0 reset = 0 bit 1 DC Digit Carry carry b3 to b4 reset = 0 bit 0 C Carry flag overflow/borrow reset = 0 🔵 Indirizzamento indiretto 🏦 Bank switching 🔋 Diagnostica power/WDT ➕ Flag aritmetica/logica Valore al reset: bit7..0 = 0 0 0 1 1 0 0 0 = 0x18 (solo TO e PD a 1)
Figura 1 — Gli 8 bit di STATUS raggruppati per funzione. Solo TO e PD partono a 1 al reset.

① C, DC, Z — i flag aritmetici (regole esatte)

Già incontrati nelle lezioni precedenti, qui definiamo le regole esatte come le implementa il simulatore — non la versione semplificata dei manuali.

FlagBitSi setta a 1 quando…Istruzioni che lo modificano
Z2 Il risultato (8 bit) è 0x00 ADDWF, SUBWF, ANDWF, IORWF, XORWF, MOVF, COMF, INCF, DECF, CLRF, CLRW + versioni LW
C0 Addizioni: risultato > 255. Sottrazioni: nessun borrow (C=1 = ok, C=0 = sforato). RLF/RRF: bit uscente. ADDWF, ADDLW, SUBWF, SUBLW, RLF, RRF
DC1 Addizioni: (W&0x0F)+(f&0x0F) > 0x0F. Sottrazioni: (f&0x0F) ≥ (W&0x0F). ADDWF, ADDLW, SUBWF, SUBLW

⚠️ C in sottrazione è invertito: SUBWF f,W calcola f−W. Se f≥W il risultato è ≥0 e C=1 (nessun borrow). Se f<W il risultato è negativo e C=0 (c’è borrow). C=0 significa che hai sforato — è uno degli errori più frequenti nei programmi PIC.

💡 Istruzioni che NON modificano C né DC: MOVWF, MOVF, MOVLW, BCF, BSF, BTFSC, BTFSS, GOTO, CALL, RETURN, NOP, SWAPF. Questo è fondamentale: puoi fare operazioni logiche o spostamenti senza perdere il C dell’ultima operazione aritmetica.


② RP0 e RP1 — il bank switching

La RAM del PIC16F84A è divisa in due banchi da 128 byte. Il bit RP0 (STATUS bit 5) seleziona quale banco è attivo. RP1 esiste ma non è usato dal F84A (solo 2 banchi). Sul PIC16F877A con 4 banchi si usano entrambi.

Mappa RAM PIC16F84A — Bank 0 e Bank 1 BANK 0 — RP0 = 0 SFR — Special Function Registers 0x00 INDF 0x01 TMR0 0x02 PCL 0x03 STATUS 0x04 FSR 0x05 PORTA 0x06 PORTB 0x08 EEDATA 0x09 EEADR 0x0A PCLATH 0x0B INTCON 0x07, 0x0C non implementati GPR — General Purpose Registers (68 byte) 0x0C … 0x4F — le tue variabili BANK 1 — RP0 = 1 SFR — Special Function Registers 0x81 OPTION_REG 0x85 TRISA 0x86 TRISB 0x88 EECON1 0x89 EECON2 + mirror di INDF, PCL, STATUS, FSR, PCLATH, INTCON (accessibili da entrambi i banchi) GPR — mirror di Bank 0 0x8C … 0xCF = stessa RAM di 0x0C…0x4F RP0=1 STATUS, PCL, FSR, PCLATH, INTCON sono mirrored — accessibili senza cambiare RP0
Figura 2 — I due banchi del PIC16F84A. RP0=0 → Bank 0; RP0=1 → Bank 1 (TRISA, TRISB, OPTION_REG).

Il pattern standard di bank switching

; === PATTERN STANDARD: configura TRISB e TRISA ===

; — Entra in Bank 1 —
BSF STATUS, RP0 ; RP0 = 1 → Bank 1 attivo

CLRF TRISB ; tutti i pin PORTB = output
MOVLW 0xFF
MOVWF TRISA ; tutti i pin PORTA = input

; — Torna in Bank 0 —
BCF STATUS, RP0 ; RP0 = 0 → Bank 0 attivo

CLRF PORTB ; azzera latch PORTB

⛔ I bug più comuni del bank switching

  • Dimenticare BCF STATUS,RP0 dopo la configurazione — tutto il codice successivo opera in Bank 1, scrivendo su registri sbagliati silenziosamente.
  • Leggere PORTB mentre si è in Bank 1 — l’indirizzo 0x06 in Bank 1 è un mirror o un registro SFR diverso, non i dati delle porte.
  • Accedere a TRISB senza entrare in Bank 1 — in Bank 0 l’indirizzo 0x86 punta a un’area non implementata.

③ IRP — bank select per l’indirizzamento indiretto

IRP (bit 7) funziona come RP0 ma per l’indirizzamento indiretto tramite INDF/FSR. Quando usi FSR per puntare a un indirizzo, IRP seleziona i banchi 0-1 (IRP=0) o 2-3 (IRP=1). Sul PIC16F84A ha solo 2 banchi quindi IRP rimane sempre 0. Per ora: non toccare IRP — tornerà nella lezione sulle strutture dati.

📌 Regola pratica PIC16F84A: usa solo RP0 per il bank switching. IRP e RP1 restano sempre 0. Quando passerai al F877A (Modulo 5) rivedrai questo con 4 banchi.


④ TO e PD — diagnostica di reset e power

TO e PD sono flag impostati dall’hardware, non dal firmware. Dicono perché il microcontrollore si è resettato o è andato in sleep. Sono fondamentali per il firmware di produzione; a livello didattico, capire il loro stato al reset è il punto chiave.

TO e PD — tabella di decodifica dello stato di reset TO PD Significato 1 1 ✅ Power-on reset o reset esterno (MCLR) — stato normale all’avvio 0 1 ⚠️ Reset da Watchdog Timer (WDT overflow) — il programma si era bloccato 0 0 🌙 WDT overflow durante SLEEP — wake-up dal risparmio energetico 1 0 💤 In sleep mode (istruzione SLEEP eseguita) — attende interrupt o WDT
Figura 3 — I quattro stati di TO:PD. Al power-on entrambi sono 1, quindi STATUS = 0x18.

Perché STATUS reset = 0x18?

Al power-on il PIC setta TO=1 e PD=1 per indicare “reset normale, non sono stato in sleep né resettato dal watchdog”. Tutti gli altri bit partono da 0. Quindi: 0b00011000 = 0x18. Ogni volta che vedi STATUS = 0x18 nel simulatore dopo Reset, è esattamente questo.

; Firmware di produzione: verifica causa del reset
BTFSS STATUS, TO ; salta se TO=1 (non è stato WDT)
GOTO WDT_RESET ; TO=0 → reset da watchdog
BTFSS STATUS, PD ; salta se PD=1 (non era in sleep)
GOTO WAKE_FROM_SLEEP ; PD=0 → wake-up da sleep
; TO=1, PD=1: avvio normale → continua


📊 Riepilogo — tutti gli 8 bit

BitNomeFunzioneR/WResetChi lo modifica
7IRPBank select per indirizzamento indiretto (FSR)R/W0Firmware (BSF/BCF)
6RP1Bank select bit 1 — inutilizzato su F84AR/W0Firmware (BSF/BCF)
5RP0Bank select: 0=Bank0, 1=Bank1R/W0Firmware (BSF/BCF)
4TOTime-Out: 0=reset da WDT, 1=power-on o MCLRR1Hardware (WDT, SLEEP, power)
3PDPower-Down: 0=SLEEP eseguito, 1=normaleR1Hardware (SLEEP, WDT, power)
2ZZero: 1 se risultato operazione = 0x00R/W0Istruzioni aritm./logiche
1DCDigit Carry: carry dal nibble basso (b3→b4)R/W0ADDWF, ADDLW, SUBWF, SUBLW
0CCarry: overflow addizione o borrow sottrazioneR/W0ADD, SUB, RLF, RRF

💻 Programma — esplora STATUS nel simulatore

; ============================================
; Lezione 07 — Esplora STATUS
; Usa Step (non Run) e monitora il valore
; esadecimale di STATUS nel pannello registri
; ============================================
LIST p=16F84A
#include <p16f84a.inc>
REG EQU 0x0C
ORG 0x00

; [A] STATUS al reset: osserva 0x18 (TO=1, PD=1)
NOP

; [B] Effetto di Z — e perché MOVWF non lo tocca
MOVLW 0xFF
MOVWF REG
INCF REG, F ; 0xFF+1=0x00 → Z=1 [B1] STATUS=0x1C
MOVLW 0x01
MOVWF REG ; [B2] STATUS ancora 0x1C — MOVWF non tocca Z!
MOVF REG, W ; [B3] REG=0x01≠0 → Z=0, STATUS=0x18

; [C] C e DC insieme
MOVLW 0x0F
MOVWF REG
MOVLW 0x01
ADDWF REG, F ; 0x0F+0x01=0x10 → DC=1,C=0,Z=0 [C1] 0x1A
MOVLW 0xFF
MOVWF REG
MOVLW 0x01
ADDWF REG, F ; 0xFF+0x01=0x00 → C=1,DC=1,Z=1 [C2] 0x1F

; [D] Bank switching — osserva RP0
BSF STATUS, RP0 ; [D1] STATUS = 0x3F — Bank 1 attivo
CLRF TRISB ; TRISB = 0x00 (output)
BCF STATUS, RP0 ; [D2] STATUS = 0x18 — Bank 0 ripristinato
CLRF PORTB

FINE GOTO FINE
END

Valori attesi di STATUS ad ogni punto marcato
PuntoSTATUSBit attiviNote
[A] NOP0x18TO=1, PD=1Valore di reset standard
[B1] dopo INCF 0xFF0x1CTO=1, PD=1, Z=10xFF+1=0x00 → Z setta
[B2] dopo MOVWF0x1CTO=1, PD=1, Z=1MOVWF non tocca Z — rimane 1!
[B3] dopo MOVF REG,W0x18TO=1, PD=1REG=0x01≠0 → Z torna 0
[C1] dopo ADDWF 0x0F+0x010x1ATO=1, PD=1, DC=1Carry nibble; nessun overflow byte
[C2] dopo ADDWF 0xFF+0x010x1FTO=1, PD=1, Z=1, DC=1, C=1Overflow totale — tutti e tre i flag
[D1] dopo BSF STATUS,RP00x3FTO=1,PD=1,RP0=1 + C/DC/Z dal passo precedenteBank 1 attivo
[D2] dopo BCF STATUS,RP00x1FTO=1, PD=1, Z=1, DC=1, C=1RP0 azzerato, flag aritmetici invariati

🏋️ Prova tu!

  1. Carica il programma e avanza step-by-step monitorando STATUS in esadecimale. Confronta con la tabella sopra e verifica che i valori coincidano.
  2. Aggiungi alla fine: MOVLW 0x05 / MOVWF REG / MOVLW 0x08 / SUBWF REG, F (calcola 0x05 − 0x08). Qual è il valore di STATUS dopo SUBWF? C=? Z=? Perché C ha quel valore?
  3. Sfida: porta STATUS esattamente a 0x1D (TO=1, PD=1, Z=1, C=1, DC=0). Quale coppia di valori sommati produce Z=1 e C=1 ma non DC=1?

💡 Esercizio 3: Z=1 e C=1 senza DC=1 richiede overflow sull’intero byte ma non sul nibble basso. Prova 0xF0 + 0x10.

❓ Quiz rapido

1. STATUS = 0x18 al reset. Esegui BSF STATUS, RP0. Quanto vale STATUS?

Mostra risposta

STATUS = 0x38. RP0 è il bit 5 (valore 0x20). 0x18 | 0x20 = 0x38. In binario: 0011 1000 — TO, PD e RP0 tutti a 1.


2. Perché dopo MOVWF REG il flag Z non cambia, ma dopo MOVF REG,W sì?

Mostra risposta

MOVWF è un trasferimento puro W→registro: non “guarda” il valore, non tocca nessun flag. MOVF invece legge il registro e aggiorna Z in base al valore letto: se è 0 → Z=1, altrimenti Z=0. È lo stesso principio di MOVLW vs CLRW dalla lezione 03.


3. Hai configurato TRISB in Bank 1 ma hai dimenticato BCF STATUS,RP0. Poi scrivi MOVWF PORTB. Cosa succede realmente?

Mostra risposta

Con RP0=1 sei ancora in Bank 1. L’indirizzo 0x06 in Bank 1 non è PORTB ma un mirror di PORTB sul F84A (fortunatamente) — ma su altri PIC potrebbe essere un registro SFR completamente diverso. In ogni caso il comportamento diventa dipendente dal dispositivo e non intenzionale. Il LED non si comporta come previsto e il bug è difficile da trovare perché non genera errori di compilazione.


4. Subito dopo il power-on, TO=? PD=? e cosa significano?

Mostra risposta

TO=1 e PD=1 — valore di reset 0x18. TO=1: il watchdog non ha causato questo reset. PD=1: il microcontrollore non era in sleep. La combinazione TO=1, PD=1 indica reset normale da power-on o da pin MCLR premuto dall’esterno. È il caso “tutto bene, avvio normale”.

Prossima lezione →

Lezione 08 — Salti e salti condizionali
GOTO, BTFSC, BTFSS, DECFSZ, INCFSZ — costruire loop e if/else in assembly.
La struttura fondamentale init → loop infinito di ogni firmware PIC.

© Prof. D. Bertolino · PIC16 From Zero to Hero · WebPicSimulator · Lezione 07