705 lines
17 KiB
C
705 lines
17 KiB
C
#include "main.h"
|
||
#include "TCA6416.h"
|
||
#include "stm32f4xx_hal.h" // 更新HAL库头文件路径
|
||
|
||
/**
|
||
* @brief 初始化TCA6416的GPIO
|
||
*/
|
||
//第一条IIC总线初始化
|
||
void TCA6416_GPIO_Init(void)
|
||
{
|
||
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||
|
||
// 使能GPIOE时钟
|
||
__HAL_RCC_GPIOE_CLK_ENABLE();
|
||
|
||
//两个芯片挂一条总线上SDA PE3 SCL PE2
|
||
GPIO_InitStruct.Pin = TCA6416_SCL_PIN | TCA6416_SDA_PIN;
|
||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; // 开漏输出
|
||
GPIO_InitStruct.Pull = GPIO_NOPULL; // 无内部上拉,依赖外部上拉
|
||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||
HAL_GPIO_Init(TCA6416_SDA_PORT, &GPIO_InitStruct);
|
||
|
||
// 初始状态设为高电平(实际由外部上拉电阻拉高)
|
||
SCL_HIGH();
|
||
SDA_HIGH();
|
||
|
||
}
|
||
//第二条IIC总线初始化
|
||
void TCA6416_GPIO_Init2(void)
|
||
{
|
||
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||
|
||
// 使能GPIOE时钟
|
||
__HAL_RCC_GPIOE_CLK_ENABLE();
|
||
|
||
//两个芯片挂一条总线上SDA PE4 SCL PE5
|
||
GPIO_InitStruct.Pin = TCA6416_SCL_PIN2 | TCA6416_SDA_PIN2;
|
||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; // 开漏输出
|
||
GPIO_InitStruct.Pull = GPIO_NOPULL; // 无内部上拉,依赖外部上拉
|
||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||
HAL_GPIO_Init(TCA6416_SDA_PORT2, &GPIO_InitStruct);
|
||
|
||
// 初始状态设为高电平(实际由外部上拉电阻拉高)
|
||
SCL_HIGH2();
|
||
SDA_HIGH2();
|
||
}
|
||
void U74HC245_GPIO_Init(void)
|
||
{
|
||
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||
|
||
// 使能GPIOE时钟
|
||
__HAL_RCC_GPIOD_CLK_ENABLE();
|
||
//74HC245 DIR端口设置
|
||
GPIO_InitStruct.Pin = GPIO_PIN_4 | GPIO_PIN_7;
|
||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 开漏输出
|
||
GPIO_InitStruct.Pull = GPIO_PULLDOWN; // 下拉
|
||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
|
||
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_4 | GPIO_PIN_7, GPIO_PIN_RESET);
|
||
|
||
}
|
||
|
||
/**
|
||
* @brief 软件I2C起始信号
|
||
*/
|
||
void I2C_Start(void)
|
||
{
|
||
SDA_OUTPUT_MODE(); // 确保SDA为输出模式
|
||
SDA_HIGH();
|
||
SCL_HIGH();
|
||
I2C_DELAY();
|
||
SDA_LOW(); // SDA下降沿(SCL为高)
|
||
I2C_DELAY();
|
||
SCL_LOW(); // 拉低SCL
|
||
}
|
||
|
||
/**
|
||
* @brief 软件I2C停止信号
|
||
*/
|
||
void I2C_Stop(void)
|
||
{
|
||
SDA_OUTPUT_MODE(); // 确保SDA为输出模式
|
||
SCL_LOW();
|
||
SDA_LOW();
|
||
I2C_DELAY();
|
||
SCL_HIGH();
|
||
I2C_DELAY();
|
||
SDA_HIGH(); // SDA上升沿(SCL为高)
|
||
I2C_DELAY();
|
||
}
|
||
|
||
/**
|
||
* @brief 软件I2C发送应答
|
||
*/
|
||
void I2C_Ack(void)
|
||
{
|
||
SCL_LOW();
|
||
SDA_LOW();
|
||
I2C_DELAY();
|
||
SCL_HIGH();
|
||
I2C_DELAY();
|
||
SCL_LOW();
|
||
}
|
||
|
||
/**
|
||
* @brief 软件I2C发送非应答
|
||
*/
|
||
void I2C_NAck(void)
|
||
{
|
||
SCL_LOW();
|
||
SDA_HIGH();
|
||
I2C_DELAY();
|
||
SCL_HIGH();
|
||
I2C_DELAY();
|
||
SCL_LOW();
|
||
}
|
||
|
||
/**
|
||
* @brief 软件I2C等待应答
|
||
* @retval 0:有应答 1:无应答
|
||
*/
|
||
uint8_t I2C_WaitAck(void)
|
||
{
|
||
uint8_t ack;
|
||
|
||
SCL_LOW();
|
||
SDA_HIGH();
|
||
SDA_INPUT_MODE();
|
||
I2C_DELAY();
|
||
SCL_HIGH();
|
||
I2C_DELAY();
|
||
|
||
ack = SDA_READ() ? 1 : 0;
|
||
|
||
SCL_LOW();
|
||
SDA_OUTPUT_MODE();
|
||
return ack;
|
||
}
|
||
|
||
/**
|
||
* @brief 软件I2C发送一个字节
|
||
* @param byte: 要发送的字节
|
||
*/
|
||
uint8_t I2C_SendByte(uint8_t byte)
|
||
{
|
||
uint8_t i;
|
||
for(i = 0; i < 8; i++)
|
||
{
|
||
SCL_LOW();
|
||
I2C_DELAY();
|
||
if(byte & 0x80)
|
||
SDA_HIGH();
|
||
else
|
||
SDA_LOW();
|
||
byte <<= 1;
|
||
I2C_DELAY();
|
||
SCL_HIGH();
|
||
I2C_DELAY();
|
||
}
|
||
SCL_LOW();
|
||
// 释放SDA,准备接收ACK
|
||
SDA_HIGH();
|
||
SDA_INPUT_MODE();
|
||
I2C_DELAY();
|
||
SCL_HIGH();
|
||
I2C_DELAY();
|
||
uint8_t ack = SDA_READ() ? 1 : 0; // 0=ACK, 1=NACK
|
||
SCL_LOW();
|
||
SDA_OUTPUT_MODE();
|
||
return ack;
|
||
}
|
||
|
||
/**
|
||
* @brief 软件I2C读取一个字节
|
||
* @retval 读取到的字节
|
||
*/
|
||
uint8_t I2C_ReadByte(void)
|
||
{
|
||
uint8_t i, byte = 0;
|
||
|
||
SDA_HIGH();
|
||
for(i = 0; i < 8; i++)
|
||
{
|
||
SCL_LOW();
|
||
I2C_DELAY();
|
||
SCL_HIGH();
|
||
byte <<= 1;
|
||
if(SDA_READ())
|
||
byte |= 0x01;
|
||
I2C_DELAY();
|
||
}
|
||
SCL_LOW();
|
||
return byte;
|
||
}
|
||
|
||
/**
|
||
* @brief 初始化TCA6416
|
||
* @retval 0:成功 1:失败
|
||
*/
|
||
uint8_t TCA6416_Init(void)
|
||
{
|
||
// 初始化GPIO
|
||
TCA6416_GPIO_Init();
|
||
HAL_Delay(50);
|
||
|
||
// 默认将所有引脚设置为输入
|
||
if(TCA6416_SetPortDirection(0, 0xFF) != 0) return 1;
|
||
if(TCA6416_SetPortDirection(1, 0xFF) != 0) return 1;
|
||
|
||
// 设置默认输出值为0
|
||
if(TCA6416_WritePort(0, 0x00) != 0) return 1;
|
||
if(TCA6416_WritePort(1, 0x00) != 0) return 1;
|
||
|
||
// 设置默认极性(非反转)
|
||
if(TCA6416_SetPortPolarity(0, 0x00) != 0) return 1;
|
||
if(TCA6416_SetPortPolarity(1, 0x00) != 0) return 1;
|
||
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* @brief 向端口写入数据
|
||
* @param port: 端口号(0或1)
|
||
* @param data: 要写入的数据
|
||
* @retval 0:成功 1:失败
|
||
*/
|
||
uint8_t TCA6416_WritePort(uint8_t port, uint8_t data)
|
||
{
|
||
uint8_t reg_addr = (port == 0) ? TCA6416_OUTPUT_PORT0 : TCA6416_OUTPUT_PORT1;
|
||
|
||
I2C_Start();
|
||
if(I2C_SendByte(TCA6416_ADDR << 1)) { I2C_Stop(); return 1; } // 直接使用返回值
|
||
|
||
if(I2C_SendByte(reg_addr)) { I2C_Stop(); return 1; } // 直接使用返回值
|
||
|
||
if(I2C_SendByte(data)) { I2C_Stop(); return 1; } // 直接使用返回值
|
||
|
||
I2C_Stop();
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* @brief 从端口读取数据
|
||
* @param port: 端口号(0或1)
|
||
* @param data: 存储读取数据的指针
|
||
* @retval 0:成功 1:失败
|
||
*/
|
||
uint8_t TCA6416_ReadPort(uint8_t port, uint8_t *data)
|
||
{
|
||
uint8_t reg_addr = (port == 0) ? TCA6416_INPUT_PORT0 : TCA6416_INPUT_PORT1;
|
||
|
||
I2C_Start();
|
||
if(I2C_SendByte(TCA6416_ADDR << 1)) { I2C_Stop(); return 1; } // 直接使用返回值
|
||
|
||
if(I2C_SendByte(reg_addr)) { I2C_Stop(); return 1; } // 直接使用返回值
|
||
|
||
I2C_Start();
|
||
if(I2C_SendByte((TCA6416_ADDR << 1) | 0x01)) { I2C_Stop(); return 1; } // 直接使用返回值
|
||
|
||
*data = I2C_ReadByte(); // 读取数据
|
||
I2C_NAck();
|
||
|
||
I2C_Stop();
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* @brief 设置端口方向(输入/输出)
|
||
* @param port: 端口号(0或1)
|
||
* @param direction: 0 = 输出, 1 = 输入
|
||
* @retval 0:成功 1:失败
|
||
*/
|
||
uint8_t TCA6416_SetPortDirection(uint8_t port, uint8_t direction)
|
||
{
|
||
uint8_t reg_addr = (port == 0) ? TCA6416_CONFIG_PORT0 : TCA6416_CONFIG_PORT1;
|
||
|
||
I2C_Start();
|
||
if(I2C_SendByte(TCA6416_ADDR << 1)) { I2C_Stop(); return 1; } // 直接使用返回值
|
||
|
||
if(I2C_SendByte(reg_addr)) { I2C_Stop(); return 1; } // 直接使用返回值
|
||
|
||
if(I2C_SendByte(direction)) { I2C_Stop(); return 1; } // 直接使用返回值
|
||
|
||
I2C_Stop();
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* @brief 设置端口极性
|
||
* @param port: 端口号(0或1)
|
||
* @param polarity: 0 = 非反转, 1 = 反转
|
||
* @retval 0:成功 1:失败
|
||
*/
|
||
uint8_t TCA6416_SetPortPolarity(uint8_t port, uint8_t polarity)
|
||
{
|
||
uint8_t reg_addr = (port == 0) ? TCA6416_POL_INV_PORT0 : TCA6416_POL_INV_PORT1;
|
||
|
||
I2C_Start();
|
||
if(I2C_SendByte(TCA6416_ADDR << 1)) { I2C_Stop(); return 1; } // 直接使用返回值
|
||
|
||
if(I2C_SendByte(reg_addr)) { I2C_Stop(); return 1; } // 直接使用返回值
|
||
|
||
if(I2C_SendByte(polarity)) { I2C_Stop(); return 1; } // 直接使用返回值
|
||
|
||
I2C_Stop();
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* @brief 写入单个引脚
|
||
* @param port: 端口号(0或1)
|
||
* @param pin: 引脚号(0-7)
|
||
* @param state: 引脚状态(0或1)
|
||
* @retval 0:成功 1:失败
|
||
*/
|
||
uint8_t TCA6416_WritePin(uint8_t port, uint8_t pin, uint8_t state)
|
||
{
|
||
uint8_t current_data;
|
||
uint8_t reg_addr = (port == 0) ? TCA6416_OUTPUT_PORT0 : TCA6416_OUTPUT_PORT1;
|
||
|
||
// 读取当前端口值
|
||
if(TCA6416_ReadPort(port, ¤t_data) != 0) return 1;
|
||
|
||
// 修改特定引脚
|
||
if(state)
|
||
current_data |= (1 << pin);
|
||
else
|
||
current_data &= ~(1 << pin);
|
||
|
||
// 写回修改后的值
|
||
return TCA6416_WritePort(port, current_data);
|
||
}
|
||
|
||
/**
|
||
* @brief 读取单个引脚
|
||
* @param port: 端口号(0或1)
|
||
* @param pin: 引脚号(0-7)
|
||
* @param state: 存储引脚状态的指针
|
||
* @retval 0:成功 1:失败
|
||
*/
|
||
uint8_t TCA6416_ReadPin(uint8_t port, uint8_t pin, uint8_t *state)
|
||
{
|
||
uint8_t port_data;
|
||
|
||
if(TCA6416_ReadPort(port, &port_data) != 0) return 1;
|
||
|
||
*state = (port_data >> pin) & 0x01;
|
||
return 0;
|
||
}
|
||
|
||
/* 第二个芯片的I2C操作函数 */
|
||
void I2C_Start2(void)
|
||
{
|
||
SDA_HIGH2();
|
||
SCL_HIGH2();
|
||
I2C_DELAY();
|
||
SDA_LOW2();
|
||
I2C_DELAY();
|
||
SCL_LOW2();
|
||
}
|
||
|
||
void I2C_Stop2(void)
|
||
{
|
||
SCL_LOW2();
|
||
SDA_LOW2();
|
||
I2C_DELAY();
|
||
SCL_HIGH2();
|
||
I2C_DELAY();
|
||
SDA_HIGH2();
|
||
I2C_DELAY();
|
||
}
|
||
|
||
void I2C_Ack2(void)
|
||
{
|
||
SCL_LOW2();
|
||
SDA_LOW2();
|
||
I2C_DELAY();
|
||
SCL_HIGH2();
|
||
I2C_DELAY();
|
||
SCL_LOW2();
|
||
}
|
||
|
||
void I2C_NAck2(void)
|
||
{
|
||
SCL_LOW2();
|
||
SDA_HIGH2();
|
||
I2C_DELAY();
|
||
SCL_HIGH2();
|
||
I2C_DELAY();
|
||
SCL_LOW2();
|
||
}
|
||
|
||
uint8_t I2C_WaitAck2(void)
|
||
{
|
||
uint8_t ack;
|
||
|
||
SCL_LOW2();
|
||
SDA_HIGH2();
|
||
I2C_DELAY();
|
||
SCL_HIGH2();
|
||
I2C_DELAY();
|
||
|
||
ack = SDA_READ2() ? 1 : 0;
|
||
|
||
SCL_LOW2();
|
||
return ack;
|
||
}
|
||
|
||
void I2C_SendByte2(uint8_t byte)
|
||
{
|
||
uint8_t i;
|
||
|
||
for(i = 0; i < 8; i++)
|
||
{
|
||
SCL_LOW2();
|
||
if(byte & 0x80)
|
||
SDA_HIGH2();
|
||
else
|
||
SDA_LOW2();
|
||
byte <<= 1;
|
||
I2C_DELAY();
|
||
SCL_HIGH2();
|
||
I2C_DELAY();
|
||
}
|
||
SCL_LOW2();
|
||
}
|
||
|
||
uint8_t I2C_ReadByte2(void)
|
||
{
|
||
uint8_t i, byte = 0;
|
||
|
||
SDA_HIGH2();
|
||
for(i = 0; i < 8; i++)
|
||
{
|
||
SCL_LOW2();
|
||
I2C_DELAY();
|
||
SCL_HIGH2();
|
||
byte <<= 1;
|
||
if(SDA_READ2())
|
||
byte |= 0x01;
|
||
I2C_DELAY();
|
||
}
|
||
SCL_LOW2();
|
||
return byte;
|
||
}
|
||
|
||
/**
|
||
* @brief 初始化第二个TCA6416
|
||
* @retval 0:成功 1:失败
|
||
*/
|
||
uint8_t TCA6416_Init2(void)
|
||
{
|
||
// 初始化GPIO
|
||
TCA6416_GPIO_Init2();
|
||
|
||
// 增加延时以确保设备稳定
|
||
HAL_Delay(10);
|
||
|
||
// 默认将所有引脚设置为输入
|
||
if(TCA6416_SetPortDirection2(0, 0xFF) != 0) return 1;
|
||
if(TCA6416_SetPortDirection2(1, 0xFF) != 0) return 1;
|
||
|
||
// 设置默认输出值为0
|
||
if(TCA6416_WritePort2(0, 0x00) != 0) return 1;
|
||
if(TCA6416_WritePort2(1, 0x00) != 0) return 1;
|
||
|
||
// 设置默认极性(非反转)
|
||
if(TCA6416_SetPortPolarity2(0, 0x00) != 0) return 1;
|
||
if(TCA6416_SetPortPolarity2(1, 0x00) != 0) return 1;
|
||
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* @brief 向第二个TCA6416的端口写入数据
|
||
* @param port: 端口号(0或1)
|
||
* @param data: 要写入的数据
|
||
* @retval 0:成功 1:失败
|
||
*/
|
||
uint8_t TCA6416_WritePort2(uint8_t port, uint8_t data)
|
||
{
|
||
uint8_t reg_addr = (port == 0) ? TCA6416_OUTPUT_PORT0 : TCA6416_OUTPUT_PORT1;
|
||
|
||
I2C_Start2();
|
||
I2C_SendByte2(TCA6416_ADDR2 << 1); // 写地址
|
||
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||
|
||
I2C_SendByte2(reg_addr); // 寄存器地址
|
||
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||
|
||
I2C_SendByte2(data); // 数据
|
||
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||
|
||
I2C_Stop2();
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* @brief 从第二个TCA6416的端口读取数据
|
||
* @param port: 端口号(0或1)
|
||
* @param data: 存储读取数据的指针
|
||
* @retval 0:成功 1:失败
|
||
*/
|
||
uint8_t TCA6416_ReadPort2(uint8_t port, uint8_t *data)
|
||
{
|
||
uint8_t reg_addr = (port == 0) ? TCA6416_INPUT_PORT0 : TCA6416_INPUT_PORT1;
|
||
|
||
I2C_Start2();
|
||
I2C_SendByte2(TCA6416_ADDR2 << 1); // 写地址
|
||
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||
|
||
I2C_SendByte2(reg_addr); // 寄存器地址
|
||
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||
|
||
I2C_Start2();
|
||
I2C_SendByte2((TCA6416_ADDR2 << 1) | 0x01); // 读地址
|
||
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||
|
||
*data = I2C_ReadByte2(); // 读取数据
|
||
I2C_NAck2();
|
||
|
||
I2C_Stop2();
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* @brief 设置第二个TCA6416的端口方向
|
||
* @param port: 端口号(0或1)
|
||
* @param direction: 0 = 输出, 1 = 输入
|
||
* @retval 0:成功 1:失败
|
||
*/
|
||
uint8_t TCA6416_SetPortDirection2(uint8_t port, uint8_t direction)
|
||
{
|
||
uint8_t reg_addr = (port == 0) ? TCA6416_CONFIG_PORT0 : TCA6416_CONFIG_PORT1;
|
||
|
||
I2C_Start2();
|
||
I2C_SendByte2(TCA6416_ADDR2 << 1); // 写地址
|
||
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||
|
||
I2C_SendByte2(reg_addr); // 寄存器地址
|
||
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||
|
||
I2C_SendByte2(direction); // 方向设置
|
||
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||
|
||
I2C_Stop2();
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* @brief 设置第二个TCA6416的端口极性
|
||
* @param port: 端口号(0或1)
|
||
* @param polarity: 0 = 非反转, 1 = 反转
|
||
* @retval 0:成功 1:失败
|
||
*/
|
||
uint8_t TCA6416_SetPortPolarity2(uint8_t port, uint8_t polarity)
|
||
{
|
||
uint8_t reg_addr = (port == 0) ? TCA6416_POL_INV_PORT0 : TCA6416_POL_INV_PORT1;
|
||
|
||
I2C_Start2();
|
||
I2C_SendByte2(TCA6416_ADDR2 << 1); // 写地址
|
||
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||
|
||
I2C_SendByte2(reg_addr); // 寄存器地址
|
||
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||
|
||
I2C_SendByte2(polarity); // 极性设置
|
||
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||
|
||
I2C_Stop2();
|
||
return 0;
|
||
}
|
||
|
||
/* 第三个芯片的操作函数(使用第二个芯片的I2C总线,但地址为TCA6416_ADDR3) */
|
||
|
||
/**
|
||
* @brief 初始化第三个TCA6416
|
||
* @retval 0:成功 1:失败
|
||
*/
|
||
uint8_t TCA6416_Init3(void)
|
||
{
|
||
// GPIO已在TCA6416_GPIO_Init()中初始化
|
||
U74HC245_GPIO_Init();
|
||
// 增加延时以确保设备稳定
|
||
HAL_Delay(10);
|
||
|
||
// 设置默认极性(非反转)
|
||
if(TCA6416_SetPortPolarity3(0, 0x00) != 0) return 1;
|
||
if(TCA6416_SetPortPolarity3(1, 0x00) != 0) return 1;
|
||
|
||
// 默认将所有引脚设置为输入
|
||
if(TCA6416_SetPortDirection3(0, 0xFF) != 0) return 1;
|
||
if(TCA6416_SetPortDirection3(1, 0xFF) != 0) return 1;
|
||
|
||
// 设置默认输出值为0
|
||
if(TCA6416_WritePort3(0, 0x00) != 0) return 1;
|
||
if(TCA6416_WritePort3(1, 0x00) != 0) return 1;
|
||
|
||
|
||
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* @brief 向第三个TCA6416的端口写入数据
|
||
* @param port: 端口号(0或1)
|
||
* @param data: 要写入的数据
|
||
* @retval 0:成功 1:失败
|
||
*/
|
||
uint8_t TCA6416_WritePort3(uint8_t port, uint8_t data)
|
||
{
|
||
uint8_t reg_addr = (port == 0) ? TCA6416_OUTPUT_PORT0 : TCA6416_OUTPUT_PORT1;
|
||
|
||
I2C_Start2();
|
||
I2C_SendByte2(TCA6416_ADDR3 << 1); // 写地址
|
||
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||
|
||
I2C_SendByte2(reg_addr); // 寄存器地址
|
||
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||
|
||
I2C_SendByte2(data); // 数据
|
||
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||
|
||
I2C_Stop2();
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* @brief 从第三个TCA6416的端口读取数据
|
||
* @param port: 端口号(0或1)
|
||
* @param data: 存储读取数据的指针
|
||
* @retval 0:成功 1:失败
|
||
*/
|
||
uint8_t TCA6416_ReadPort3(uint8_t port, uint8_t *data)
|
||
{
|
||
uint8_t reg_addr = (port == 0) ? TCA6416_INPUT_PORT0 : TCA6416_INPUT_PORT1;
|
||
|
||
I2C_Start2();
|
||
I2C_SendByte2(TCA6416_ADDR3 << 1); // 写地址
|
||
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||
|
||
I2C_SendByte2(reg_addr); // 寄存器地址
|
||
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||
|
||
I2C_Start2();
|
||
I2C_SendByte2((TCA6416_ADDR3 << 1) | 0x01); // 读地址
|
||
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||
|
||
*data = I2C_ReadByte2(); // 读取数据
|
||
I2C_NAck2();
|
||
|
||
I2C_Stop2();
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* @brief 设置第三个TCA6416的端口方向
|
||
* @param port: 端口号(0或1)
|
||
* @param direction: 0 = 输出, 1 = 输入
|
||
* @retval 0:成功 1:失败
|
||
*/
|
||
uint8_t TCA6416_SetPortDirection3(uint8_t port, uint8_t direction)
|
||
{
|
||
uint8_t reg_addr = (port == 0) ? TCA6416_CONFIG_PORT0 : TCA6416_CONFIG_PORT1;
|
||
|
||
I2C_Start2();
|
||
I2C_SendByte2(TCA6416_ADDR3 << 1); // 写地址
|
||
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||
|
||
I2C_SendByte2(reg_addr); // 寄存器地址
|
||
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||
|
||
I2C_SendByte2(direction); // 方向设置
|
||
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||
|
||
I2C_Stop2();
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* @brief 设置第三个TCA6416的端口极性
|
||
* @param port: 端口号(0或1)
|
||
* @param polarity: 0 = 非反转, 1 = 反转
|
||
* @retval 0:成功 1:失败
|
||
*/
|
||
uint8_t TCA6416_SetPortPolarity3(uint8_t port, uint8_t polarity)
|
||
{
|
||
uint8_t reg_addr = (port == 0) ? TCA6416_POL_INV_PORT0 : TCA6416_POL_INV_PORT1;
|
||
|
||
I2C_Start2();
|
||
I2C_SendByte2(TCA6416_ADDR3 << 1); // 写地址
|
||
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||
|
||
I2C_SendByte2(reg_addr); // 寄存器地址
|
||
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||
|
||
I2C_SendByte2(polarity); // 极性设置
|
||
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||
|
||
I2C_Stop2();
|
||
return 0;
|
||
}
|
||
|
||
|