Funktiot C-kielessä¶
Aloitetaan funktioihin tutustuminen laatimalla muutama funktion prototyyppi ja sitten tehdään bittioperaatioita toteuttavia funktiota.
Itseasiassa, tässä materiaalissa olevat tehtävistä saat valmiita funktioita lopputyötä varten, joilla luetaan SensorTagin eri antureilta dataa. Tehtävien yhteydeen on sen vuoksi laitettu vastaavan sensorin datakirjasta sen datarekisterin sisällön kuvaus. Tästä datarekisterin arvosta sitten saamme bittioperaatioilla ulos varsinaisen sensorin mittausarvon. Ok, funktiot eivät ole aivan täydellisiä vielä, kuten datakirjasta sattaa huomata. Mutta jatkamme tästä myöhemmin..
Tehtävien yhteydessä selvitetään miten rekisterin kuvaukset tulee lukea. Kurssilla ei tarvitse osata lukea datakirjoja, selvitys komponenttien käyttämiseen annetaan materiaalissa.
Ennenkuin aloitat:
Funktio-tehtävien vastauksiin ei tarvitse tehdä main-funktiota, ellei sitä erityisesti pyydetä.
Omaa funktiotasi voit testata kuitenkin main
-funktion avulla seuraavasti:
#include <stdio.h>
// #include <tehtävässä halutut>
// Prototyyppi tähän
... tehtavan_funktio(sen_argumentit);
int main() {
tulos = tehtavan_funktio(sen_argumentit);
printf("...",tulos);
return 0;
}
// Funktion toteutus tänne..
... tehtavan_funktio(sen_argumentit) {
...
}
Jokaisessa tehtävässä annetaan testausta varten esimerkkiargumentit ja niillä saatava lopputulos.
Tehtävän vastauksena riittää yksi C-kooditiedosto, jossa on kolme asiaa:
- Tehtävän vaatimat #include-käskyt
- Funktion prototyyppi
- Funktion toteutus.
- Lopullisessa vastauksessasi älä tulosta printf:llä mitään ellei tehtävä sitä edellytä. Tästä seuraa usein tarkistimen kaatuminen tms virhe.
C-kielisen kooditiedoston nimeämiskäytäntö on tiedosto.c
Voit esimerkiksi kommentoida ulos ( /* .. */
tai //
) testikoodista main-funktion, ettei tarvitse tehdä uutta tiedostoa.
Lämpötilasensori (1p)¶
Alla SensorTag:n lämpötila-anturin datarekisterin kuvaus. Rekisteri on 16-bittinen binääriluku (bitin järjestysnumero 0..15 keltaisella). Osalle rekisterin biteistä on annettu nimet, eli T0-T13, joita vastaavat bittien järjestysnumerot (lue kahden potenssit) ovat 2-15. Näistä biteistä saadaan itse lämpötila-arvo am. operaatiolla:
- Bitit T0-T13 pitää irroittaa rekisteristä muuttujaan sopivalla bittioperaatiolla
- Kertomalla muuttuja kertoimella
0.03125
saadaan lämpötila Celsius-asteina
Tehtävä: Laadi funktio, joka tekee konversion rekisterinarvosta celsius-asteiksi ja palauttaa asteet liukulukuna. Funktiolle annetaan kaksi parametria: 16-bittinen rekisterin arvo ja kerroin. Teemme funktiosta yleiskäyttöisemmän, jolloin eri kerroin voidaan antaa myös parametrina funktiolle.
Käytä prototyyppiä float lampotila(uint16_t rekisteri, float kerroin);
Tarvitset otsikkotiedoston inttypes.h
, muutoin johdetut muuttujatyypit eivät toimi.
Tarkistus: 16-bittisellä rekisteriarvolla 0b0011001000000000
tuloksena pitäisi olla 100.00
C
Koitko tämän tehtävän hyödylliseksi oppimisen kannalta?
Ilmankosteus (1p)¶
Alla SensorTag:n ilmankosteus-anturin datarekisterin kuvaus. Rekisteri on 16-bittinen. Kosteus-% saadaan kaavalla kosteus = HUMIDITY[15:0] / 2**16 * 100
.
Tehtävä: Laadi funktio, joka tekee konversion 16-bittisestä rekisterinarvosta ja palauttaa kosteus-% liukulukuna.
Käytä prototyyppiä float kosteus(uint16_t rekisteri);
Tarvitset otsikkotiedoston
inttypes.h
, muutoin johdetut muuttujatyypit eivät toimi. Lisäksi otsikkotiedostolla
math.h
, saat käyttöön tarvittaessa
pow-funktion potenssilaskuja varten.
gcc
:llä koodia kääntäessä voit tarvita lisäparametrin
-lm
käännöskutsuun, joka liittää matikkakirjaston ohjelmaasi.
Tarkistus: rekisteriarvoilla 0b1000000000000000
tuloksena pitäisi olla 50
%.
Koitko tämän tehtävän hyödylliseksi oppimisen kannalta?
Valosensori (1p)¶
Alla SensorTag:n valoisuus-anturin datarekisterin kuvaus. Rekisteri on 16-bittinen (keltaisella numeroidut bitit 0..15). Tässä tehtävässä kiinnostaa kaksi eri bittiryhmää E0-E3
ja R0-R11
. Nämä molemmat ryhmät pitää erottaa rekisteristä sopivilla bittioperaatioilla. Sen jälkeen valaistusvoimakkuus luksi saadaan alareunan kaavalla lux = 0.01 * 2**E[3:0] * R[11:0]
. Kaavassa esitykset E[3:0] ja R[11:0] tarkoittavat vastaavia rekisteristä haettuja binäärilukuja.
Tehtävä: Laadi funktio, joka tekee konversion 16-bittisestä rekisterinarvosta lukseihin ja palauttaa tämän arvo liukulukuna.
Käytä prototyyppiä float valoisuus(uint16_t rekisteri);
Tarvitset otsikkotiedoston
inttypes.h
, muutoin johdetut muuttujatyypit eivät toimi. Lisäksi otsikkotiedostolla
math.h
, saat käyttöön tarvittaessa
pow-funktion potenssilaskuja varten.
gcc
:llä koodia kääntäessä voit tarvita lisäparametrin
-lm
käännöskutsuun, joka liittää matikkakirjaston ohjelmaasi.
Tarkistus: rekisteriarvoilla 0b0110110000110101
tuloksena pitäisi olla 2000
Luksia.
Koitko tämän tehtävän hyödylliseksi oppimisen kannalta?
Ilmanpaineanturi (1p)¶
Alla SensorTag:n ilmanpaine-anturin datarekisterien kuvaus, joka on hieman erilainen kuin aiemmissa tehtävissä. Ilmanpaineen arvo koostuu kolmesta 8-bittisestä rekisterinarvosta nimeltään: press_msb
, press_lsb
ja press_xlsb
.
Ilmanpaine (hPa) saadaan näistä 20-bittisenä binäärilukuna koostuen ym rekisterien arvoista: press_msb[7:0],press_lsb[7:0],press_xlsb[7:4]
Tässä siis msb-rekisteristä tulee 8 ylintä bittiä, lsb-rekisteristä seuraavat 8 ja loput 4 xlsb-rekisteristä.
Alla kuvassa 8-bittisten rekisterien bittien tarkoitukset. Huomaa rekisterien kuvausjärjestys on tässä "alimmasta ylimpään".
Tehtävä: Laadi funktio, joka tekee konversion näistä kolmesta 8-bittisestä rekisterinarvosta msb
,lsb
ja xlsb
ilmanpainearvoon.
Käytä prototyyppiä uint32_t ilmanpaine(uint8_t xlsb, uint8_t lsb, uint8_t msb);
Tarvitset otsikkotiedoston inttypes.h
, muutoin johdetut muuttujatyypit eivät toimi.
Tarkistus: rekisteriarvoilla xlsb=0b00000000, lsb=0b01101010, msb=0b00011000
tuloksena pitäisi olla 100000
hPa.
(Tarkistin korjattu 18.9.)
Koitko tämän tehtävän hyödylliseksi oppimisen kannalta?