5.3. c-kielen perusteet. 3_8

26
1 5.3. Sulautetun järjestelmän C-kielen perusteet 3/8, Portit 7.1.2008 pva ”Jos haluat edetä nopeasti, kulje yksin. Jos haluat edetä kauas, kulje yhdessä”. - afrikkalainen sanonta Tässä osiossa tärkeää: mikro-ohjaimen porttien ja muiden rekistereiden monipuoliset manipulointimenetelmät. Osion sisältö 1. Port_output_allport 2. Port_output_portable 3. Port_output_BitValue 4. Port_output_bit_macros 5. Port_input_allport 6. Port_input_one_bit 7. Port_input_bit_macro 8. Port_input_loop_macro 9. Omatekemät makrot 10. Portin osoite 11. Bit fields Opiskeluvinkki: Aluksi tutki ja käytä ainoastaan kohtien 1 ja 2 (output) ja 5 ja 6 (input) tapoja käsitellä portteja (tai rekistereitä). Muihin osion kohtiin kannattaa tutustua myöhemmin oppimisen edistyessä, tai tarpeen mukaan. Liika on liikaa. Liian monta erilaista asiaa yhdellä kertaa hämmentää ja saattaa hämärtää varsinaisen opittavan asian. Seuraavassa opit paljon uutta asiaa. Kannattaa tutustua koodiin ja sen kommentteihin perusteellisesti, koska koodeista ja harjoituksista saatava osaaminen luo pohjan vastaiselle opiskelulle. Vaikka esimerkit ovat porteista, määritykset voi soveltaa kaikkiin muihinkin rekistereihin. Tähän dokumenttiin liittyy olennaisena osana porttien raudasta kertova dokumentti ”AVR portit ja rekisterit.pdf”. Tutki sitä samalla kun opiskelet portin manipulointia ja teet allaolevat harjoitukset.

Upload: digindom

Post on 08-Apr-2015

183 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: 5.3. C-kielen perusteet. 3_8

1

5.3. Sulautetun järjestelmän C-kielen perusteet 3/8, Portit 7.1.2008 pva

”Jos haluat edetä nopeasti, kulje yksin. Jos haluat edetä kauas, kulje yhdessä”. - afrikkalainen sanonta Tässä osiossa tärkeää: mikro-ohjaimen porttien ja muiden rekistereiden

monipuoliset manipulointimenetelmät. Osion sisältö

1. Port_output_allport 2. Port_output_portable 3. Port_output_BitValue 4. Port_output_bit_macros 5. Port_input_allport 6. Port_input_one_bit 7. Port_input_bit_macro 8. Port_input_loop_macro 9. Omatekemät makrot 10. Portin osoite 11. Bit fields

Opiskeluvinkki: Aluksi tutki ja käytä ainoastaan kohtien 1 ja 2 (output) ja 5 ja 6 (input) tapoja käsitellä portteja (tai rekistereitä). Muihin osion kohtiin kannattaa tutustua myöhemmin oppimisen edistyessä, tai tarpeen mukaan. Liika on liikaa. Liian monta erilaista asiaa yhdellä kertaa hämmentää ja saattaa hämärtää varsinaisen opittavan asian. Seuraavassa opit paljon uutta asiaa. Kannattaa tutustua koodiin ja sen kommentteihin perusteellisesti, koska koodeista ja harjoituksista saatava osaaminen luo pohjan vastaiselle opiskelulle. Vaikka esimerkit ovat porteista, määritykset voi soveltaa kaikkiin muihinkin rekistereihin.

Tähän dokumenttiin liittyy olennaisena osana porttien raudasta kertova dokumentti ”AVR portit ja rekisterit.pdf”.

Tutki sitä samalla kun opiskelet portin manipulointia ja teet allaolevat harjoitukset.

Page 2: 5.3. C-kielen perusteet. 3_8

2

Yleistä C-kieli on kätevä kieli sulautettujen systeemien ohjelmointiin, sillä se tukee erilaisia bittioperaatioita. Pienten mikro-ohjaimien ohjelmointi on hieman yksinkertaistaen ”vähän C-koodausta” ja ”paljon bitin nypläystä”. Bittien ”nypläämisessä” tavujen siirtely paikasta toiseen on usein tapahtuva toimen-pide. Tyypillisesti mikro-ohjain valvoo ja ohjaa ympäristönsä elektroniikkaa I/O-piirien (Input/Output, tulo- ja lähtöpiirit) eli porttien avulla. I/O-piirit ovat ohjelmassa ’kiinnitetty’ funktioihin ja tieto kulkee porttien kautta mennen tullen. Portti on kuten ovi, joka mahdollistaa mikro-ohjaimen ohjelmalle seurata millainen on ulkoinen maailma ja halutessaan se voi muuttaa sitä. MCU monitoroi ulkoista maail-maa lukemalla portin inputissa olevia kytkimiä tai erilaisia antureita, sensoreita. MCU muuttaa ulkoista maailmaa ohjaamalla toimilaitteita, esim. teho-ohjaimia, moottoreita, jne. samojen porttien kautta. AVR-GCC-ohjelmoija tavoittaa I/O-rekisterit suoraan symbolisella osoitteella: PORTB = 0x33; // B-porttiin sijoitetaan hexa-luku 3 3, 0011 0011 bin

Jos käytetään memory-mapped systeemiä, koodista tulee siirrettävää (sitä voidaan käyttää myös muissa laite- ja käänninympäristöissä) ja se on myös luettavampaa. Tässä esitetään miten eri tavoilla AVR:n porttirekistereitä voi manipuloida, käsitellä. Samoja koodeja voi käyttää (sopivasti modifioituina) myös kaikkien muiden AVR:n rekisterien manipuloinnissa. Joten teksti ja esimerkkikoodit ovat monikäytöisiä ja ehdottomasti tutkimisen/oppimisen arvoisia. Kiikku on yhden bitin muisti. Kiikku voi olla ”kiikun tai kaakun”, eli kiikun tila (ts. bitti) voi olla joko nolla tai ykkönen. SRAM datamuisti on rakennettu rinnan liitetyistä ki ikuista. Kun kiikkuja on 8 kpl rinnan, muistipaikkaan voi tallettaa tavun = 8 bittiä. Myös rekisteri on rakennettu rinnan liitetyistä kii kuista. Kiikkuja voi olla joko 8 kpl, jolloin saadaan 8-bittinen rekisteri, 16 kpl, jne. Rekisterissä bittejä voidaan käsitellä, manipuloida. Bittejä voidaan siirtää oikealle tai vasemmalle, arvoon voi lisätä ykkösen tai muita lukuja, vähentää, vertailla, jne. Akku on CPU:n tärkein rekisteri, siinä tietoa voidaan käsitellä kaikkein monipuolisemmin.

Portti on rekisteri, jonka bitit on tuotu IC-piirin I/O-pinneihin.

Page 3: 5.3. C-kielen perusteet. 3_8

3

Hyvä Kysymys? Miksi samaan porttiin kirjoitettaessa käytetään nimeä PORTB ja luettaessa PINB? Koska kirjoitukselle ja luennalle on oma osoite eli rekisterimuistipaikkansa. PORTB-rekisterin osoite on 0x18, PINB-rekisterin osoite on 0x16 C-koodissa PORTB ja PINB ovat makroja joita käytetään muuttujien lailla.

Hyvä Kysymys? Miksi meidän ei tarvitse tietää osoitteista mitään? Kun käytät C-kielen muuttujaa esim. näin: uint8_t = arvo; arvo = 5;

silloin C-käännin “ymmärtää”, että haluat tallettaa luvun 5 muistipaikkaan jonka se tuntee nimellä arvo. Meidän ei tarvitse tietää missä muistin fyysisessä osoitteessa ko. muuttuja sijaitsee, C-käännin tietää. Samoin, jos haluat tallettaa ko. luvun vaikka A-porttiin = PORTA, C-käännin ”tietää”, että PORTA:n osoite on 0x3B ja sijoittaa luvun sinne. Joten riittää komento: PORTA = 5;

5.3.1. Port_output_allport, portin ohjaus heksaluvulla Portin bitteja manipuloidaan heksaluvuilla eli kaikkia bittejä samalla kertaa. Menetelmä on helppo ymmärtää ja käyttää, siksi sillä on mielekästä aloittaa opiskelu. Tällainen esimerkki meillä oli jo käytössä kun ensimmäistä ohjelmaa analysoitiin. Kun portin suuntarekisteri DDRx määrittää koko portin lähdöksi, output ja PORTx- porttirekisteri määritetään ”ylös” High, pinnin jännite asettuu mikro-ohjaimen käyttöjännitteeseen Vcc = 5 V. Pinnin jännite on 3,3 V (tai joku muu), jos käyttöjännite on 3,3 V (tai joku muu). Jos pinni asetetaan alatilaan, low, sen jännite asettuu GND-jännitteeseen eli 0 V. eka.c lähdekoodin listaus /************************************************** ******** Project : eka_1.c Hardware: PV-M32-MOOkit (4 MHz) + PV-LEDIT Software: WinAVR 20070525 Date : 11.07.2007 Author : pva Comments: vilkuttaa B-portin LEDejä *************************************************** *******/ #include <avr/io.h> #include <util/delay.h> #define WAIT(time) for(uint16_t i=0;i<2000;i++)_del ay_loop_2(time);

Page 4: 5.3. C-kielen perusteet. 3_8

4

int main(void) { DDRB = 0xFF; // suunta ulos while(1) { PORTB = 0xF0; // B-porttiin 1111 000 WAIT(500); // kulutetaan aikaa PORTB = 0x0F; // B-porttiin 0000 1111 WAIT(500); } }

Analysointi Porttirekisterien asetukset ovat yksinkertaisia, koska c-käännin löytää konfigurointi-tiedot io.h header-tiedostosta. Porttia ohjataan heksaluvuilla, joten käyttö heti selkeää. Tämän koodin erikoisuus on viive-määritys. Se on tehty esikääntimen komennolla #define ja se toimii siten, että missä tahansa kohtaa koodissa esiintyvä WAIT(time)

korvataan määreellä for(uint16_t i=0;i<2000;i++)_delay_loop_2(time); Parasta käyttää “kopipastaa” koska kirjoitusasu on tärkeä. 5.3.2. Port_output_portable, portin bitti-ohjaus Seuraavaksi esitettävä koodiversio on tarkoitettu jokapäiväiseen ohjelmointityöhön. Tällä tavoin koodista tulee portattavaa, eli se voidaan pienellä työllä (tarvittaessa) siirtää C-kääntimestä ja/tai mikro-ohjaimesta (MCU) toiseen. Mikä tärkeintä; koodista tulee paljon luettavampaa. Tutkitaan aluksi bittien siirto-operaattorin toiminta, koska sen ymmärtäminen on tarpeen oikeaoppisessa portin (ja muidenkin rekisterien) ohjauksessa. Bittikohtaiset siirto-operaattorit Siirto-operaattorikäskyt siirtävät rekisterin bittejä vasemmalle tai oikealle, niin monta askelta kuin koodin ohjausnumero edellyttää. PORTB = 1<<2;

Kuvan esimerkkikäsky kertoo, että bittejä siirretään kaksi askelta vasemmalle, kakkosbitti asetetaan ykköseksi, kaikki muut nollataan. Bitin siirrossa äärimmäisenä vasemmalla oleva bitti 'putoaa roskakoriin' ja oikeanpuolimmaiseksi bitiksi nousee (tässä tapauksessa) ensin ykkönen, jota siirretään 2 kertaa vasemmalle.

Page 5: 5.3. C-kielen perusteet. 3_8

5

Kuva 5.3.1. Bittien siirto. Toinen tulkinta koodille: B-rekisterin kakkosbitti asetetaan ykköseksi ja kaikki muut nollataan. 5.3.2.1. Bittikohtainen siirto vasemmalle x << 1; Kaikki rekisterin bitit siirtyvät yhden askeleen vasemmalle. x << 2; Kaikki rekisterin bitit siirtyvät kahden askeleen verran vasemmalle. x = x << 1; Muuttujan x bitit siirtyvät yhden pykälän vasemmalle, oikeanpuolimaiseksi bitiksi tulee 0. Tämä on käytännössä sama kuin kertominen kahdella.

Huom! siirto-operaatio ei muuta muuttujan arvoa, ellet käytä sijoitusoperaatiota x = x >> 3;

5.3.2.2. Bittikohtainen siirto oikealle x >> 1; Kaikki rekisterin bitit siirtyvät yhden askeleen oikealle. x >> 3; Kaikki rekisterin bitit siirtyvät kolme askelta oikealle. x = x >> 1; Muuttujan x bitit siirtyvät yhden pykälän oikealle, vasemmanpuolimmaiseksi bitiksi tulee 0. Tämä on käytännössä sama kuin jakaminen kahdella.

Page 6: 5.3. C-kielen perusteet. 3_8

6

Käskyn toiminta selviää parhaiten tutkimalla ja ajamalla ohjelmia. Bittien siirto vasemmalta oikealle ja päinvastoin, esimerkki /************************************************** ******** Project : vasen-oikea.c Hardware: PV-M32 + PV-LEDIT on PORTB ja on PORTA Software: WinAVR-20071221 Date : 07.01.2008 Author : pva Comments: bittien siirto vasemmalta oikealle ja oikealta vasemmalle *************************************************** *******/ #include <avr/io.h> #include <util/delay.h> #define WAIT(time) for(uint16_t i=0;i<2000;i++)_del ay_loop_2(time); int main(void) { DDRB = 0xFF; DDRA = 0xFF; uint8_t bitti = 0x80; // 1000 0000 bin PORTB = bitti; WAIT(100); while (1) { while(1) // oikealle { bitti = bitti >> 1; // siirretään bittejä 1 a skel oikealle // tulos asetetaan bitti-muuttujan uudeksi ar voksi PORTB = bitti; WAIT(100); if(bitti==0)break; // kun nolla, hypätään sil mukasta ulos } bitti = 0x01; PORTA = bitti; WAIT(100); while(1) // vasemmalle { PORTA = 1<<bitti; // siirto vasemmalle WAIT(100); bitti++; if(bitti>8)break; } bitti = 1<<7; PORTB = bitti; WAIT(100); // aloitetaan alusta } } Analysointi Kommentit ohjelmassa kertovat kaiken. Harjoituksia

1. Muuta koodia niin, että valoisa LED ’juoksee’ nopeammin. 2. Muuta koodia niin, että ’pimeä’ LED ’juoksee’ samoin, muut loistaa.

Page 7: 5.3. C-kielen perusteet. 3_8

7

5.3.2.3. Portin ja/tai rekisterin yksittäisen bitin asetus tai nollaus Käytännössä meillä on neljä eri mahdollisuutta:

- bitti asetetaan ykköseksi, muut bitit nollataan - bitti asetetaan ykköseksi, muut bitit jäävät ennalleen - bitti nollataan, muut bitit asetetaan ykköseksi - bitti nollataan, muut bitit jäävät ennalleen

Määritys uint8_t = etumerkitön char, 8-bittiä

onkin jo tuttu juttu. Sen käyttö on suositeltavaa, sillä se on ANSI-C99-normin mukaista. Yksittäisten bittien manipuloinnista on oma dokumentti, “8.1. Special. Bittioperaatiot.pdf”, jossa nuo ylläolevat aiheet käydään esimerkkien kanssa läpi. Jos aihe tässä vaiheessa kiinnostaa, ota se esille. Muuten voit palata siihen aina kuin on tarvetta. 5.3.3. Port_output_BitValue BV tulee sanoista Bit Value, bitin arvo. Tätä menetelmää näkyvät monet AVR-koodaajat suosivan koska siten koodista tulee luettavampaa. C-koodin eräs ongelmahan on se, että sillä voidaan kirjoittaa, haluttaessa, hyvinkin kryptistä = vaikeaselkoista koodia. Me ei sorruta sellaiseen, eihän. avr-gcc-kääntimen kirjastossa on polun C:\WinAVR-20070525\avr\include\avr päässä sfr_defs.h-header-tiedosto. Sieltä löytyy määritys: #define _BV(bit)(1 << (bit))

Operaatio (1<<n) (tai _BV(n) – sama asia) asettaa yhden bitin (n) _BV(0) = 1 << 0 = 0000 0001 = 0x01 _BV(1) = 1 << 1 = 0000 0010 = 0x02 _BV(2) = 1 << 2 = 0000 0100 = 0x04 _BV(3) = 1 << 3 = 0000 1000 = 0x08 _BV(4) = 1 << 4 = 0001 0000 = 0x10 etc. sen jälkeen voit maskata lukua käyttämällä OR, AND EXOR operaatioita, jolloin asetetaan, nollataan tai käännetään 8-bittisen rekisterin yksi bitti, muut jäävät ennalleen. PORTB = _BV(0); // asettaa 0-bitin ykköseksi, mu ut nollataan PORTB = ~_BV(0); // nollaa 0-bitin, muut ykköseks i PORTB |= _BV(3); // asettaa 3-bitin ykköseksi, mu ut jäävät ennalleen PORTB &= ~_BV(3); // nollaa 3-bitin, muut ennallaa n PORTB = ~_BV(i); // nollaa i-bitin, muut ykköseks i

Page 8: 5.3. C-kielen perusteet. 3_8

8

Koodista tulee luettavampaa, jos käytät pinnin numeron sijasta sen nimeä, esim PB0..7. Ne on määritetty avr-libc-kirjaston headereissa. PORTB |= _BV(PB1); PORTB |= _BV(PORTB1);

Alaviivaa, underscore, _ omatekemän muuttujan (funktion) nimen alussa tulee välttää, se on tarkoitettu järjestelmäkirjaston käyttöön.

Portin pinnien nimet on määritelty portpins.h headerissa, joka löytyy samasta polusta (C:\WinAVR-20070525\avr\include\avr). Tutustu ko. tiedostoon, sillä koodin tekemisen lisäksi on syytä oppia kääntimen rakennetta ja toimintaa edes alkeiden verran. Siitä on paljon hyötyä myöhemmin, kun ammatti- tai gurukoodaajana perehdyt Embedded Linux-koodaukseen.

Seuraavaksi koodiesimerkki:

BitValue_m32.c, harjoitus /************************************************** ******** Project : BitValue_1.c Hardware: PV-M32, PV-LEDIT on PORTB Software: WinAVR-20070525 Date : 12.07.2007 Author : pva Comments: asettaa ja nollaa yksittäisiä bittejä BV on BitValue, bitin arvo *************************************************** *******/ #include <avr/io.h> #include <util/delay.h> // prototyyppi void wait(uint16_t time); int main(void) { DDRB = 0xFF; while(1) { PORTB = 0xF0; // 1111 0000 wait(500); PORTB = _BV(0); // asettaa 0-bitin, muut no llataan wait(500); PORTB &= ~_BV(0); // nollaa 0-bitin, muut e nnallaan wait(500); } }

Analyysi

Kommentit kertovat kaiken.

Page 9: 5.3. C-kielen perusteet. 3_8

9

Extra Käytä portin tai rekisterin bitin nimeä numeroiden sijasta. Niitä kaikkia jotka on määritetty avr-libc-kirjastossa, voi aivan hyvin käyttää ja koodista tulee luettavampaa. PORTB |= _BV(PB1);

Asettaa B-portin ykkösbitin ykköseksi, muut jää ennalleen.

Voit käyttää myös seuraavaa merkintää:

PORTB = _BV(PORTB0); // B-porttiin 0000 0001 PORTB = _BV(PORTB7); // B-porttiin 1000 0000

tai PORTB = _BV(PB0); PORTB = _BV(PB7);

Se on sama asia. Määritykset löytyvät: portpins.h tiedostostosta, polku: C:\WinAVR-20070525\avr\include\avr

Kokeile.

Toinen BitValue-harjoitus /************************************************** ******** Project : bit_value_2.c Hardware: PV-M32 (4 MHz), PV-LEDIT Software: WinAVR 20060421 Date : 08.12.2006 Author : pva Comments: asettaa ja nollaa yksittäisiä bittejä BV on BitValue, bitin arvo *************************************************** *******/ #include <avr/io.h> #include <util/delay.h> // function prototype void wait(uint16_t time); int main(void) { DDRB = 0xFF; while(1) { PORTB = 0xF0; // 1111 0000 wait(500); PORTB = _BV(PB0); // Bit Value, asettaa ykköseksi 0-bitin, muut nolla taan wait(1000); PORTB = 0x0F; // 0000 1111 wait(500); PORTB |= _BV(PB7); // Bit Value, asettaa 7-bitin, muut jäävät ennallee n // | on putki eli OR-operaatio ja sitten sijoitus wait(1000);

Page 10: 5.3. C-kielen perusteet. 3_8

10

PORTB &= ~_BV(2); // nollataan 2-bitti, muut jäävät ennalleen /* & on AND-operaatio, ~ (tilde) invertoi bitit PORTB 1111 0100 ~BV(2)1111 1011 invertoidaan 0000 0100 AND --------------- = 1111 0000 */ wait(1000); PORTB = 0x00; wait(500); } }

Bit Value 3 Näinkin voidaan toimia: int main(void) { DDRB = 0xFF; PORTB = 0xFF; uint8_t i = 0; while(1) { PORTB = ~_BV(i); // Bit Value, asettaa i-bitin, muut nollataa n // sitten ~ (tilde) invertoi kaikki bitit i++; // i = i+1; wait(100); if(i>7) i = 0; } } } Muuttuja i asetetaan aluksi nollaksi, kun nollabitti asetetaan ykköseksi komennolla _BV(i); sitten bitit invertoidaan tildellä ja tulos asetetaan B-porttiin. PORTB = ~_BV(i);

Sitten i-muuttujaa kasvatetaan yhdellä joka kierroksella, kunnes i on suurempi kuin 7, se asetetaan takaisin nollaksi ja sama uudelleen jatkuu.

Page 11: 5.3. C-kielen perusteet. 3_8

11

Setting by UCR |= _BV(TXCIE); works fine. Clearing by UCR &= _BV(TXCIE); doesn´t work. But this works fine: UCR &= ~_BV(TXCIE); This both works UCR |= (1<<TXCIE);//set UCR &= ~(1<<TXCIE);//clear

5.3.4. Port_output_bit_macros Makrot tässä makroista vain vähäsen, jotta ne saadaan käyttöön. Laajempi esitys makroista on toisessa dokumentissa. Tässä esitetään makron käyttöä portin bittien manipuloinnissa. #define MYLED PB1 #define MYLED_ON (PORTB |=_BV(PB1)) #define MYLED_OFF (PORTB &=~_BV(PB1)) #define MYLED_TOGGLE (PORT ^=_BV(PB1)) Esikääntimelle annetaan ohje korvata koodissa teksti MYLED tekstillä PB1 ja muissa määrityksissä toimitaan samalla tavalla. MYLED_ON ja LED loistaa. MYLED_OFF ja LED sammuu. MYLED_TOGGLE kääntää LEDin tilan. bittien_asetus_1.c esimerkki /************************************************** ******** Project : bittien_asetus_1.c Hardware: PV-M32 + PV-LEDIT on PORTB Software: WinAVR-20071221 Date : 5.01.2008 Author : pva Comments: bitin asetus, nollaus ja invertointi *************************************************** *******/ #include <avr/io.h> #include <util/delay.h> #define MYLED PB1 #define MYLED_ON (PORTB |=_BV(PB0)) #define MYLED_OFF (PORTB &=~_BV(PB0))

Page 12: 5.3. C-kielen perusteet. 3_8

12

#define MYLED_TOGGLE (PORTB ^=_BV(PB7)) // prototyyppi void wait(uint16_t time); int main(void) { DDRB = 0xFF; // PORTB = 0xFF; kokeile ensin ilman tätä // sitten poista kommentti ja kokeile while (1) { MYLED_ON; wait(300); MYLED_OFF; wait(300); MYLED_TOGGLE; // toggle = invertoi } }

Analyysi Jos perehdyit ed. esimerkkiin kunnolla, koodi on ”selväkielistä”. 5.3.5. Port_input_allport, portin käyttö tulona, input Kun portin suuntarekisteriin kirjoitetaan bitin arvoksi nolla, 0, portin ko. pinnin suunta on sisäänpäin, input. Nyt portin pinniin tuotu looginen ykkönen tai nolla näkyy input- eli PINx-rekisterin vastaavana tilana. PINx-rekisterin tila on luettava talteen muuttujan arvoksi. Kuva 5.3.5.1 osoittaa miten porttia käytetään tulona kytkemällä siihen kytkin. Kytkimen asento, auki tai kiinni, näkyy PINx-rekisterissä bitin 1/0-tilana. Samaa ideaa voidaan soveltaa ovi-, ikkuna- yms. kytkimien valvontaan tai muuhun digitaaliseen tilatietoon.

PINx

DDRx

PORTx

Bit1Bit0

Bit2Bit3....

0

10

Portin x bitin 0suunta 0 = tulo

Portin x tulobitissä0 on ylösvetovastus (1)

Pin

R>35k

10

Ulkoinen kytkin -> 00

virta

0

Kuva 5.3.5.1. Yksinkertainen tulo, input

Page 13: 5.3. C-kielen perusteet. 3_8

13

Kun DDRx-rekisteriin kirjoitetaan nolla, 0, se liittää portin ulkoisen pinnin PINx-rekisteriin. Jos ko. pinniä ei ole liitetty ulkoisesti mihinkään, se kelluu. Kytkemätön, kelluva, input-pinni toimii ikäänkuin antenni. Siihen indusoituvat kaikki mahdolliset häiriöjännitteet ja ne sekoittavat ohjaimen toiminnan. Siksi inputiksi ohjelmoidun portin pinnit tulee liittää joko ”maihin”, GND, tai käyttöjännitteeseen, +5 V. DDRx bit = 1 DDRx bit = 0 PORTx bit = 1 High, “1” pull-up, ylösvetovastus ”ON” PORTx bit = 0 Low, “0” floating, kelluu Portin pinnin liittäminen tapahtuu joko ulkoisilla ylös- tai alasvetovastuksilla. AVR:ssä on mahdollista liittää ko. pinniin myös sisäinen ylösvetovastus. Se tapahtuu kirjoittamalla PORTX-rekisterin vastaava bitti ykköseksi (katso kuvaa), kun portti on määritetty tuloksi, input. Jos kuvan ulkoista kytkintä ei ole painettu, sisäinen vastus R, ylösvetovastus, ikään kuin ’vetää’ portin pinnin tilaan 1. Kun vastuksen läpi ei kulje virtaa ja portin tuloimpedanssi on hyvin suuri, niin vastuksen kummassakin päässä vaikuttaa sama jännite +5 V eli looginen ykkönen. Jos kytkintä painetaan, se maadoittaa portin pinnin, tulon tila on nyt 0 V eli looginen nolla. Portin tila voidaan lukea muuttujan arvoksi ja käyttää ohjelmassa. WinAVR-kääntimessä portin luku noudattaa samaa muotoa kuin porttiin kirjoittaminen. Portin tulojen tila voidaan lukea muuttujan arvoksi PINx komennolla, jossa x on portin nimi. Siis komento PIND, Port INput D, jossa D-portin tila luetaan. Kun porttia käytetään input- eli sisääntulotilassa, on portin suuntarekisteri määritettävä olemaan sisäänpäin, input, eli DDRD = 0x00; // kaikki bitit input

Tuloportin tila luetaan muuttujan arvoksi esim. seuraavasti muuttuja = PIND; // luetaan D-portin tila ja sijoit etaan muuttujaan

Useimmat virheet aloittelija (ja liian usein kokenutkin!) tekee yrittämällä lukea PORTx-rekisterin tilaa. Pitää lukea PINx-rekisteriä.

Miten tavu luetaan portista? x = PINB; // lukee B-portin kaikki bitit x-muuttuja an

Jos kytkimen lukutulokset ovat ”mitä sattuu”, syy mitä ilmeisemmin on kytkivärähtelyissä, Bounce. Kun kytkimen asentoa muutetaan, muutoksen jälkeen tavalliset pienet kytkimet värähtelevät alle 20 ms, isot mekaaniset kytkimet jopa 50 ms tai ylikin. Eliminoi värähtelyn vaikutus lisäämällä koodiin noin 20 ms viive.

Page 14: 5.3. C-kielen perusteet. 3_8

14

Koko portin tilan lukeminen ja tulostus, esim. /************************************************** ******** Project : input_all.c Hardware: PV-M32 + PV-LEDIT on PORTB + PV-TINT on P ORTD Software: WinAVR-20070525 Date : 18.07.2007 Author : pva Comments: painele INT0- ja INT1-nappeja ja tarkkail e ledejä INT0 = PD2 INT1 = PD3 INT2 = PB2 Katso PV-TINT-kortin kytkentäkaaviota, niin ymmärrä t miksi bitti 4 ja 5 ovat pimeitä (transistorien kannat vetävät ko. pinnit maihin) *************************************************** *******/ #include <avr/io.h> int main(void) { DDRB = 0xFF; // all output DDRD = 0x00; // all input PORTD = 0xFF; // bitit "ylös" while(1) { PORTB = PIND; // Port Input D // lukee D-portin tilat ja sijoitetaan tulos B -porttiin // painele INT0- ja INT1-nappeja } }

Analysointi Kaikki olennainen selviää kommenteista. 5.3.6. Port_input_one_bit, yksittäisen bitin lukeminen Usein on tarpeen tietää jonkin yksittäisen bitin tila joko portissa tai jossain muussa rekisterissä. Kun halutaan tietää onko B-portin 0-bitti ylhäällä, kirjoitetaan koodi: if (PINB & (1 << PB0)) // "PB0" on bitin numero

Lauseke on tosi, jos PINB0 on ykkönen.

Oletus 1 PINB xxxx xxxx1 // x saa olla 1 tai 0 1<<PB0 0000 00001 ------------------------------ & AND 0000 00001 tosi-true

Oletus 2 PINB xxxx xxxx0 // x saa olla 1 tai 0 1<<PB0 0000 00001 ------------------------------ & AND 0000 00000 epä-tosi-false

Page 15: 5.3. C-kielen perusteet. 3_8

15

Esimerkki /************************************************** ******** Project : input_3.c Hardware: PV-M32 (4 MHz) + PV-TINT D-portissa ja PV-LEDIT B-portissa Software: WinAVR 20060421 Date : 24.11.2006 Author : pva Comments: lukee D-portin painokytkimiä, jos INT1 o n painettu

sytyttää B-portissa LEDi-kuvion INT1 = PD3 Katso kortin kytkentäkaaviota, *************************************************** *******/ #include <avr/io.h> #define LUKU 0xC7 // vakion määritys // transistorit vetävät PD4 ja PD5 alas = 0 int main(void) { DDRB = 0xFF; PORTB = 0x00; DDRD = 0x00; // suunta input PORTD = 0xFF; // pinnit 'ylös', // jotta napin painallus voidaan lukea while(1) { if(PIND == LUKU) PORTB = LUKU; // jos INT1 painettu, eli PD3 == 0 (INT1 == P D3) else PORTB = 0x81; } }

Analysointi Portin tilan lukeminen ja testaaminen käy mukavasti edellä opitulla AND-operaattorilla ja if-lause-testillä. Input, if-lause ja AND-operaatio /************************************************** ******** Project : input_ehto.c Hardware: PV-M32 + PV-TINT D-portissa ja PV-LEDIT B -portissa Software: WinAVR-20070525 Date : 19.07.2007 Author : pva Comments: lukee D-portin painokytkimiä, jos painett u sytyttää B-portissa LEDi-kuvion INT0 = PD2 INT1 = PD3 INT2 = PB2 ja tarkkaile B-portin ledejä Katso kortin kytkentäkaaviota. *************************************************** *******/

Page 16: 5.3. C-kielen perusteet. 3_8

16

#include <avr/io.h> #define LUKU 0xC7 // vakion määritys // transistorit vetävät PD4 ja PD5 alas = 0 int main(void) { DDRB = 0xFF; PORTB = 0x0F; DDRD = 0x00; // suunta input PORTD = 0xFF; // pinnit 'ylös', // jotta napin painallus voidaan lukea while(1) { if(~PIND & (1 << PD2)) // jos INT0 painettu, eli PD2 == 0 (INT0 == P D2) PORTB = 1<<7; else if(PIND == LUKU) PORTB = 1<<0; // jos INT1 painettu, eli PD3 == 0 (INT1 == P D3) else PORTB = 0x18; // jos ei mitään painettu } } Analysointi Esikääntimelle kerrotaan määrityksestä: #define LUKU 0xC7 // vakion määritys

0xC7 on binäärisenä 1100 0111 D-portin tila on 1100 1111 (napit ”ylhäällä”). Mutta jos INT1-nappia on painettu, niin tila on 1100 0111. Kun testataan onko LUKU yhtäkuin PIND tila, ehto on tosi jos INT1-nappia on painettu eli 3-pinni on nolla. if(PIND == LUKU) PORTB = 1<<0; // jos INT1 painettu, eli PD3 == 0 (INT1 == P D3)

Tämä ei liene ongelma. Mutta toisen painonapin testauskoodi vaatii hieman selitystä. if(~PIND & (1 << PD2)) // jos INT0 painettu, eli PD2 == 0 (INT0 == P D2) PORTB = 1<<7;

D-portin tilahan on 1100 1111, kun napit ovat ”ylhäällä”. Kaksi nollaa johtuu siitä, että kortilla on kaksi trasnsistoria, joiden kannat on kytketty ovat ko. bitteihin. Invertoinnin (tilde) jälkeen tila on 0011 0000. Jos PD2 eli INT0 on painettu, tila on invertoinnin jälkeen 0011 0100.

Page 17: 5.3. C-kielen perusteet. 3_8

17

~PIND 0011 0100 kun INT0 on painettu alas 1<<PD2 0000 0100 ----------------------------- AND & JA

tulos 0000 0100 eli tosi, jolloin ehtolause on tosi=true ja B-portin 0-bitti asetetaan ykköseksi. Jos nappia ei olisi painettu, tulos olisi 0000 0000 eli epätosi=false.

C-kielessä kaikki nollasta poikkeavat luvut ovat tosi, true, nolla on epätosi eli false.

Vaihtoehtoinen input /************************************************** ******** Project : input_6.c Hardware: PV-M32 (4 MHz) + PV-TINT D-portissa ja PV-LEDIT B-portissa Software: WinAVR 20060421 Date : 08.12.2006 Author : pva Comments: input-demo, painele INT0- ja INT1-nappeja INT0 = PD2 INT1 = PD3 INT2 = PB2 ja tarkkaile B-portin ledejä Katso kortin kytkentäkaaviota, niin ymmärrät miksi bitti 4 ja 5 ovat pimeitä (transistorien kannat vetävät ko. pinnit alas) *************************************************** *******/ #include <avr/io.h> int main(void) { DDRB = 0xFF; DDRD = 0x00; // input PORTD = 0xFF; // bitit "ylös" while(1) { if((PIND & (1 << 2)) != 0) // jos INT0==PD2 painettu PORTB = _BV(0); else PORTB = _BV(7); } }

Analysointi Tutkitaan onko D-portin 2-pinni painettu.

Page 18: 5.3. C-kielen perusteet. 3_8

18

if ((PIND & (1 << PD2)) != 0) Tuo merkintä kaipaa selitystä: Huutomerkki ! ei ole C-kielessä huutomerkki vaan se on unaarinen negaatio-operaattori joka muuttaa nollasta poikkeavan operandin arvoon nolla ja nollaoperandin arvoon 1. Sen käyttö on yleistä rakenteissa, esim. if (!valid) // valid = voimassaoleva

toinen tapa esittää sama asia: if (valid == 0). PIND 1100 1111 // jos nappia ei painettu PIND 1100 1011 // jos nappia on painettu

PIND 1100 1011 // jos nappia on painettu 1<<2 0000 0100 --------------------& AND tulos 0000 0000

Eli kun INT0-nappia on painettu, ehtotesti oikeastaan on if(0 == 0) // jos PD2 painettu

Testitulos on selvästikin tosi. Jos INT0 ei ole painettu PIND 1100 1111 // jos nappia ei painettu 1<<2 0000 0100 --------------------& AND tulos 0000 0100

Eli kun INT0-nappia ei ole painettu, ehto kuuluu if(1 == 0)

Joka selvästikään ei ole tosi. "PD2" on bitin numero (katso avr-libc). AND operaatio maskaa kaikki muut bitit. 5.3.7. Port_input_bit_macro Makrot tässä makroista vain vähäsen, jotta ne saadaan käyttöön. Laajempi esitys makroista on toisessa dokumentissa. Makrot ovat osa C-esikäsittelijää. Ne prosessoidaan ennenkuin C-käännin kääntää varsinaisen koodin. Makron käyttö tekee koodista luettavamman (?) ja jos käytetään yleiskäyttöisiä makroja, siirrettävämmän.

Page 19: 5.3. C-kielen perusteet. 3_8

19

Makrossa määritetty koodi kopioituu lähdetekstiin erikseen jokaiseen kohtaan, jossa makroa käytetään. Makron määrittely on voimassa esiintymiskohdastaan eteenpäin koko käännösyksikössä.

- makro on tehokkaampi kuin vastaava funktio, mutta ei yhtä monipuolinen. - ei tyyppitarkistuksia, mutta sillä voi olla sivuvaikutuksia

makrot nopeuttavat koodia (ei keskeytyskäsittelyä) ctype.h set of macros

makron nimi korvataan pätkällä koodia, joka suorittaa varsinaisen toiminnon. Se tulee aina koodin alkuun. - loppuun ei puolipistettä - yksi rivi tavallisesti #define TEHO virta*jannite makro korvaa tunnisteen tekstillä #define forever for(;;) - määrittelee uuden sanan, forever, päättymättömälle silmukalle Tutki sfr_defs.h headeria. Se löytyy polusta: C:\WinAVR-20070525\avr\include\avr Siellä on määritys: #define bit_is_set(sfr, bit) (_SFR_BYTE(sfr) & _BV( bit))

Määritys testaa onko I/O-rekisterin bitti set eli asetettu eli 1. Makro palauttaa zeron eli nollan, jos bitti on yhtä kuin nolla, ja se palauttaa non-zeron eli ykkösen, jos bitti on asetettu eli se on 1.

Samassa paikassa on toinenkin määritys: #define bit_is_clear(sfr, bit) (!(_SFR_BYTE(sfr) & _BV(bit)))

Se testaa onko bitti nolla.

Näillä makroilla on helppo tehdä koodi, joka testaa onko joku tietty portin bitti yksi vai onko se nolla. Esim. onko pinniin liitettyä painonappia painettu vai ei, onko ovikytkin auki vai ei, jne.

Yhden bitin testaus, harjoitus /************************************************** ******** Project : input_one_macro.c Hardware: PV-M32 + PV-TINT D-portissa + PV-LEDIT B- portissa Software: WinAVR-20070525 Date : 19.07.2007 Author : pva Comments: yksittäinen bitti input-demo, painele INT 0 INT0 = PD2 INT1 = PD3 avr-libc kirjastosta löytyy mm. seuraavat makrot: bit_is_set(sfr, bit) ==> rekisterin bitti 1 bit_is_clear(sfr, bit) ==> rekisterin bitti 0 *************************************************** *******/

Page 20: 5.3. C-kielen perusteet. 3_8

20

#include <avr/io.h> int main(void) { DDRB = 0xFF; PORTB = 0x00; DDRD = ~(1 << 3); // 3.bitti "0" in, muut "1" o ut // ~ on tilde, invertoi bitit PORTD = 1 << 3; // 3. bitti ylös, muuta alas while(1) { if(bit_is_clear(PIND, 3)) // jos INT1 painettu // eli onko D-portin 3.bitti nolla PORTB = 1 << 0; // 0-bitti ON else PORTB = 1 << 7; // 7-bitti ON } }

Harjoitus Lisää koodiin INT0-napin testaus.

Voit määrittää ikuisesta silmukasta myös makron #define IKUINEN for(;;)

5.3.8. Port_input_loop_macro Tutki sfr_defs.h headeria. Se löytyy polusta: C:\WinAVR-20071221\avr\include\avr Siellä on määritykset: #define loop_until_bit_is_set(sfr, bit) do { } whil e (bit_is_clear(sfr, bit)) #define loop_until_bit_is_clear(sfr, bit) do { } wh ile (bit_is_set(sfr, bit))

Joita voidaan käyttää seuraavasti: loop_until_bit_is_clear(PIND, 3); // odota kunnes D-portin 3. painettu (eli INT1)

loop_until_bit_is_set(PIND, 5); // odota kunnes D-portin 5.bitti on yksi

Page 21: 5.3. C-kielen perusteet. 3_8

21

Yhden bitin testaus, odotellaan kunnes bitti on asetettu/nollattu /************************************************** ******** Project : input_loop_macro.c Hardware: PV-M32 + PV-TINT D-portissa + PV-LEDIT B- portissa Software: WinAVR-20070525 Date : 19.07.2007 Author : pva Comments: input-demo, painele INT0 ja INT1 INT0 = PD2 INT1 = PD3 avr-libc kirjastosta löytyy mm. seuraavat makrot: loop_until_bit_is_set(sfr, bit) ==> Odota kunnes bitti on 1 loop_until_bit_is_clear(sfr, bit) ==> Odota kunnes bitti on 0 *************************************************** *******/ #include <avr/io.h> #include <util/delay.h> // function prototype void wait(uint16_t time); // lisää wait-funktion mä äritys int main(void) { DDRB = 0xFF; PORTB = 0x01; DDRD = ~(1 << 3); // 3.bitti "0" in, muut "1" o ut // ~ on tilde, invertoi bitit PORTD = 1 << 3; // 3. bitti ylös, muuta alas while(1) { loop_until_bit_is_clear(PIND, 3); // kunnes IN T1 painettu PORTB = 1 << 7; // 7-bitti ON wait(1000); PORTB = 1 << 0; // 0-bitti ON } }

Kommentit kertovat kaiken. Kokeile käyttää makroa IKUINEN. Kertausta Ehto- ja silmukkalauseilla saadaan hieman älyä ohjelmiin. Mikro-ohjain osaa niiden ohjeiden perusteella päätellä, mitä sen tulee tehdä seuraavaksi. Se osaa mm.

- saunan lämpötilan perusteella kytkeä kiukaan lämmityksen päälle tai pois ja kun kaikki on ok, se kutsuu saunojat paikalle

- sulkea tai avaa ovien lukot tiettyyn kellonaikaan, mutta päästää koodin tuntijan sisälle tällä välilläkin

- tutkii milloin modeemin sarjaportista on tulossa bittejä, kerää ne tavuksi, tallettaa ja jää odottamaan seuraavia

- tarkkailee sähkömoottorin kierrosnopeutta ja jos se poikkeaa ohjearvoista, säätää nopeuden oikeaksi

- jos ei-toivottu tunkeilija hiippailee varastossa, se osaa suorittaa hälytyksen ja kutsua poliisin paikalle

- ja vaikka mitä muuta

Page 22: 5.3. C-kielen perusteet. 3_8

22

Kaikki em. perustuu testaukseen, jota CPU tekee kaiken muun puuhastelunsa ohessa. Testin perusteella ohjelma päättää, tehdäänkö niin tai näin, hypätäänkö jonkun/joidenkin käskyjen ohi, vai tehdäänkö sama vielä kerran uudelleen. #define bit_is_clear ( sfr, bit ) (~inb(sfr) & _BV(bit)) - testaa onko bit sfr-I/O-rekisterissä nollattu *************** define bit_is_set ( sfr, bit ) (inb(sfr) & _BV(bit)) - testaa onko bit sfr-I/O-rekisterissä asetettu ************* #define loop_until_bit_is_clear ( sfr, bit ) do { } while (bit_is_set(sfr, bit)) - odota kunnes bit nollautt sfr I/O-rekstertirssä *************** #define loop_until_bit_is_set ( sfr, bit ) do { } while (bit_is_clear(sfr, bit)) - odota kunnes bit on asetettu ****************** 5.3.9. Omatekemät makrot Yksi tapa on käyttää direktiiviä #define ja tekstikorvausta. Nimet kannattaa valita helpottamaan koodin toiminnan ymmärtämistä. #define BIT0 0 #define BIT1 1 #define BIT2 2 joten, asetetaan kakkosbitti, muu jää ennalleen: PORTB |= (1<<BIT2); tai, nollataan kakkosbitti, muut jää ennalleen: PORTB &= ~(1<<BIT2);

Set the bits with ANSI-C. It's more easy if you are using different compilers.

Page 23: 5.3. C-kielen perusteet. 3_8

23

/************************************************** ******** Project : oma_makro.c, Hardware: PV-M32 + PV-LEDIT Software: WinAVR-20070525 Date : 01.12.2007 Author : pva Comments: Kokeile muitakin määärityksiä *************************************************** *******/ #include <avr/io.h> #include <util/delay.h> #define BIT0 0 #define BIT1 1 #define BIT2 2 int main(void) { DDRB = 0xFF; // out PORTB = 0xF0; while(1) { PORTB |= (1<<BIT0); // asettaa 0-bitin, muut jää ennalleen wait(500); PORTB = 0xFF; wait(500); PORTB &= ~(1<<BIT2); // nollaa 2-bitin, muut jää ennalleen wait(500); PORTB = 0xF0; wait(500); } } Analyysi Lisää wait-funktion määritys. 5.3.10. Portin osoite Kääntimen header-kirjasto, iom32.h, joka löytyy polusta: C:\WinAVR-20071221\avr\include\avr on määritelty mm. porttien rekistereiden osoitteet. Sieltä löytyy myös B-portin osoitteiden määritykset. /* Port B */ #define PINB _SFR_IO8(0x16) #define DDRB _SFR_IO8(0x17) #define PORTB _SFR_IO8(0x18)

Siis, kun kirjoitamme vaikka PORTB-rekisteriin, niin oikeastaan kirjoitamme datan osoitteeseen 0x18, johon kirjoitetaan konekielen käskyillä.

Page 24: 5.3. C-kielen perusteet. 3_8

24

/************************************************** ******** Project : port_osoite.c Hardware: PV-M322, (4 MHz) + PV-EMO + PV-LEDIT on P ORTB Software: WinAVR-20071221 Date : 06.01.2008 Author : pva Comments: tulostaa B-portin PINB-rekisterin osoitte en lcd-näyttöön. Kopioi projektikansioon lcd_tat.c, lcd_tat.h Lisää lcd_tat.c AVRStudioon: klikkaa hiirellä vasemman "puu-ikkunnan" Source Files, Add Existing Source Files... Antaa pari varoitusta, mutta älä välitä tässä vaihe essa PINB-osoite = 0x36 DDRB-osoite = 0x37 PORTB-osoite = 0x38 *************************************************** *******/ #include <avr/io.h> #include <stdio.h> #include <util/delay.h> #include "lcd_tat.h" // function prototype void wait(uint16_t time); int main(void) { DDRB = 0xFF; uint16_t oso = 0; // tavallinen muuttuja uint16_t *poso = 0; // osoitinmuuttuja LCD_init(1, 0, 0); // Otetaan prinft()-funktio käyttöön siten, että tulostus // ohjataan LCD_WriteChar()-funktioon = LCD-näytö lle. fdevopen((void *) LCD_WriteChar, NULL); while(1) { LCD_Clear(); // näytön tyhjennys ja kursori "ko tiin" wait(100); oso = &PINB; // luetaan PINB-rekisterin osoite muuttujaan poso = &PORTB; // luetaan PORTB-osoite osoitinm uuttujaan printf("PINB-osoite:"); LCD_SetCursorXY(0, 1); // kursori seuraavalle r iville printf("ox%x ", oso); // osoitetulostus hexana *poso = 0x18; // out to PORTB wait(2000); PORTB = 0x00; } } // *** Primitive wait() *** void wait(uint16_t time) { volatile uint16_t i;

Page 25: 5.3. C-kielen perusteet. 3_8

25

for(i=0;i<2000;i++) _delay_loop_2(time); } Analysointi Kirjaston määritys on #define PINB _SFR_IO8(0x16)

Me saamme ohjelman tulostamana osoitteeksi: PINB-osoite = 0x36

Miksi näin? Katso AVR muistikarttaa dokumentissa doc2503.pdf, sivulla 17, SRAM Data Memory. Siitä näet, että käskytyypin perusteella osoitetaan I/O-rekistereitä joko Register File-osoitteella tai 0x20 suuremmalla Data Address Space-osoitteella. Meidän koodimme käyttää jälkimmäistä osoitusmuotoa, jolloin PINB osoite on 0x36. Samoin toimivat kaikkien muidenkin rekisterien osoitteet. 5.3.11. Bit fields Tämä on kesken, uusitaan seuraavassa painoksessa. Tämän tekstin ymmärtäminen onnistuu vasta kun olet opiskellut structit. Mutta olen liittänyt sen tähän, koska se on hyödyllinen porttien käsittelyssä. Voit opiskella tämän kohdan myöhemmin. Kun muistissa on ahdasta, on usein tarpeen pakata monta eri tietoa samaan tavuun. Tai kun halutaan ohjata yhtä portin bitiä, mutta sisällyttää samaan ohjaustavuun monta eri ohjaustietoa. Näin voidaan tehdä by bitwise logical operators. Tämän lisäksi C-kielessä on mielenkiintoinen ominaisuus: bitfields, joka mahdollistaa yhden yksittäisen bitin manipuloinnin. Monta etua:

- jos muisti on rajoitettu, voit tallettaa monta Boolean muuttujaa (true/false) yhteen tavuun

- monta laitetta voi kertoa tilatietonsa yhdessä tavussa - certain encryption routines need to access the bits within a byte

Bitfieldin tulee olla jäsenenä sturctissa tai unioinissa. Mallikoodi bitfield Tulossa

Page 26: 5.3. C-kielen perusteet. 3_8

26

Kertausta Bittien asetuksia ykköseksi, ”1” PORTB = 1 << 7; // 1000 0000 asettaa 7-bitin, nolla a muut PORTB |= 1 << 7; // asettaa 7-bitin, muut jää ennal leen PORTB |= 1 << PB5; // asettaa 5-bitin, muut jää enn alleen

Voidaan käyttää myös bitin nimeä (tässä PB5), kuten tehdään kaikissa tulevissa rekisterimäärityksissä. PORTB = _BV(0); // Bit Value, asettaa 0-bitin, m uut nollataan PORTB |= _BV(7); // Bit Value, asettaa 7-bitin, muu t jäävät ennalleen

Yksi mahdollinen tapa on toimia näin: Määritetään esikääntimen komennot #define EKALED PB1 #define EKALED_ON (PORTB |= _BV(PB1)) #define EKALED_OFF (PORTB &= ~_BV(PB1)) #define EKALED_TOGGLE (PORTB ^= _BV(PB1))

Ja sitten koodissa - jos halutaan B-portin ekaled loistamaan, annetaan komento EKALED_ON;

Bittien nollaus nollaksi, ”0” PORTB = ~(1 << 3); // nollaa 3-bitin, muut ykkösek si PORTB &= ~(1 << 0); // nollaa 0-bitin, muut ennalla an