Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

Problema grave in interrupt

Raccolta di codici sorgenti

Moderatore: Foto UtentePaolino

0
voti

[1] Problema grave in interrupt

Messaggioda Foto Utenteivanpascolo » 7 nov 2014, 19:55

Ciao a tutti,
scrivo per sapere se qualcuno ha già riscontrato una stranezza molto grave sul compilatore XC8 di Microchip (sto utilizzando un PIC16F1704).
Di seguito vi riporto il firmware di un programma che ho ridotto all'osso per capirci qualche cosa.
In pratica utilizzo il timer0 impostato a 1 ms (il tutto utilizzando il comodissimo code configurator) per incrementare la variabile "sys_tick", nel main verifico quando "sys_tick - t0" >100, questo significa che sono passati 101ms. Ho utilizzato anche la variabile t1 giusto per cercare l'origine del mio problema.
Ho inserito anche "if ((t1<100)||(t1>101)" per mettere un breakpoint e controllare le variabili quando sbagliava. Con il breakpoint in CLRWDT() i valori delle variabili sono:
sys_tick = 23048
t0 = 23028
t1 = 264

Tutte e tre le variabili sono dichiarate come unsigned long.

Ma come fa (sys_tick - t0) che in questo caso vale 20 a mettere in t1 264? Il bello è che lo fa anche per valori successivi. Ne ho provate 1000 senza alcun risultato.
Ho spostato l'istruzione "sys_tick++" all'interno del main con una pausa di 1ms e il risultato è stato: FUNZIONA TUTTO.Ho provato a dichiarare le variabili unsigned char (8bit) e FUNZIONA TUTTO. ma con variabili a 16 e 32 bit ogni tanto fa cilecca.

Di seguito il listato:
Codice: Seleziona tutto
void main(void)
{
   
    SYSTEM_Initialize();
         
/**********************************************************
*               PROGRAMMA PRINCIPALE                     *
*********************************************************/
   
    while (1){       
        CLRWDT();     
        t1 = (sys_tick - t0);
        if (t1 > 100) {
            if ((t1<100)||(t1>101)){
                CLRWDT();
                CLRWDT();
            }
            else t0=sys_tick;
        }
    }
}

void interrupt ISR (void){     
    if(INTCONbits.TMR0IE == 1 && INTCONbits.TMR0IF == 1)
    {       
        INTCONbits.TMR0IF = 0;
        sys_tick ++;
    }
}


Ringrazio anticipatamente se qualcuno volesse darmi una mano... sono disperato.
Grazie
Ivan
Avatar utente
Foto Utenteivanpascolo
20 3
New entry
New entry
 
Messaggi: 71
Iscritto il: 29 set 2014, 20:44

0
voti

[2] Re: Problema grave in interrupt

Messaggioda Foto Utenteivanpascolo » 7 nov 2014, 20:52

Piccolo aggiornamento, ho sostituito "sys_tick++" con " "sys_tick = "sys_tick + 1" e sbaglia sempre con questo risultato:
sys_tick = 720896
t0 = 720837
t1 = 65594

Ovvero dopo circa 720 sec. non capisco cosa sta succedendo.

Ivan
Avatar utente
Foto Utenteivanpascolo
20 3
New entry
New entry
 
Messaggi: 71
Iscritto il: 29 set 2014, 20:44

0
voti

[3] Re: Problema grave in interrupt

Messaggioda Foto UtenteDarwinNE » 7 nov 2014, 23:46

Non saprei aiutare in maniera specifica. Tuttavia, consiglierei di dare un'occhiata al codice assembly prodotto dal compilatore.

P.S. usa il tag CODE per mostrare il codice.
Follow me on Mastodon: @davbucci@mastodon.sdf.org
Avatar utente
Foto UtenteDarwinNE
31,0k 7 11 13
G.Master EY
G.Master EY
 
Messaggi: 4420
Iscritto il: 18 apr 2010, 9:32
Località: Grenoble - France

0
voti

[4] Re: Problema grave in interrupt

Messaggioda Foto UtenteWALTERmwp » 7 nov 2014, 23:59

Ciao Foto Utenteivanpascolo, come ti è già stato scritto è meglio che tu ricorra alle tag(s) del tastino "Code" per inserire lo script del tuo programma.

Poi, sarebbe il caso di sapere quali sono le impostazioni date.
Non si vede il codice di inizializzazione come, per esempio, il prescaler del timer utilizzato; quali siano i tipi di variabili utilizzate non si sa ( ... t0, sys_tick ... ), e anche per loro non si conosce l'inizializzazione.

Completa il quadro della situazione e magari qualcuno, con più informazioni, può provare a darti una mano.

Saluti
W - U.H.F.
Avatar utente
Foto UtenteWALTERmwp
30,2k 4 8 13
G.Master EY
G.Master EY
 
Messaggi: 8982
Iscritto il: 17 lug 2010, 18:42
Località: le 4 del mattino

1
voti

[5] Re: Problema grave in interrupt

Messaggioda Foto Utenteposta10100 » 7 nov 2014, 23:59

ivanpascolo ha scritto: non capisco cosa sta succedendo.

Succede che il timer0 è da 8 bit, se usi variabili più grandi, ad esempio int o long, oltre a portarti dietro il segno, chissà cosa combina il compilatore.
Se invece usi la unsigned char, hai una variabile da 8 bit senza segno, esattamente come il registro del timer.

DarwinNE ha scritto:consiglierei di dare un'occhiata al codice assembly prodotto dal compilatore.

Se dai un occhio al codice assembly sono molto confidente che la mia ipotesi è corretta. ;-)

O_/
http://millefori.altervista.org
Tool gratuito per chi sviluppa su millefori.

Tutti sanno che una cosa è impossibile da realizzare, finché arriva uno sprovveduto che non lo sa e la inventa. (A. Einstein)
Se non c'e` un 555 non e` un buon progetto (IsidoroKZ)

Strumento per formule
Avatar utente
Foto Utenteposta10100
5.550 4 10 13
Master EY
Master EY
 
Messaggi: 4832
Iscritto il: 5 nov 2006, 0:09

0
voti

[6] Re: Problema grave in interrupt

Messaggioda Foto Utenteivanpascolo » 8 nov 2014, 0:21

Tutte le varie impostazioni sono generate dal code generator e mi è difficile inserire tutto il codice (ci sono dei file .h), comunque metto quello che WALTERmwp mi ha chiesto.

Codice: Seleziona tutto
void OSCILLATOR_Initialize(void)
{
   
    OSCCON = 0xF0;
    OSCSTAT = 0x00;   
    OSCTUNE = 0x00;           
    while(PLLR == 0)
    {
    }


La parte riguardante l'interrupt:

Codice: Seleziona tutto
OPTION_REG = (OPTION_REG & 0xC0) | 0xD4 & 0x3F;

    TMR0 = 0x06;   
    INTCONbits.TMR0IF = 0;

    // Enabling TMR0 interrupt
    INTCONbits.TMR0IE = 1;

    INTCONbits.GIE = 1;

    INTCONbits.PEIE = 1;



E le variabili:

Codice: Seleziona tutto
/**********************************************************
*                VARIABILI GLOBALI                       *
*********************************************************/

unsigned long sys_tick = 0;
unsigned long t0 = 0, t1 = 0;



L'interrupt funziona alla perfezione, ogni ms incrementa la variabile sys_tick... proverò a verificare l'assembler del compilatore ma non è cosa semplice e dal momento che non sbaglia sempre nello stesso punto credo che sarà ancora piu' dura.

Grazie
Ivan
Ultima modifica di Foto Utenteivanpascolo il 8 nov 2014, 1:12, modificato 1 volta in totale.
Avatar utente
Foto Utenteivanpascolo
20 3
New entry
New entry
 
Messaggi: 71
Iscritto il: 29 set 2014, 20:44

0
voti

[7] Re: Problema grave in interrupt

Messaggioda Foto Utenteposta10100 » 8 nov 2014, 0:25

ivanpascolo ha scritto:dal momento che non sbaglia sempre nello stesso punto credo che sarà ancora piu' dura.

Il che mi fa sospettare sempre più della dimensione errata delle variabili.
Se usi una variabile a 16 bit e il registro ne contiene 8, nei restanti 8 cosa ci metti?
E' molto probabile che il compilatore si limiti ad allocarla e quindi può contenere qualsiasi cosa, da qui il difetto che si sposta.
Prova a impostare a 0 la variabile a 16 o 32 bit prima di utilizzarla, se sei fortunato non la tocca più e forse funziona.

O_/
http://millefori.altervista.org
Tool gratuito per chi sviluppa su millefori.

Tutti sanno che una cosa è impossibile da realizzare, finché arriva uno sprovveduto che non lo sa e la inventa. (A. Einstein)
Se non c'e` un 555 non e` un buon progetto (IsidoroKZ)

Strumento per formule
Avatar utente
Foto Utenteposta10100
5.550 4 10 13
Master EY
Master EY
 
Messaggi: 4832
Iscritto il: 5 nov 2006, 0:09

0
voti

[8] Re: Problema grave in interrupt

Messaggioda Foto Utenteivanpascolo » 8 nov 2014, 1:23

posta10100, non capisco quando scrivi "Se usi una variabile a 16 bit e il registro ne contiene 8, nei restanti 8 cosa ci metti?"
I registri del timer non dovrebbero centrare nulla con le variabili globali (che all'inizio metto comunque a zero) , il fatto che sia un timer a 8 bit dovrebbe essere legato solo al conteggio per l'overflow e non per l'incremento della variabile sys_tick.
Quindi secondo te se usassi il timer 1 che è a 16 bit con una variabile unsigned short int (16 bit) dovrebbe funzionare? Domani provo anche questa.
Avatar utente
Foto Utenteivanpascolo
20 3
New entry
New entry
 
Messaggi: 71
Iscritto il: 29 set 2014, 20:44

0
voti

[9] Re: Problema grave in interrupt

Messaggioda Foto UtenteWALTERmwp » 8 nov 2014, 4:10

Foto Utenteivanpascolo, intanto vorrei capire come fai ad avere un timer0 impostato ad un millisecondo, e di conseguenza presumo un interrupt ad un millisecondo, con un prescaler impostato a 1:32 e un TMR0 a 0x06 ?
Potrei avere certamente commesso un errore nel fare la verifica ma potresti trovare conferma, oppure darmi evidenza di quanto hai riportato; faccio riferimento a questo:
Codice: Seleziona tutto
OPTION_REG = (OPTION_REG & 0xC0) | 0xD4 & 0x3F;

    TMR0 = 0x06;
Saluti
W - U.H.F.
Avatar utente
Foto UtenteWALTERmwp
30,2k 4 8 13
G.Master EY
G.Master EY
 
Messaggi: 8982
Iscritto il: 17 lug 2010, 18:42
Località: le 4 del mattino

1
voti

[10] Re: Problema grave in interrupt

Messaggioda Foto Utenteivanpascolo » 8 nov 2014, 9:47

Il clock interno è impostato a 32MHZ,ho provato a ricalcolare il prescaler e tmr0 con il timer calculator di Mikroelektronika e i valori coincidono.
Comunque ho generato tutto con il code generator e non ho mai avuto problemi sui tempi del timer, chiaramente ho provato con l'oscilloscopio impostando un segnale in uscita ad un pin del micro ed è perfetto.
Ritornando all'origine del mio problema ho fatto altri tentativi:

Dichiarato le variabili intere senza segna sia a 32 che a 16 bit e niente da fare.
Ho provato ad utilizzare il timer 1 (che è a 16 bit) con variabili di tipo unsigned short int (16 bit senza segno) e niente da fare.
Una considerazione, ogni volta che sbaglia il valore del sys_tick è sempre multiplo di 256...
Avatar utente
Foto Utenteivanpascolo
20 3
New entry
New entry
 
Messaggi: 71
Iscritto il: 29 set 2014, 20:44

Prossimo

Torna a Firmware e programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 9 ospiti