Interfejs I2C
Interfejs I2C – praca z modułem IMU – MPU6050 (dokumentacja techniczna, mapa rejestrów)
1. Przygotowanie projektu
- utworzenie projektu: STM32 Project
- wybranie płytki: Nucelo STM32L432
- w zakładce Project Manager/Code Generator i aktywujemy opcję „Generate peripheral initialization….”
- konfigurowanie wyprowadzeń:
- SYS/Debug -> Serial Wire (SWD)
- PB3 – jako wyjście o nazwie „LED”
- konfigurowanie modułu komunikacji I2C:
- Connectivity/I2C1 i wybrać z listy I2C
- upewnić się, że I2C1_SDA jest na pin PA10, w celu przeniesienia przyciskamy “ctrl” klikamy myszką na pin i przenosimy
- upewnić się, że I2C1_SCL jest na pin PA9
- konfigurowanie modułu UART – terminal PC
- Connectivity/ USART2 wybrać mode: Asynchronous, ustawić prędkość komunikacji na 9600 (Baud Rate)
- generujemy projekt
2. Podłączenie modułu MPU-6050
- podłączyć przewodami zgodnie z tabelką:
Opis | Płytka NUCLEO | Moduł MPU-6050 |
Zasilanie +5V | 5V | VCC |
Zasilanie GND | GND | GND |
komunikacja I2C - SDA | D0 - PA10 | SDA |
komunikacja I2C - SCL | D1 - PA9 | SCL |
3.Obsługa I2C – odczyt rejestru
- do obsługi modułu podłączone po interfejsie I2C potrzebujemy znać jego adres (dokumentacja techniczna – 9.2). Moduł posiada AD0 podpięte do GND.
- uruchomić funkcję readAndShow() – co robi ta funkcja, jaka wartość powinna być w rejestrze “Who Am I” mapy rejestrów?
- “<<—-” – komentarze tak oznaczone należy uzupełnić odpowiednimi wartościami
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
void readAndShow() { char bufforText[30]; uint8_t adresMPU6050=0x00<<1; //Adres modulu MPU6050 uint8_t adresRejestru; //Adres rejestru jaki chcemy odczytac adresRejestru=0x00; //<<---- podac adres rejestru Who Am I //Ustawienie adresu rejestru jaki chcemy odczytac if(HAL_I2C_Master_Transmit(&hi2c1, adresMPU6050, &adresRejestru, 1, 100) !=HAL_OK) { sprintf(bufforText,"ERROR: blad adresu modulu\r\n"); HAL_UART_Transmit(&huart2, bufforText, strlen(bufforText), 100); } //Odczytanie jednego bajtu danych z wczesniej ustawionego rejestru uint8_t wartosc=0; if(HAL_I2C_Master_Receive(&hi2c1, adresMPU6050, &wartosc, 1, 100)!=HAL_OK) { sprintf(bufforText,"ERROR: blad odczytu rejestru\r\n"); HAL_UART_Transmit(&huart2, bufforText, strlen(bufforText), 100); } sprintf(bufforText,"Wartosc w rejestrze: %d \r\n",wartosc); HAL_UART_Transmit(&huart2, bufforText, strlen(bufforText), 100); } |
4.Obsługa I2C zapisanie do rejestru – odczyt temperatury
- uruchomić funkcję readTemp() – co robi ta funkcja?
- domyślnie funkcja sprint nie potrafi wyświetlać liczb typu float, należy skonfigurować kompilator według instrukcji na stronie “Zestaw STM32”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
void readTemp() { char bufforText[30]; uint8_t adresMPU6050=0x00<<1; //<<----Adres modulu MPU6050 uint8_t adresRejestru; //Adres rejestru jaki chcemy odczytac //Aktywacja modulu MPU6050 uint8_t tab[2]; tab[0]=0x00; //<<---- podać adres rejestru PWR_MGMT_1 tab[1]=0; if(HAL_I2C_Master_Transmit(&hi2c1, adresMPU6050,tab, sizeof(tab), 100)!=HAL_OK) { sprintf(bufforText,"ERROR: blad aktywacji modulu\r\n"); HAL_UART_Transmit(&huart2, bufforText, strlen(bufforText), 100); } adresRejestru=0x00; //<<---- podać adres rejestru TEMP_OUT[15:8] //Ustawienie adresu rejestru jaki chcemy odczytac if(HAL_I2C_Master_Transmit(&hi2c1, adresMPU6050, &adresRejestru, 1, 100) !=HAL_OK) { sprintf(bufforText,"ERROR: blad adresu modulu\r\n"); HAL_UART_Transmit(&huart2, bufforText, strlen(bufforText), 100); } //Odczytanie dwoch bajtow danych z wczesniej ustawionego rejestru uint8_t wartosc[2]={0}; if(HAL_I2C_Master_Receive(&hi2c1, adresMPU6050, wartosc, 2, 100)!=HAL_OK) { sprintf(bufforText,"ERROR: blad odczytu rejestru\r\n"); HAL_UART_Transmit(&huart2, bufforText, strlen(bufforText), 100); } int16_t tempOut= wartosc[0]<<8|wartosc[1]; float temperatura= tempOut; //<<---- dokonczyc wzor na przeliczenie temperatury sprintf(bufforText,"Temperatura: %f \r\n",temperatura); HAL_UART_Transmit(&huart2, bufforText, strlen(bufforText), 100); } |
5. Poziomnica
- Dołączyć bibliotekę “math.h” (#include “math.h”)
- uruchomić funkcję poziomnica() – co robi ta funkcja?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
void poziomnica() { char bufforText[30]; uint8_t adresMPU6050 = 0x00 << 1; //<<----Adres modulu MPU6050 uint8_t adresRejestru; //Adres rejestru jaki chcemy odczytac //<<----Aktywacja modulu MPU6050 //<<---- odczytac wartosci z rejestrow od ACCEL_XOUT[15:8] do ACCEL_ZOUT[7:0] uint8_t wartosc[6] = { 0 }; //<<----przekonwertowac na liczby w formacie int16_t int16_t acc_x = 0; int16_t acc_y = 0; int16_t acc_z = 0; float poziom = atan2(acc_x, acc_z) * (180 / M_PI); sprintf(bufforText, "Poziom: %f \r\n", poziom); HAL_UART_Transmit(&huart2, bufforText, strlen(bufforText), 100); } |
6.Pytania dodatkowe:
- uint8_t adresMPU6050=0x68<<1; //Adres modulu MPU6050 – dlaczego jest przesunięcie bitowe (0x68<<1)
- dlaczego odczyty poziomu jak płytka leży na nożkach są na poziomie 180 stopni?