Lezione 28
🎓 PIC16 — From Zero to Hero · Lezione 28 · Modulo 5
I²C — Comunicazione con sensori e display 🌡️🖥️
Il modulo MSSP del PIC16F877A in modalità I²C Master. Lettura di temperatura
dal DS1621 e scrittura di testo su LCD HD44780 tramite I/O expander PCF8574.
🎯 Cosa impari in questa lezione
- Principio del bus I²C: 2 fili (SDA + SCL), multi-slave, open-drain + pull-up
- Condizioni di bus: START, Repeated START, STOP, ACK, NACK
- Modulo MSSP in I²C Master mode: registri
SSPCON,SSPCON2,SSPSTAT,SSPADD - Formula baud rate:
Fbaud = Fosc / (4 × (SSPADD+1)) - Sequenza completa di lettura con Repeated START (write cmd → read data)
- Lettura temperatura dal DS1621: 2 byte, gradi interi + frazione (±0.5°C)
- LCD HD44780 via PCF8574 I/O expander: nibble mode, mapping bit, strobe EN
📋 Scheda lezione
Lezione: 28 / 42
Modulo: 5 — Periferiche avanzate
Device: PIC16F877A
Prerequisiti: Lez. 25 (UART), Lez. 26 (ADC)
Difficoltà: ★★★★★
Periferica: MSSP I²C Master
Slave: DS1621, PCF8574+LCD
1 · Il protocollo I²C — transazione e timing
I²C usa solo 2 fili per connettere fino a 127 dispositivi: SCL (clock generato dal master) e SDA (dati bidirezionali). Entrambe le linee sono open-drain — ogni dispositivo può solo portarle a 0, mai a 1. Il livello alto è garantito da resistenze di pull-up esterne (tipicamente 4.7kΩ per 100kHz). Una transazione parte con lo START (SDA scende mentre SCL è alto), poi master invia l’indirizzo a 7 bit + bit R/W, lo slave risponde con ACK (SDA=0 durante il 9° clock). I dati seguono in byte, ognuno con ACK. Il STOP (SDA sale mentre SCL è alto) libera il bus.
2 · Codice — configurazione MSSP e invio comandi al DS1621
; ============================================================ ; Lezione 28 — I2C Master: invio START, indirizzo, dati ; PIC16F877A @ 4 MHz, modulo MSSP in I2C Master mode ; Frequenza I2C: Fbaud = Fosc / (4 × (SSPADD+1)) ; 100kHz: SSPADD = 4MHz/(4×100000) - 1 = 9 ; ============================================================ LIST P=16F877A #INCLUDE <p16f877a.inc> __CONFIG _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF & _BOREN_OFF & _LVP_OFF ; Registri MSSP I2C: ; SSPCON (0x14) Bank0: WCOL SSPOV SSPEN CKP SSPM3-0 ; SSPM=1000 → I2C Master mode ; SSPCON2 (0x91) Bank1: GCEN ACKSTAT ACKDT ACKEN RCEN PEN RSEN SEN ; SSPSTAT (0x94) Bank1: SMP CKE D/A P S R/W UA BF ; SSPBUF (0x13) Bank0: buffer TX/RX ; SSPADD (0x93) Bank1: baud rate divisor ; Indirizzo slave DS1621 (sensore temp): 0x90 (A2=A1=A0=0) #DEFINE DS1621_ADDR 0x90 ; 7 bit addr + write bit (0) ORG 0x0000 GOTO INIT ORG 0x0005 INIT BSF STATUS,RP0 ; Bank 1 ; RC3=SCL, RC4=SDA → open-drain, pull-up esterni necessari BSF TRISC,3 ; RC3 input (I2C usa open-drain) BSF TRISC,4 ; RC4 input MOVLW D'9' MOVWF SSPADD ; 100kHz @ 4MHz MOVLW b'10000000' ; SMP=1 (slew rate off per 100kHz) MOVWF SSPSTAT BCF STATUS,RP0 ; Bank 0 ; SSPCON: SSPEN=1, SSPM=1000 (I2C Master) MOVLW b'00101000' ; SSPEN=1, SSPM=1000 MOVWF SSPCON ; Configura DS1621: invia comando 0xAC (Access Config) ; poi byte 0x00 (continuous conversion, pol=active high) CALL I2C_START MOVLW DS1621_ADDR ; 0x90 = addr+write CALL I2C_SEND_BYTE MOVLW 0xAC ; Access Config CALL I2C_SEND_BYTE MOVLW 0x00 ; continuous, polarity=0 CALL I2C_SEND_BYTE CALL I2C_STOP ; Invia Start Convert (0xEE) CALL I2C_START MOVLW DS1621_ADDR CALL I2C_SEND_BYTE MOVLW 0xEE ; Start Convert T CALL I2C_SEND_BYTE CALL I2C_STOP MAIN GOTO MAIN ; configurazione completata ; ============================================================ ; I2C_START — genera condizione di START (SDA↓ mentre SCL alto) ; ============================================================ I2C_START BSF STATUS,RP0 BSF SSPCON2,SEN ; invia START BCF STATUS,RP0 I2C_START_WAIT BSF STATUS,RP0 BTFSC SSPCON2,SEN ; SEN=0 quando START completato GOTO I2C_START_WAIT BCF STATUS,RP0 RETURN ; ============================================================ ; I2C_STOP — genera condizione di STOP (SDA↑ mentre SCL alto) ; ============================================================ I2C_STOP BSF STATUS,RP0 BSF SSPCON2,PEN ; invia STOP BCF STATUS,RP0 I2C_STOP_WAIT BSF STATUS,RP0 BTFSC SSPCON2,PEN ; PEN=0 quando STOP completato GOTO I2C_STOP_WAIT BCF STATUS,RP0 RETURN ; ============================================================ ; I2C_SEND_BYTE — trasmette byte in W, aspetta ACK ; Copia W in SSPBUF, attende fine trasmissione ; ============================================================ I2C_SEND_BYTE MOVWF SSPBUF ; carica byte da trasmettere I2C_TX_WAIT BSF STATUS,RP0 BTFSS SSPSTAT,BF ; BF=1 → trasmissione in corso BTFSC SSPCON2,ACKEN ; controlla anche ACKEN GOTO I2C_TX_WAIT ; Controlla ACK ricevuto dallo slave BTFSC SSPCON2,ACKSTAT ; ACKSTAT=0 → ACK OK, =1 → NACK GOTO I2C_NACK ; errore: nessun ACK BCF STATUS,RP0 RETURN I2C_NACK BCF STATUS,RP0 RETURN ; gestione errore (semplificata) END
3 · Lettura DS1621 — sequenza con Repeated START
Leggere un dato da un sensore I²C richiede due fasi: prima si scrive il registro da leggere (0xAA = “Read Temperature”), poi si rilancia una condizione di Repeated START senza liberare il bus e si invia l’indirizzo in modalità lettura (bit R/W=1). Lo slave risponde con i dati. Il master segnala la fine della lettura con un NACK prima dell’ultimo byte, poi invia STOP.
; ============================================================ ; Lezione 28 — I2C: lettura temperatura da DS1621 ; Sequenza: START → addr+W → 0xAA → RESTART → addr+R → leggi → STOP ; PIC16F877A @ 4 MHz, I2C 100kHz ; DS1621 restituisce 2 byte: integer (°C) + 0x80 se +0.5°C ; ============================================================ LIST P=16F877A #INCLUDE <p16f877a.inc> __CONFIG _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF & _BOREN_OFF & _LVP_OFF #DEFINE DS1621_W 0x90 ; addr + write (R/W=0) #DEFINE DS1621_R 0x91 ; addr + read (R/W=1) CBLOCK 0x20 TEMP_INT ; gradi interi (con segno, complemento a 2) TEMP_FRAC ; 0x00=.0°C, 0x80=.5°C I2C_RX_BYTE ; byte ricevuto tramite I2C ENDC ORG 0x0000 GOTO INIT ORG 0x0005 INIT ; (configurazione MSSP come lez. 28 programma 1) BSF STATUS,RP0 BSF TRISC,3 BSF TRISC,4 MOVLW D'9' MOVWF SSPADD MOVLW b'10000000' MOVWF SSPSTAT BCF STATUS,RP0 MOVLW b'00101000' MOVWF SSPCON ; Avvia conversione continua (già configurato) MAIN CALL DS1621_READ_TEMP ; TEMP_INT = temperatura in gradi (es. 23 → 0x17) ; TEMP_FRAC = 0x00 (.0°C) o 0x80 (.5°C) ; Qui potremmo trasmettere via UART (vedi lez. 26) CALL DELAY_1S GOTO MAIN ; ============================================================ ; DS1621_READ_TEMP ; Legge 2 byte di temperatura e li salva in TEMP_INT, TEMP_FRAC ; Sequenza I2C: S → 0x90 → 0xAA → Rs → 0x91 → RX → RX → P ; ============================================================ DS1621_READ_TEMP ; 1. Invia comando "Read Temperature" (0xAA) CALL I2C_START MOVLW DS1621_W CALL I2C_SEND MOVLW 0xAA ; Read Temperature command CALL I2C_SEND ; 2. Repeated START + indirizzo in lettura CALL I2C_RESTART MOVLW DS1621_R ; 0x91 CALL I2C_SEND ; 3. Ricevi byte integer (ACK dal master → vogliamo il secondo) CALL I2C_RECV_ACK ; ricevi con ACK (seguirà altro byte) MOVF SSPBUF,W MOVWF TEMP_INT ; 4. Ricevi byte frazionario (NACK → ultimo byte) CALL I2C_RECV_NACK ; ricevi con NACK (fine lettura) MOVF SSPBUF,W MOVWF TEMP_FRAC CALL I2C_STOP RETURN ; ============================================================ ; I2C_START ; ============================================================ I2C_START BSF STATUS,RP0 BSF SSPCON2,SEN BCF STATUS,RP0 IS_W BTFSC SSPSTAT,S ; attendi S=1 (START sul bus) GOTO $+2 GOTO IS_W RETURN ; ============================================================ ; I2C_RESTART — Repeated START (senza STOP intermedio) ; ============================================================ I2C_RESTART BSF STATUS,RP0 BSF SSPCON2,RSEN ; Repeated START BCF STATUS,RP0 IRS BSF STATUS,RP0 BTFSC SSPCON2,RSEN GOTO IRS BCF STATUS,RP0 RETURN ; ============================================================ ; I2C_STOP ; ============================================================ I2C_STOP BSF STATUS,RP0 BSF SSPCON2,PEN BCF STATUS,RP0 IP_W BSF STATUS,RP0 BTFSC SSPCON2,PEN GOTO IP_W BCF STATUS,RP0 RETURN ; ============================================================ ; I2C_SEND — trasmette W, attende completamento ; ============================================================ I2C_SEND MOVWF SSPBUF ITW BSF STATUS,RP0 BTFSS SSPSTAT,BF BTFSC SSPCON2,ACKSTAT GOTO ITW BCF STATUS,RP0 RETURN ; ============================================================ ; I2C_RECV_ACK — riceve byte, risponde ACK (altri byte seguono) ; ============================================================ I2C_RECV_ACK BSF STATUS,RP0 BSF SSPCON2,RCEN ; abilita ricezione BCF STATUS,RP0 IRW BSF STATUS,RP0 BTFSS SSPSTAT,BF ; attendi buffer pieno GOTO IRW ; Invia ACK (ACKDT=0=ACK, poi ACKEN=1 per inviarlo) BCF SSPCON2,ACKDT ; ACK BSF SSPCON2,ACKEN ; invia ACK IAW BTFSC SSPCON2,ACKEN GOTO IAW BCF STATUS,RP0 RETURN ; ============================================================ ; I2C_RECV_NACK — riceve byte, risponde NACK (fine lettura) ; ============================================================ I2C_RECV_NACK BSF STATUS,RP0 BSF SSPCON2,RCEN BCF STATUS,RP0 INW BSF STATUS,RP0 BTFSS SSPSTAT,BF GOTO INW BSF SSPCON2,ACKDT ; NACK (=1) BSF SSPCON2,ACKEN INA BTFSC SSPCON2,ACKEN GOTO INA BCF STATUS,RP0 RETURN DELAY_1S MOVLW D'100' MOVWF 0x70 DLA MOVLW D'250' MOVWF 0x71 DLB MOVLW D'40' MOVWF 0x72 DLC DECFSZ 0x72,F GOTO DLC DECFSZ 0x71,F GOTO DLB DECFSZ 0x70,F GOTO DLA RETURN END
4 · LCD via PCF8574 — nibble mode e mapping bit
Il PCF8574 è un I/O expander I²C a 8 bit: riceve un byte via I²C e porta i suoi 8 pin di output al livello corrispondente. Connettendo questi 8 pin all’LCD HD44780 si ottiene un LCD I²C. Il mapping standard assegna P7:P4 ai dati D7:D4, P3 al backlight, P2 al segnale EN (enable), P1 a R/W (tenuto sempre basso = write), P0 a RS (0=comando, 1=dato). Poiché si usano solo i 4 bit alti del bus dati, si lavora in nibble mode: ogni byte dell’LCD richiede due trasferimenti I²C, uno per il nibble alto e uno per il nibble basso, ciascuno con uno strobe dell’EN.
⚠️ Attenzione al delay post-comando: l’LCD HD44780 richiede tempi di esecuzione diversi per comandi diversi. Il comando “Clear Display” (0x01) richiede ~1.52ms, gli altri comandi ~37µs, la scrittura di caratteri ~37µs. Il DELAY_1MS usato in questo esempio è sicuro per tutti i casi ma rallenta la scrittura. In applicazioni ad alta velocità si usa il busy flag (bit DB7 letto con RS=0, R/W=1) invece dei delay fissi.
; ============================================================ ; Lezione 28 — I2C: scrittura su LCD con PCF8574 I/O expander ; PCF8574 addr: 0x40 (A2=A1=A0=0), controlla LCD HD44780 via I2C ; Nibble mode: D7-D6-D5-D4-BL-EN-RW-RS ; PIC16F877A @ 4 MHz, I2C 100kHz ; ============================================================ LIST P=16F877A #INCLUDE <p16f877a.inc> __CONFIG _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF & _BOREN_OFF & _LVP_OFF #DEFINE LCD_ADDR 0x40 ; PCF8574 write address #DEFINE BL b'00001000' ; backlight bit #DEFINE EN b'00000100' ; enable strobe #DEFINE RW b'00000010' ; 0=write (sempre 0 qui) #DEFINE RS_CMD 0x00 ; RS=0: command #DEFINE RS_DATA 0x01 ; RS=1: data CBLOCK 0x20 LCD_BYTE ; byte da inviare all'LCD LCD_NIBBLE ; nibble corrente LCD_RS ; 0=command, 1=data I2C_TEMP ; registro temporaneo I2C ENDC ORG 0x0000 GOTO INIT ORG 0x0005 INIT ; Init MSSP BSF STATUS,RP0 BSF TRISC,3 BSF TRISC,4 MOVLW D'9' MOVWF SSPADD MOVLW b'10000000' MOVWF SSPSTAT BCF STATUS,RP0 MOVLW b'00101000' MOVWF SSPCON ; Delay power-up LCD: 50ms CALL DELAY_50MS ; Sequenza init LCD 4-bit CALL LCD_INIT ; ============================================================ ; MAIN: stampa "Hello PIC!" sulla prima riga ; ============================================================ MAIN MOVLW 0x80 ; DDRAM addr 0x00 (riga 1, col 0) MOVWF LCD_BYTE CLRF LCD_RS CALL LCD_SEND MOVLW 'H' CALL LCD_PUTCHAR MOVLW 'e' CALL LCD_PUTCHAR MOVLW 'l' CALL LCD_PUTCHAR MOVLW 'l' CALL LCD_PUTCHAR MOVLW 'o' CALL LCD_PUTCHAR MOVLW ' ' CALL LCD_PUTCHAR MOVLW 'P' CALL LCD_PUTCHAR MOVLW 'I' CALL LCD_PUTCHAR MOVLW 'C' CALL LCD_PUTCHAR MOVLW '!' CALL LCD_PUTCHAR ; Seconda riga MOVLW 0xC0 ; DDRAM addr 0x40 (riga 2) MOVWF LCD_BYTE CLRF LCD_RS CALL LCD_SEND MOVLW 'I' CALL LCD_PUTCHAR MOVLW '2' CALL LCD_PUTCHAR MOVLW 'C' CALL LCD_PUTCHAR MOVLW ' ' CALL LCD_PUTCHAR MOVLW 'O' CALL LCD_PUTCHAR MOVLW 'K' CALL LCD_PUTCHAR LOOP GOTO LOOP ; ============================================================ ; LCD_PUTCHAR — invia carattere ASCII in W all'LCD ; ============================================================ LCD_PUTCHAR MOVWF LCD_BYTE MOVLW 1 MOVWF LCD_RS ; RS=1 (data) CALL LCD_SEND RETURN ; ============================================================ ; LCD_SEND — invia LCD_BYTE in nibble mode via PCF8574 ; Prima il nibble alto, poi il nibble basso ; ============================================================ LCD_SEND ; Nibble alto (bit7:4) MOVF LCD_BYTE,W ANDLW 0xF0 ; mantieni solo bit7:4 MOVWF LCD_NIBBLE ; Aggiungi RS e BL MOVF LCD_RS,F BTFSC STATUS,Z GOTO LCD_NO_RS_H MOVF LCD_NIBBLE,W IORLW RS_DATA MOVWF LCD_NIBBLE LCD_NO_RS_H MOVF LCD_NIBBLE,W IORLW BL ; sempre backlight acceso ; Strobe EN: alto → basso MOVWF I2C_TEMP IORWF I2C_TEMP,W CALL PCF8574_SEND ; EN=0 MOVF I2C_TEMP,W IORLW EN ; EN=1 CALL PCF8574_SEND CALL DELAY_1MS MOVF I2C_TEMP,W ANDLW b'11111011' ; EN=0 CALL PCF8574_SEND ; Nibble basso (bit3:0 → sposta in posizione 7:4) MOVF LCD_BYTE,W ANDLW 0x0F BCF STATUS,C RLF LCD_NIBBLE,F ; × 2 RLF LCD_NIBBLE,F ; × 4 RLF LCD_NIBBLE,F ; × 8 RLF LCD_NIBBLE,F ; × 16 (nibble basso ora in bit7:4) MOVWF LCD_NIBBLE MOVF LCD_RS,F BTFSC STATUS,Z GOTO LCD_NO_RS_L MOVF LCD_NIBBLE,W IORLW RS_DATA MOVWF LCD_NIBBLE LCD_NO_RS_L MOVF LCD_NIBBLE,W IORLW BL MOVWF I2C_TEMP IORLW EN CALL PCF8574_SEND ; EN=1 CALL DELAY_1MS MOVF I2C_TEMP,W ANDLW b'11111011' CALL PCF8574_SEND ; EN=0 CALL DELAY_1MS RETURN ; ============================================================ ; LCD_INIT — sequenza di inizializzazione HD44780 in 4-bit ; ============================================================ LCD_INIT CALL DELAY_50MS MOVLW 0x30 ; Function Set 8-bit (3×) CALL LCD_PULSE CALL DELAY_5MS MOVLW 0x30 CALL LCD_PULSE CALL DELAY_1MS MOVLW 0x30 CALL LCD_PULSE MOVLW 0x20 ; Switch to 4-bit CALL LCD_PULSE ; Ora in 4-bit: invia comandi completi MOVLW 0x28 ; 4-bit, 2 righe, 5×8 MOVWF LCD_BYTE CLRF LCD_RS CALL LCD_SEND MOVLW 0x0C ; Display ON, cursor OFF MOVWF LCD_BYTE CALL LCD_SEND MOVLW 0x01 ; Clear display MOVWF LCD_BYTE CALL LCD_SEND CALL DELAY_5MS MOVLW 0x06 ; Entry mode: increment, no shift MOVWF LCD_BYTE CALL LCD_SEND RETURN LCD_PULSE MOVWF I2C_TEMP IORLW BL IORLW EN CALL PCF8574_SEND CALL DELAY_1MS MOVF I2C_TEMP,W IORLW BL ANDLW b'11111011' CALL PCF8574_SEND CALL DELAY_1MS RETURN ; ============================================================ ; PCF8574_SEND — invia W al PCF8574 via I2C ; ============================================================ PCF8574_SEND MOVWF I2C_TEMP ; START BSF STATUS,RP0 BSF SSPCON2,SEN BCF STATUS,RP0 PS1 BSF STATUS,RP0 BTFSC SSPCON2,SEN GOTO PS1 BCF STATUS,RP0 ; Indirizzo MOVLW LCD_ADDR MOVWF SSPBUF PS2 BSF STATUS,RP0 BTFSS SSPSTAT,BF GOTO PS2 BCF STATUS,RP0 ; Dato MOVF I2C_TEMP,W MOVWF SSPBUF PS3 BSF STATUS,RP0 BTFSS SSPSTAT,BF GOTO PS3 BCF STATUS,RP0 ; STOP BSF STATUS,RP0 BSF SSPCON2,PEN BCF STATUS,RP0 PS4 BSF STATUS,RP0 BTFSC SSPCON2,PEN GOTO PS4 BCF STATUS,RP0 RETURN DELAY_50MS MOVLW D'50' MOVWF 0x70 D5A CALL DELAY_1MS DECFSZ 0x70,F GOTO D5A RETURN DELAY_5MS MOVLW D'5' MOVWF 0x70 D1A CALL DELAY_1MS DECFSZ 0x70,F GOTO D1A RETURN DELAY_1MS MOVLW D'250' MOVWF 0x71 D1B DECFSZ 0x71,F GOTO D1B RETURN END
🧪 Prova tu
- Nel simulatore, carica il programma 1. Nel pannello I²C configura uno slave con indirizzo 0x48 (DS1621 con tutti i pin di indirizzo a 0). Esegui step by step: verifica che dopo I2C_START il bit S di SSPSTAT diventi 1, e che dopo I2C_SEND_BYTE il bit ACKSTAT di SSPCON2 sia 0 (ACK ricevuto).
- Modifica il programma 2 per stampare la temperatura via UART nel formato “T=+023.5C “. Usa TEMP_INT per i gradi (controlla il segno: se bit7=1 è negativo, calcola il valore assoluto con COMF+ADDLW 1), TEMP_FRAC per decidere se aggiungere “.0” o “.5”.
- Carica il programma LCD. Verifica nel pannello I²C la sequenza di byte inviati al PCF8574. Il primo byte per ‘H’ dovrebbe essere 0x4D (nibble alto con EN=1, BL=1, RS=1), poi 0x49 (EN=0). Calcola manualmente il byte per il nibble basso di ‘H’.
- Sfida: combina il DS1621 e l’LCD in un unico programma: leggi la temperatura ogni secondo e visualizzala sulla riga 2 dell’LCD, mantenendo “Hello PIC!” fisso sulla riga 1. Entrambi i device sono sullo stesso bus I²C — il master gestisce alternandosi tra i due indirizzi (0x90 per DS1621, 0x40 per PCF8574).
❓ Quiz rapido
1. Perché RC3 e RC4 vanno configurati come input (TRISC,3=1 e TRISC,4=1) anche se il modulo MSSP usa queste linee come output?
Mostra risposta
Il bus I²C usa linee open-drain: ogni dispositivo può solo portare la linea a 0 (assorbendo corrente), mai a 1. Il livello alto viene garantito dalla resistenza di pull-up esterna. Sul PIC16F877A, quando il modulo MSSP è attivo e TRISC è configurato come input, il modulo MSSP prende il controllo dei driver dei pin in modo open-drain. Se TRISC fosse 0 (output), il latch di output del GPIO sovrascrive il modulo MSSP e la linea potrebbe essere forzata a 1 dal PIC stesso, violando il protocollo open-drain e causando conflitti di bus se uno slave tenta di portare la linea a 0.
2. Cosa succederebbe se si omettesse il Repeated START e si usasse invece STOP + START per la fase di lettura dal DS1621?
Mostra risposta
Funzionerebbe comunque in molti casi, ma è meno affidabile. Il Repeated START mantiene il master in controllo del bus senza liberarlo: nessun altro master (in sistemi multi-master) può inserirsi tra la scrittura del comando e la lettura. Con STOP+START c’è una finestra temporale durante la quale un altro master potrebbe acquisire il bus e inviare una transazione diversa al DS1621, resettando il puntatore del registro interno. Il DS1621 specificatamente richiede il Repeated START per garantire che si stia leggendo il registro appena comandato.
3. Il PCF8574 ha indirizzo I²C 0x40 con A2=A1=A0=0. Se si vogliono 2 LCD sullo stesso bus, quali indirizzi si usano?
Mostra risposta
Il PCF8574 ha indirizzo base 0x40 (0100 000x dove x=R/W). I bit A2:A0 sono configurabili hardware collegando i pin corrispondenti a Vdd o Vss: A2=A1=A0=0 → 0x40; A0=1 → 0x42; A1=1 → 0x44; A2=1 → 0x48. Per due LCD si usano 0x40 e 0x42 (diversi solo per A0). Sullo stesso bus si possono avere fino a 8 PCF8574 (indirizzi 0x40, 0x42, 0x44, 0x46, 0x48, 0x4A, 0x4C, 0x4E), permettendo 8 LCD indipendenti. Il DS1621 (indirizzo base 0x90) non confligge perché ha un indirizzo di base diverso.
Prossima lezione →
Lezione 29 — SPI: comunicazione ad alta velocità
Il modulo MSSP in modalità SPI Master. Lettura da ADC esterno MCP3204, scrittura su DAC MCP4921 e controllo di display OLED SSD1306.
© Prof. D. Bertolino · PIC16 From Zero to Hero · WebPicSimulator · Lezione 28