diff --git a/User/application/inc/TCA6416.h b/User/application/inc/TCA6416.h new file mode 100644 index 0000000..42eaf3f --- /dev/null +++ b/User/application/inc/TCA6416.h @@ -0,0 +1,28 @@ +#ifndef __TCA6416_H +#define __TCA6416_H + +#include "stm32f1xx_hal.h" + +/* TCA6416 I2C地址 */ +#define TCA6416_ADDR 0x20 // 基础地址 (A0=A1=A2=GND) + +/* 寄存器地址定义 */ +#define TCA6416_INPUT_PORT0 0x00 // 输入端口0 +#define TCA6416_INPUT_PORT1 0x01 // 输入端口1 +#define TCA6416_OUTPUT_PORT0 0x02 // 输出端口0 +#define TCA6416_OUTPUT_PORT1 0x03 // 输出端口1 +#define TCA6416_CONFIG_PORT0 0x06 // 配置端口0 +#define TCA6416_CONFIG_PORT1 0x07 // 配置端口1 +#define TCA6416_POL_INV_PORT0 0x04 // 极性反转端口0 +#define TCA6416_POL_INV_PORT1 0x05 // 极性反转端口1 + +/* 函数声明 */ +HAL_StatusTypeDef TCA6416_Init(I2C_HandleTypeDef *hi2c); +HAL_StatusTypeDef TCA6416_WritePort(I2C_HandleTypeDef *hi2c, uint8_t port, uint8_t data); +HAL_StatusTypeDef TCA6416_ReadPort(I2C_HandleTypeDef *hi2c, uint8_t port, uint8_t *data); +HAL_StatusTypeDef TCA6416_SetPortDirection(I2C_HandleTypeDef *hi2c, uint8_t port, uint8_t direction); +HAL_StatusTypeDef TCA6416_SetPortPolarity(I2C_HandleTypeDef *hi2c, uint8_t port, uint8_t polarity); +HAL_StatusTypeDef TCA6416_WritePin(I2C_HandleTypeDef *hi2c, uint8_t port, uint8_t pin, uint8_t state); +HAL_StatusTypeDef TCA6416_ReadPin(I2C_HandleTypeDef *hi2c, uint8_t port, uint8_t pin, uint8_t *state); + +#endif /* __TCA6416_H */ diff --git a/User/application/src/TCA6416.c b/User/application/src/TCA6416.c new file mode 100644 index 0000000..dacfa3a --- /dev/null +++ b/User/application/src/TCA6416.c @@ -0,0 +1,133 @@ +#include "TCA6416.h" + +/** + * @brief 初始化TCA6416 + * @param hi2c: I2C句柄指针 + * @retval HAL状态 + */ +HAL_StatusTypeDef TCA6416_Init(I2C_HandleTypeDef *hi2c) +{ + HAL_StatusTypeDef status; + + // 默认将所有引脚设置为输入 + status = TCA6416_SetPortDirection(hi2c, 0, 0xFF); + if (status != HAL_OK) return status; + + status = TCA6416_SetPortDirection(hi2c, 1, 0xFF); + if (status != HAL_OK) return status; + + // 设置默认输出值为0 + status = TCA6416_WritePort(hi2c, 0, 0x00); + if (status != HAL_OK) return status; + + status = TCA6416_WritePort(hi2c, 1, 0x00); + if (status != HAL_OK) return status; + + // 设置默认极性(非反转) + status = TCA6416_SetPortPolarity(hi2c, 0, 0x00); + if (status != HAL_OK) return status; + + status = TCA6416_SetPortPolarity(hi2c, 1, 0x00); + + return status; +} + +/** + * @brief 向端口写入数据 + * @param hi2c: I2C句柄指针 + * @param port: 端口号(0或1) + * @param data: 要写入的数据 + * @retval HAL状态 + */ +HAL_StatusTypeDef TCA6416_WritePort(I2C_HandleTypeDef *hi2c, uint8_t port, uint8_t data) +{ + uint8_t reg_addr = (port == 0) ? TCA6416_OUTPUT_PORT0 : TCA6416_OUTPUT_PORT1; + return HAL_I2C_Mem_Write(hi2c, TCA6416_ADDR << 1, reg_addr, I2C_MEMADD_SIZE_8BIT, &data, 1, HAL_MAX_DELAY); +} + +/** + * @brief 从端口读取数据 + * @param hi2c: I2C句柄指针 + * @param port: 端口号(0或1) + * @param data: 存储读取数据的指针 + * @retval HAL状态 + */ +HAL_StatusTypeDef TCA6416_ReadPort(I2C_HandleTypeDef *hi2c, uint8_t port, uint8_t *data) +{ + uint8_t reg_addr = (port == 0) ? TCA6416_INPUT_PORT0 : TCA6416_INPUT_PORT1; + return HAL_I2C_Mem_Read(hi2c, TCA6416_ADDR << 1, reg_addr, I2C_MEMADD_SIZE_8BIT, data, 1, HAL_MAX_DELAY); +} + +/** + * @brief 设置端口方向(输入/输出) + * @param hi2c: I2C句柄指针 + * @param port: 端口号(0或1) + * @param direction: 0 = 输出, 1 = 输入 + * @retval HAL状态 + */ +HAL_StatusTypeDef TCA6416_SetPortDirection(I2C_HandleTypeDef *hi2c, uint8_t port, uint8_t direction) +{ + uint8_t reg_addr = (port == 0) ? TCA6416_CONFIG_PORT0 : TCA6416_CONFIG_PORT1; + return HAL_I2C_Mem_Write(hi2c, TCA6416_ADDR << 1, reg_addr, I2C_MEMADD_SIZE_8BIT, &direction, 1, HAL_MAX_DELAY); +} + +/** + * @brief 设置端口极性 + * @param hi2c: I2C句柄指针 + * @param port: 端口号(0或1) + * @param polarity: 0 = 非反转, 1 = 反转 + * @retval HAL状态 + */ +HAL_StatusTypeDef TCA6416_SetPortPolarity(I2C_HandleTypeDef *hi2c, uint8_t port, uint8_t polarity) +{ + uint8_t reg_addr = (port == 0) ? TCA6416_POL_INV_PORT0 : TCA6416_POL_INV_PORT1; + return HAL_I2C_Mem_Write(hi2c, TCA6416_ADDR << 1, reg_addr, I2C_MEMADD_SIZE_8BIT, &polarity, 1, HAL_MAX_DELAY); +} + +/** + * @brief 写入单个引脚 + * @param hi2c: I2C句柄指针 + * @param port: 端口号(0或1) + * @param pin: 引脚号(0-7) + * @param state: 引脚状态(0或1) + * @retval HAL状态 + */ +HAL_StatusTypeDef TCA6416_WritePin(I2C_HandleTypeDef *hi2c, uint8_t port, uint8_t pin, uint8_t state) +{ + HAL_StatusTypeDef status; + uint8_t current_data; + uint8_t reg_addr = (port == 0) ? TCA6416_OUTPUT_PORT0 : TCA6416_OUTPUT_PORT1; + + // 读取当前端口值 + status = HAL_I2C_Mem_Read(hi2c, TCA6416_ADDR << 1, reg_addr, I2C_MEMADD_SIZE_8BIT, ¤t_data, 1, HAL_MAX_DELAY); + if (status != HAL_OK) return status; + + // 修改特定引脚 + if (state) + current_data |= (1 << pin); + else + current_data &= ~(1 << pin); + + // 写回修改后的值 + return HAL_I2C_Mem_Write(hi2c, TCA6416_ADDR << 1, reg_addr, I2C_MEMADD_SIZE_8BIT, ¤t_data, 1, HAL_MAX_DELAY); +} + +/** + * @brief 读取单个引脚 + * @param hi2c: I2C句柄指针 + * @param port: 端口号(0或1) + * @param pin: 引脚号(0-7) + * @param state: 存储引脚状态的指针 + * @retval HAL状态 + */ +HAL_StatusTypeDef TCA6416_ReadPin(I2C_HandleTypeDef *hi2c, uint8_t port, uint8_t pin, uint8_t *state) +{ + HAL_StatusTypeDef status; + uint8_t port_data; + + status = TCA6416_ReadPort(hi2c, port, &port_data); + if (status != HAL_OK) return status; + + *state = (port_data >> pin) & 0x01; + return HAL_OK; +}