Potřebuji poradit s nechtěným opakovaným vyvoláním přerušení timeru.
Nejprve uvedu, že používám MPLAB 8.9 a MPLABX a C32 compilátory od Microchipu.
Programovací jazyk C a neznám do hloubky procesor MIPS a jeho registry.
MCU PIC32MX695
Periférie mám prostudované z DS a REF.příručky.
BĚŽNÝ STAV:
- T1 konfigurován 1:1 CLK:TMR a nastaven na vyvolání INT při TMR 5000 (IP1)
- T4 konfigurován 1:64 a nastaven na volání INT při TMR při 200 (IP6)
- obslužné rutiny provedou potřebné a vynulují IFS
**PROBLÉM:
- T4 generuje jednou za cca 1000 vyvolání přerušení dvojíté přerušení
Vysvětlím co myslím tím dvojíté: poprvé vyvolá T4 interupt správně po 200 cyklech CLK*64 a ihned v zápětí vyvolá přerušení znovu. Kontroloval jsem TMR4 a v tu chvíli má hodnotu 1. Měl by mít hodnotu 200.
(poznámka: v uvedeném kódu nepočítám od 0 ale od 65300 do 65535, zkoušel jsem obojí - nemělo žádný vliv na chybu).
**
Z debugingu jsem zjistil, že se střídá vyvolávání rutiny přerušení T1 a T4 takto: T1 - T1 - T1 - T4 - T1… a jednou za čas dojde k variantě T1 - T1 - T4 - T1 - T1… Je to dáno nastavením časování a tak je to správně a nechci to měnit. Ještě se může stát, že přerušení T4 přeruší vykonávání T1 rutiny a to je taky správně, protože má vyšší prioritu.
Kód jsem upravoval různě a debugoval, přidal jsem si další timer T2 abych sledoval jak se střídavě vyvolávají INT.
A opravdu se potvrdilo náhodné vyvolání INT T4.
Ostatní periférie můžeme vyloučit protože jsou vypnuté.
Konfigurace portů je v pořádku.
Zkoušel jsem celý kód přepsat do použití pblib tzn. funkce a makra a stejný problém.
Protože jsem problém neidentifikoval píšu sem o pomoc.
Pravděpodbně mi pomůže někdo s dobrou znalostí řadiče přerušení a procesoru MIPS.
Rady typu kup si něco jiného, nepoužívej timery apod. prosím nepište - jsem dospělý a vím co chci takže sám vím co je pro mě to nejlepší… a nyní je to MCU PIC32MX695! takže prosím pouze konstruktivní nápady a rady
#define SYSCLK 80000000
//konfigurace MCU
SYSTEMConfigPerformance(SYSCLK);
//konfigurace periférií
//timer T1
IPC1bits.T1IP = 1; //T1 interrupt priority 1
T1CON = 0x0; //stop operaci timer1 - mozna neni nutne, ale pro jistotu
TMR1 = 0x0; //nulovani timeru
PR1 = 5000; //prah pro preruseni (toto je od 0 do 5000, zkousel jsem i od 60000 do 65535)
IFS0bits.T1IF = 0; //clear T1 interrupt flag
T1CONbits.ON = 1; //zapnuti periferie
//timer T4
IPC4bits.T4IP = 6; //interrupt priority
T4CON = 0x0; //stop operaci timer4 - mozna neni nutne, ale pro jistotu
T4CONbits.TCKPS = 0x06; //prescaler 64 - generovat impulz pro timer CLK/64
TMR4 = 0x0000; //nulovani timeru
PR4 = 0xFFFF; //prah 65535 - pocitam poprve od 0, nasledne od 65300 viz. dale
IFS0bits.T4IF = 0; //clear T4 interrupt flag
T4CONbits.ON = 1;
//zapnuti systemu preruseni, konfiguraci radice preruseni jako multivectored provede funkce pblib
INTEnableSystemMultiVectoredInt();
IEC0bits.T1IE = 1; //Timer1 interrupt enable
IEC0bits.T4IE = 1; //Timer1 interrupt enable
//rutiny
void __ISR(_TIMER_1_VECTOR, ipl1) IT1Interrupt(void) //obsluha LED displaye
{
//...muj kod, globalni promenne jsou deklarovany volatile - zkousel jsem vse
//...muj kod, pracuje s LAT registry
//...muj kod, nenastavuje ani jinak neovlivnuje TMR4
IFS0bits.T1IF = 0; //vynulovat T1 IF
TMR1 = 0x00; //vynulovat timer1
}
void __ISR(_TIMER_4_VECTOR, ipl6) IT4Interrupt(void)
{
//...muj kod, globalni promenne jsou deklarovany volatile - zkousel jsem vse
//...muj kod, pracuje s LAT registry
//...muj kod, nenastavuje ani jinak neovlivnuje TMR1
WriteTimer4(65300); //pocitat od 65300 do 65535 - varianta pouziti funkce knihovny pblib
mT4ClearIntFlag(); //vynulovat T4 IF - varianta pouziti makra knihovny pblib
}
administrator: přesunuto z "Off – topic"