#include <stdio.h>
#include "esp_log.h"
#include "driver/spi_master.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include <string.h>
#define BMP280_ID 0xD0
#define BMP280_RESET 0xE0
#define BMP280_STATUS 0xF3
#define BMP280_CTRL_MEAS 0xF4
#define BMP280_CONFIG 0xF5
#define BMP280_PRESS_MSB 0xF7
#define BMP280_PRESS_LSB 0xF8
#define BMP280_PRESS_XLSB 0xF9
#define BMP280_TEMP_MSB 0xFA
#define BMP280_TEMP_LSB 0xFB
#define BMP280_TEMP_XLSB 0xFC
#define BMP280_DIG_T1_LSB 0x88
#define SPI_MOSI 23
#define SPI_MISO 19
#define SPI_SCLK 18
#define SPI_CS 5
static const char *TAG = "SPI-BMP280";
spi_device_handle_t bmp280_spi;
int32_t t_fine;
uint16_t dig_T1, dig_P1;
int16_t dig_T2, dig_T3, dig_P2, dig_P3, dig_P4, dig_P5, dig_P6, dig_P7, dig_P8, dig_P9;
esp_err_t bmp280_read_reg(uint8_t reg_addr, uint8_t *reg_data, uint32_t len)
{
spi_transaction_t t;
memset(&t, 0, sizeof(spi_transaction_t));
t.addr = reg_addr | 0x80; // Establece el MSB a 1 para indicar lectura
t.length = len * 8; // convierte el numero de bytes en bits
t.rx_buffer = reg_data;
return spi_device_transmit(bmp280_spi, &t);
}
esp_err_t bmp280_write_reg(uint8_t reg_addr, uint8_t reg_data)
{
spi_transaction_t t;
memset(&t, 0, sizeof(spi_transaction_t));
t.addr = reg_addr & 0x7F; // Establece el MSB a 0 para indicar escritura
t.tx_buffer = ®_data;
t.length = 8;
return spi_device_transmit(bmp280_spi, &t);
}
void bmp280_read_calib_data()
{
uint8_t calib_data[23]; // 12 Registros divididos en lsb y msb
bmp280_read_reg(BMP280_DIG_T1_LSB, calib_data, 23);
dig_T1 = (calib_data[1] << 8) | calib_data[0]; // inicia la lectura a partir de 0x88 (LSB dig_T1)
dig_T2 = (calib_data[3] << 8) | calib_data[2];
dig_T3 = (calib_data[5] << 8) | calib_data[4];
dig_P1 = (calib_data[7] << 8) | calib_data[6];
dig_P2 = (calib_data[9] << 8) | calib_data[8];
dig_P3 = (calib_data[11] << 8) | calib_data[10];
dig_P4 = (calib_data[13] << 8) | calib_data[12];
dig_P5 = (calib_data[15] << 8) | calib_data[14];
dig_P6 = (calib_data[17] << 8) | calib_data[16];
dig_P7 = (calib_data[19] << 8) | calib_data[18];
dig_P8 = (calib_data[21] << 8) | calib_data[20];
dig_P9 = (calib_data[23] << 8) | calib_data[22];
}
uint32_t bmp280_read_adc_press()
{
uint8_t data[3];
bmp280_read_reg(BMP280_PRESS_MSB, data, 3);
uint32_t adc_P = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4);
return adc_P;
}
uint32_t bmp280_read_adc_temp()
{
uint8_t data[3];
bmp280_read_reg(BMP280_TEMP_MSB, data, 3);
uint32_t adc_T = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4);
return adc_T;
}
int32_t bmp280_compensate_temp(int32_t adc_T)
{
int32_t var1, var2, T;
var1 = ((((adc_T >> 3) - ((int32_t)dig_T1 << 1))) * ((int32_t)dig_T2)) >> 11;
var2 = (((((adc_T >> 4) - ((int32_t)dig_T1)) * ((adc_T >> 4) - ((int32_t)dig_T1))) >> 12) * ((int32_t)dig_T3)) >> 14;
t_fine = var1 + var2;
T = (t_fine * 5 + 128) >> 8;
return T;
}
uint32_t bmp280_compensate_press(int32_t adc_P)
{
int64_t var1, var2, p;
var1 = ((int64_t)t_fine) - 128000;
var2 = var1 * var1 * (int64_t)dig_P6;
var2 = var2 + ((var1 * (int64_t)dig_P5) << 17);
var2 = var2 + (((int64_t)dig_P4) << 35);
var1 = ((var1 * var1 * (int64_t)dig_P3) >> 8) + ((var1 * (int64_t)dig_P2) << 12);
var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)dig_P1) >> 33;
if (var1 == 0)
{
return 0; // avoid exception caused by division by zero
}
p = 1048576 - adc_P;
p = (((p << 31) - var2) * 3125) / var1;
var1 = (((int64_t)dig_P9) * (p >> 13) * (p >> 13)) >> 25;
var2 = (((int64_t)dig_P8) * p) >> 19;
p = ((p + var1 + var2) >> 8) + (((int64_t)dig_P7) << 4);
return (uint32_t)p;
}
esp_err_t spi_master_init()
{
spi_bus_config_t spi_bus_config = {
.mosi_io_num = SPI_MOSI, // Pin de MOSI
.miso_io_num = SPI_MISO, // Pin de MISO
.sclk_io_num = SPI_SCLK, // Pin de SCLK
.quadwp_io_num = -1, // No utilizado
.quadhd_io_num = -1 // No utilizado
};
spi_device_interface_config_t spi_device_config = {
.address_bits = 8, // 1 Byte
.mode = 0, // Modo SPI 0
.clock_speed_hz = 10000000, // 10 MHz
.spics_io_num = SPI_CS, // Pin de CS
.queue_size = 1 // Tamaño de cola para transacciones
};
// Inicializar el bus SPI
ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &spi_bus_config, SPI_DMA_CH_AUTO));
// Añadir el dispositivo BMP280 al bus SPI
ESP_ERROR_CHECK(spi_bus_add_device(SPI3_HOST, &spi_device_config, &bmp280_spi));
return ESP_OK;
}
void bmp280_init()
{
bmp280_read_calib_data();
ESP_LOGI(TAG, "BMP280 initialized");
}
void app_main(void)
{
spi_master_init();
bmp280_init();
bmp280_write_reg(BMP280_CONFIG, 0x04);
bmp280_write_reg(BMP280_CTRL_MEAS, 0xB7);
uint8_t chip_id;
while (1)
{
int32_t adc_T = bmp280_read_adc_temp();
int32_t adc_P = bmp280_read_adc_press();
float temperature = bmp280_compensate_temp(adc_T) / 100.0; // devuelve temperatura en formato * 100
int32_t pressure = bmp280_compensate_press(adc_P) / 256.0; // devuelve la presion en formato * 256
bmp280_read_reg(BMP280_ID, &chip_id, 1);
ESP_LOGI(TAG, "ID: 0x%02X", chip_id);
ESP_LOGI(TAG, "Temperatura: %.2f °C, Pa: %d.%02d", temperature, (int)(pressure / 100), (int)(pressure % 100));
vTaskDelay(pdMS_TO_TICKS(3000));
}
}