A PIC18F család prioritásos megszakítással rendelkezik. Ez azt jelenti, hogy az alacsonyszintű megszakításkiszolgálás (címe : 18H) felfüggesztésre kerül akkor, ha magasszintű (címe : 8H) interruptkérés érkezik. Ehhez persze engedélyezni kell a prioritásos megszakítás lehetőségét.
Ha nem engedélyezzük a prioritásos megszakítást, akkor csak a 8H cím kerül alkalmazásra, amikor megszakításkezelést alkalmazunk.
Először egy olyan megszakításra nézünk példát, amely nem rendlekezik prioritásos megszakítással, noha az RCON regiszter IPEN bitje logikai 1-ben van, tehát a kétszintű megszakítás enegdélyezve van, de az alacsonyszintű IT Handler hiányzik.
(A programok elkészítésekor az MCC18-as fordító "main.c" programját használtuk fel kiindulásként. mplabc18\v3.46\example\Interrupt\main.c)
#include <p18f14k50.h>
#pragma config LVP = OFFvoid InterruptHandlerHigh(void);
main()
{
INTCON = 0x20; // 0010 0000
// TMR0IE = 1
INTCON2 = 0x84; // 1000 0100
// TMR0IP = 1
// magasszintű IT
RCONbits.IPEN = 1; // prioritásos IT
TMR0H = 0;
TMR0L = 0;
T0CON = 0x80; // 1000 0000
// TMR0 bekapcsolva
// 16 bit, 1:2 osztó
INTCONbits.GIEH = 1; // Globális IT
// engedélyezése
TRISC = 0x00; // C port kimenet
LATC = 0x00; // C port nullázása
while(1)
{
}
}#pragma code InterruptVectorHigh = 0x08
void InterruptVectorHigh(void)
{
_asm
goto InterruptHandlerHigh
_endasm
}
#pragma code
#pragma interrupt InterruptHandlerHighvoid InterruptHandlerHigh()
{
if (INTCONbits.TMR0IF)
{
INTCONbits.TMR0IF = 0;
LATC++;
}
}
A következő példában egy LED-et (C port 2. bit) villogtatunk, az ehhez szükséges késleltetést szoftveresen valósítottuk meg. Amikor a Timer0 túlcsordul, akkor megszakítás keletkezik, a Villog() függvény végrehajtása felfüggesztésre kerül.
#include <p18f14k50.h>
#pragma config LVP = OFFvoid InterruptHandlerHigh(void);
void Villog()
{
int i;
for(i = 0; i < 3000; i++);
LATCbits.LATC2 = ~LATCbits.LATC2;
}main()
{
INTCON = 0x20;
INTCON2 = 0x84;
RCONbits.IPEN = 1;
TMR0H = 0;
TMR0L = 0;
T0CON = 0x80;
INTCONbits.GIEH = 1;
TRISC = 0;
LATC = 0x00;
while (1)
{
Villog();
}
}#pragma code InterruptVectorHigh = 0x08
void InterruptVectorHigh(void)
{
_asm
goto InterruptHandlerHigh
_endasm
}
#pragma code
#pragma interrupt InterruptHandlerHighvoid InterruptHandlerHigh()
{
if (INTCONbits.TMR0IF)
{
INTCONbits.TMR0IF = 0;LATCbits.LATC0 = !LATCbits.LATC0;
}
}
Ebben a példában már felhasználjuk a kétszintű megszakítást, elkészítettük az alacsonyszintű megszakításhoz tartozó IT Handler-t is.
A magasszintű IT-t a Timer0 túlcsordulása, az alacsonyszintű IT-t pedig az AD átalakító működésének a befejezése fog kiváltani.
Az AD átalakítót felkonfiguráljuk az ADCON1,2,3 regiszterek írásával. Elinditjuk a konverziót, de csak egyszer fog ez a modul működni a while(1); miatt. Amikor az AD átalakító a működését befejezte, ad egy megszakítást, amelynek hatására a C port 2. bitje logikai 1-be kerül.
#include <p18f14k50.h>
#include "adc.h"
#pragma config LVP = OFFvoid InterruptHandlerHigh(void);
void InterruptHandlerLow(void);main()
{
INTCON = 0x20;
INTCON2 = 0x84;
RCONbits.IPEN = 1;
TMR0H = 0;
TMR0L = 0;
T0CON = 0x80;
INTCONbits.GIEH = 1;
TRISC = 0;
LATC = 0x00;
ADCON0 = 0B00101001;
ADCON1 = 0B00000000;
ADCON2 = 0B10101010;
PIE1bits.ADIE = 1;
IPR1bits.ADIP = 0; // alacsony, 0x18
INTCONbits.GIEL = 1;
while (1)
{
ConvertADC();
while(1);
}
}#pragma code InterruptVectorHigh = 0x08
void InterruptVectorHigh(void)
{
_asm
goto InterruptHandlerHigh
_endasm
}#pragma code InterruptVectorLow = 0x18
void InterruptVectorLow(void)
{
_asm
goto InterruptHandlerLow
_endasm
}#pragma code
#pragma interrupt InterruptHandlerHighvoid InterruptHandlerHigh()
{
if(INTCONbits.TMR0IF)
{
INTCONbits.TMR0IF = 0;
LATCbits.LATC0 = !LATCbits.LATC0;
}
}#pragma code
#pragma interrupt InterruptHandlerLowvoid InterruptHandlerLow()
{
if(PIR1bits.ADIF)
{
PIR1bits.ADIF = 0;
LATCbits.LATC2 = 1;
}
}
Ez a program hasonlít az előzőre, de az AD-nek is magasszintű a megszakítása. Bent maradt a C kódban az alacsonyszintű IT Handler is, de soha nem kerül végrehajtásra.
#include <p18f14k50.h>
#include "adc.h"
#pragma config LVP = OFFvoid InterruptHandlerHigh(void);
void InterruptHandlerLow(void);main()
{
INTCON = 0x20;
INTCON2 = 0x84;
RCONbits.IPEN = 1;
TMR0H = 0;
TMR0L = 0;
T0CON = 0x80;
INTCONbits.GIEH = 1;
TRISC = 0;
LATC = 0x00;
ADCON0 = 0B00101001;
ADCON1 = 0B00000000;
ADCON2 = 0B10101010;
PIE1bits.ADIE = 1;
IPR1bits.ADIP = 1; // magas, 0x08
while(1)
{
ConvertADC();
while(1);
}
}#pragma code InterruptVectorHigh = 0x08
void InterruptVectorHigh (void)
{
_asm
goto InterruptHandlerHigh
_endasm
}#pragma code InterruptVectorLow = 0x18
void InterruptVectorLow (void)
{
_asm
goto InterruptHandlerLow
_endasm
}#pragma code
#pragma interrupt InterruptHandlerHighvoid InterruptHandlerHigh()
{
if(INTCONbits.TMR0IF)
{
INTCONbits.TMR0IF = 0;
LATCbits.LATC0 = !LATCbits.LATC0;
}
if(PIR1bits.ADIF)
{
PIR1bits.ADIF = 0;
LATCbits.LATC1 = 1;
}
}#pragma code
#pragma interrupt InterruptHandlerLowvoid InterruptHandlerLow()
{
// Az AD magasszintű,
// ide nem kerülhet az IT!!!
if(PIR1bits.ADIF)
{
PIR1bits.ADIF = 0;
LATCbits.LATC3 = 1;
}
}
Ez a példa szinte megegyezik az előzővel, a különbség az, hogy a Timer1 túlcsordulása is megszakítást fog okozni, amely alacsonyszintű lesz, azaz a megszakításkor a vezérlés a 18H címre ugrik.
#include <p18f14k50.h>
#include "adc.h"
#pragma config LVP = OFFvoid InterruptHandlerHigh(void);
void InterruptHandlerLow(void);main()
{
INTCON = 0x20;
INTCON2 = 0x84;
RCONbits.IPEN = 1;
TMR0H = 0;
TMR0L = 0;
T0CON = 0x80; // 1000 0000
TMR1H = 0;
TMR1L = 0;
T1CON = 0B10001101; //0x81
IPR1bits.TMR1IP = 0; // alacsony
PIE1bits.TMR1IE = 1; // engedélyezés
INTCONbits.GIEH = 1; // magas IT engedély
INTCONbits.GIEL = 1; // alacsony IT engedély
TRISC = 0;
LATC = 0x00;
ADCON0 = 0B00101001;
ADCON1 = 0B00000000;
ADCON2 = 0B10101010;
PIE1bits.ADIE = 1;
IPR1bits.ADIP = 1; // magas, 0x08
while (1)
{
ConvertADC();
while(1);
}
}#pragma code InterruptVectorHigh = 0x08
void InterruptVectorHigh (void)
{
_asm
goto InterruptHandlerHigh
_endasm
}#pragma code InterruptVectorLow = 0x18
void InterruptVectorLow(void)
{
_asm
goto InterruptHandlerLow
_endasm
}#pragma code
#pragma interrupt InterruptHandlerHighvoid InterruptHandlerHigh()
{
if (INTCONbits.TMR0IF)
{
INTCONbits.TMR0IF = 0;
LATCbits.LATC0 = !LATCbits.LATC0;
}
if(PIR1bits.ADIF)
{
PIR1bits.ADIF = 0;
LATCbits.LATC1 = 1;
}
}#pragma code
#pragma interrupt InterruptHandlerLowvoid InterruptHandlerLow()
{
if(PIR1bits.TMR1IF)
{
PIR1bits.TMR1IF = 0;
LATCbits.LATC3 = ~LATCbits.LATC3;
}
}
Megismerjük most a PIC18F mikrovezérlők megszakításkezelését, és készítünk két egyszerű példaprogramot is. Ezek az egy- és a kétszintű megszakításkezelést mutatják be, de sablonként is jól használhatók saját fejlesztéseknél is.. . . .
Ebben a cikkben egy kétsoros LCD felprogramozását és a hozzátartozó sajátfüggvényeket, makrókat mutatjuk be. Nem térünk ki viszont az LCD-k felépítésére, vezérlésére.. . . .
Ebben a cikkben egy kétsoros LCD felprogramozását és a hozzátartozó sajátfüggvényeket, makrókat mutatjuk be. Nem térünk ki viszont az LCD-k felépítésére, vezérlésére.. . . .