13. Keskeytykset ja niiden käyttäminen 2

Edellisessä osassa tutustuttiin keskeytykseen ja kuinka keskeytyksiä käytetään Launchpadin kytkimen S2 ja porttipinnin P1.3 osalta. Tässä osassa käydään läpi kuinka saadaan selville myös muiden porttipinnien keskeytykset.

On usein tarpeellista kytkeä porttipinneihin muitakin laitteita kuin kytkimiä, joiden aiheuttamien keskeytysten avulla ohjelma tekee jonkin asian. Tässä esimerkissä ei kuitenkaan ole mitään monimutkaista, vaan käytetään toista kytkintä sytyttämään vihreä led ja hyödynnetään edellisen osan esimerkkikoodia. Periaate keskeytyksissä kuitenkin on sama, kun keskeytysreuna (nouseva tai laskeva) havaitaan, niin keskeytysrutiini suoritetaan.

Kytkentä

Kytkentä on Launchpadin kytkimen osalta tietysti samanlainen, mutta lisätty kytkin kytketään porttiin P1.4 alla olevan kuvan mukaisesti.

Kytkimille täytyy asettaa joko ulkoinen ylösvetovastus, tai se voidaan asettaa sisäisesti. Launchpadin kytkimeen S2 ei ole kytketty ulkoista ylösvetovastusta, vaan se täytyy aktivoida ohjelmallisesti. Asia on täsmälleen sama, kuin jos kytkimeen olisi oikeasti lisätty ulkoinen vastus kuten yllä olevassa kuvassa. Tässä ei kuitenkaan erillisiä vastuksia ole lisätty ja yllä oleva kuva on vain havainnollistamisen vuoksi esitetty.

Ohjelma

Kun ohjelma kirjoitetaan, siitä tulee seuraavanlainen:

#include <msp430g2231.h>

void main(void)
{
    WDTCTL = WDTPW + WDTHOLD; // watchdog pysäytys
    P1DIR |= BIT0 + BIT6; // Molemmat launchpadin ledit lähdöksi 
    P1DIR &= ~(BIT3 + BIT4); // S2 (P1.3) kytkin ja lisätty kytkin S3 (P1.4) tuloksi 
    // Ledit pois päältä, huomaa että käytetään sulkuja ~ merkin kanssa 
    P1OUT &= ~(BIT0 + BIT6);

    P1IE |= BIT3 + BIT4; // S2 ja S3 kytkimen keskeytyksen sallinta 
    P1IES |= BIT3 + BIT4; // S2 ja S3 keskeytys laskevalle reunalle, eli kun kytkintä painetaan 

    P1REN |= BIT3+BIT4; // otetaan kytkimen S3+S4 vastus käyttöön 
    P1OUT |= BIT3+BIT4; // asetetaan kytkimen S3+S4 vastus ylösvedoksi 
    P1IFG &= ~(BIT3 + BIT4); // Nollataan keskeytysliput varmuuden vuoksi 

    __enable_interrupt(); // viimeiseksi alustuskomennoksi sallitaan globaalit keskeytykset
    while(1)
    {
        // ei tehdä mitään 
    }
}

Käytännössä ohjelma ei juurikaan eroa edellisestä, ainoastaan P1.4 on otettu käyttöön ja asetettu porttirekisterit oikeaan tilaan. Ylösvetovastuksen määrittelevät rivit lienevät tuttuja jos olet lukenut jo osan 11. Seuraavaksi muokataan jo tehtyä keskeytysrutiinia kytkinten painalluksiin reagoimiseksi.

#pragma vector=PORT1_VECTOR
__interrupt void P1_keskeytys(void)
{
     switch(P1IFG)
     {
          case 0x00: break; // ei keskeytyksiä käsittelemättä 
          case 0x01: break; // P1.0 
          case 0x02: break; // P1.1 
          case 0x04: break; // P1.2 
          case 0x08: // P1.3 (S2) 
               P1OUT ^= BIT0; // toggletetaan lediä, eli vilkutetaan sitä päällä ja pois 
               break;
          case 0x10: // P1.4 (S3) 
               P1OUT ^= BIT6; // toggletetaan lediä, eli vilkutetaan sitä päällä ja pois 
               break;
          case 0x20: break; // P1.5
          case 0x40: break; // P1.6
          case 0x80: break; // P1.7
          default: break; // ei pitäisi tapahtua 
     }
     P1IFG = 0; // nollataan keskeytykset 
}

Kuten huomaat, on yllä olevassa keskeytysrutiinissa jonkun verran enemmän koodia kuin aikaisemmin. Tämä johtuu nimenomaan siitä, että tässä tutkitaan kumpaa kytkintä on painettu. Tutkiminen tapahtuu switch-case -lausekkeessa lukemalla rekisteri P1IFG ja suorittamalla arvon mukainen lohko. Jos haluaisit tutkia porttia P2, niin muuta koodia seuraavasti:

#pragma vector=PORT1_VECTOR --> #pragma vector=PORT2_VECTOR 
...
switch(P1IFG) --> switch(P2IFG)
...
P1IFG = 0;  --> P2IFG = 0;

Jos halusit tutkia porttia P3 (mikäli sellainen kontrollerissasi on) niin muutat koodia silloin yllä olevan logiikan mukaisesti (jonka toivottavasti huomasit).

Tutkimisen olisi voinut tehdä myös kahdella if-lauseella, jolloin koodista tulee hieman siistimpää, mutta tällä tavalla tehtynä uusien keskeytyslaitteiden lisääminen on koodin tekemisen kannalta helppoa.

Ohjelman kulku

Kuten edellisessä osassa, koodi toimii siten, että alustusten jälkeen suoritus siirtyy pääohjelman silmukkaan missä ei tehdä mitään. Kun kytkintä on painettu, niin syttyy joko punainen tai vihreä LED riippuen kumpaa kytkintä on painettu. Alla vielä pari valokuvaa kytkinten painalluksesta ja lisätystä 1 uF:n suodatinkondensaattorista (kytkinvärähtelyjen takia). Kuvista voi ehkä päätellä, että punainen led syttyy kun kytkintä S3 painetaan vaikka oikeasti syttyykin vihreä led, kuten oli tarkoitus. Kuvien ottohetkellä sattui vain ajatusvirhe jonka vuoksi vaikutelma on tällainen ;).

 

Seuraavassa osassa tutkitaan lisää keskeytyksiä, mutta ajastimen käytön muodossa. Luodaan ohjelma, joka kerran sekunnissa kasvattaa muuttujan arvoa.