Digilent Pmod i STM32 (cz. 10) – PmodGYRO, PmodTMP3 i PmodWiFi
W ostatnim odcinku cyklu opisującego wybrane moduły peryferyjne Pmod firmy Digilent omówimy PmodGYRO z 3-osiowym żyroskopem, PmodTMP3 z czujnikiem temperatury oraz PmodWiFi zawierający modem do komunikacji bezprzewodowej. Przykłady przedstawione w niniejszym artykule przygotowano dla środowiska Atollic TrueSTUDIO, a także zestawu uruchomieniowego KAmeleon (www.kameleonboard.org) z wykorzystaniem biblioteki STM32Cube_FW_L4.
PmodGYRO
Na początek przedstawimy PmodGYRO, czyli moduł z układem L3G4200D od firmy STMicroelectronics. Jest to 3-osiowy żyroskop umożliwiający pomiar prędkości kątowej w jednym z wybranych zakresów:
- 250 dps (8,75 mdps/LSB),
- 500 dps (17,50 mdps/LSB),
- 2000 dps (70,00 mdps/LSB).
Dane pomiarowe mogą być odczytywane bezpośrednio z rejestrów układu lub zapisywane w wewnętrznej kolejce FIFO. Dodatkowo, L3G4200D umożliwia włączenie do toru przetwarzania danych filtrów górno- i dolnoprzepustowego.
Przerwania w układzie L3G4200D
Układ L3G4200D umożliwia konfigurację źródeł przerwań przyporządkowanych do dwóch dostępnych linii: INT1 i INT2. Pierwsza z nich obsługuje przerwania od przekroczenia progów – niskiego lub wysokiego, dla każdej z trzech osi. Dodatkowo można zdefiniować czas przekroczenia progu, po którym ma zostanie zgłoszone przerwanie. Przerwanie od przekroczenia progu przestaje być aktywne natychmiast po powrocie mierzonej wielkości do dozwolonego zakresu lub po odczekaniu zdefiniowanego czasu bez ponownego przekroczenia progu. Sposób działania może być wybrany za pomocą bitu WAIT w rejestrze INT1_DURATION (0x38). Opisany mechanizm przerwań przedstawiono na rysunkach 2 i 3.
Rysunek 2. Działanie przerwania INT1 z bitem WAIT ustawionym na 0
Rysunek 3. Działanie przerwania INT1 z bitem WAIT ustawionym na 1
Druga linia przerwań – INT2, może być użyta do sygnalizacji gotowości danych do odczytu lub poziomu zajętości kolejki FIFO. Dostępne źródła przerwań to:
- dane gotowe do odczytu,
- osiągnięta zdefiniowana liczba elementów w kolejce,
- przepełnienie kolejki,
- kolejka pusta.
Układ L3G4200D udostępnia także 8-bitowy czujnik temperatury o rozdzielczości 1°C/LSB i zakresie zgodnym z zakresem pracy całego układu: od -40°C do 85°C.
Połączenie z zestawem KAmeleon
Do komunikacji z układem L3G4200D można użyć interfejsy SPI, a także I2C. Są one dostępne na złączach J1 (złącze Pmod SPI typu 2A z sygnałami INT1 i INT2) i J2 (złącze Pmod I2C). W przykładzie wykorzystano interfejs SPI ze względu na możliwość podłączenia złącza J1 bezpośrednio do złącza Pmod-SPI zestawu KAmeleon, tak jak na fotografii 4. Piny mikrokontrolera, a także odpowiadające im sygnały modułu PmodGYRO przedstawiono w tabeli 1.
Tabela 1. Sygnały PmodGYRO oraz odpowiadające im piny mikrokontrolera; w tabeli pominięto sygnały niepołączone (NC) i linie zasilania występujące na złączu Pmod
Sygnał | Numer pinu PmodGYRO (J1) | Pin STM32L496ZG (KAmeleon Pmod-SPI) |
~CS | 1 | PB0 |
MOSI | 2 | PA7 |
MISO | 3 | PE14 |
SCLK | 4 | PA1 |
INT1 | 7 | PE12 |
INT2 | 8 | PE13 |
Fotografia 4. Moduł PmodGYRO podłączony do płytki KAmeleon
Kod projektu
Obsługa modułu PmodGYRO znajduje się w plikach PmodGYRO.c, a także PmodGYRO.h. Za konfigurację modułu jest odpowiedzialna funkcja PmodGYRO_Config przedstawiona na listingu 1. Konfiguruje ona interfejs SPI1 w trybie 3 (CPOL = 1, CPHA = 1) z programową kontrolą pinu CS, a następnie ustawia wybrane rejestry układu L3G4200D:
- CTRL_REG1 (0x20): włączony pomiar na osi Z, częstotliwość pomiaru (ODR) 100 Hz, pasmo 12,5 Hz,
- INT1_THS_ZH (0x36), INT1_THS_ZL (0x37): próg generacji przerwania 35,84 dps (4096 * 8,75 mdps),
- INT1_CFG (0x30): włączenie przerwania od górnego progu na osi Z,
- CTRL_REG3 (0x22): włączenie przerwania na linii INT1.
Na koniec konfigurowany jest pin PE12 w trybie przerwania aktywnego na zboczu narastającym.
Listing 1. Konfiguracja interfejsu SPI i przerwania dla modułu PmodGYRO
void PmodGYRO_Config(void) { pmodGyroSpi.Instance = SPI1; pmodGyroSpi.Init.Mode = SPI_MODE_MASTER; pmodGyroSpi.Init.Direction = SPI_DIRECTION_2LINES; pmodGyroSpi.Init.DataSize = SPI_DATASIZE_8BIT; pmodGyroSpi.Init.CLKPolarity = SPI_POLARITY_HIGH; pmodGyroSpi.Init.CLKPhase = SPI_PHASE_2EDGE; pmodGyroSpi.Init.NSS = SPI_NSS_SOFT; pmodGyroSpi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128; pmodGyroSpi.Init.FirstBit = SPI_FIRSTBIT_MSB; pmodGyroSpi.Init.TIMode = SPI_TIMODE_DISABLE; pmodGyroSpi.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; pmodGyroSpi.Init.NSSPMode = SPI_NSS_PULSE_DISABLE; HAL_SPI_Init(&pmodGyroSpi); writeRegister(0x20, 0x0C); writeRegister(0x36, 0x10); writeRegister(0x37, 0x00); writeRegister(0x30, 0x20); writeRegister(0x22, 0x80); __HAL_RCC_GPIOE_CLK_ENABLE(); GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Pin = GPIO_PIN_12; HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); HAL_NVIC_SetPriority(EXTI15_10_IRQn, 0x0F, 0); HAL_NVIC_EnableIRQ(EXTI15_10_IRQn); }
Piny dla interfejsu SPI są konfigurowane w funkcji HAL_SPI_MspInit, wywoływanej przez biblioteczną funkcję HAL_SPI_Init. Sygnały MISO, MOSI i SCLK są ustawiane w funkcji alternatywnej dla SPI1, natomiast CS jest konfigurowany jako wyjście GPIO.
Konfiguracja przerwań
Po wystąpieniu przerwania na linii INT1, konieczne jest odczytanie rejestru INT1_SRC (0x31), w którym znajduje się informacja o zdarzeniach będących źródłem przerwania. Odczytanie tego rejestru powoduje wyczyszczenie bitu IA oraz ustawienie stanu niskiego na linii INT1. Odczyt rejestru zaimplementowano w funkcji PmodGYRO_ReadInterruptFlags.
Do celów odczytu i zapisu rejestrów układu L3G4200D zaimplementowano funkcje pomocnicze readRegister i writeRegister, przedstawione na listingu 2. Na początku każdej transakcji wysyłany jest bajt zawierający adres rejestru oraz dwa bity sterujące: RW definiujący czy jest to odczyt (1) czy zapis (0) oraz MS włączający inkrementację adresu (1) w przypadku transmisji wielu bajtów. W przykładzie wszystkie transakcje zawierają dwa bajty: adresu oraz danych.
Listing 2. Odczyt i zapis rejestrów układu L3G4200D za pośrednictwem interfejsu SPI
uint8_t readRegister(uint8_t address) { // Write the register address with the Read flag set first. uint8_t txbuf[2] = {address | 0x80, 0x00}; uint8_t rxbuf[2] = {0x00}; HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET); HAL_SPI_TransmitReceive(&pmodGyroSpi, txbuf, rxbuf, 2, 100); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET); return rxbuf[1]; } void writeRegister(uint8_t address, uint8_t data) { // Write the register address and the given data. uint8_t txbuf[2] = {address, data}; uint8_t rxbuf[2] = {0x00}; HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET); HAL_SPI_TransmitReceive(&pmodGyroSpi, txbuf, rxbuf, 2, 100); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET); }
W przykładowej aplikacji nie zaimplementowano odczytu danych, ponieważ reaguje ona wyłącznie na skonfigurowane przerwania od przekroczenia zadanego progu. Funkcja obsługująca przerwanie – HAL_GPIO_EXTI_Callback, odczytuje rejestr INT1_SRC za pośrednictwem opisanej funkcji PmodGYRO_ReadInterruptFlags, a następnie zapala diodę LED0, podłączoną do pinu PC6, na 100 ms. Z uwagi na fakt, że opóźnienie jest realizowane przez funkcję HAL_Delay, przerwanie od GPIO musi mieć niższy priorytet niż przerwanie od licznika SysTick. Pierwsze z nich jest konfigurowane w funkcji PmodGYRO_Config (priorytet 0x0F), natomiast priorytet drugiego z przerwań jest ustawiany w pliku stm32l4xx_hal_conf.h jako TICK_INT_PRIORITY (0x0A).