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.
C-kääntäjän asennus¶
Tehtävien palauttaminen¶
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
- Please, include all arguments in the same line.
- 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.
Jos kääntäjässä on varoituksia tai virheitä, tarkistus ei edes käynnisty. Tällöin näet käännösvirheet punaisella. Ole hyvä ja varmista, että testaat koodisi kehitysympäristössäsi. Älä lähetä Lovelaceen koodia, jota et ole onnistuneesti kääntänyt ja ajanut.
Tärkeä huomautus edistyneille käyttäjille: malloc
- ja free
-operaatioita ei sallita koodissa.
HUOM : Kun käännät koodiasi C-harjoituksia varten, varmista, että käännät C99-standardille (-std=c99
) lipulla gcc
-komennossa.
Ilmankosteus (1p)¶
Alla SensorTag:n ilmankosteus-anturin (HDC1000) datarekisterin kuvaus.
Datalehdestä voimme nähdä, että rekisteri on 16-bittinen. Kosteus-% saadaan kaavalla
kosteus = HUMIDITY[15:0] / 2**16 * 100
. (Merkintätapa [15:0] tarkoittaa 16-bittisen rekisterin kaikkia bittejä.)
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 0x8000
tuloksena pitäisi olla 50
%.
Koitko tämän tehtävän hyödylliseksi oppimisen kannalta?
Lämpötilasensori (1p)¶
Alla SensorTag:n lämpötila-anturin (TMP0007) datarekisterin kuvaus.
Datalehdestä voimme nähdä, että rekisterin koko, johon lämpötila tallennetaan, 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 (irroitetut bitit) 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 yhden parametrin: 16-bittinen rekisterin arvo.
Käytä prototyyppiä float lampotila(uint16_t rekisteri);
Tarvitset otsikkotiedoston inttypes.h
, muutoin johdetut muuttujatyypit eivät toimi.
Tarkistus: 16-bittisellä rekisteriarvolla 0b0011001000000000
tuloksena pitäisi olla 100.00
C
Pikakorjaus!: Jos saat pyöristysvirheitä vastauksessasi, käytä Kaksinkertaisen tarkkuuden liukuluku
Koitko tämän tehtävän hyödylliseksi oppimisen kannalta?
Valosensori (1p)¶
Alla SensorTag:n valoisuus-anturin (OPT3001) datarekisterin kuvaus. Sivulla 20
datalehdestä kerrotaan, että rekisterin koko on 16-bittiä (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 (BMP280) datarekisterien kuvaus, joka on hieman erilainen kuin aiemmissa tehtävissä. Sivulla 24
datalehdestä kerrotaan, että 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=-34, lsb=-68, msb=24
tuloksena pitäisi olla 101325
hPa.
Koitko tämän tehtävän hyödylliseksi oppimisen kannalta?