Salve a tutti del forum.
Non so se posso pubblicare il codice che ho sviluppato per verificare la shield MCP23017 (usando solo la libreria Wire.h)
La mia perplessità riguarda il funzionamento dell'interrupt di Arduino e le sue limitazioni.
In particolare al metodo: attachInterrupt(digitalPinToInterrupt(intPin), ISR, mode);
In effetti il codice di Arduino è composto dai seguenti metodi:
volatile boolean var
MCPIntA() - Legge dalla GPIOA dell'MCP23017 e scrive nel DEFVAL il valore letto
mc_write() - Sequenza di lettura i2c
mc_read() - Sequenza di scrittura i2c
refresh()
imposta una var.boolean a true (questo metodo è richiamato dall'interrupt).
setup() richiama diversi metodi per:
configurare Il registro B di Arduino
ottenere l'indirizzo della shield con a bordo MCP23017
configurare i registri dell'MCP23017 (IO - Interrupt - etc)
configurare la Serial (Monitor)
configurazione dell'interrupt lato arduino mediante il metodo "attachInterrupt()" il quale richiama il metodo "refresh()"
loop()
esegue una verifica su una variabile booleana (la quale è modificabile solo dal metodo refresh()
Se true
Esegue il metodo MCPIntA().
Reimposta a false la var.booleana.
Ora se il metodo refresh() richiamasse direttamente il metodo MCPIntA(), Arduino si blocca.
Se nel metodo refresh() esegue una operazione su un qualsiasi pin, Arduino si blocca.
Per tutte le operazioni che non riguardano l'IO di Arduino, quest'ultimo non si blocca.
E' normale ?
Grazie per aver letto, ancor di più se mi rispondete
Le ISR, per definizione, DEVONO essere il più breve possibili, quindi, ad esempio, SET di una flag, incremento di una variabile e poco altro ... il resto lo si fa nel loop (es: se la flag è SET allora significa che era scattato l'interrupt e devo fare qualche cosa). Non solo, considera che, quando entri in una ISR, gli interrupt vengono disabilitati, per cui, tutto ciò che è legato ad essi, NON funziona più (es. la funzione delay(), la porta seriale, ecc. ecc.) e vengono automaticamente riabilitati all'uscita dalla ISR.
Quindi, usa la ISR solo per segnalare, ad esempio con una flag che è avvenuto un evento o per gestire dei contatori, ma NON per fare altre cose che impiegano troppo tempo o usano a loro volta degl interrupt.
La digitalWrite() in una ISR DEVE funzionare, se non ti funziona è perché è richiamata in qualche funzione che fa altre cose, che impegna troppo tempo o che, probabilmente, fa a sua volta uso di interrupt.
Il modello sopra esposto funziona se l'ISR si limita solo ad aggiornare una variabile booleana.
Il metodo MCPIntA() richiama due metodi in sequenza quali Lettura di un registro tramite i2C e scrittura su i2c. Potenzialmente devo intendere che quando si entra fisicamente nell'ISR anche le comunicazioni i2c si arrestano e considerando che i metodi readMCP e writeMCP attendono un segnale di fine istruzione dal MCP rimane tutto in un loop aperto.
Non si finisce mai di imparare!!
Grazie
Nick
A proposito, sto usando i registri di Arduino con DDRx/PORTx/PINx e vanno alla grande (grazie ancora).
nmsantarelli:
... Il metodo MCPIntA() richiama due metodi in sequenza quali Lettura di un registro tramite i2C e scrittura su i2c.
... che ti ho detto io ? Quando entri in una ISR gli interrupt sono disabilitati fino a quando non esci ... e cosa credi che usi la libreria Wire per I2C? ... delle temporizzazioni basate su interrupt (basta che vai a studiarti i sorgenti) e quindi, ovviamente, non possono funzionare.