#include "mcc_generated_files/mcc.h"
#include "common.h"
#include "BMP280_Lib.h"
#include "I2C.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
// writes 1 byte '_data' to register 'reg_addr'
void BMP280_Write8(uint8_t reg_addr, uint8_t _data)
{
BMP280_Start();
BMP280_Write(BMP280_I2C_ADDRESS);
BMP280_Write(reg_addr);
BMP280_Write(_data);
BMP280_Stop();
}
// reads 8 bits from register 'reg_addr'
uint8_t BMP280_Read8(uint8_t reg_addr)
{
uint8_t ret;
BMP280_Start();
BMP280_Write(BMP280_I2C_ADDRESS);
BMP280_Write(reg_addr);
BMP280_Start();
BMP280_Write(BMP280_I2C_ADDRESS | 1);
ret = BMP280_Read(0);
BMP280_Stop();
return ret;
}
// reads 16 bits from register 'reg_addr'
uint16_t BMP280_Read16(uint8_t reg_addr)
{
union
{
uint8_t b[2];
uint16_t w;
} ret;
BMP280_Start();
BMP280_Write(BMP280_I2C_ADDRESS);
BMP280_Write(reg_addr);
BMP280_Start();
BMP280_Write(BMP280_I2C_ADDRESS | 1);
ret.b[0] = BMP280_Read(1);
ret.b[1] = BMP280_Read(0);
BMP280_Stop();
return(ret.w);
}
uint32_t BMP280_Read24(uint8_t reg_addr)
{
uint32_t value;
BMP280_Start();
BMP280_Write(BMP280_I2C_ADDRESS);
BMP280_Write(reg_addr);
BMP280_Start();
BMP280_Write(BMP280_I2C_ADDRESS | 1);
value = BMP280_Read(1)<<16;
value |= BMP280_Read(1)<<8;
value |= BMP280_Read(1);
BMP280_Stop();
value >>4;
return(value);
}
// BMP280 sensor configuration function
void BMP280_Configure(BMP280_mode mode, BMP280_sampling T_sampling,
BMP280_sampling P_sampling, BMP280_filter filter, standby_time standby)
{
//uint8_t _ctrl_meas, _config;
_config = ((standby << 5) | (filter << 2)) & 0xFC;
_ctrl_meas = (T_sampling << 5) | (P_sampling << 2) | mode;
BMP280_Write8(BMP280_REG_CONFIG, _config);
BMP280_Write8(BMP280_REG_CONTROL, _ctrl_meas);
}
// initialises the BMP280 sensor, returns 1 if OK and 0 if error
uint8_t BMP280_begin(BMP280_mode mode,
BMP280_sampling T_sampling,
BMP280_sampling P_sampling,
BMP280_filter filter,
standby_time standby)
{
if(BMP280_Read8(BMP280_REG_CHIPID) != BMP280_CHIP_ID){
UART_new_line();
UART_send_string((char*)" BMP280 connection error or device address wrong!");
UART_new_line();
UART_send_string((char*)" Restart device");
return 0;
}
else{
char ID_buf[30];
int8_t myID = BMP280_Read8(BMP280_REG_CHIPID);
memset(BMP_buf, '\0', sizeof(BMP_buf));
UART_new_line();
sprintf(ID_buf," Sensor with ID: %X is connected",myID);
UART_send_string(ID_buf);
}
// reset the BMP280 with soft reset
BMP280_Write8(BMP280_REG_SOFTRESET, 0xB6);
__delay_ms(100);
// if NVM data are being copied to image registers, wait 100 ms
while ( (BMP280_Read8(BMP280_REG_STATUS) & 0x01) == 0x01 )
__delay_ms(100);
BMP280_calib.dig_T1 = BMP280_Read16(BMP280_REG_DIG_T1);
BMP280_calib.dig_T2 = BMP280_Read16(BMP280_REG_DIG_T2);
BMP280_calib.dig_T3 = BMP280_Read16(BMP280_REG_DIG_T3);
BMP280_calib.dig_P1 = BMP280_Read16(BMP280_REG_DIG_P1);
BMP280_calib.dig_P2 = BMP280_Read16(BMP280_REG_DIG_P2);
BMP280_calib.dig_P3 = BMP280_Read16(BMP280_REG_DIG_P3);
BMP280_calib.dig_P4 = BMP280_Read16(BMP280_REG_DIG_P4);
BMP280_calib.dig_P5 = BMP280_Read16(BMP280_REG_DIG_P5);
BMP280_calib.dig_P6 = BMP280_Read16(BMP280_REG_DIG_P6);
BMP280_calib.dig_P7 = BMP280_Read16(BMP280_REG_DIG_P7);
BMP280_calib.dig_P8 = BMP280_Read16(BMP280_REG_DIG_P8);
BMP280_calib.dig_P9 = BMP280_Read16(BMP280_REG_DIG_P9);
BMP280_Configure(mode, T_sampling, P_sampling, filter, standby);
return 1;
}
// Takes a new measurement, for forced mode only!
// Returns 1 if ok and 0 if error (sensor is not in sleep mode)
uint8_t BMP280_ForcedMeasurement()
{
uint8_t ctrl_meas_reg = BMP280_Read8(BMP280_REG_CONTROL);
if ( (ctrl_meas_reg & 0x03) != 0x00 )
return 0; // sensor is not in sleep mode
// set sensor to forced mode
BMP280_Write8(BMP280_REG_CONTROL, ctrl_meas_reg | 1);
// wait for conversion complete
while (BMP280_Read8(BMP280_REG_STATUS) & 0x08)
__delay_ms(1);
return 1;
}
// read (updates) adc_P, adc_T and adc_H from BMP280 sensor
void BMP280_Update()
{
union
{
uint8_t b[4];
uint32_t dw;
} ret;
ret.b[3] = 0x00;
BMP280_Start();
BMP280_Write(BMP280_I2C_ADDRESS);
BMP280_Write(BMP280_REG_PRESS_MSB);
BMP280_Start();
BMP280_Write(BMP280_I2C_ADDRESS | 1);
ret.b[2] = BMP280_Read(1); //msb
ret.b[1] = BMP280_Read(1); //lsb
ret.b[0] = BMP280_Read(1); //xlsb
adc_P = (ret.dw >> 4) & 0xFFFFF;
ret.b[2] = BMP280_Read(1); //msb
ret.b[1] = BMP280_Read(1); //lsb
ret.b[0] = BMP280_Read(0); //xlsb
BMP280_Stop();
adc_T = (ret.dw >> 4) & 0xFFFFF;
}
// Reads temperature from BMP280 sensor.
// Temperature is stored in hundreds C (output value of "5123" equals 51.23 DegC).
// Temperature value is saved to *temp, returns 1 if OK and 0 if error.
uint8_t BMP280_readTemperature(int32_t *temp)
{
int32_t var1, var2;
char t[32];
BMP280_Update();
// calculate temperature
var1 = ((((adc_T / 8) - ((int32_t)BMP280_calib.dig_T1 * 2))) *
((int32_t)BMP280_calib.dig_T2)) / 2048;
var2 = (((((adc_T / 16) - ((int32_t)BMP280_calib.dig_T1)) *
((adc_T / 16) - ((int32_t)BMP280_calib.dig_T1))) / 4096) *
((int32_t)BMP280_calib.dig_T3)) / 16384;
t_fine = var1 + var2;
*temp = (t_fine * 5 + 128) / 256;
return 1;
}
// Reads pressure from BMP280 sensor.
// Pressure is stored in Pa (output value of "96386" equals 96386 Pa = 963.86 hPa).
// Pressure value is saved to *pres, returns 1 if OK and 0 if error.
uint32_t BMP280_readPressure(uint32_t *pres)
{
int32_t var1, var2;
uint32_t p;
// calculate pressure
var1 = (((int32_t)t_fine) / 2) - (int32_t)64000;
var2 = (((var1/4) * (var1/4)) / 2048 ) * ((int32_t)BMP280_calib.dig_P6);
var2 = var2 + ((var1 * ((int32_t)BMP280_calib.dig_P5)) * 2);
var2 = (var2/4) + (((int32_t)BMP280_calib.dig_P4) * 65536);
var1 = ((((int32_t)BMP280_calib.dig_P3 * (((var1/4) * (var1/4)) / 8192 )) / 8) +
((((int32_t)BMP280_calib.dig_P2) * var1)/2)) / 262144;
var1 =((((32768 + var1)) * ((int32_t)BMP280_calib.dig_P1)) / 32768);
if (var1 == 0)
return 0; // avoid exception caused by division by zero
p = (((uint32_t)(((int32_t)1048576) - adc_P) - (var2 / 4096))) * 3125;
if (p < 0x80000000)
p = (p * 2) / ((uint32_t)var1);
else
p = (p / (uint32_t)var1) * 2;
var1 = (((int32_t)BMP280_calib.dig_P9) * ((int32_t)(((p/8) * (p/8)) / 8192))) / 4096;
var2 = (((int32_t)(p/4)) * ((int32_t)BMP280_calib.dig_P8)) / 8192;
p = (uint32_t)((int32_t)p + ((var1 + var2 + (int32_t)BMP280_calib.dig_P7) / 16));
*pres = p;
return 1;
}
void initialize_BMP280()
{
UART_new_line();
UART_send_string((char*)" Initializing BMP280..");
__delay_ms(10);
if(BMP280_begin(MODE_FORCED, SAMPLING_X1, SAMPLING_X1, FILTER_OFF, STANDBY_0_5) == 0)
{
// connection error or device address wrong!
UART_new_line();
UART_send_string((char*)" BMP280 connection error or device address wrong!");
UART_new_line();
UART_send_string((char*)" Restart device");
}
else {
UART_new_line();
UART_send_string((char*)" BMP280 connected");
}
__delay_ms(100);
}
void display_BMP280()
{
BMP280_PWR_RC5_SetHigh();
__delay_ms(500);
if(BMP280_begin(MODE_FORCED, SAMPLING_X1, SAMPLING_X1, FILTER_OFF, STANDBY_0_5) == 0)
{
// connection error or device address wrong!
UART_new_line();
UART_send_string((char*)" BMP280 connection error or device address wrong!");
UART_new_line();
UART_send_string((char*)" Restart device");
}
else {
UART_new_line();
UART_send_string((char*)" BMP280 connected");
}
UART_new_line();
// Read temperature (in hundreds C) and pressure (in Pa)
if(BMP280_ForcedMeasurement())
{
// values from the BMP280 sensor
BMP280_readTemperature(&temperature); // read temperature
BMP280_readPressure(&pressure); // read pressure
// print data on the screen
// 1: print temperature
if(temperature < 0){
memset(BMP_buf, '\0', sizeof(BMP_buf));
Float2Ascii ((float)temperature / 100.0, BMP_buf, 2);
UART_send_string((char*)" Temperature is:");
EUSART_Write('-');
UART_send_string(BMP_buf);
EUSART_Write('C');
UART_new_line();
}
else{
memset(BMP_buf, '\0', sizeof(BMP_buf));
Float2Ascii ((float)temperature / 100.0, BMP_buf, 2);
UART_send_string((char*)" Temperature is:");
UART_send_string(BMP_buf);
EUSART_Write('C');
UART_new_line();
}
// 2: print pressure
memset(BMP_buf, '\0', sizeof(BMP_buf));
Float2Ascii ((float)pressure / 100.0, BMP_buf, 2);
UART_send_string((char*)" Pressure is:");
UART_send_string(BMP_buf);
UART_send_string((char*)" hPa");
UART_new_line();
}
else
{
UART_send_string((char*)" Forced measurement failed!");
UART_new_line();
}
BMP280_PWR_RC5_SetLow();
}
// end of driver code.