ESP32 zahada C
Jaroslav Buchta
jaroslav.buchta na hascomp.cz
Neděle Červenec 16 14:22:13 CEST 2023
Ted zkoumam nejaky kod, (nekoukejte na funkcnost, to ted neni dulezite)
a nechapu, proc linkeru nevadi za nejakych okolnosti, ze jsou ve 2
souborech identicke globalni funkce. ESP-IDGF je 5.0.3
Tak jak to je, se to bez reci prelozi.
Pokud prejmenuju jednu funkci (init v souboru mcp9804_spy.c) tak vznikne
chyba, kterou bych cekal i v predchozim stavu
D:/tst/____/unity_fixture_test/components/temperature/mcp9804.c:37:
multiple definition of `mcp9804_get_temperature';
esp-idf/temperature/libtemperature.a(mcp9804_spy.c.obj):D:/tst/____/unity_fixture_test/components/temperature/mcp9804_spy.c:24:
first defined here
Kdyz ji prejmenuju jen v souboru mcp9804.c je to zase OK.
Je to nejaka zamerna featura nebo cim to je? Jedine, co me napada, ze
linker najde vsechny funkce ve prvnim modulu a tim padem se uz na druhy
ani nediva, ale stejne nevim, jestli je to vlastnost, nebo chyba linkeru...
------------- další část ---------------
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
#include <esp_log.h>
#include "mcp9804_spy.h"
#include "mcp9804_common.h"
static const char *TAG = "mcp9804_spy";
static uint8_t i2c_register_address;
static uint16_t i2c_returned_value;
void test(void)
{
}
void mcp9804_init(void)
{
i2c_register_address = 0;
i2c_returned_value = 0;
}
float mcp9804_get_temperature(void)
{
int16_t temperature_raw = i2c_returned_value;
return convert_temperature(temperature_raw);
}
void i2c_readRegister_ExpectAndReturn(uint8_t reg_addr, uint16_t value)
{
i2c_register_address = reg_addr;
i2c_returned_value = value;
}
------------- další část ---------------
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
#include <esp_log.h>
#include "mcp9804.h"
#include "mcp9804_common.h"
static const char *TAG = "mcp9804";
#define MCP9804_DATA_BUFFER_SIZE 2
#define SDA_PIN GPIO_NUM_4
#define SCL_PIN GPIO_NUM_5
static uint16_t configuration;
static uint16_t configuration_shadow;
static void configure_i2c(void);
static void mcp9804_write(uint8_t reg_addr, uint16_t data);
static uint16_t mcp9804_read(uint8_t reg_addr);
static void mcp9804_read_configuration(void);
void test(void)
{
}
void mcp9804_init(void)
{
ESP_LOGD(TAG, "Initializing MCP9804...");
configure_i2c();
ESP_LOGD(TAG, "MCP9804 initialized");
}
float mcp9804_get_temperature(void)
{
int16_t temperature_raw = mcp9804_read(MCP9804_REG_TA);
return convert_temperature(temperature_raw);
}
static void configure_i2c(void)
{
i2c_config_t conf = {
.mode = I2C_MODE_MASTER,
.sda_io_num = SDA_PIN,
.scl_io_num = SCL_PIN,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = 100000UL,
.clk_flags = 0,
};
ESP_ERROR_CHECK(i2c_param_config(I2C_NUM_0, &conf));
ESP_ERROR_CHECK(i2c_driver_install(I2C_NUM_0, conf.mode, 0, 0, 0));
}
/**
* @brief Writes to the register at the given address
* @param[in] reg_addr Register address
* @param[in] data Data to write
*/
static void mcp9804_write(uint8_t reg_addr, uint16_t data)
{
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (MCP9804_ADDR << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, reg_addr & 0xF, true);
uint8_t data_to_write[] = {(data >> 8) & 0xFF, data & 0xFF};
i2c_master_write(cmd, data_to_write, MCP9804_DATA_BUFFER_SIZE, true);
i2c_master_stop(cmd);
ESP_ERROR_CHECK(i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000 / portTICK_PERIOD_MS));
i2c_cmd_link_delete(cmd);
}
/**
* @brief Reads the register at the given address
* @param[in] reg_addr Register address
* @return Data read from the register
*/
static uint16_t mcp9804_read(uint8_t reg_addr)
{
uint8_t data[MCP9804_DATA_BUFFER_SIZE] = {0};
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (MCP9804_ADDR << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, reg_addr & 0xF, true);
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (MCP9804_ADDR << 1) | I2C_MASTER_READ, true);
i2c_master_read(cmd, data, MCP9804_DATA_BUFFER_SIZE, I2C_MASTER_LAST_NACK);
i2c_master_stop(cmd);
ESP_ERROR_CHECK(i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000 / portTICK_PERIOD_MS));
i2c_cmd_link_delete(cmd);
return (uint16_t)(data[0] << 8) | (data[1] & 0xFF);
}
------------- další část ---------------
idf_component_register(
SRCS "mcp9804_spy.c" "mcp9804.c" "mcp9804_common.c"
REQUIRES driver
INCLUDE_DIRS "include"
)
------------- další část ---------------
#include <mcp9804_common.h>
float convert_temperature(int16_t temperature_raw)
{
temperature_raw &= 0x1FFF;
if ((temperature_raw & 0x1000) != 0)
{
temperature_raw |= 0xe000;
}
float temperature = (float)temperature_raw / 16.0F;
return temperature;
}
Další informace o konferenci Hw-list