diff --git a/MSOS_ESP/main/CMakeLists.txt b/MSOS_ESP/main/CMakeLists.txt index cf3a33a..408786f 100644 --- a/MSOS_ESP/main/CMakeLists.txt +++ b/MSOS_ESP/main/CMakeLists.txt @@ -1,3 +1,3 @@ -idf_component_register(SRCS "hello_world_main.c" "iic.c" "oled.c" "state.c" +idf_component_register(SRCS "hello_world_main.c" "iic.c" "oled.c" "state.c" "tca9535.c" PRIV_REQUIRES spi_flash esp_driver_i2c log INCLUDE_DIRS ".") diff --git a/MSOS_ESP/main/hello_world_main.c b/MSOS_ESP/main/hello_world_main.c index 5b172b2..7f17933 100644 --- a/MSOS_ESP/main/hello_world_main.c +++ b/MSOS_ESP/main/hello_world_main.c @@ -16,6 +16,7 @@ #include "iic.h" #include "oled.h" #include "state.h" +#include "tca9535.h" void app_main(void) { @@ -48,6 +49,7 @@ void app_main(void) state_init(); iic_init(); + tca9535_init(); oled_init(); while(1){ diff --git a/MSOS_ESP/main/iic.c b/MSOS_ESP/main/iic.c index 36a6a32..100be0e 100644 --- a/MSOS_ESP/main/iic.c +++ b/MSOS_ESP/main/iic.c @@ -53,6 +53,18 @@ esp_err_t iic_send_bytes(unsigned char addr, unsigned char *txd, unsigned int le return i2c_master_transmit(s_iic_dev, (const uint8_t *)txd, (size_t)len, IIC_TIMEOUT_MS); } +esp_err_t iic_read_reg(unsigned char addr, unsigned char reg, unsigned char *rxd, unsigned int len) +{ + if (rxd == NULL || len == 0 || s_iic_dev == NULL) { + return ESP_ERR_INVALID_STATE; + } + esp_err_t ret = i2c_master_device_change_address(s_iic_dev, (uint16_t)addr, IIC_TIMEOUT_MS); + if (ret != ESP_OK) { + return ret; + } + return i2c_master_transmit_receive(s_iic_dev, ®, 1, rxd, len, IIC_TIMEOUT_MS); +} + unsigned char iic_read_byte(unsigned char addr) { uint8_t byte = 0; diff --git a/MSOS_ESP/main/iic.h b/MSOS_ESP/main/iic.h index 3cf6262..581d2e2 100644 --- a/MSOS_ESP/main/iic.h +++ b/MSOS_ESP/main/iic.h @@ -12,6 +12,7 @@ esp_err_t iic_init(void); void iic_scan(void); esp_err_t iic_send_bytes(unsigned char addr, unsigned char *txd, unsigned int len); +esp_err_t iic_read_reg(unsigned char addr, unsigned char reg, unsigned char *rxd, unsigned int len); unsigned char iic_read_byte(unsigned char addr); #endif diff --git a/MSOS_ESP/main/tca9535.c b/MSOS_ESP/main/tca9535.c new file mode 100644 index 0000000..0eceb2b --- /dev/null +++ b/MSOS_ESP/main/tca9535.c @@ -0,0 +1,148 @@ +#include "tca9535.h" +#include "iic.h" +#include "esp_log.h" + +static const char *TAG = "TCA9535"; + +esp_err_t tca9535_read_reg(uint8_t reg, uint8_t *val) +{ + if (val == NULL) { + return ESP_ERR_INVALID_ARG; + } + return iic_read_reg(TCA9535_ADDRESS, reg, val, 1); +} + +esp_err_t tca9535_write_reg(uint8_t reg, uint8_t val) +{ + unsigned char buf[2] = {reg, val}; + return iic_send_bytes(TCA9535_ADDRESS, buf, 2); +} + +esp_err_t tca9535_set_dir(uint16_t dir) +{ + esp_err_t ret = tca9535_write_reg(TCA9535_REG_CONFIG0, (uint8_t)(dir & 0xFF)); + if (ret != ESP_OK) { + return ret; + } + return tca9535_write_reg(TCA9535_REG_CONFIG1, (uint8_t)(dir >> 8)); +} + +esp_err_t tca9535_set_output(uint16_t val) +{ + esp_err_t ret = tca9535_write_reg(TCA9535_REG_OUTPUT0, (uint8_t)(val & 0xFF)); + if (ret != ESP_OK) { + return ret; + } + return tca9535_write_reg(TCA9535_REG_OUTPUT1, (uint8_t)(val >> 8)); +} + +esp_err_t tca9535_get_output(uint16_t *val) +{ + if (val == NULL) { + return ESP_ERR_INVALID_ARG; + } + uint8_t p0 = 0, p1 = 0; + esp_err_t ret = tca9535_read_reg(TCA9535_REG_OUTPUT0, &p0); + if (ret != ESP_OK) { + return ret; + } + ret = tca9535_read_reg(TCA9535_REG_OUTPUT1, &p1); + if (ret != ESP_OK) { + return ret; + } + *val = (uint16_t)p0 | ((uint16_t)p1 << 8); + return ESP_OK; +} + +esp_err_t tca9535_get_input(uint16_t *val) +{ + if (val == NULL) { + return ESP_ERR_INVALID_ARG; + } + uint8_t p0 = 0, p1 = 0; + esp_err_t ret = tca9535_read_reg(TCA9535_REG_INPUT0, &p0); + if (ret != ESP_OK) { + return ret; + } + ret = tca9535_read_reg(TCA9535_REG_INPUT1, &p1); + if (ret != ESP_OK) { + return ret; + } + *val = (uint16_t)p0 | ((uint16_t)p1 << 8); + return ESP_OK; +} + +esp_err_t tca9535_pin_mode(uint8_t pin, uint8_t mode) +{ + if (pin >= TCA9535_PIN_COUNT) { + return ESP_ERR_INVALID_ARG; + } + uint8_t reg = (pin < 8) ? TCA9535_REG_CONFIG0 : TCA9535_REG_CONFIG1; + uint8_t bit = pin & 0x07; + uint8_t cur = 0; + esp_err_t ret = tca9535_read_reg(reg, &cur); + if (ret != ESP_OK) { + return ret; + } + if (mode == TCA9535_INPUT) { + cur |= (1 << bit); + } else { + cur &= ~(1 << bit); + } + return tca9535_write_reg(reg, cur); +} + +esp_err_t tca9535_digital_write(uint8_t pin, uint8_t val) +{ + if (pin >= TCA9535_PIN_COUNT) { + return ESP_ERR_INVALID_ARG; + } + uint8_t reg = (pin < 8) ? TCA9535_REG_OUTPUT0 : TCA9535_REG_OUTPUT1; + uint8_t bit = pin & 0x07; + uint8_t cur = 0; + esp_err_t ret = tca9535_read_reg(reg, &cur); + if (ret != ESP_OK) { + return ret; + } + if (val) { + cur |= (1 << bit); + } else { + cur &= ~(1 << bit); + } + return tca9535_write_reg(reg, cur); +} + +esp_err_t tca9535_digital_read(uint8_t pin, uint8_t *val) +{ + if (pin >= TCA9535_PIN_COUNT || val == NULL) { + return ESP_ERR_INVALID_ARG; + } + uint8_t reg = (pin < 8) ? TCA9535_REG_INPUT0 : TCA9535_REG_INPUT1; + uint8_t bit = pin & 0x07; + uint8_t cur = 0; + esp_err_t ret = tca9535_read_reg(reg, &cur); + if (ret != ESP_OK) { + return ret; + } + *val = (cur >> bit) & 0x01; + return ESP_OK; +} + +esp_err_t tca9535_init(void) +{ + esp_err_t ret = tca9535_write_reg(TCA9535_REG_POLARITY0, 0x00); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "TCA9535初始化失败"); + return ret; + } + tca9535_write_reg(TCA9535_REG_POLARITY1, 0x00); + tca9535_write_reg(TCA9535_REG_OUTPUT0, 0x00); + tca9535_write_reg(TCA9535_REG_OUTPUT1, 0x00); + ret = tca9535_set_dir(0xFFFF); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "TCA9535初始化失败"); + return ret; + } + ESP_LOGI(TAG, "TCA9535初始化成功, 地址0x%02X", TCA9535_ADDRESS); + return ESP_OK; +} diff --git a/MSOS_ESP/main/tca9535.h b/MSOS_ESP/main/tca9535.h new file mode 100644 index 0000000..061c007 --- /dev/null +++ b/MSOS_ESP/main/tca9535.h @@ -0,0 +1,37 @@ +#ifndef TCA9535_H_ +#define TCA9535_H_ + +#include "esp_err.h" +#include + +#define TCA9535_ADDRESS 0x20 + +#define TCA9535_REG_INPUT0 0x00 +#define TCA9535_REG_INPUT1 0x01 +#define TCA9535_REG_OUTPUT0 0x02 +#define TCA9535_REG_OUTPUT1 0x03 +#define TCA9535_REG_POLARITY0 0x04 +#define TCA9535_REG_POLARITY1 0x05 +#define TCA9535_REG_CONFIG0 0x06 +#define TCA9535_REG_CONFIG1 0x07 + +#define TCA9535_INPUT 1 +#define TCA9535_OUTPUT 0 + +#define TCA9535_PIN_COUNT 16 + +esp_err_t tca9535_init(void); + +esp_err_t tca9535_read_reg(uint8_t reg, uint8_t *val); +esp_err_t tca9535_write_reg(uint8_t reg, uint8_t val); + +esp_err_t tca9535_set_dir(uint16_t dir); +esp_err_t tca9535_set_output(uint16_t val); +esp_err_t tca9535_get_output(uint16_t *val); +esp_err_t tca9535_get_input(uint16_t *val); + +esp_err_t tca9535_pin_mode(uint8_t pin, uint8_t mode); +esp_err_t tca9535_digital_write(uint8_t pin, uint8_t val); +esp_err_t tca9535_digital_read(uint8_t pin, uint8_t *val); + +#endif