STM32Butterfly2 i akcelerometr LIS35D
W pierwszym kroku wywoływana jest funkcja time_init(), która inicjalizuje licznik SysTick. Licznik ten używany jest w celu generowania dokładnych opóźnień. Działanie funkcji polega na skonfigurowaniu częstotliwości występowania przerwania generowanego przez przepełnienie się licznika, ustawienie priorytetu generowanego przerwania oraz włączenie go.
Następnie wywoływana jest funkcja nlcd_init(), która przygotowuje do pracy wyświetlacz LCD, pochodzący z telefonu Nokia 3310. W ramach działania włączane są zegary używanych portów GPIO i kontrolera SPI oraz realizowana jest konfiguracja linii GPIO i kontrolera SPI. Po zakończeniu konfiguracji przeprowadzana jest inicjalizacja wyświetlacza, która polega na wysłaniu odpowiednich komend do niego.
W kolejnym kroku wywoływana jest funkcja i2cm_init, która odpowiada za konfigurację kontrolera I2C. Funkcja ta jako parametr przyjmuje częstotliwość z jaką wysyłane będą dane. Poniżej przedstawiono jej listing.
errno_t i2cm_init( unsigned clk_speed) { //GPIO configuration RCC->APB2ENR |= I2C1_GPIO_ENR; io_config(I2C1_PORT,I2C1_SDA_PIN,GPIO_MODE_50MHZ,GPIO_CNF_ALT_OD); io_config(I2C1_PORT,I2C1_SCL_PIN,GPIO_MODE_50MHZ,GPIO_CNF_ALT_OD); io_set(I2C1_PORT,I2C1_SCL_PIN); io_set(I2C1_PORT,I2C1_SDA_PIN); //I2C module configuration RCC->APB1ENR |= I2C1_ENR; /* Enable I2C module*/ i2c->CR1 |= CR1_PE_SET; /* Reset the i2c device */ i2c->CR1 |= CR1_SWRST; nop(); i2c->CR1 &= ~CR1_SWRST; uint16_t tmpreg = i2c->CR2; /* Clear frequency FREQ[5:0] bits */ tmpreg &= CR2_FREQ_RESET; tmpreg |= (uint16_t)(CONFIG_PCLK1_HZ/1000000); i2c->CR2 = tmpreg; //Set speed i2cm_set_speed(clk_speed); /* CR1 configuration */ /* Get the I2Cx CR1 value */ tmpreg = i2c->CR1; /* Clear ACK, SMBTYPE and SMBUS bits */ tmpreg &= CR1_CLEAR_MASK; /* Configure I2Cx: mode and acknowledgement */ /* Set SMBTYPE and SMBUS bits according to I2C_Mode value */ /* Set ACK bit according to I2C_Ack value */ tmpreg |= I2C_MODE_I2C | I2C_ACK_ENABLE; /* Write to I2Cx CR1 */ i2c->CR1 = tmpreg; /* Set I2Cx Own Address1 and acknowledged address */ i2c->OAR1 = I2C_AcknowledgedAddress_7bit; i2c->SR1 = 0; i2c->SR2 = 0; /* Enable interrupt controller */ nvic_set_priority( I2C1_EV_IRQn, IRQ_PRIO, IRQ_SUB); nvic_set_priority( I2C1_ER_IRQn, IRQ_PRIO, IRQ_SUB); nvic_irq_enable(I2C1_EV_IRQn,true); nvic_irq_enable(I2C1_ER_IRQn,true); return ERR_OK; }
Na początku swojego działania funkcja włącza zegary dla portu GPIO oraz kontrolera I2C. Następnym działaniem jest konfiguracja używanych linii. Do przeprowadzenia konfiguracji stosowana jest funkcja io_config, która wymaga podania czterech parametrów. Pierwszy z nich określa port, do którego podłączone są linie. Drugi parametr definiuje konfigurowaną linię. Trzeci i czwarty parametr określają tryb działania linii, w tym przypadku działanie obu linii jest konfigurowane jako alternatywne. Dodatkowo w ramach konfiguracji linii realizowane jest podciągnięcie ich do VCC. Realizowane jest to przez ustawienie stanu wysokiego na linii przy użyciu funkcji io_set, która przyjmuje dwa parametry określające port oraz linie.
Następnym działaniem jest włączenie kontrolera I2C, jest to realizowane przez ustawienie odpowiedniego bitu w rejestrze CR1 używanego kontrolera I2C. Po włączeniu następuje programowe zresetowanie kontrolera. Działanie to polega na ustawieniu, a następnie wyzerowaniu bitu SWRST rejestru konfiguracyjnego. Kolejnym działaniem jest ustawienie częstotliwości z jaką taktowany jest kontroler, informacja ta zapisana jest w sześciu najmłodszych bitach rejestru CR2 kontrolera I2C. W celu zachowania niezmienionej wartości pozostałych bitów proces ten realizowany jest poprzez skopiowanie zawartości rejestru do zmiennej pomocniczej, a następnie wyzerowanie bitów odpowiedzialnych za wybór częstotliwości i ustawienie pożądanej wartości. Tak zmieniona wartość zmiennej pomocniczej jest zapisywana do rejestru CR2.
Kolejnym krokiem jest skonfigurowanie częstotliwości z jaką będą wysyłane dane przez kontroler. Odpowiada za to funkcja i2cm_set_speed, która jako parametr przyjmuje właśnie pożądaną częstotliwość. Ze względu na złożoność, wynikającą z zależności od innych wartości, proces ten realizowany jest w odrębnej funkcji. Kolejnym realizowanym zadaniem jest ustawienie trybu działania kontrolera I2C, operacja ta jest wykonywana analogicznie jak przy konfiguracji częstotliwości taktowania kontrolera (działanie na kopii rejestru konfiguracyjnego).
Po zakończeniu konfiguracji trybu działania ustawiany jest adres urządzenia oraz zerowane są oba rejestry stanu działania. Na koniec działania funkcji konfiguracyjnej realizowane jest ustawienie priorytetu przerwania pochodzących od kontrolera I2C oraz następuje ich włączenie. W ramach obsługi obu przerwań realizowane jest wysyłanie oraz odbiór danych.
Przeprowadzenie konfiguracji kontrolera I2C umożliwia wykonanie inicjalizacji układu LIS35DE. Jest ona przeprowadzana w ramach funkcji lis35_init(), której listing przedstawiono poniżej.
static int lis35_init(void) { static const uint8_t init_val[] = { LIS35_REG_CR1, //Reg addr LIS35_REG_CR1_XEN | LIS35_REG_CR1_YEN | LIS35_REG_CR1_ZEN | LIS35_REG_CR1_ACTIVE //Reg Val }; return i2cm_transfer_7bit( LIS35_I2CADDR, init_val, sizeof(init_val), NULL, 0 ); }