Il programma esegue una funzione ad interrupt ogni tot tempo che fa lampeggiare il led 13 e stampa su seriale il messaggio "POPIPOPI"
Poi nel void loop() ad ogni secondo, quindi un ciclo più lento, stampa un messaggio seriale che scrive "Ciao a tutti!"
DUBBI CHE MI CHIEDO:
1)Quando parte l'interrupt per ogni tot tempo, se il programma, dentro l'interrupt stesso, è molto lento più di quanto è il tempo di richiamo dell'interrupt succede che si auto richiama? E fa pasticci?
2)Quando scrivo un messaggio via seriale il singolo invio dei byte viene fatto tutto d'un colpo?
O può succedere che se invio un stringa di tanti caratteri succede che mi vengono stampati i primi tot poi capita l'interrupt e poi riprende a stampare?
3)La seriale print() e write() sono gestite da un interrupt prioritario?
4)Il programma che ho allegato sembra funzionare e non noto che il messaggio "POPIPOPI" venga spezzettato pensando di vedere per esempio:
POPIPOPI
POPCiao a tuIPOPItti! < Quello che penso succeda :frowning:
POPIPOPI
POPIPOPI
Ciao a tutti!
POPIPOPI
ecc ecc
Ho letto dei post che avevano dubbi simili e qualcuno diceva che aveva pasticci con la seriale e con gli interrupt con i timer... BHO...
Stai violando TUTTE le regole di una ISR ... la quale DEVE essere la più veloce possibile, NON deve usare la seriale né altre cose che usano interrupts ... per cui ... è normale che tu abbia malfunzionamenti!
Nella ISR pochissime cose ... l'incremento di un contatore, l'ouput su un pin, il set di una flasg e poco altro, il resto ... FUORI dalla ISR.
Scusa Guglielmo ma hai letto TUTTO il mio post?
Se mi dici che è normale che abbia malfunzionamenti quando HO SCRITTO CHE FUNZIONA c'è qualcosa che non va ahah...
Ho detto che il programma funziona perfettamente NON che non funziona.
NON cambia quello che ti ho scritto ... è cosa che NON si deve fare e ... se funziona è un caso (ma comunque dubito che in situazioni più complesse funzioni correttamente).
Come ho scritto sopra quella ISR è concettualmente SBAGLIATA ... poi fai come vuoi ...
Guglielmo
P.S.: Studiati QUESTA pagina ... priôprio all'inizio ci sono le "regole fondamentali"
E' il modo più pulito che si usa spessissimo, ad esempio, quando c'è di mezzo un RTOS ... si chiama "deferred interrupt" ... nell'interrupt alzi una flag per indicare che l'interrupt è avvenuto, altrove verifichi la flag e, se la trovi attiva, fai quello che devi fare
SI, per non perdere caratteri e velocizzare il tutto, normalmente si usano gli interrupt nella gestione di vari bus, incluso le trasmissioni seriali via UART.
Non è meglio, è OBBLIGATORIO ... devi avvisare il compilatore che quella variabile può essere modificata indipendentemente dal flusso del programma (es. all'interno della ISR che non fa parte del normale flusso del programma). Inoltre eviti che, durante la fase di ottimizzazione del compilato, magari non vedendo nulla che la modifica (ad esempio la modifica avviene in una ISR che non fa parte del regolare flusso del programma) la elimini o faccia ... altri danni
NO, se vai a vedere come funziona nel "core" Arduino UNO la ricezione di dati dalla seriale, vedrai che è fatta ad interrupt, ma ... essendo tu già in una ISR e NON avendo le MCU AVR una gestione prioritaria a livelli degli interrupts, gli interrupt sono disabilitati fino a quando non esci dalla ISR e quindi NON puoi usare altre cose che usano gli interrupts.
La cosa sarebbe differente su MCU più complesse (tipicamente a 32 bit) che sono in grado di gestire più livelli di interrupt con vari gradi di priorità ...
Mmmm ... evidentemente perdi troppo tempo nel loop() ... puoi provare a mettere le mani nel "core" Arduino della UNO per aumentare le dimensioni del buffer seriale (studiandoti il file HardwareSerial.h ed applicando li la modifica), anche se è cosa che io sconsiglio sempre (possibilità di introdurre errori, obbligo di dover rifare la modifica ogni volta che Arduino aggiorna il "core", ecc.), oppure ... cambiare scheda e passare a schede più veloci, con più memoria e con buffer seriali di maggiori dimensioni.
Comunque qui parecchi usano la UNO per il MIDI e nessuno ha mai lamentato i tuoi problemi quindi ... rivedi bene il tuo programma, perché forse va migliorato/corretto.
Ho letto tutti gli interventi e qui c'è da chiarire.
All'interno della ISR puoi usare Serial.read(), Serial.available().
Se ci sono dati nel buffer ring che vive in memoria ram otterrai i dati.
Durante la ISR non potranno essere inseriti dati nel buffer ring ecco anche perché la ISR dovrebbe impegnare pochi cicli di CPU e terminare.
quindi leggo il messaggio seriale lo metto in una variabile globale dichiarata volatile per poi leggerla nel loop() giusto?
poi intendi che quando la cpu esegue l'interrupt per leggere i dati seriali nel buffer in quel preciso momento essa non puo' riceve altri dati seriali provenienti dall'esterno?
avevo letto che la recezione dei bytes seriali è di tipo hardware non gira su software... poi il software gestisce la lettura effettiva dei dati nel buffer nella memoria ram dedicata per tali dati...
Stai solo creando confusione ...
... la ricezione dei dati avviene via interrupt e quindi, quando si è in una ISR NON si ricevono dati. Ovvio che, se PRIMA di entrare nella ISR sono arrivati dei dati e NON sono stati letti, stanno nel buffer, ma NON stai ricevendo dei dati, stai leggendo un'area di memoria.
Dato che il suo problema è ricevere dati all'interno di una ISR (e non semplicemente svuotare il buffer circolare) ... NON si risolve il suo problema.
Continua a dire che c'è un problema nel suo programma, qui tantissimi usano MIDI con la UNO senza tutti questi problemi ...
Si la periferica UART è hardware, ma riguardo al buffer hardware questo è grande un solo byte, il nome di questo buffer hardware è UDR0 che sostanzialmente è un registro mappato su RAM. Quando un byte viene ricevuto da UART viene messo in UDR0 e se abilitati (gli interrupt) la UART solleva una IRQ specifica, alla IRQ è associata una ISR che ha il compito di leggere UDR0 e salvarlo nel buffer ring.
ISR (Interrupt Service Routine)
IRQ (Interrupt Request)
Trovi tutti i dettagli nel datasheet della MCU ATmega328P
Ciao.