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
| Modulo | 1 — Assembly Base |
| Lezione | 07 di 42 |
| Livello | ⭐⭐ Principiante+ |
| Tempo | ~30 minuti |
| Registro | STATUS (0x03) |
| Reset value | 0x18 — 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.
① 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.
| Flag | Bit | Si setta a 1 quando… | Istruzioni che lo modificano |
|---|---|---|---|
| Z | 2 | Il risultato (8 bit) è 0x00 | ADDWF, SUBWF, ANDWF, IORWF, XORWF, MOVF, COMF, INCF, DECF, CLRF, CLRW + versioni LW |
| C | 0 | Addizioni: risultato > 255. Sottrazioni: nessun borrow (C=1 = ok, C=0 = sforato). RLF/RRF: bit uscente. | ADDWF, ADDLW, SUBWF, SUBLW, RLF, RRF |
| DC | 1 | 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.
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.
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
| Bit | Nome | Funzione | R/W | Reset | Chi lo modifica |
|---|---|---|---|---|---|
| 7 | IRP | Bank select per indirizzamento indiretto (FSR) | R/W | 0 | Firmware (BSF/BCF) |
| 6 | RP1 | Bank select bit 1 — inutilizzato su F84A | R/W | 0 | Firmware (BSF/BCF) |
| 5 | RP0 | Bank select: 0=Bank0, 1=Bank1 | R/W | 0 | Firmware (BSF/BCF) |
| 4 | TO | Time-Out: 0=reset da WDT, 1=power-on o MCLR | R | 1 | Hardware (WDT, SLEEP, power) |
| 3 | PD | Power-Down: 0=SLEEP eseguito, 1=normale | R | 1 | Hardware (SLEEP, WDT, power) |
| 2 | Z | Zero: 1 se risultato operazione = 0x00 | R/W | 0 | Istruzioni aritm./logiche |
| 1 | DC | Digit Carry: carry dal nibble basso (b3→b4) | R/W | 0 | ADDWF, ADDLW, SUBWF, SUBLW |
| 0 | C | Carry: overflow addizione o borrow sottrazione | R/W | 0 | ADD, 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
| Punto | STATUS | Bit attivi | Note |
|---|---|---|---|
| [A] NOP | 0x18 | TO=1, PD=1 | Valore di reset standard |
| [B1] dopo INCF 0xFF | 0x1C | TO=1, PD=1, Z=1 | 0xFF+1=0x00 → Z setta |
| [B2] dopo MOVWF | 0x1C | TO=1, PD=1, Z=1 | MOVWF non tocca Z — rimane 1! |
| [B3] dopo MOVF REG,W | 0x18 | TO=1, PD=1 | REG=0x01≠0 → Z torna 0 |
| [C1] dopo ADDWF 0x0F+0x01 | 0x1A | TO=1, PD=1, DC=1 | Carry nibble; nessun overflow byte |
| [C2] dopo ADDWF 0xFF+0x01 | 0x1F | TO=1, PD=1, Z=1, DC=1, C=1 | Overflow totale — tutti e tre i flag |
| [D1] dopo BSF STATUS,RP0 | 0x3F | TO=1,PD=1,RP0=1 + C/DC/Z dal passo precedente | Bank 1 attivo |
| [D2] dopo BCF STATUS,RP0 | 0x1F | TO=1, PD=1, Z=1, DC=1, C=1 | RP0 azzerato, flag aritmetici invariati |
🏋️ Prova tu!
- Carica il programma e avanza step-by-step monitorando STATUS in esadecimale. Confronta con la tabella sopra e verifica che i valori coincidano.
- 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? - 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