BME280 – czujnik temperatury, wilgotności oraz ciśnienia (część 2)

Funkcje drivera I2C

Po konfiguracji i wygenerowaniu przez konfigurator odpowiednich plików po kliknięciu na Generate Project Content, można używać funkcji drivera magistrali I2C.

Otwarcie drivera

Pierwszą rzeczą jaką należy zrobić jest otwarcie drivera za pomocą funkcji open. Pokazane to zostało na listingu 1.

Listing 1. Otwarcie interfejsu I2C

Argumentami funkcji open są dwie struktury: p_ctrl i  p_cfg. Struktura p_ctrl zawiera informację opisującą interfejs i flagę określającą czy interfejs został prawidłowo otwarty. Struktura p_cfg zawiera wszystkie konfiguracje pokazane na rysunku 23.

Funkcja open zwraca status:

  • SSP_SUCCESS – interfejs został poprawnie otwarty i może być używany,
  • SSP_ERR_IN_USE – interfejs jest już otwarty i nie można go powtórnie otworzyć,
  • SSP_ERR_INVALID_RATE – nie można wyliczyć wybranej prędkości transmisji.

Do odczytywania i zapisywania danych z czujnika BME280 zostały napisane dwie funkcje: BME280_I2C_Write i BME280_I2C_Read.

Funkcja Callback

Ponieważ w konfiguracji określiliśmy nazwę Callback, to funkcje przesyłania danych po magistrali nie są blokujące. Użytkownik musi zdefiniować funkcję callback wywoływaną przez zdarzenia zgłaszane przez funkcje zapisywania i odczytywania danych z magistrali. Dla drivera magistrali I2C zdefiniowano w SSP zdarzenia I2C_EVENT_ABORTED (transfer niedokończony), I2C_EVENT_RX_COMPLETE (operacja odczytywania zakończona sukcesem), a także I2C_EVENT_TX_COMPLETE (operacja zapisywania zakończona sukcesem). Dla naszych potrzeb zdefiniowałem dwie zmienne globalne i funkcję BME280_Callback – listing 2.

Listing 2. Funkcja BME280_Callback

Poprawne zakończenie odczytania lub zapisania danych jest sygnalizowane wpisaniem jedynki do odpowiednich zmiennych. Wpisanie wartości 10 sygnalizuje transfer danych, który nie zakończył się sukcesem. Użytkownik musi przed wywołaniem funkcji zapisu i odczytu wyzerować odpowiednią zmienną i po wykonaniu funkcji write lub read czekać na wpisanie do tej zmiennej wartości 1. Funkcje przykładowe czekają na wpisanie 1 w nieskończonych pętlach, czyli blokują cały program. Jednak łatwo jest je zmodyfikować tak, by oczekiwanie trwało przez określony czas i jeżeli potwierdzenie w tym czasie nie nadejdzie nastąpi wyjście z pętli i będzie zgłaszany błąd.

Funkcja przesyłania danych

Funkcja przesłania danych przez magistralę I2C BME280_I2C_Write została pokazana na listingu 3. Jej argumentami są: wskaźnik na bufor z danymi do wysłania (*buff), ilość danych do wysłania (size) i flaga stop określająca czy sekwencja zapisu ma się zakończyć sekwencją STOP. Samo zapisanie danych wykonuje funkcja write wykorzystująca funkcję warstwy HAL z argumentami: struktura p_ctrl opisująca czy interfejs został poprawnie otwarty, wskaźnik na bufor z danymi, ilość danych i flaga stop.

Listing 3. Funkcja zapisywania danych do czujnika BME280

Poprawne zapisanie danych do wysłania przez interfejs I2C powoduje zwrócenie przez funkcję write wartości SSP_SUCCESS. Kiedy operacja zapisu nie powiedzie się, zwracana jest wartość SPP_ERR_ABORTED. W naszym przypadku zapisanie danych do wysłania nie czeka na zakończenie transferu i program musi czekać na wpisanie jedynki do  zmiennej BME280_data_tx po wystąpieniu zdarzenia I2C_EVENT_TX_COMPLETE.

Funkcja odczytywania danych

Funkcja BME280_I2C_Read jest przeznaczona do odczytania danych z sensora BME280 przez układ Master i ma trzy argumenty: wskaźnik na bufor z odczytanymi danymi, ilość odczytywanych danych i flaga stop. Odczytywanie realizuje funkcja read. Mechanizmy rozpoznawania zakończenia sekwencji odczytywania są takie same jak w przypadku poprzedniej funkcji.

Listing 4. Funkcja odczytywania danych z czujnika BME280

Implementacja obsługi sensora BME280 na innym mikrokontrolerze (innego producenta) wymaga napisania na nowo obsługi I2C. Pozostałe funkcje opisywane poniżej mogą pozostać bez zmian.

Odczytywanie danych z sensora

Dane pomiarowe z trzech czujników są dostępne w rejestrach od adresu 0xF7 do 0xFE – rysunek 25.

Rysunek 25. Rejestry wyniku pomiarów z czujników BME280

Producent w danych technicznych zaleca, żeby odczytywać wszystkie dane pomiarowe z rejestrów w jednym cyklu odczytu. Zapobiega to możliwości mieszania się danych w rejestrach z kolejnych pomiarów. Jeżeli nie odczytujemy wilgotności, to w takim razie w jednym cyklu trzeba odczytać rejestry od 0xF7 do 0xFC. Odczytywanie danych ze wszystkich czujników wymaga odczytu rejestrów od adresu 0xF7 do 0xFE. Odczytywanie bloku rejestrów ma szczególne znaczenie w trybie normalnym. Układy logiczne sensora mają podwójne buforowanie danych. Pomiary są najpierw zapisywane do bufora cienia i potem przepisywane do bufora danych wyjściowych. Blokowanie zapisu do bufora danych z bufora cienia działa jedynie w momencie odczytywania danych przez magistralę. Dla interfejsu SPI koniec sesji odczytania danych jest wykrywane za pomocą narastającego zbocza sygnału CSB, natomiast dla I2C przez wykrycie sekwencji STOP.

Sekwencja odczytywania danych z rejestrów sensora przez magistralę I2C została pokazana na rysunku 19. W pierwszym etapie master wysyła sekwencje START, adres Slave z bitem RW=0 i adres rejestru. Nie jest wysyłana sekwencja STOP. W drugim etapie wysyłamy powtórnie sekwencję START, adres slave z bitem RW=1, odczytujemy zadaną ilość bajtów i na koniec sekwencję STOP. Na listingu 5 pokazano funkcję, która odczytuje blok danych od zadanego adresu rejestru i umieszcza go w buforze. Wskaźnik na bufor jest argumentem tej funkcji.

Listing 5. Odczytanie zadanej ilości danych od rejestru z argumentu reg

Z tych danych trzeba „złożyć” słowa o długości odpowiadającej rozdzielczości pomiarów. Pomiar ciśnienia i temperatury ma rozdzielczość 20-bitową, natomiast pomiar wilgotności 16-bitową.

Dane kalibracyjne w pamięci BME280

Sensor BME280 ma zapisane w pamięci nieulotnej dane kalibracyjne potrzebne do uzyskania dużej dokładności w szerokim zakresie pomiarowym. Są tam umieszczane w procesie produkcyjnym, a więc użytkownik nie ma możliwości modyfikacji. Może je tylko odczytać i wykorzystać do obliczenia kompensacji pomiarów. Te dane są dostępne w rejestrach od adresu 0x88 do adresu 0xA1 oraz od adresu 0xE1 do 0xE7 (kompensacja wilgotności) – rysunek 26.

Rysunek 26. Umieszczenie danych kompensacyjnych w rejestrach

Funkcje odczytywania danych z rejestrów

Do odczytania danych kompensacji przygotowane zostały 3 funkcje. Pierwsza z nich to BME280_read_reg16 odczytująca 2 kolejne bajty od adresu z argumentu i zwracająca 16-bitową wartość. Natomiast, druga funkcja odczytuje i zwraca jeden bajt spod adresu z jej argumentu.

Listing 6. Odczytanie rejestru 16-bitowego

Listing 7. Odczytanie rejestru 8-bitowego

Dane kalibracyjne będą umieszczone w zmiennych globalnych zadeklarowanych w listingu 8.

Listing 8. Deklaracja zmiennych dla danych kalibracyjnych

Trzecia funkcja BME280_readCalibrationData odczytuje rejestry kalibracyjne, a także umieszcza dane kalibracyjne w zmiennych z listingu 8. Wykorzystuje się je później w prcedurach kompensacji pomiarów.

Listing 9. Odczytanie danych kalibracyjnych

Czujnik BME280 można znaleźć w sklepie Kamami.pl. Oferta obejmuje również moduły z zamontowanym sensorem.

Do pobrania

O autorze

Absolwent Wydziału Elektroniki Politechniki Wrocławskiej, współpracownik miesięcznika Elektronika Praktyczna, autor książek o mikrokontrolerach Microchip i wyświetlaczach graficznych, wydanych nakładem Wydawnictwa BTC.
Zawodowo zajmuje się projektowaniem zaawansowanych systemów mikroprocesorowych.