#pragma once #include "driver/gpio.h" #include "driver/i2c_master.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/queue.h" #include "esp_log.h" #define TAG1 "SC7660" // SC7660寄存器地址 #define SC7660_ADDR 0x19 // 假设I2C地址为0x19,请根据实际硬件确认 #define SC7660_CTRL_REG0 0x1F #define SC7660_CTRL_REG1 0x20 #define SC7660_CTRL_REG2 0x21 #define SC7660_CTRL_REG3 0x22 #define SC7660_CTRL_REG4 0x23 #define SC7660_CTRL_REG5 0x24 #define SC7660_CTRL_REG6 0x25 #define SC7660_CLICK_CFG 0x38 #define SC7660_CLICK_SRC 0x39 #define SC7660_CLICK_THS 0x3A #define SC7660_TIME_LIMIT 0x3B #define SC7660_TIME_LATENCY 0x3C #define SC7660_TIME_WINDOW 0x3D #define SC7660_INT1_CFG 0x30 #define SC7660_INT1_THS 0x32 #define SC7660_INT1_DURATION 0x33 #define SC7660_STATUS_REG 0x27 #define SC7660_OUT_X_L 0x28 #define SC7660_OUT_X_H 0x29 #define SC7660_OUT_Y_L 0x2A #define SC7660_OUT_Y_H 0x2B #define SC7660_OUT_Z_L 0x2C #define SC7660_OUT_Z_H 0x2D #define SC7660_CTRL_REG58 58 // 中断引脚配置 #define SC7660_INT1_GPIO GPIO_NUM_9 class SC7660Driver { private: i2c_master_dev_handle_t dev_handle; // QueueHandle_t interrupt_queue; esp_err_t write_register(uint8_t reg, uint8_t value) { uint8_t write_buf[2] = {reg, value}; return i2c_master_transmit(dev_handle, write_buf, sizeof(write_buf), -1); } esp_err_t read_register(uint8_t reg, uint8_t *value) { esp_err_t ret = i2c_master_transmit(dev_handle, ®, 1, -1); if (ret != ESP_OK) return ret; return i2c_master_receive(dev_handle, value, 1, -1); } esp_err_t read_registers(uint8_t reg, uint8_t *data, size_t len) { esp_err_t ret = i2c_master_transmit(dev_handle, ®, 1, -1); if (ret != ESP_OK) return ret; return i2c_master_receive(dev_handle, data, len, -1); } public: SC7660Driver(i2c_master_bus_handle_t bus_handle) { i2c_device_config_t dev_cfg = { .dev_addr_length = I2C_ADDR_BIT_LEN_7, .device_address = SC7660_ADDR, .scl_speed_hz = 400000, // 400kHz }; ESP_ERROR_CHECK(i2c_master_bus_add_device(bus_handle, &dev_cfg, &dev_handle)); // 创建中断队列 // interrupt_queue = xQueueCreate(10, sizeof(uint32_t)); } ~SC7660Driver() { i2c_master_bus_rm_device(dev_handle); //vQueueDelete(interrupt_queue); } esp_err_t init() { ESP_LOGI(TAG1, "Initializing SC7660..."); ESP_ERROR_CHECK(write_register(SC7660_CTRL_REG0, 0x08)); // 1. 进入掉电模式进行配置 ESP_ERROR_CHECK(write_register(SC7660_CTRL_REG1, 0x47)); // 2. 配置双击检测参数(基于文档7.5节示例) // 设置ODR为25Hz,使能XYZ轴 ESP_ERROR_CHECK(write_register(SC7660_CTRL_REG4, 0x88)); // 配置高通滤波器(作用于CLICK功能) ESP_ERROR_CHECK(write_register(SC7660_CTRL_REG2, 0x31)); // 设置量程为±2G,BDU=1 ESP_ERROR_CHECK(write_register(SC7660_CTRL_REG3, 0x40)); // 使能X和Y轴的双击检测 ESP_ERROR_CHECK(write_register(SC7660_CTRL_REG6, 0x00)); // 设置点击阈值 ESP_ERROR_CHECK(write_register(SC7660_CTRL_REG5, 0x00)); // 设置时间限制窗口 ESP_ERROR_CHECK(write_register(SC7660_INT1_CFG, 0x2A)); // 设置中断持续时间 ESP_ERROR_CHECK(write_register(SC7660_INT1_THS, 0x03)); // 设置双击时间窗口 ESP_ERROR_CHECK(write_register(SC7660_INT1_DURATION, 0x50)); // 3. 配置中断 // 将双击中断映射到INT1引脚 ESP_ERROR_CHECK(write_register(SC7660_CTRL_REG58, 0x02)); ESP_LOGI(TAG1, "SC7660 initialization complete"); return ESP_OK; } // esp_err_t setup_interrupt() { // // 配置GPIO9为输入,用于接收INT1中断 // gpio_config_t io_conf = { // .pin_bit_mask = (1ULL << SC7660_INT1_GPIO), // .mode = GPIO_MODE_INPUT, // .pull_up_en = GPIO_PULLUP_DISABLE, // .pull_down_en = GPIO_PULLDOWN_DISABLE, // .intr_type = GPIO_INTR_POSEDGE, // 上升沿触发 // }; // ESP_ERROR_CHECK(gpio_config(&io_conf)); // // 安装GPIO ISR服务 // ESP_ERROR_CHECK(gpio_install_isr_service(0)); // // 添加ISR处理程序 // ESP_ERROR_CHECK(gpio_isr_handler_add(SC7660_INT1_GPIO, interrupt_handler, this)); // return ESP_OK; // } // static void IRAM_ATTR interrupt_handler(void* arg) { // SC7660Driver* driver = (SC7660Driver*)arg; // uint32_t gpio_num = SC7660_INT1_GPIO; // xQueueSendFromISR(driver->interrupt_queue, &gpio_num, NULL); // } // void handle_interrupts() { // uint32_t io_num; // while (xQueueReceive(interrupt_queue, &io_num, portMAX_DELAY)) { // if (io_num == SC7660_INT1_GPIO) { // // 唤醒设备 // ESP_LOGI(TAG1, "weak up."); // } // } // } // // 任务函数 // static void interrupt_task(void* arg) { // SC7660Driver* driver = (SC7660Driver*)arg; // driver->handle_interrupts(); // } // esp_err_t start_interrupt_handler() { // return xTaskCreate(interrupt_task, "sc7660_int", 2048, this, 5, NULL) == pdPASS ? ESP_OK : ESP_FAIL; // } };