LinkedIn YouTube Facebook
Szukaj

Wstecz
Artykuły

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);