309 lines
8.8 KiB
C
309 lines
8.8 KiB
C
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
#include "freertos/queue.h"
|
|
#include "driver/gpio.h"
|
|
#include "driver/i2c_master.h"
|
|
|
|
#define I2C_MASTER_NUM I2C_NUM_1
|
|
#define I2C_MASTER_SCL_IO GPIO_NUM_22 // CONFIG_EXAMPLE_I2C_SCL /*!< gpio number for I2C master clock */
|
|
#define I2C_MASTER_SDA_IO GPIO_NUM_21 // CONFIG_EXAMPLE_I2C_SDA /*!< gpio number for I2C master data */
|
|
#define I2C_MASTER_FREQ_HZ 100000 // CONFIG_I2C_TRANS_SPEED /*!< I2C master clock frequency */
|
|
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master do not need buffer */
|
|
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master do not need buffer */
|
|
#define LM75A_SLAVE_ADDR 0x48 // CONFIG_LM75A_SLAVE_ADDR /*!< LM75A slave address, you can set any 7bit value */
|
|
#define ACK_VAL 0x0 /*!< I2C ack value */
|
|
#define NACK_VAL 0x1 /*!< I2C nack value */
|
|
#define WRITE_BIT I2C_MASTER_WRITE /*!< I2C master write */
|
|
#define READ_BIT I2C_MASTER_READ /*!< I2C master read */
|
|
#define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/
|
|
#define ACK_CHECK_DIS 0x0 /*!< I2C master will not check ack from slave */
|
|
|
|
/*
|
|
#define GPIO_INPUT_IO_0 CONFIG_LM75A_OS_PIN
|
|
#define GPIO_OUTPUT_IO_0 CONFIG_LM75A_VCC_PIN
|
|
#define GPIO_OUTPUT_PIN_SEL (1ULL << GPIO_OUTPUT_IO_0)
|
|
#define GPIO_INPUT_PIN_SEL (1ULL << GPIO_INPUT_IO_0)
|
|
#define ESP_INTR_FLAG_DEFAULT 0
|
|
*/
|
|
|
|
// static xQueueHandle gpio_evt_queue = NULL;
|
|
// static int gpio_int_task_enable = 0;
|
|
// static TaskHandle_t gpio_int_task_handle = NULL;
|
|
|
|
/**
|
|
* @brief test code to read esp-i2c-slave
|
|
* We need to fill the buffer of esp slave device, then master can read them out.
|
|
*
|
|
* _______________________________________________________________________________________
|
|
* | start | slave_addr + rd_bit +ack | read n-1 bytes + ack | read 1 byte + nack | stop |
|
|
* --------|--------------------------|----------------------|--------------------|------|
|
|
*
|
|
*/
|
|
static esp_err_t i2c_master_read_slave(i2c_port_t i2c_num, uint8_t *data_rd, size_t size)
|
|
{
|
|
if (size == 0)
|
|
{
|
|
return ESP_OK;
|
|
}
|
|
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
|
i2c_master_start(cmd);
|
|
i2c_master_write_byte(cmd, (LM75A_SLAVE_ADDR << 1) | READ_BIT, ACK_CHECK_EN);
|
|
if (size > 1)
|
|
{
|
|
i2c_master_read(cmd, data_rd, size - 1, ACK_VAL);
|
|
}
|
|
i2c_master_read_byte(cmd, data_rd + size - 1, NACK_VAL);
|
|
i2c_master_stop(cmd);
|
|
esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_PERIOD_MS);
|
|
i2c_cmd_link_delete(cmd);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Test code to write esp-i2c-slave
|
|
* Master device write data to slave(both esp32),
|
|
* the data will be stored in slave buffer.
|
|
* We can read them out from slave buffer.
|
|
*
|
|
* ___________________________________________________________________
|
|
* | start | slave_addr + wr_bit + ack | write n bytes + ack | stop |
|
|
* --------|---------------------------|----------------------|------|
|
|
*
|
|
*/
|
|
static esp_err_t i2c_master_write_slave(i2c_port_t i2c_num, uint8_t *data_wr, size_t size)
|
|
{
|
|
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
|
i2c_master_start(cmd);
|
|
i2c_master_write_byte(cmd, (LM75A_SLAVE_ADDR << 1) | WRITE_BIT, ACK_CHECK_EN);
|
|
i2c_master_write(cmd, data_wr, size, ACK_CHECK_EN);
|
|
i2c_master_stop(cmd);
|
|
esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_PERIOD_MS);
|
|
i2c_cmd_link_delete(cmd);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief i2c master initialization
|
|
*/
|
|
static void i2c_master_init()
|
|
{
|
|
int i2c_master_port = I2C_MASTER_NUM;
|
|
i2c_config_t conf;
|
|
conf.mode = I2C_MODE_MASTER;
|
|
conf.sda_io_num = I2C_MASTER_SDA_IO;
|
|
conf.sda_pullup_en = GPIO_PULLUP_DISABLE;
|
|
conf.scl_io_num = I2C_MASTER_SCL_IO;
|
|
conf.scl_pullup_en = GPIO_PULLUP_DISABLE;
|
|
conf.master.clk_speed = I2C_MASTER_FREQ_HZ;
|
|
conf.clk_flags = 0;
|
|
|
|
i2c_param_config(i2c_master_port, &conf);
|
|
i2c_driver_install(i2c_master_port, conf.mode,
|
|
I2C_MASTER_RX_BUF_DISABLE,
|
|
I2C_MASTER_TX_BUF_DISABLE, 0);
|
|
}
|
|
|
|
int lm75a_read_temperature(int show)
|
|
{
|
|
uint8_t buf[2];
|
|
float tmp;
|
|
buf[0] = 0;
|
|
i2c_master_write_slave(I2C_MASTER_NUM, buf, 1);
|
|
i2c_master_read_slave(I2C_MASTER_NUM, buf, 2);
|
|
tmp = buf[0];
|
|
if (buf[1] & 128)
|
|
tmp += 0.5;
|
|
if (show)
|
|
printf("lm75a_read_temperature=%.1f\n", tmp);
|
|
return tmp;
|
|
}
|
|
|
|
/*
|
|
static void IRAM_ATTR gpio_isr_handler(void *arg)
|
|
{
|
|
uint32_t gpio_num = (uint32_t)arg;
|
|
xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
|
|
}
|
|
|
|
static void gpio_int_task(void *arg)
|
|
{
|
|
uint32_t io_num;
|
|
gpio_int_task_enable = 1;
|
|
while (gpio_int_task_enable)
|
|
{
|
|
if (xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY))
|
|
{
|
|
|
|
// read temperature to clean int;
|
|
if (io_num == GPIO_INPUT_IO_0)
|
|
{
|
|
printf("GPIO[%d] intr, val: %d\n\n", io_num, gpio_get_level(io_num));
|
|
lm75a_read_temperature(0); // read to clean interrupt.
|
|
}
|
|
}
|
|
}
|
|
printf("quit gpio_int_task\n");
|
|
if (gpio_evt_queue)
|
|
{
|
|
vQueueDelete(gpio_evt_queue);
|
|
gpio_evt_queue = NULL;
|
|
}
|
|
gpio_int_task_handle = NULL;
|
|
vTaskDelete(NULL);
|
|
}
|
|
|
|
void init_os_gpio()
|
|
{
|
|
printf("init_os_gpio!\n");
|
|
|
|
if (gpio_evt_queue == NULL)
|
|
gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
|
|
|
|
if (gpio_int_task_handle == NULL)
|
|
{
|
|
xTaskCreate(gpio_int_task, "gpio_int_task", 2048, NULL, 10, &gpio_int_task_handle);
|
|
// install gpio isr service
|
|
gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
|
|
// hook isr handler for specific gpio pin again
|
|
gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void *)GPIO_INPUT_IO_0);
|
|
}
|
|
}
|
|
|
|
static void deinit_os_gpio()
|
|
{
|
|
printf("deinit_os_gpio!\n");
|
|
|
|
if (gpio_int_task_handle)
|
|
{
|
|
gpio_isr_handler_remove(GPIO_INPUT_IO_0);
|
|
gpio_uninstall_isr_service();
|
|
gpio_int_task_enable = 0;
|
|
int io = 0;
|
|
xQueueSend(gpio_evt_queue, &io, 0); // send a fake signal to quit task.
|
|
}
|
|
}
|
|
|
|
static void lm75a_vcc_enable()
|
|
{
|
|
gpio_config_t io_conf;
|
|
// enable output for vcc
|
|
io_conf.intr_type = GPIO_PIN_INTR_DISABLE;
|
|
io_conf.mode = GPIO_MODE_OUTPUT;
|
|
io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL;
|
|
io_conf.pull_down_en = 0;
|
|
io_conf.pull_up_en = 0;
|
|
gpio_config(&io_conf);
|
|
|
|
// enable input for interrupt
|
|
io_conf.intr_type = GPIO_PIN_INTR_NEGEDGE; // GPIO_PIN_INTR_ANYEDGE;
|
|
io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL;
|
|
io_conf.mode = GPIO_MODE_INPUT;
|
|
io_conf.pull_up_en = 1;
|
|
gpio_set_pull_mode(GPIO_INPUT_IO_0, GPIO_FLOATING);
|
|
gpio_config(&io_conf);
|
|
gpio_set_level(GPIO_OUTPUT_IO_0, 1);
|
|
}
|
|
|
|
static void lm75a_vcc_disable()
|
|
{
|
|
gpio_set_level(GPIO_OUTPUT_IO_0, 0);
|
|
}
|
|
*/
|
|
|
|
void lm75a_init()
|
|
{
|
|
// lm75a_vcc_enable();
|
|
i2c_master_init();
|
|
}
|
|
|
|
void lm75a_deinit()
|
|
{
|
|
// deinit_os_gpio();
|
|
i2c_driver_delete(I2C_MASTER_NUM);
|
|
// lm75a_vcc_disable();
|
|
}
|
|
|
|
void lm75a_set_tos(int tos)
|
|
{
|
|
uint8_t buf[4];
|
|
printf("lm75a_set_tos: %d\n", tos);
|
|
// set Tos:
|
|
buf[0] = 0x3;
|
|
buf[1] = (tos & 0xff);
|
|
buf[2] = 0;
|
|
i2c_master_write_slave(I2C_MASTER_NUM, buf, 3);
|
|
}
|
|
|
|
void lm75a_set_thys(int thys)
|
|
{
|
|
uint8_t buf[4];
|
|
printf("lm75a_set_thys: %d\n", thys);
|
|
// set Thyst:
|
|
buf[0] = 0x2;
|
|
buf[1] = (thys & 0xff);
|
|
buf[2] = 0;
|
|
i2c_master_write_slave(I2C_MASTER_NUM, buf, 3);
|
|
}
|
|
|
|
void lm75a_get_tos()
|
|
{
|
|
uint8_t buf[4];
|
|
float tmp;
|
|
buf[0] = 0x3;
|
|
i2c_master_write_slave(I2C_MASTER_NUM, buf, 1);
|
|
i2c_master_read_slave(I2C_MASTER_NUM, buf, 2);
|
|
tmp = buf[0];
|
|
if (buf[1] & 128)
|
|
tmp += 0.5;
|
|
|
|
printf("lm75a_get_tos: %.1f\n", tmp);
|
|
}
|
|
|
|
void lm75a_get_thys()
|
|
{
|
|
uint8_t buf[4];
|
|
float tmp;
|
|
buf[0] = 0x2;
|
|
i2c_master_write_slave(I2C_MASTER_NUM, buf, 1);
|
|
i2c_master_read_slave(I2C_MASTER_NUM, buf, 2);
|
|
tmp = buf[0];
|
|
if (buf[1] & 128)
|
|
tmp += 0.5;
|
|
|
|
printf("lm75a_get_thys: %.1f\n", tmp);
|
|
}
|
|
|
|
void lm75a_set_int(int en)
|
|
{
|
|
uint8_t buf[2];
|
|
|
|
en = !!en;
|
|
if (en)
|
|
{
|
|
printf("lm75a_set_int: %d\n", en);
|
|
buf[0] = 0x1;
|
|
buf[1] = (1 << 1); // D1 set to 1;
|
|
i2c_master_write_slave(I2C_MASTER_NUM, buf, 2);
|
|
i2c_master_read_slave(I2C_MASTER_NUM, buf, 2); // do one time read to clean interrupt before enter interrupt mode.
|
|
// gpio_set_intr_type(GPIO_INPUT_IO_0, GPIO_INTR_NEGEDGE);
|
|
// init_os_gpio();
|
|
}
|
|
else
|
|
{
|
|
printf("lm75a_set_int: %d\n", en);
|
|
// deinit_os_gpio();
|
|
buf[0] = 0x1;
|
|
buf[1] = 0;
|
|
i2c_master_write_slave(I2C_MASTER_NUM, buf, 2);
|
|
i2c_master_read_slave(I2C_MASTER_NUM, buf, 2); // do one time read to clean interrupt before enter interrupt mode.
|
|
}
|
|
}
|
|
|
|
void lm75a_get_osio()
|
|
{
|
|
// printf("os_io: %d\n", gpio_get_level(GPIO_INPUT_IO_0));
|
|
}
|