I2C con expander PCF8574

  • Mauro Laurenti
  • Moderatore
  • Moderatore
Di più
15 Anni 5 Mesi fa #11 da Mauro Laurenti
Risposta da Mauro Laurenti al topic Re: I2C con expander PCF8574
Ciao,

una precisazione.
Se hai modo di testare la funzione per leggere gli ingressi, ricorda che il pin da utilizzare come ingresso deve valere 1.

Questa e' anche la ragione per cui di default la porta viene settata con tutti i pin ad 1.

Collegando un pin a massa dovrai leggere 0 mentre lasciando il pin aperto leggerai 1.

Saluti,

Mauro

Si prega Accesso o Crea un account a partecipare alla conversazione.

  • Ricky85
  • Autore della discussione
  • Anziano Utente
  • Anziano Utente
Di più
15 Anni 5 Mesi fa #12 da Ricky85
Risposta da Ricky85 al topic Re: I2C con expander PCF8574
Ecco lo schema elettrico della prova precedente!

Ora faccio qualche test anche per la lettura...

Si prega Accesso o Crea un account a partecipare alla conversazione.

  • Ricky85
  • Autore della discussione
  • Anziano Utente
  • Anziano Utente
Di più
15 Anni 5 Mesi fa #13 da Ricky85
Risposta da Ricky85 al topic Re: I2C con expander PCF8574
Ed ecco la prova in lettura...

Ho aggiunto un terzo PCF8574A ed un interruttore 3 vie.

In posizione 0 ho tutti i led spenti, in posizione 1 si accendono i 4 led meno significativi del expander 1, in posizione 2 si accendono i 4 led più significativi del expander 1.



Code:
#include <p18f4550.h> #include <PCF8574.h> #include <delay.h> #pragma config FOSC = HS #pragma config WDT = OFF #pragma config LVP = OFF #pragma config PBADEN = OFF char i; unsigned char data =0b11111111; unsigned char add1 = 0b01110000; //indirizzo del primo expander unsigned char add2 = 0b01110010; //Indirizzo del secondo expander unsigned char add3 = 0b01110100; //Indirizzo del terzo expander void main (void){ // Imposto PORTA tutti ingressi LATA = 0x00; TRISA = 0xFF; // Imposto PORTB tutti ingressi LATB = 0x00; TRISB = 0xFF; // Imposto PORTC tutti ingressi, RC1 come output LATC = 0x00; TRISC = 0b11111101; // Imposto PORTD tutte uscite LATD = 0x00; TRISD = 0x00; // Imposto PORTE tutti ingressi LATE = 0x00; TRISE = 0xFF; // Inizializza il modulo I2C a 100KHz @20MHz OpenI2C(MASTER, SLEW_OFF); SSPADD = 49; PCF8574_write_data (add1, 0b01010101); //Spengo tutti i led sul primo expander PCF8574_write_data (add2, 0b11111111); //Spengo tutti i led sul secondo expander delay_ms (1000); //Pausa per vedere che si sia spento tutto while (1) { unsigned char I2C_data = 0b11111110; unsigned char next_step = 1; //Variabile per il calcolo dei bit da spingere verso gli expander PCF8574_read_data (add3, &data); if (data == 0b11111111){ PCF8574_write_data (add1, 0b11111111); } else if (data == 0b11111110){ PCF8574_write_data (add1, 0b00001111); } else if (data == 0b11111101){ PCF8574_write_data (add1, 0b11110000); } delay_ms (500); } }

ed ecco lo schema...

File allegato:

Nome del file: 2_exp_out_...p_in.pdf
Dimensione del file:55.15 KB


Ora preparo una prova un po più "complessa"...

Si prega Accesso o Crea un account a partecipare alla conversazione.

  • Ricky85
  • Autore della discussione
  • Anziano Utente
  • Anziano Utente
Di più
15 Anni 5 Mesi fa #14 da Ricky85
Risposta da Ricky85 al topic Re: I2C con expander PCF8574
Ecco un altro piccolo esempio...

Questa volta sfruttando la linea di interrupt dell'integrato PCF8574A
Code:
#include <p18f4550.h> #include <PCF8574.h> #include <portb.h> #include <delay.h> #pragma config FOSC = HS #pragma config WDT = OFF #pragma config LVP = OFF #pragma config PBADEN = OFF int counter_stop (void); int counter_up (void); int counter_down (void); char i; unsigned char senso = 0b11111110; unsigned char data; unsigned char data_old = 0b11111110; unsigned char counter_direction = 0; unsigned char next_step = 1; unsigned char next_step_old = 1; unsigned char add1 = 0b01110000; //indirizzo del primo expander unsigned char add2 = 0b01110010; //Indirizzo del secondo expander unsigned char add3 = 0b01110100; //Indirizzo del secondo expander unsigned char I2C_data = 0b11111110; unsigned char I2Cdata_old; //Prototipo di funzione void High_Int_Event (void); //Interrupt vector Alta priorità #pragma code high_interrupt_vector = 0x08 void high_interrupt (void) { // Salto per la gestione dell'interrupt _asm GOTO High_Int_Event _endasm } #pragma code #pragma interrupt High_Int_Event //Funzione per la gestione dell'interruzione void High_Int_Event (void) { //Indice per l'antirimbalzo int i; // Controllo che l'interrupt sia stato generato da PORTB // Resetto il flag d'interrupt per permettere nuove interruzioni //USARE SEMPRE// Per chiudere l'interrupt INTCONbits.RBIF = 0; //Controllo la presenza del interrupt su RB4 if (PORTBbits.RB4 == 0) { for (i=0;i<25000;i++) { } if (PORTBbits.RB4 == 0) { PCF8574_read_data (add3, &data); if (data == 0b11111111){ counter_stop(); } else if (data == 0b11111110){ counter_up(); } else if (data == 0b11111101){ counter_down(); } } } } void main (void){ // Imposto PORTA tutti ingressi LATA = 0x00; TRISA = 0xFF; // Imposto PORTB tutti ingressi LATB = 0x00; TRISB = 0xFF; // Imposto PORTC tutti ingressi, RC1 come output LATC = 0x00; TRISC = 0b11111101; // Imposto PORTD tutte uscite LATD = 0x00; TRISD = 0x00; // Imposto PORTE tutti ingressi LATE = 0x00; TRISE = 0xFF; // Abilita i resistori di pull-up sulla PORTB //USARE SEMPRE// EnablePullups(); // Abilito le interruzioni su PORTB //USARE SEMPRE// INTCONbits.RBIE = 1; // Abilito modalità compatibile (di default vale già 0) //USARE SEMPRE// RCONbits.IPEN = 0; // Abilito l'interrupt globale //USARE SEMPRE// INTCONbits.GIE = 1; // Abilito l'interrupt periferiche //USARE SEMPRE// INTCONbits.PEIE = 1 ; // Inizializza il modulo I2C a 100KHz @20MHz OpenI2C(MASTER, SLEW_OFF); SSPADD = 49; PCF8574_write_data (add1, 0b11111110); //Spengo tutti i led sul primo expander PCF8574_write_data (add2, 0b11111111); //Spengo tutti i led sul secondo expander delay_ms (50); //Pausa per vedere che si sia spento tutto while (1) { if (counter_direction == 0){ PCF8574_write_data (add1, data_old); } else if (counter_direction == 1){ PCF8574_write_data (add1, I2C_data); data_old=I2C_data; next_step_old = next_step; if (I2C_data <= 0b01111111){ I2C_data = 0b11111110; delay_ms (500); PCF8574_write_data (add1, I2C_data); next_step = 1; } (I2C_data=I2C_data-next_step); (next_step=next_step*2); delay_ms (500); } else if (counter_direction == 2){ PCF8574_write_data (add1, I2C_data); data_old=I2C_data; next_step_old = next_step; if (I2C_data >= 0b11111110){ I2C_data = 0b01111111; delay_ms (500); PCF8574_write_data (add1, I2C_data); next_step = 64; } (I2C_data=I2C_data+next_step); (next_step=next_step/2); delay_ms (500); } } } int counter_stop (void){ counter_direction=0; } int counter_up (void){ next_step=next_step_old; counter_direction=1; } int counter_down (void){ next_step=next_step_old; counter_direction=2; }

Come schema è valido il precedente, tranne l'aggiunta di un collegamento tra la linea INT del integrato PCF8574A verso il pin RB4 del PIC18F4550

Ed ecco l'effetto finale...

Video2

Si prega Accesso o Crea un account a partecipare alla conversazione.

  • Mauro Laurenti
  • Moderatore
  • Moderatore
Di più
15 Anni 5 Mesi fa #15 da Mauro Laurenti
Risposta da Mauro Laurenti al topic Re: I2C con expander PCF8574
ottimo.

solo due note:

1) La linea di INT suppongo sia collegata con resistore di pull-up (da 4.7Kohm). Non lo hai specificato ma deve essere fatto in questo modo, visto che la linea INT e´ un Open Drain (osservazione a trabocchetto).

2) Nella routine d´interrupt il flag per permettere nuove interruzioni deve essere riabilitato alla fine e non all´inizio.

3) In questo caso hai una sola sorgente d´interrupt, ma e´ sempre bene controllare chi ha generato l´interrupt.

4) Ottimo lo stile di programmazione. Unica inconsistenza e´ che alcuni commenti sono sulla stessa linea, mentre gran parte sono posti sopra la linea (cosa da preferire per indentare il commento con l´istruzione).

Ultimo suggerimento, dai un nome al video altrimenti non avrà molta visibilità su Youtube. I video consigliati insieme al tuo sono quelli di persone che hanno la tua stessa camera e non hanno cambiato il nome! :)

Ciao,

Mauro

Si prega Accesso o Crea un account a partecipare alla conversazione.

Moderatori: Mauro LaurentiPinnaStefAMatteo Garia

Registrati al sito

Accedi a tutte le risorse e articoli non visibili pubblicamente, puoi registrarti con pochi passi.

Registrati al sito LaurTec.