ZL27ARM: obsługa czujnika MEMS do pomiaru ciśnienia – BMP085
Aby w rejestrze F6 znajdowały się dane dotyczące temperatury, musi być wykonany wcześniej zapis wartości 0x2E pod adres 0xF4, w celu poinformowania BMP085, że interesuje nas odczyt wyniku pomiaru temperatury. Inaczej wygląda odczyt ciśnienia:
unsigned long BMP085_ReadPressure(void) { unsigned char msb, lsb, xlsb; BMP085_WriteRegister(0xF4, (0x34+(OSS<<6))); delay_ms(50); // max time is 4.5ms I2C_GenerateSTART(BMP085_I2C,ENABLE); //Test on EV5 and clear it while(!I2C_CheckEvent(BMP085_I2C, I2C_EVENT_MASTER_MODE_SELECT)); //Send LIS35 address, set I2C master in transmiter mode I2C_Send7bitAddress(BMP085_I2C, BMP085_Addr, I2C_Direction_Transmitter); //Test on EV6 and clear it while(!I2C_CheckEvent(BMP085_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); //Send base register address, set address autoincrement I2C_SendData(BMP085_I2C, 0xF6); //Test on EV8 and clear it while(!I2C_CheckEvent(BMP085_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); //Re-generate START, transmition from slave beginning I2C_GenerateSTART(BMP085_I2C,ENABLE); //Test on EV5 and clear it while(!I2C_CheckEvent(BMP085_I2C, I2C_EVENT_MASTER_MODE_SELECT)); //Send LIS35 address, set I2C master in receiver mode I2C_Send7bitAddress(BMP085_I2C, BMP085_Addr, I2C_Direction_Receiver); //Test on EV6 and clear it while(!I2C_CheckEvent(BMP085_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); //Test on EV7 and clear it while(!I2C_CheckEvent(BMP085_I2C, I2C_EVENT_MASTER_BYTE_RECEIVED)); //Read a byte from the LI35 msb = I2C_ReceiveData(BMP085_I2C); //Test on EV7 and clear it while(!I2C_CheckEvent(BMP085_I2C, I2C_EVENT_MASTER_BYTE_RECEIVED)); //Read a byte from the LI35 lsb = I2C_ReceiveData(BMP085_I2C); //Before receiving last byte, disable acknowledge and generate stop I2C_AcknowledgeConfig(BMP085_I2C, DISABLE); I2C_GenerateSTOP(BMP085_I2C, ENABLE); //Test on EV7 and clear it while(!I2C_CheckEvent(BMP085_I2C, I2C_EVENT_MASTER_BYTE_RECEIVED)); //Read a byte from the LI35 xlsb = I2C_ReceiveData(BMP085_I2C); //Enable Acknowledge for next transmission I2C_AcknowledgeConfig(BMP085_I2C, ENABLE); return (((unsigned short) msb << 16) | ((unsigned short) lsb << 8) | ((unsigned short) xlsb)) >> (8-OSS); }
Po zapisie do rejestru 0xF4 wartości 0x34+(OSS<<6), celem poinformowania czujnika, że odczyt będzie dotyczył ciśnienia z określoną wartością OSS (wartość ustalona przez producenta czujnika) precyzją, zostają odczytane trzy kolejne rejestry zaczynając od 0xF6. Jako, że przy odczycie ciągłym danych z czujnika, inkrementuje on adres rejestru samodzielnie, nie musimy podawać 3 adresów, a jedynie pierwszy po czym odczytujemy 3 bajty z magistrali I2C obrazujące zawartość rejestrów o adresach 0xF6, 0xF7 i 0xF8.
Dalej w funkcji konwertującej dane z rejestrów czujnika ciśnienia, wykonywane są obliczenia na otrzymanych danych. Należy zwrócić uwagę, że do obliczenia temperatury oraz ciśnienia wykorzystane zostały zmienne wcześniej odczytane z pamięci EEPROM oraz to że do obliczenia ciśnienia atmosferycznego użyta została zmienna ut (opisująca temperaturę) a co za tym idzie, temperatura winna być odczytana i obliczona przed rozpoczęciem wyliczania ciśnienia. Na końcu obliczona zostaje wysokość na podstawie ciśnienia. Wszystkie trzy informację zostają przekształcone na łańcuch tekstowy w funkcji main za pomocą funkcji sprintf z odpowiednim formatowaniem:
//Liczba dziesietna 5 cyfrowa z 2 cyfrowa liczba po przecinku sprintf((char *)Tekstalt,"%5d.%02dm \0",altitude/100,altitude-((altitude/100)*100)); //liczba dziesietna 4 cyfrowa sprintf((char *)Teksttemp,"%4d\0",temperature); //liczba dziesietna 7 cyfrowa sprintf((char *)Tekstpres,"%7d\0",pressure);
Wyjaśnienia może wymagać wyświetlenie wysokości, przede wszystkim jej przekształcenie na zmienną string. Zmienna altitude zawiera wysokość nad poziomem morza w centymetrach, więc jako pierwszy argument do funkcji sprintf zostaje przekazana zmienna altitude/100 celem wyświetlenia liczby metrów bez części dziesiętnych. Do ciągu znaków w tablicy Tekstalt zostaje dodana „.” i następnie część dziesiętna wysokości. Aby wyświetlić część dziesiętną wysokości od wysokości podanej w centymetrach odjęta zostaje wysokość w metrach*100 jak wynik operacji: altitude-((altitude/100)*100). Informacje na temat temperatury, ciśnienia oraz wysokości zostają wyświetlone w odpowiednich miejscach na wyświetlaczu OLED:
//Wyswietlenie danych LCD_WriteTextXY(Tekstalt,7,1); LCD_WriteTextXY(Teksttemp,2,0); LCD_WriteTextXY(Tekstpres,10,0);