LinkedIn YouTube Facebook
Szukaj

Newsletter

Proszę czekać.

Dziękujemy za zgłoszenie!

Wstecz
IoT

STM32Butterfly2: obsługa cyfrowego termometru MCP9801

Pierwszym zadaniem realizowanym przez funkcję jest konfiguracja linii SDA (PB7) i SCL (PB6) do komunikacji w standardzie I2C. Działanie to polega na włączeniu zegara portu GPIO oraz kontrolera I2C i konfiguracji obu linii jako alternatywne z podciągnięciem do potencjału dodatniego. Konfiguracja linii realizowana jest przez funkcję io_config, która jako pierwszy parametr przyjmuje nazwę portu, drugi określa konfigurowaną linię, natomiast trzeci i czwarty parametr określają tryb działania linii. Samo podciągnięcie jest realizowane przez funkcję io_set, ustawiającą stan linii.

W następnym kroku, poprzez ustawianie odpowiednich bitów rejestru odpowiedzialnego za kontroler I2C, włączany jest kontroler i następuje jego zresetowanie. Następnie ustawiana jest częstotliwość kontrolera, czynność ta jest wykonywana przez odczyt rejestru CR2 kontrolera I2C, wyzerowanie odpowiednich bitów i ustawienie konkretnych bitów. Takie działanie ma na celu zachowanie wartości pozostałych bitów. Kolejnym zadaniem jest ustawienie prędkości wysyłania danych, odpowiada za to funkcja i2cm_set_speed, która jako parametr przyjmuje częstotliwość nadawania danych.

Kolejnym działaniem jest ustawienie trybu działania kontrolera: jako I2C, jako Host oraz ustawienia bitu ACK rejestru CR1. Kolejnym zadaniem jest ustawienie adresu oraz wyzerowanie dwóch rejestrów informujących o stanie kontrolera I2C. Ostatnim zadaniem realizowanym w konfiguracji kontrolera jest ustawienie priorytetu przerwań generowanych przez kontroler I2C oraz włączenie ich obsługi. Realizowane jest to przez funkcje nvic_set_priority i nvic_irq_enable.

Po skonfigurowaniu kontrolera następuje inicjalizacja czujnika temperatury, realizuje to funkcja tempsensor_init. Zwraca ona rezultat działania mniejszy od zera jeśli wystąpił problem lub równy zero jeśli inicjalizacja została wykonana poprawnie. Listing funkcji został przedstawiony poniżej.

static int tempsensor_init(void)
{
	static const uint8_t tmp[] = { MCP9800_CONFIG_REG , MCP9800_RES_12BIT };	//Config register
	//Send configuration data
	return i2cm_transfer_7bit(TEMPSENSOR_I2CADDR,tmp,sizeof(tmp),NULL,0);
}

 

Jak można zauważyć w pierwszym kroku tworzona jest tablica składająca się z dwóch elementów. Pierwszy element określa numer rejestru czujnika temperatury, na którym odbywać się będzie działanie, natomiast drugi element powoduje ustawienie 6 i 7 bitu w wyniku czego czujnik pracuje z 12-bitową rozdzielczością. W kolejnym kroku następuje wysłanie utworzonej tablicy przy użyciu funkcji i2cm_transfer_7bit. Jako pierwszy parametr przyjmuje ona adres urządzenia docelowego, jako drugi bufor danych do wysłania, trzeci parametr określa ilość danych do wysłania, czwarty parametr jest buforem danych odbieranych, natomiast ostatni parametr określa ilość danych do odebrania.

W przypadku błędu w inicjalizacji czujnika następuje przejście do warunku, w którym obsługiwany jest błąd inicjalizacji. W warunku tym na wyświetlaczu prezentowany jest komunikat o błędzie, a program przechodzi do nieskończonej pętli, która blokuje dalsze działanie programu.

W przypadku poprawnej inicjalizacji program wyświetla komunikat powitalny na wyświetlaczu i wykonuje nieskończoną pętle w ramach której odczytuje temperaturę z czujnika i wyświetla ją na wyświetlaczu. Odczyt temperatury realizowany jest przez funkcję tempsensor_get, jej listing został przedstawiony poniżej.

static int tempsensor_get(struct temp *t)
{
	static const unsigned char temp_reg = MCP9800_TEMP_REG;
	static unsigned char temp[2];
	int ecode;
	//Read the temperature
	ecode = i2cm_transfer_7bit(TEMPSENSOR_I2CADDR,&temp_reg,sizeof(temp_reg),temp,sizeof(temp));
	//Convert to integer
	if(ecode>=0)
	{
		t->t = temp[0];
		t->ft = (((int)(temp[1]>>4))*10)/16;
	}
	return ecode;
}

 

Na początku działania funkcji definiowane są trzy zmienne. Pierwsza określa adres rejestru od którego odbywać się będzie odczyt danych z czujnika temperatury. Druga zmienna jest buforem do zapisu odebranych danych. Trzecia zmienna jest kodem zwracanym przez funkcje i2cm_transfer_7bit, informującym o wystąpieniu ewentualnego błędu. W przypadku braku błędu następuje zdekodowanie otrzymanych danych i zapis do struktury, w której oddzielnie przechowywana jest wartość całkowita ze znakiem i oddzielnie wartość po przecinku.

W przypadku braku błędu następuje wyświetlanie uzyskanej wartości temperatury przy użyciu funkcji display_temp, jeśli wystąpił błąd na wyświetlaczy prezentowany jest odpowieni komunikat o tym fakcie.

W programie głównym brak jest operacji inicjalizujących zegary oraz część peryferii, są one realizowane w obsłudze przerwania wywoływanego przez reset. Właśnie w ramach obsługi przerwania reset_handler następuje skopiowanie danych z pamięci Flash do pamięci SRAM, ich inicjalizacja wyzerowanie sekcji .bss, inicjalizacja peryferii oraz  wywołanie programu głównego – main().