目录
- 一、TCA9535 I/O 扩展器
- 1、TCA9535 的 I2C 地址
- 2、TCA9535 的读写操作
- 3、TCA9535 的控制寄存器
- 4、输入寄存器 0/1
- 5、输出寄存器 0/1
- 6、极性反转寄存器 0/1
- 7、配置寄存器 0/1
- 二、硬件设计
- 1、接线说明
- 2、硬件参考
- 三、程序设计
- 1、tca9535_softiic.c
- 2、tca9535_softiic.h
- 3、main.c
- 四、功能展示 - 串口显示
一、TCA9535 I/O 扩展器
- TCA9535 由两个 8 位配置(输入或输出可选)、输入端口、输出端口和极性反转(高电平有效或低电平有效运行)寄存器组成。可为两线双向 I2C 总线或(SMBus)协议提供 16 位通用并行输入和输出(I/O)扩展。
- 在上电时,I/O 被配置为输入。系统控制器可通过写入 I/O 配置位将 I/O 启用为输入或输出。
- TCA9535 通常用于控制 LED(用于反馈或状态灯)、控制其他设备的启用或重置信号,甚至读取其他设备或按钮的输出。
- 三个硬件引脚(A0、A1 和 A2)用于编程和改变固定 I2C 地址,并允许最多 8 个设备共享同一个 I2C 总线或 SMBus。
|
|
1、TCA9535 的 I2C 地址
- TCA9535 具有 3 个硬件地址引脚(A0、A1 和 A2)。用户通过将每个引脚拉至 VCC 或 GND 来选择设备的 I2C 地址,以表示地址中的位值。这样最多可以将 8 个 TCA9535 设备连接到同一总线上而不会发生地址冲突。
- TCA9535 设备通电时 3 个硬件地址引脚上的电压不得改变,以防止由于传输过程中设备地址更改而导致可能的 I2C 故障。
- TCA9535 设备的 3 个硬件地址引脚都必须连接到 VCC 或 GND,不能悬空。
- 目标地址的最后一位定义要执行的操作(读取或写入)。高电平(1)选择读取操作,而低电平(0)选择写入操作。
- 本文所使用模块将 A2、A1、A0 都接到 GND,即 8 位写地址:‘0100’0000’ (0x40);8 位读地址:‘0100’0001’ (0x41)。
|
|
2、TCA9535 的读写操作
- 数据通过写入和读取命令在控制器和 TCA9535 之间交换,这是通过读取或写入目标设备中的寄存器来实现的。
|
|
- 仅当总线空闲时才可以启动数据传输。如果 SDA 和 SCL 线在 STOP 条件后都为高电平,则认为总线处于空闲状态。
- 如果控制器想要向 TCA9535 发送数据:
- 控制器会在总线上发送一个 START 条件,然后发送目标的地址,以及设置为 0 的最后一位(R/W 位),这表示写入;
- 在目标发送确认位后,控制器会发送它希望写入的寄存器的寄存器地址;
- 目标再次确认,让控制器知道它已准备就绪;
- 控制器开始将寄存器数据发送到目标,直到控制器发送了所有必要的数据(有时只有一个字节);
- 最后控制器使用 STOP 条件终止传输。
- 如果控制器想要从 TCA9535 读取数据:
- 控制器会在总线上发送一个 START 条件,然后发送目标的地址,以及设置为 0 的最后一位(R/W 位),这表示写入;
- 在目标发送确认位后,控制器会发送它希望写入的寄存器的寄存器地址;
- 目标再次确认,让控制器知道它已准备就绪;
- 控制器再次发送 START 条件,然后发送 R/W 位设置为 1 的目标地址(表示读取);
- 目标确认读取请求,控制器继续发出时钟脉冲,但释放 SDA 线,以便目标可以传输数据;
- 在每个数据字节结束时,控制器向目标发送 ACK,让目标知道它已准备好接收更多数据;
- 当控制器收到预期的字节数时,它会发送 NACK,向目标发出信号以停止通信并释放总线。
- 控制器随后会发送 STOP 条件。


3、TCA9535 的控制寄存器
- 成功确认地址字节后,总线控制器将发送表 7-3 所示的命令字节,该命令字节存储在 TCA9535 的控制寄存器中。

4、输入寄存器 0/1
- 输入端口寄存器(寄存器 0 和 1)反映了引脚的输入逻辑电平,无论引脚是否由配置寄存器定义为输入或输出。
- 输入端口寄存器只对读取操作起作用,写入这些寄存器不起作用。
- 默认值 X 由外部应用的逻辑电平决定。

5、输出寄存器 0/1
- 输出端口寄存器(寄存器 2 和 3)显示了由配置寄存器定义为输出的引脚的传出逻辑电平。
- 此寄存器中的位值对定义为输入的引脚没有影响。反过来,从此寄存器读取的值反映了控制输出选择的触发器中的值,而不是实际的引脚值。

6、极性反转寄存器 0/1
- 极性反转寄存器(寄存器 4 和 5)允许对配置寄存器定义为输入的引脚进行极性反转。
- 如果设置极性反转寄存器中的某个位(写入 1),则相应引脚的极性将反转。
- 如果清除此寄存器中的某个位(写入 0),则相应引脚的原始极性将保留。

7、配置寄存器 0/1
- 配置寄存器(寄存器 6 和 7)配置 I/O 引脚的方向。
- 如果此寄存器中的某个位设置为 1,则相应的端口引脚将启用为具有高阻抗输出驱动器的输入。
- 如果此寄存器中的某个位清除为 0,则相应的端口引脚将启用为输出。

二、硬件设计
1、接线说明
| TCA9535 | STM32F407ZGT6 | 引脚定义 |
|---|---|---|
| G | GND | 电源负极 GND |
| V | 3.3V | 电源正极 VCC |
| SCL | B9 | IIC 接口 SDA 数据引脚 |
| SDA | B8 | IIC 接口 SCL 时钟引脚 |
2、硬件参考
- TCA9535 具有标准双向 I2C 接口,该接口由控制器设备控制,以便配置或读取此设备的状态。
- I2C 接口由串行时钟 (SCL) 和串行数据 (SDA) 线组成,SDA 和 SCL 线都必须通过上拉电阻连接到 VCC。
- INT 具有开漏结构。INT 需要一个合适的上拉电阻到 VCC(通常约为 10 kΩ)。


三、程序设计
- 程序说明:配置端口 P00 ~ P03 为输出,控制 P00 ~ P03 引脚输出高低电平。
1、tca9535_softiic.c
#include "./SYSTEM/delay/delay.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/SoftIIC/softiic.h"
#include "./BSP/TCA9535/tca9535_softiic.h"
/**
* @brief 初始化TCA9535
* @param 无
* @retval 无
*/
void TCA9535_Init_SoftIIC(void)
{
SoftIIC_Init(); /* 初始化软件IIC接口 */
TCA9535_ReadAllReg_Data(TCA9535_Address_Read0); /* 读取TCA9535输出和配置寄存器的数据 */
TCA9535_Set_Cfg(TCA9535_Address_Write0, TCA9535_Output_Port_0|TCA9535_Output_Port_1
|TCA9535_Output_Port_2|TCA9535_Output_Port_3); /* 设置TCA9535配置寄存器0、1 */
TCA9535_Set_Output(TCA9535_Address_Write0, TCA9535_Output_Port_ALL_OFF); /* 设置TCA9535输出寄存器0、1 */
}
/**
* @brief 读取TCA9535单个寄存器的数据
* @param read_address:TCA9535执行读操作时的8位IIC地址
* @param reg:要读取的寄存器地址
* @retval data:读取到的寄存器数据
*/
uint8_t TCA9535_ReadReg_Data(uint8_t read_address, uint8_t reg)
{
uint8_t data = 0; /* 用于存储读取到的寄存器数据 */
SoftIIC_Start(); /* 产生软件IIC起始信号 */
SoftIIC_Send_Byte(read_address & ~0x01); /* 发送设备地址和写命令(最低位为0表示写) */
SoftIIC_Wait_Ack(); /* 等待ACK */
SoftIIC_Send_Byte(reg); /* 发送要读取的寄存器地址 */
SoftIIC_Wait_Ack(); /* 等待ACK */
SoftIIC_Start(); /* 再次产生软件IIC起始信号 */
SoftIIC_Send_Byte(read_address); /* 发送设备地址和读命令(最低位为1表示读) */
SoftIIC_Wait_Ack(); /* 等待ACK */
data = SoftIIC_Read_Byte(0); /* 读取一个字节的数据,并发送NACK(表示不再读取数据) */
SoftIIC_Stop(); /* 产生软件IIC停止信号 */
return data; /* 返回读取到的寄存器数据 */
}
/**
* @brief 向TCA9535单个寄存器写入数据
* @param write_address:TCA9535执行写操作时的8位IIC地址
* @param reg:要写入的寄存器地址
* @param data:要写入的数据
* @retval 无
*/
void TCA9535_WriteReg_Data(uint8_t write_address, uint8_t reg, uint8_t data)
{
SoftIIC_Start(); /* 产生软件IIC起始信号 */
SoftIIC_Send_Byte(write_address); /* 发送设备地址和写命令(最低位为0表示写) */
SoftIIC_Wait_Ack(); /* 等待ACK */
SoftIIC_Send_Byte(reg); /* 发送要写入的寄存器地址 */
SoftIIC_Wait_Ack(); /* 等待ACK */
SoftIIC_Send_Byte(data); /* 发送要写入的数据 */
SoftIIC_Wait_Ack(); /* 等待ACK */
SoftIIC_Stop(); /* 产生软件IIC停止信号 */
}
/**
* @brief 读取TCA9535P输出和配置寄存器的数据
* @param read_address:TCA9535执行读操作时的8位IIC地址
* @retval 无
*/
void TCA9535_ReadAllReg_Data(uint8_t read_address)
{
uint8_t data1,data2,data3,data4;
printf("TCA9535_Output_Port0:");
data1 = TCA9535_ReadReg_Data(read_address, TCA9535_Output_Port0); /* 读取TCA9535_Output_Port0寄存器的数据 */
printf("%X\r\n", data1);
printf("TCA9535_Output_Port1:");
data2 = TCA9535_ReadReg_Data(read_address, TCA9535_Output_Port1); /* 读取TCA9535_Output_Port1寄存器的数据 */
printf("%X\r\n", data2);
printf("TCA9535_Configuration_Port0:");
data3 = TCA9535_ReadReg_Data(read_address, TCA9535_Configuration_Port0); /* 读取TCA9535_Configuration_Port0寄存器的数据 */
printf("%X\r\n", data3);
printf("TCA9535_Configuration_Port1:");
data4 = TCA9535_ReadReg_Data(read_address, TCA9535_Configuration_Port1); /* 读取TCA9535_Configuration_Port1寄存器的数据 */
printf("%X\r\n", data4);
}
/**
* @brief 设置TCA9535配置寄存器0、1
* @param write_address:TCA9535执行写操作时的8位IIC地址
* @param data:16位数据,每一位代表一个端口的方向,0表示输出,1表示输入
* @retval 无
*/
void TCA9535_Set_Cfg(uint8_t write_address, uint16_t data)
{
uint8_t Cfg_data[2]; /* 定义一个2字节的数组,用于存储配置数据 */
Cfg_data[0] = (uint8_t)~(data & 0x00FF); /* 获取低8位,并取反存储在Cfg_data[0] */
Cfg_data[1] = (uint8_t)~((data >> 8) & 0x00FF); /* 获取高8位,并取反存储在Cfg_data[1] */
TCA9535_WriteReg_Data(write_address, TCA9535_Configuration_Port0, Cfg_data[0]); /* 写入配置寄存器Port 0,配置端口的方向 */
TCA9535_WriteReg_Data(write_address, TCA9535_Configuration_Port1, Cfg_data[1]); /* 写入配置寄存器Port 1,配置端口的方向 */
}
/**
* @brief 设置TCA9535输出寄存器0、1
* @param write_address:TCA9535执行写操作时的8位IIC地址
* @param data:16位数据,每一位代表一个端口的输出状态,0表示低电平,1表示高电平
* @retval 无
*/
void TCA9535_Set_Output(uint8_t write_address, uint16_t data)
{
uint8_t output_data[2]; /* 定义一个2字节的数组,用于存储输出数据 */
output_data[0] = (uint8_t)(data & 0x00FF); /* 获取低8位,存储在output_data[0] */
output_data[1] = (uint8_t)((data >> 8) & 0x00FF); /* 获取高8位,存储在output_data[1] */
TCA9535_WriteReg_Data(write_address, TCA9535_Output_Port0, output_data[0]); /* 写入输出寄存器Port 0,设置端口的输出状态 */
TCA9535_WriteReg_Data(write_address, TCA9535_Output_Port1, output_data[1]); /* 写入输出寄存器Port 1,设置端口的输出状态 */
}
2、tca9535_softiic.h
#ifndef __TCA9535_SOFTIIC_H
#define __TCA9535_SOFTIIC_H
#include "./SYSTEM/sys/sys.h"
/******************************************************************************************/
/* TCA9535 IIC地址 */
/* 8位TCA9535 IIC器件地址 */
#define TCA9535_Address_Write0 TCA9535_Address_LLL << 1
#define TCA9535_Address_Read0 (TCA9535_Address_LLL << 1) | 0x01
/* 7位TCA9535 IIC器件地址 */ /* 0100 A2 A1 A0 */
#define TCA9535_Address_LLL 0x20 /* 0100 000 */
#define TCA9535_Address_LLH 0x21 /* 0100 001 */
#define TCA9535_Address_LHL 0x22 /* 0100 010 */
#define TCA9535_Address_LHH 0x23 /* 0100 011 */
#define TCA9535_Address_HLL 0x24 /* 0100 100 */
#define TCA9535_Address_HLH 0x25 /* 0100 101 */
#define TCA9535_Address_HHL 0x26 /* 0100 110 */
#define TCA9535_Address_HHH 0x27 /* 0100 111 */
/******************************************************************************************/
/******************************************************************************************/
/* TCA9535 寄存器映射 */
#define TCA9535_Input_Port0 0x00 /* 输入寄存器0,可读不可写 */
#define TCA9535_Input_Port1 0x01 /* 输入寄存器1,可读不可写 */
#define TCA9535_Output_Port0 0x02 /* 输出寄存器0,可读可写 */
#define TCA9535_Output_Port1 0x03 /* 输出寄存器1,可读可写 */
#define TCA9535_Polarity_Inversion_Port0 0x04 /* 极性反转寄存器0,可读可写 */
#define TCA9535_Polarity_Inversion_Port1 0x05 /* 极性反转寄存器1,可读可写 */
#define TCA9535_Configuration_Port0 0x06 /* 配置寄存器0,可读可写 */
#define TCA9535_Configuration_Port1 0x07 /* 配置寄存器1,可读可写 */
/******************************************************************************************/
/******************************************************************************************/
/* TCA9535 配置为输出端口 */
#define TCA9535_Output_Port_0 0x0001 /* 端口PA0 */
#define TCA9535_Output_Port_1 0x0002 /* 端口PA1 */
#define TCA9535_Output_Port_2 0x0004 /* 端口PA2 */
#define TCA9535_Output_Port_3 0x0008 /* 端口PA3 */
#define TCA9535_Output_Port_4 0x0010 /* 端口PA4 */
#define TCA9535_Output_Port_5 0x0020 /* 端口PA5 */
#define TCA9535_Output_Port_6 0x0040 /* 端口PA6 */
#define TCA9535_Output_Port_7 0x0080 /* 端口PA7 */
#define TCA9535_Output_Port_10 0x0100 /* 端口PB0 */
#define TCA9535_Output_Port_11 0x0200 /* 端口PB1 */
#define TCA9535_Output_Port_12 0x0400 /* 端口PB2 */
#define TCA9535_Output_Port_13 0x0800 /* 端口PB3 */
#define TCA9535_Output_Port_14 0x1000 /* 端口PB4 */
#define TCA9535_Output_Port_15 0x2000 /* 端口PB5 */
#define TCA9535_Output_Port_16 0x4000 /* 端口PB6 */
#define TCA9535_Output_Port_17 0x8000 /* 端口PB7 */
#define TCA9535_Output_Port_ALL_ON 0xFFFF /* 全部打开 */
#define TCA9535_Output_Port_ALL_OFF 0x0000 /* 全部关闭 */
/******************************************************************************************/
/******************************************************************************************/
/* 函数声明 */
void TCA9535_Init_SoftIIC(void); /* 初始化TCA9535 */
uint8_t TCA9535_ReadReg_Data(uint8_t read_address, uint8_t reg); /* 读取TCA9535寄存器的数据 */
void TCA9535_WriteReg_Data(uint8_t write_address, uint8_t reg, uint8_t data); /* 向TCA9535寄存器写入数据 */
void TCA9535_ReadAllReg_Data(uint8_t read_address); /* 读取TCA9535P输出和配置寄存器的数据 */
void TCA9535_Set_Cfg(uint8_t write_address, uint16_t data); /* 设置TCA9535配置寄存器0/1 */
void TCA9535_Set_Output(uint8_t write_address, uint16_t data); /* 设置TCA9535输出寄存器0/1 */
/******************************************************************************************/
#endif /* __TCA9535_SOFTIIC_H */
3、main.c
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/delay/delay.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/TCA9535/tca9535_softiic.h"
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */
delay_init(168); /* 延时初始化 */
usart_init(115200); /* 串口初始化为115200 */
TCA9535_Init_SoftIIC(); /* TCA9535软件IIC初始化 */
while(1)
{
TCA9535_Set_Output(TCA9535_Address_Write0, TCA9535_Output_Port_0|TCA9535_Output_Port_1|TCA9535_Output_Port_2|
TCA9535_Output_Port_3); /* 设置TCA9535使能寄存器0、1 */
TCA9535_ReadAllReg_Data(TCA9535_Address_Read0); /* 读取TCA9535P所有寄存器的数据 */
delay_ms(2000);
TCA9535_Set_Output(TCA9535_Address_Write0, TCA9535_Output_Port_ALL_OFF); /* 设置TCA9535控制寄存器0、1 */
TCA9535_ReadAllReg_Data(TCA9535_Address_Read0); /* 读取TCA9535P所有寄存器的数据 */
delay_ms(5000);
}
}
四、功能展示 - 串口显示
- 注意:上电后输出寄存器和配置寄存器的所有位默认值为 1。







![[cg] vulkan external_memory](https://img-blog.csdnimg.cn/img_convert/61fb1f03a62878392b6ca0a34b9eadd5.png)












