4. Ledit vilkkumaan

Launchpadissa ledit on kytketty siten, että ne syttyvät kun ledeille kirjoitetaan "1" eli käyttöjännite. Alla oleva kuva esittää niiden kytkentää mikrokontrolleriin:

Esimerkkiohjelma 1: if-else sekä rekisterit P1OUT/P1DIR

Seuraavaksi tehdään hieman jännempi ohjelma, eli ohjataan Launchpadin vihreää lediä. Perehdytään aiheeseen kirjoittamalla uusi ohjelma Launchpadille (muokkaamalla edellistä ohjelmaa):

#include <msp430g2231.h>

void main(void)
{
     unsigned int kokonaisluku_muuttuja = 500;
     unsigned char kirjain_muuttuja = 10;          
     WDTCTL = WDTPW + WDTHOLD; // Pysäytetään vahtikoira
     P1DIR |= BIT6; // asetetaan bitti numero 6 outputiksi (Launchpadin LED)
     P1OUT &= ~BIT6; // LED on 1-aktiivinen, eli syttyy kun bittiin 6 kirjoitetaan 1.
       // Tässä ensin asetetaan LED pois päältä    
      
     while(1) // pääohjelman pääsilmukka          
     {
           kokonaisluku_muuttuja++;
           // muuttujan arvoa kasvatetaan myös näin kirjain_muuttuja +10;
           // muuttujan arvoa kasvatetaan aina 10:llä
           if(kirjain_muuttuja == 100)
           {
                   // sytytetään LED
                   P1OUT |= BIT6;
           }
           else
           {
                  // sammutetaan LED
                  P1OUT &= ~BIT6;
           }
     }
}

Ohjelma suorittaa pääsilmukkaa niin kauan kuin virtaa riittää. Voit kirjoittaa ohjelman omaan lähdekoodiisi ja suorittaa sitä vaikkapa debuggerin avulla. Voit huomata, että LED loistaakin himmeämpänä kuin virran merkkivalo. Tämä johtuu siitä, että ohjelma ohjaa lediä päälle ja pois hyvin nopealla tahdilla ja koska LED on enemmän sammuksissa kuin päällä, niin LED loistaa himmeämmin.

Kuten huomaat, on ohjelma tällä kertaa hieman mutkikkaampi. Selitän ensin ohjelmaa yleisesti, jonka jälkeen avataan hieman rekistereiden P1OUT ja P1DIR merkitystä.

Ohjelman kulku

Tässä ohjelmassa vahtikoiran pysäyttämisen jälkeen tehdään alustus mikrokontrollerin portin P1 kuudennelle bitille eli MSP430G2231 kontrollerin nastalle nro 8. Se alustetaan lähdöksi ja asetetaan lähtöbitti nollaan "0". Launchpadin ledit palavat silloin, kun mikrokontrolleri ohjaa niitä "1" -tilaan.

Pääsilmukassa kasvatetaan kokonaisluku_muuttujaa yhdellä ja kirjain_muuttujaa 10:llä. Tässä ohjelmassa on näin esitelty kaksi erilaista tapaa kasvattaa muuttujien arvoja. Jos muuttujien arvoja haluttaisiin vähentää, käytettäisiin plus-merkkien paikalla miinus-merkkiä.

Pääsilmukassa suoritetaan yksi vertailuoperaatio if-lauseen sulkujen sisällä. If lauseessa sulkujen sisään tulee aina ehto, minkä mukaan toimitaan. Tässä ehtona on, että jos kirjain_muuttujan numeerinen arvo on yhtä suuri kuin 100, sytytetään LED kirjoittamalla P1OUT rekisteriin arvo 1 kyseisen bitin (ledin) kohdalle. Jos ehto ei täyty, niin LED sammutetaan kirjoittamalla samaan paikkaan 0.

Ehtolause if-else

Ehtolauseet kuuluvat olennaisena osana ohjelman suoritukseen. Aiemmissa kappaleissa tulikin esille, kuinka ohjelman suoritusta voidaan muuttaa ehtolauseiden avulla. Yleisesti ottaen syntaksi menee seuraavasti (pseudokoodilla kirjoitettuna):

JOS muuttujan arvo on nolla
tehdään asia XXX
MUUTOIN
tehdään asia XXX

JOS -lohko voidaan kirjoittaa myös ilman MUUTOIN-lohkoakin, jolloin ohjelma vain tarkistaa täyttyykö ehdossa ilmoitettu asia. Kun MUUTOIN lohko on mukana, ohjelman suoritus siirtyy aina sen lohkon sisään mikäli JOS-lohkossa ollut ehto ei täyttynyt (on epätosi).

Rekisterit P1OUT ja P1DIR

Mikrokontrollerin toimintaa ohjataan erilaisilla rekistereillä. Samoin myös mikrokontrollerin pinnejä ohjataan erilaisten rekistereiden avulla.

P1DIR -rekisterillä ohjataan sitä, onko porttien nastat tuloja vai lähtöjä. Jos halutaan, että porttipinni on tulo, niin P1DIR arvo on "0". Jos taas halutaan käyttää pinniä lähtönä, niin P1DIR bitin arvo on "1". Jos haluttaisiin käyttää porttia P2 (mitä ei tässä kontrollerissa kyllä ole), niin rekisterin nimi olisi tällöin P2DIR ja kirjoitettavat arvot täsmälleen samat.

P1OUT on puolestaan lähtöarvo portille 1 silloin, kun P1 on alustettu lähdöksi. Jos jokin porttipinni tai vaikka koko portti olisi tulona, niin rekisteristä P1IN luettaisiin pinnien arvot. P1IN käytöstä lisää myöhemmin.

MSP430-mikrokontrollereiden ohjelmoinnissa samat asiat rekistereiden ohjaamisen suhteen pätevät eri mikropiireille, kunhan kyseessä on MSP430 -kontrolleri. Jos siis vaihdat Launchpadin mukana tulevan MSP430G2231 piirin laatikossa tulleeseen toiseen piiriin MSP430G2211, niin sama koodi käy siihenkin. Ennen käännöstä täytyy vain sisällytettävä kirjasto eli h-tiedosto muuttaa kyseistä piiriä vastaavaksi, eli msp430g2211.h:ksi.

Bitit BIT0 - BIT7

Jos avaat CCS:n editorissa header-tiedoston msp430g2231.h, niin löydät sieltä määritykset kyseisille sanoille BIT0 - BIT7. Ne on kirjoitettu tiedostoon siis näin:

#define BIT0     (0x0001) <- vastaa P1.0 Launchpadilla
 #define BIT1     (0x0002)
 #define BIT2     (0x0004)
 #define BIT3     (0x0008)
 #define BIT4     (0x0010)
 #define BIT5     (0x0020)
 #define BIT6     (0x0040)
 #define BIT7     (0x0080) <- vastaa P1.7 Launchpadilla.      HUOM! Älä muuta header-tiedostoa itse!

Kun muutat luvut binääriseksi (paperilla tai laskimella), voit huomata kuinka kukin bitti vastaa porttipinniä 0 - 7. Luvuista 0x0001 - 0x0080 voidaan ottaa ylimääräiset nollat pois edestä ajattelun helpottamiseksi, jolloin luvut ovat 0x1 - 0x80 ja helpompia käsitellä (vain 8 bittiä).  Porttipinneissä pätee sama logiikka kuin binääriluvuissa. Jos haluat kirjoittaa kaikki portit kerralla ykkösiksi, voit tehdä sen monella eri tavalla:

P1OUT = 0xFF;  // kirjoitetaan heksaluku joka vastaa 1111 1111
 P1OUT = 255;   // kirjoitetaan desimaaliluku joka vastaa 1111 1111
 P1OUT |= BIT0 + BIT1 + BIT2 + BIT3 + BIT4 + BIT5 + BIT6 + BIT7;  // kirjoitetaan yllä
  // mainittujen bittien summa, joka vastaa 1111 1111
 P1OUT = ~0;   // ~ merkillä (tilde) muutetaan nollat ykkösiksi ja päinvastoin
  // koska 0 desimaalina vastaa 0x00 tai 0000 0000 niin komplementtiluku on tietenkin
  // 255 desimaalina tai 0xFF tai 1111 1111

Koska MSP430G2231 ja MSP430G2211 mikrokontrollereissa on käytössä vain 8 pinniä portista 1, niin suurin mahdollinen pinneillä esitettävä luku on myös 28 - 1 = 255 tai 0xFF.

Note: Suuremmilla mikrokontrollereilla on käytössä enemmän pinnejä ja muistia sekä enemmän muitakin ominaisuuksia, niihin voit tutustua TI:n sivuilla tarkemmin.

Bittioperaatiot |= ja &=

Operaattorilla |= tehdään OR-operaatio kahden tulon kesken. Esimerkkikoodien tapauksessa OR operaatio tehtiin määrityksen BIT6 ja P1OUT rekisterin kesken. Myös muuttujia voidaan tällä tavalla käsitellä. Jos kyseisen bitin paikalla olisikin ollut jo valmiiksi "1", niin mitään ei olisi tapahtunut. Jos taas bitti on nollassa, se asetetaan arvoon "1".

&= operaattorilla tehdään AND-operaatio kahden tulon kesken. Myös muuttujille voidaan tehdä AND-operaatio. AND-operaatiossa kahden muuttujan tulo on "1" vain jos molemmat ovat "1", tässä tapauksessa AND-operaatiota käytettiin tarkistamaan onko bitti 1 ja jos on niin sen arvo käännetään ~(tilde) -merkillä. Tällöin bitti nollautuu.