I’m trying to interface with the HDC2010 sensor, which uses the I2C protocol. I’ve successfully done this using the polling method, but now I want to implement it using the Data Ready (DRDY) interrupt method. I’ve connected the INT1 pin of the sensor to a GPIO pin on my microcontroller. When I manually trigger the interrupt, it correctly enters the interrupt service routine. However, it’s not automatically generating interrupts when new data is available.
#include <zephyr/kernel.h> #include <zephyr/drivers/i2c.h> #include <zephyr/device.h> #include <zephyr/devicetree.h> #include <zephyr/sys/printk.h> #include <zephyr/drivers/gpio.h> #define I2C_NODE DT_NODELABEL(hdc2010) // config reg #define CONFIG_REG 0X0E #define MEASUREMENT_CONFIG 0x0F // who i am reg #define DEVICE_ID_L 0xFE #define DEVICE_ID_H 0xFF // menu id #define MENU_ID_L 0xFC #define MENU_ID_H 0xFD // reading temp reg #define TEMP_L 0X00 #define TEMP_H 0X01 // config interrupt pin #define INTERRUPT_CONFIG 0x07 // init flag int initFlag = 0; // init temp flag int tempFlag = 0; // init hum flag int humFlag = 0; uint8_t config[2] = {CONFIG_REG, 0x80}; #define SW0_NODE DT_ALIAS(sw5) int temp; static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET(SW0_NODE, gpios); static const struct i2c_dt_spec hdc2010 = I2C_DT_SPEC_GET(I2C_NODE); int dataReady = 0; static struct gpio_callback button_cb_data; // who am i int readDeviceId(const struct i2c_dt_spec *hdc2010, uint16_t *id, uint16_t *id1) { int ret; // first reading device id uint8_t reg[2] = {DEVICE_ID_L, DEVICE_ID_H}; uint8_t device_id[2] = {DEVICE_ID_L, DEVICE_ID_H}; ret = i2c_write_read_dt(hdc2010, ®[0], 1, &device_id[0], 1); if (ret) { printk("device id error\n"); return -1; } ret = i2c_write_read_dt(hdc2010, ®[1], 1, &device_id[1], 1); if (ret) { printk("device id error\n"); return -1; } *id = (device_id[1] << 8) | device_id[0]; // second reading menu id reg[0] = MENU_ID_L; reg[1] = MENU_ID_H; ret = i2c_write_read_dt(hdc2010, ®[0], 1, &device_id[0], 1); if (ret) { printk("menu id error\n"); return -1; } ret = i2c_write_read_dt(hdc2010, ®[1], 1, &device_id[1], 1); if (ret) { printk("menu id error"); return -1; } *id1 = (device_id[1] << 8) | device_id[0]; printk("%x %x device id and menu id\n", *id, *id1); return 0; } // init int hdc2010Init(const struct i2c_dt_spec *hdc2010) { uint8_t oldConfig; int ret; if (initFlag) { return 0; } uint8_t tempReg[2] = {CONFIG_REG, 0}; ret = i2c_write_read_dt(hdc2010, &tempReg[0], 1, &oldConfig, 1); if (ret) { printk("writing in reg problem\n"); return -1; } uint8_t newConfig = oldConfig | 7 << 4; config[1] = newConfig; ret = i2c_write_dt(hdc2010, config, sizeof(config)); if (ret != 0) { printk("soft reseting is fail\n"); return -1; } /* Bits 2 and 1 of the MEASUREMENT_CONFIG register controls the measurement mode */ // Upper two bits of the MEASUREMENT_CONFIG register controls the temperature resolution // default value is 14 // Bit 0 of the MEASUREMENT_CONFIG register can be used to trigger measurements config[0] = MEASUREMENT_CONFIG; config[1] = 0X4b; ret = i2c_write_dt(hdc2010, config, sizeof(config)); if (ret != 0) { printk("setup measurement config failed \n"); return -1; } initFlag = 1; tempFlag = 1; return 0; } // deinit hdc2010 int hdc2010DeInit() { tempFlag = 0; humFlag = 0; initFlag = 0; return 0; } // reading values for sensor temperature int Hdc2010ReadingTemperature(const struct i2c_dt_spec *hdc2010, int *val) { int ret; volatile uint16_t temp; float intermediate, value; hdc2010Init(hdc2010); uint8_t tempReg[2] = {TEMP_L, TEMP_H}; uint8_t reading[2]; ret = i2c_write_read_dt(hdc2010, &tempReg[0], 1, &reading[0], 1); if (ret) { printk("failed at reading temperature\n"); return -1; } ret = i2c_write_read_dt(hdc2010, &tempReg[1], 1, &reading[1], 1); if (ret) { printk("failed at reading temperature\n"); return -1; } temp = (reading[1] << 8) | reading[0]; intermediate = temp / 65536.0; intermediate = intermediate * 165; value = intermediate - 40.00; *val = value; printk("%0.2f C\n", value); hdc2010DeInit(); return 0; } int hdc_enable_interrupt(const struct i2c_dt_spec *hdc2010) { uint8_t oldConfig; int ret; uint8_t tempReg[2] = {CONFIG_REG, 0}; ret = i2c_write_read_dt(hdc2010, &tempReg[0], 1, &oldConfig, 1); if (ret) { printk("reading in reg problem int\n"); return -1; } uint8_t newConfig = oldConfig | 1 << 2; // setting intEn pin in config reg tempReg[1] = newConfig; ret = i2c_write_dt(hdc2010, tempReg, sizeof(tempReg)); if (ret) { printk("setting int pin is not set\n"); return -1; } return ret; } // setting up polarity for interrupt int hdc2010_setInterruptPolarity(const struct i2c_dt_spec *hdc2010, int polarity) { uint8_t oldConfig; int ret; uint8_t tempReg[2] = {CONFIG_REG, 0}; ret = i2c_write_read_dt(hdc2010, &tempReg[0], 1, &oldConfig, 1); if (ret) { printk("writing in reg problem\n"); return -1; } uint16_t newConfig; if (polarity) { newConfig = oldConfig | 1 << 1; // setting polarity of pin active high } else { newConfig = oldConfig & ~(1 << 1); // setting polarity of pin active low } tempReg[1] = newConfig; ret = i2c_write_dt(hdc2010, tempReg, sizeof(tempReg)); if (ret) { printk("setting int pin is not set\n"); return -1; } return ret; } // trigger reading int triggerMeasurement(const struct i2c_dt_spec *hdc2010) { uint8_t oldConfig; int ret; uint8_t tempReg[2] = {MEASUREMENT_CONFIG, 0}; ret = i2c_write_read_dt(hdc2010, &tempReg[0], 1, &oldConfig, 1); if (ret) { printk("writing in reg problem\n"); return -1; } uint8_t newConfig = oldConfig | 1 << 0; // setting start measurement tempReg[1] = newConfig; ret = i2c_write_dt(hdc2010, tempReg, sizeof(tempReg)); if (ret) { printk("setting int pin is not set\n"); return -1; } return 0; } // setting up drdy bit int hdc2010_enableDRDYInterrupt(const struct i2c_dt_spec *hdc2010) { uint8_t config; int ret; uint8_t tempReg[2] = {INTERRUPT_CONFIG, 0}; ret = i2c_write_read_dt(hdc2010, &tempReg[0], 1, &config, 1); if (ret) { printk("writing in reg problem\n"); return -1; } uint8_t newConfig = config | 1 << 7; // setting intEn pin in config reg tempReg[1] = newConfig; ret = i2c_write_dt(hdc2010, tempReg, sizeof(tempReg)); if (ret) { printk("setting int pin is not set\n"); return -1; } return 0; } // setting up interrupt drdy int HDC2010_Enable_DRDY_Interrupt(const struct i2c_dt_spec *hdc2010, int polarity) { int ret = hdc2010_enableDRDYInterrupt(hdc2010); ret = hdc_enable_interrupt(hdc2010); if (ret) { printk("hdc2010 enable interrupt error\n"); return -1; } ret = hdc2010_setInterruptPolarity(hdc2010, polarity); if (ret) { printk("hdc2010 enabling polarity error\n"); } ret = triggerMeasurement(hdc2010); return 0; } void button_pressed(const struct device *dev, struct gpio_callback *cb, uint32_t pins) { dataReady = 1; printk("interrupt triggered\n"); /// Hdc2010ReadingTemperature(&hdc2010, &temp); // triggerMeasurement(&hdc2010); } int main(void) { int ret; if (!device_is_ready(button.port)) { printk("inti problem\n"); return; } // static const struct i2c_dt_spec hdc2010 = I2C_DT_SPEC_GET(I2C_NODE); if (!device_is_ready(hdc2010.bus)) { printk("device is not ready\n"); return 0; } // sensor init part is here ret = hdc2010Init(&hdc2010); if (ret) { printk("hdc2010 sensor init failed\n"); return -1; } printk("init completed\n"); ret = gpio_pin_configure_dt(&button, GPIO_INPUT); ret = gpio_pin_interrupt_configure_dt(&button, GPIO_INT_EDGE_TO_ACTIVE); if (ret) { printk("error\n"); return 0; } // // temp part uint8_t tempReg[2] = {MEASUREMENT_CONFIG, 0}; uint8_t oldConfig; ret = i2c_write_read_dt(&hdc2010, &tempReg[0], 1, &oldConfig, 1); if (ret) { printk("writing in reg problem\n"); return -1; } printk("%x measurement\n", oldConfig); tempReg[0] = CONFIG_REG; oldConfig; ret = i2c_write_read_dt(&hdc2010, &tempReg[0], 1, &oldConfig, 1); if (ret) { printk("writing in reg problem\n"); return -1; } printk("%x config\n", oldConfig); gpio_init_callback(&button_cb_data, button_pressed, BIT(button.pin)); gpio_add_callback(button.port, &button_cb_data); int temp; ret = HDC2010_Enable_DRDY_Interrupt(&hdc2010, 0); if (ret) { printk("error\n"); return 0; } tempReg[0] = INTERRUPT_CONFIG; ret = i2c_write_read_dt(&hdc2010, &tempReg[0], 1, &oldConfig, 1); if (ret) { printk("writing in reg problem\n"); return -1; } printk("%x DRDY BIT\n", oldConfig); while (1) { k_msleep(1000); } return 0; }
this is code i have written , drivers were not available in zephyr so i have to wrote them, see if there is problem.
&i2c0 { status = "okay"; hdc2010: hdc2010@40 { compatible = "i2c-device"; status = "okay"; reg = <0x40>; }; }; / { buttons { compatible = "gpio-keys"; button5: button_5 { gpios = <&gpio0 4 (GPIO_PULL_UP | GPIO_ACTIVE_HIGH)>; }; }; aliases{ sw5=&button5; }; };
and this is my overlay file.