I2C con expander PCF8574
- Mauro Laurenti
-
- Moderatore
-
Less
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
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
-
Less
Di più
- Messaggi: 50
- Ringraziamenti ricevuti 0
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...
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
-
Less
Di più
- Messaggi: 50
- Ringraziamenti ricevuti 0
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.
ed ecco lo schema...
Ora preparo una prova un po più "complessa"...
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...
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
-
Less
Di più
- Messaggi: 50
- Ringraziamenti ricevuti 0
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
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
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.
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
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 Laurenti, Pinna, StefA, Matteo Garia
Registrati al sito
Accedi a tutte le risorse e articoli non visibili pubblicamente, puoi registrarti con pochi passi.
