WebElektronika

Interrupt a PIC32MX130F064B mikrovezérlőnél II.

person access_time 2015.02,02.
Folytatjuk a PIC32MX család megszakításkezelésének a megismerését gyakorlati példák segítségével. Most a Timer0-t fogjuk felhasználni, de kitérünk még egyszer az INT0 lábon található megszakításkérés lehetőségére is.


Most azt nézzük meg, amikor a megszakításkérést a PIC32MX mikrovezérlő Timer moduljai okozzák. A Timer1 felépítése látható az első ábrán.

kep
1. ábra   A Timer1 felépítése  (forrás)

 

A Timer-eket ezekben a példákban mindig az adott konfigurációs regiszter (pl.: T1CON) közvetlen írásával állítjuk be, ezért nézzük meg a Timer1-hez tartozó konfigurációs regiszter bitkiosztását (2. ábra), illetve az ahhoz tartozó magyarázatrészletet (3. ábra).

kep
2.ábra   A T1CON regiszter felépítése
 

 

kep1
3. ábra   A T1CON regiszter bitjei (részlet)
 

Látni fogjuk a példákban, hogy T1CON = 0x8070;. Binárisan kiírva : 0x8070 = 0B1000 0000 0111 0000; Tehát például a legnagyobb helyiértékű bittel (ON) kapcsoljuk be a Timer1 modult.

 

1. példa

Az első példaprogramunkban beemeljük a "plib.h" file-t, amelyben meghivatkozásra kerül az "int.h" is, amelyre szükségünk van az IT-vel kapcsolatos makrók miatt.

Ezután definiáljuk a "LED0"-t és a "LED1"-et, hogy ne kelljen állandóan a LATB regisztert használnunk, majd elkészítjük az IT handlert is. Noha csak a Timer1 adhat megszakítást, ennek ellenére az IT handlerben figyeljük a T1 IT flag-jét. Ha ez logikai 1-ben van, tehát a T1 timer adta a megszakítást, akkor a két LED-nek az állapotát negáljuk, és töröljük a T1 IT flag-jét.

#include <p32xxxx.h>
#include <plib.h>

#define    LED0    LATBbits.LATB0
#define    LED1    LATBbits.LATB1

void __ISR(0, ipl1) InterruptHandlerTimer(void)
{
    if(mT1GetIntFlag())
    {
        LED0 = ~ LED0;
        LED1 = ~ LED0;
        mT1ClearIntFlag();
    }
}

main()
{
    mPORTBSetPinsDigitalOut(BIT_0 | BIT_1);

    PR1 = 0x03FF;            // eddig számolunk el a T1-gyel
    T1CON = 0x8070;       // 0B1000 0000 0111 0000

    mT1SetIntPriority(1);
    INTEnableSystemSingleVectoredInt();
    mT1IntEnable(1);

    while(1);

}

A "main()" függvényben beállítjuk a "B" port első két bitjét kimenetre, ezután pedig a Timer1-hez tartozó PR1 regiszterbe írjuk azt a számot, ameddig szeretnénk elszámolni a Timer1-gyel. Ezt követően kerül sor a Timer1 beállítására, amelyet a T1CON regiszter közvetlen írásával végzünk el.

Ha ezzel végeztünk, akkor következik az időzítőhöz tartozó megszakítás beállítása is. Ezután a "while" végtelen ciklusba kerül a vezérlés, amely csak a megszakítás kérésekor kerül az IT handler-be.

 

2. példa

Ebben a példában az IT handler más módszerrel került megvalósításra. Sok különbség nincs az előző példa és eközött, a "main()" függvényben tiltottuk a JTAG-et és a különböző portbeállítások csak makróval történtek.

Az IT handlerben lévő makróval érjük a LED-ek állapotváltását is.

#include <p32xxxx.h>
#include <plib.h>

#pragma interrupt InterruptHandler ipl1 vector 0
void InterruptHandler(void)
{
    if(mT1GetIntFlag())
    {
        mPORTBToggleBits(BIT_0 | BIT_1);                   // negáljuk a kimeneteket
        mT1ClearIntFlag();
    }
}

main()
{
    mJTAGPortEnable(DEBUG_JTAGPORT_OFF);
    mPORTBSetPinsDigitalOut(BIT_0 | BIT_1);
    PORTClearBits(IOPORT_B, BIT_0);                        // nullázuk a kimenetet
    PORTSetBits(IOPORT_B, BIT_1);                             // logikai 1-be állítjuk a kimenetet

    PR1 = 0x02FF;
    T1CON = 0x8070;

    mT1SetIntPriority(1);
    INTEnableSystemSingleVectoredInt();
    mT1IntEnable(1);

    while(1);
}

 

3. példa

Ebben a példában már nem csak a Timer1 adhat megszakításkérést, hanem a Timer2 és a Timer3 is. Viszont csak egy IT handler van. Tehát egy handlerben figyeljük a különböző IT flag-eket. Ezt "nesting"-nek is nevezzük, egy handlerben iratkoznak fel a különböző IT kérések figyelései.

#include <p32xxxx.h>
#include <plib.h>

#define    LED0    LATBbits.LATB0
#define    LED1    LATBbits.LATB1
#define    LED2    LATBbits.LATB2

void __ISR(0, ipl1) InterruptHandler(void)
{
    if (mT1GetIntFlag())
    {
        LED0 = ~ LED0;
        mT1ClearIntFlag();
    }
    if (mT2GetIntFlag())
    {
        LED1 = ~ LED1;
        mT2ClearIntFlag();
    }
    if (mT3GetIntFlag())
    {
        LED2 = ~ LED2;
        mT3ClearIntFlag();
    }
}

main()
{
    mPORTBSetPinsDigitalOut(BIT_0 | BIT_1 | BIT_2);
    PORTClearBits(IOPORT_B, BIT_0 | BIT_1 | BIT_2);
    
    PR1 = 0x01FF;
    PR2 = 0x03FF;
    PR3 = 0x05FF;
    T1CON = 0x8070;
    T2CON = 0x8070;
    T3CON = 0x8070;
    
    mT1SetIntPriority(1);
    mT2SetIntPriority(1);
    mT3SetIntPriority(1);
    
    INTEnableSystemSingleVectoredInt();
    mT1IntEnable(1);
    mT2IntEnable(1);
    mT3IntEnable(1);

    while( 1);
}

 

4. példa

Ebben a példában lecserlésre került a Timer3, helyét az INT0 lábon lévő állapotváltásra létrejövő megszakítás vette át.

#include <p32xxxx.h>
#include <plib.h>

#define    LED0    LATBbits.LATB0
#define    LED1    LATBbits.LATB1
#define    LED2    LATBbits.LATB2

void __ISR(0, ipl1) InterruptHandlerTimer(void)
{
    if (mT1GetIntFlag())
    {
        LED0 = ~ LED0;
        mT1ClearIntFlag();
    }
    if(mT2GetIntFlag())
    {
        LED1 = ~ LED1;
        mT2ClearIntFlag();
    }
    if(mINT0GetIntFlag())
    {
        LED2 = ~ LED2;
        mINT0ClearIntFlag();
    }
}

main()
{
    mPORTBSetPinsDigitalOut(BIT_0 | BIT_1 | BIT_2);
    mPORTBSetPinsDigitalIn(BIT_7);

    PR1 = 0x01FF;
    PR2 = 0x03FF;
    T1CON = 0x8070;
    T2CON = 0x8070;
    
    mT1SetIntPriority(1);
    mT2SetIntPriority(1);
    mINT0SetIntPriority(1);
    
    INTEnableSystemSingleVectoredInt();
    
    mT1IntEnable(1);
    mT2IntEnable(1);
    mINT0IntEnable(1);

    while( 1);
}