Newsgroup: it.hobby.elettronica.digitale
Titolo: PIC & Interrupts - Problema di overflow

Salve a tutti, sto realizzando un progetto con PIC16F876  in C (High-Tech
C). Ho già realizzato le routine per la gestione della RS232, il mio
problema è invece la gestione degli interrupts al ricevimento dei dati sulla
seriale. Ho scritto il seguente codice ed il problema che si presenta è che
generato il primo interrupt il PIC continua ad eseguire il codice della
routine di interrupt in un loop infinito, senza tornare mai al main. Vi
ringrazio in anticipo, ecco il codice:
#include <pic.h>
#include "serial.c"
#include "delay.c"
void interrupt isr(void){
   GIE = 0;
   if(RCIF){
      RCIF = 0;
      putst("Interrupt!\n"); // Invia tramite seriale la stringa
"Interrupt!"
   }
  GIE = 1;
}
void main(void){
    TRISB = 0;
    serial_setup();
    PIR1 = 0;
    RCIE = 1; // Abilita RX Interrupt
    PEIE = 1; // Abilita Peripheral Interrupt
    GIE = 1;
    while(1){
       PORTB = 0b00000010;
       DelayMs(100);
       PORTB = 0b00000000;
       DelayMs(100);
    }
}

Nessuno mi saprebbe aiutare? E' da ieri che ci sbatto la testa! Grazie in
anticipo...

 }
Non ricordo bene qual è il bit relativo, ma il bit di flag per l'interrupt
deve essere manualmente azzerato. Probabilmente è proprio quel RCIF di cui
parli. Forse è anche bene leggere il registro che contiene il byte appena
ricevuto. Magari mettilo semplicemente in W anche se non ti serve, così
credo si resetti qualcosa.
Sei sicuro che la funzione putst() sia fatta a regola d'arte?
Per provare, fai semplicemente accendere un led (o alzare/abbassare)
un pin del PIC ogni volta che entri nell'interrupt, senza usare
la putst(). Trasmetti un byte alla volta sulla seriale e vide che succede.
Altra possibilità... non è che hai un corto (involontario o meno) tra i due
pin RX e TX della UART? In questo caso tutto quello che trasmetti con
putst() viene anche ricevuto... ed ogni volta che ricevi ritrasmetti quindi
non la finisci più.
Un consiglio. Evita dei gestori di interrupt troppo lunghi, sia in termini
di codice che in termini di tempo d'elaborazione. L'interrupt interrompe
la normale esecuzione del programma per eseguire dei compiti ben precisi
in poco tempo.
A parte che se vuoi trasmettere una stringa ad ogni byte ricevuto puoi
fare un semplice polling nel main() sul bit RCIF... il tuo main è così
piccolo e i dati ricevuti non ti servono neanche.
Se invece, come normalmente accade, ricevere dei byte dalla seriale mentre
fai altre cose, anche molte, ti conviene usare un interrupt di ricezione
come hai fatto tu. Ma il compito ben preciso di cui si deve occupare
l'interrupt è quello di prendere il byte dal registro di ricezione e
memorizzarlo in RAM. Questo ti evita degli overrun nel caso in cui sei
occupato a fare altro e ti stanno arrivando tanti byte insieme dalla
seriale.
Se devi fare qualcosa in funzione del byte che hai ricevuto, lo puoi
fare tranquillamente nel main, analizzando con tutta calma il pacchetto
che hai ricevuto.
Facci sapere.


[CUT]
Devi leggere il registro, ad esempio puoi scrivere:
void interrupt isr(void){
    GIE = 0;
    if(RCIF){
       RCIF = 0;
       SerRx = RCREG;    // legge il carattere presente nel registro di
ricezione
       putst("Interrupt!\n"); // Invia tramite seriale la stringa
       "Interrupt!"
    }
   GIE = 1;
}
dove SerRx lo puoi definire come unsigned char.
Se non effettui la lettura del registro hai due effetti:
- l'interrupt viene sempre chiamato
- rischi un errore di overrun
Fammi sapere
Ciao
Pow

 Facci sapere.
Ti ringrazio per i consigli, li seguirò sicuramente. Naturalmente quello che
ho postato non ha nulla a che vedere con il progetto che sto sviluppando,
era solo uno stralcio di codice scritto per testare il funzionamento degli
interrupts Infatti nel progetto finale il polling non lo posso fare perchè
sicuramente mi perderei qualche byte in ingresso sulla seriale vista la
complessità del programma. Ed ora grazie a voi ho capito dove sbagliavo! Non
so come ringraziarvi, sia tu che POWERMOS mi avete risolto un problema non
da poco! Veramente ottimo questo NG, ora che l'ho scoperto sicuramente
comincerò a seguirlo assiduamente.


Non so come ringraziarti, stavo commettendo un errore di una banaltà
veramente mostruosa! Pensavo che bastasse mettere la flag a 0 (RCIF = 0), ma
giustamente per farlo correttamente dovevo svuotare il buffer come da te
consigliato. Di nuovo grazie, ora funziona alla perfezione.

 }
Premetto che non conosco l'High-Tech C, ma mi sembra
una schifezza chiamare putst("Interrupt!\n") dall'interno di
una isr.
Come regola, una isr deve fare il minimo indispensabile per
gestire l'evento che l'ha causata e ritornare immediatamente.


Ti ringrazio per il consiglio. Ho inserito la putst solo per debugging,
visto che questo è un codice di test per comprendere il funzionamento degli
interrupt del PIC. Il progetto non ha nulla a che vedere con questo codice.


Felice di poter servire ;-))))
Ciao e buon lavoro
Pow