1.XL9555介绍
void i2c_init_num0(void)
{
i2c_config_t i2c_config_struct = {0};
uint8_t init_flag = 0;
i2c_config_struct.mode = I2C_MODE_MASTER; //配置I2C模式为master
i2c_config_struct.sda_io_num = IIC0_SDA_GPIO_PIN; //配置I2C的SDA引脚号
i2c_config_struct.scl_io_num = IIC0_SCL_GPIO_PIN; //配置I2C的SCL引脚号
i2c_config_struct.sda_pullup_en = GPIO_PULLUP_ENABLE; //配置SDA引脚上拉使能
i2c_config_struct.scl_pullup_en = GPIO_PULLUP_ENABLE; //配置SCL引脚上拉使能
i2c_config_struct.master.clk_speed = IIC_FREQ; //设置I2C通信速率
i2c_param_config(I2C_NUM_0, &i2c_config_struct); //设置I2C初始化参数
init_flag = i2c_driver_install(I2C_NUM_0, //端口号
i2c_config_struct.mode, //主机模式
I2C_MASTER_RX_BUF_DISABLE, //从机模式下接收缓存大小(主机模式下不使用)
I2C_MASTER_TX_BUF_DISABLE, //从机模式下发送缓存大小(主机模式下不使用)
0); //用于分配中断的标志(通常从机模式使用)
if(init_flag != ESP_OK)
{
while (1)
{
printf("%s,ret: %d",__func__, init_flag);
vTaskDelay(1000);
}
}
}
2.xl9555寄存器介绍
1.XL9555寻址
XL9555器件地址是7位,如下图

Fixed bits:代表固定的位为"0100",
Programmable bits:可编程的位 "A2 A1 A0”,在硬件上,若把这三个引脚都接地处理,则这三位为“000”。最终得到XL9555器件地址为“0100000”7位。若读操作为0x41;写操作为0x40。
2.XL9555寄存器

因XL9555只有8个寄存器是对16个GPIO进行配置的,所以控制寄存器只有低三位有效如图Table5
主要分为四种:
输入查询: Input Port 0 (0x00) Input Port 1 (0x01)
输出设置: Output Port 0(0x02) Output Port 1(0x03)
极性翻转: Polarity Inversion Port 0(0x04) Polarity Inversion Port 1(0x05)
端口配置:Configuration Port 0(0x06) Configuration Port 1(0x07)
3.软件配置
1.初始化配置ESP32S3模组的I2C外设和XL9555初始化。代码如下
void i2c_init_num0(void)
{
i2c_config_t i2c_config_struct = {0};
uint8_t init_flag = 0;
i2c_config_struct.mode = I2C_MODE_MASTER; //配置I2C模式为master
i2c_config_struct.sda_io_num = IIC0_SDA_GPIO_PIN; //配置I2C的SDA引脚号
i2c_config_struct.scl_io_num = IIC0_SCL_GPIO_PIN; //配置I2C的SCL引脚号
i2c_config_struct.sda_pullup_en = GPIO_PULLUP_ENABLE; //配置SDA引脚上拉使能
i2c_config_struct.scl_pullup_en = GPIO_PULLUP_ENABLE; //配置SCL引脚上拉使能
i2c_config_struct.master.clk_speed = IIC_FREQ; //设置I2C通信速率
i2c_param_config(I2C_NUM_0, &i2c_config_struct); //设置I2C初始化参数
init_flag = i2c_driver_install(I2C_NUM_0, //端口号
i2c_config_struct.mode, //主机模式
I2C_MASTER_RX_BUF_DISABLE, //从机模式下接收缓存大小(主机模式下不使用)
I2C_MASTER_TX_BUF_DISABLE, //从机模式下发送缓存大小(主机模式下不使用)
0); //用于分配中断的标志(通常从机模式使用)
if(init_flag != ESP_OK)
{
while (1)
{
printf("%s,ret: %d",__func__, init_flag);
vTaskDelay(1000);
}
}
}
void xl9555_init(void)
{
gpio_config_t gpio_init_struct = {0};
uint16_t reg_data;
i2c_init_num0(); //初始化i2c_num_0
gpio_init_struct.intr_type = GPIO_INTR_DISABLE;
gpio_init_struct.mode = GPIO_MODE_INPUT;
gpio_init_struct.pin_bit_mask = (1ull << XL9555_INT_IO);
gpio_init_struct.pull_down_en = GPIO_PULLDOWN_DISABLE;
gpio_init_struct.pull_up_en = GPIO_PULLUP_ENABLE;
gpio_config(&gpio_init_struct); /* 配置XL_INT引脚 */
xl9555_read_Input_Value(®_data, XL9555_GPIO_Port0 | XL9555_GPIO_Port1); //读一次所有的GPIO口,清除中断
// printf("xl9555_init InputReg_data:%d\n",reg_data);
xl9555_ioconfig(0xF003); //配置相应引脚的IO模式(输入(0)、输出(1))
}
3.XL9555读写时序
1.写寄存器时序

/**
* @brief 设置XL9555的16位IO值
* @param data:控制IO的变量
* @param GPIO_Port: 要控制IO所属的端口
* @retval ESP_OK:读取成功;其他:读取失败
*/
esp_err_t xl9555_write_Output_Value (uint16_t data, uint8_t GPIO_Port)
{
esp_err_t ret = ESP_FAIL;
uint8_t tmp[2] = {0};
if((GPIO_Port & XL9555_GPIO_Port0) == 0x1)
{
tmp[0] = XL9555_OUTPUT_PORT0_REG;
tmp[1] = (uint8_t)(data & 0x00FF);
ret = i2c_num0_write_byte(XL9555_ADDR, tmp, 2);
}
if((GPIO_Port & XL9555_GPIO_Port1) == 0x2)
{
tmp[0] = XL9555_OUTPUT_PORT1_REG;
tmp[1] = (uint8_t)((data & 0xFF00) >> 8);
ret = i2c_num0_write_byte(XL9555_ADDR, tmp, 2);
}
return ret;
}
esp_err_t i2c_num0_write_byte(uint8_t addr, uint8_t *byte, uint16_t len)
{
esp_err_t ret = ESP_FAIL;
i2c_cmd_handle_t cmd = i2c_cmd_link_create(); //用于创建一个I2C命令链接,在发送或接收I2C数据时,需要先建立一个命令链,然后添加相应的命令
i2c_master_start(cmd); //向I2C命令链中添加开始信号
i2c_master_write_byte(cmd, (addr << 1)|I2C_FLAG_WRITE, ACK_CHECK_EN); //向命令链中添加一个写设备地址和写命令的字节。
i2c_master_write(cmd, byte, len, ACK_CHECK_EN); //向命令链中添加写设备寄存器与寄存器数据命令的字节
i2c_master_stop(cmd); //向命令链中添加停止信号命令
ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, 100 * (1+len)/portTICK_PERIOD_MS); //开始发送命令
i2c_cmd_link_delete(cmd); //释放命令链接存储空间
return ret;
}
在《XL9555 数据手册》P16 中,还提供有对寄存器组写时序图,如下图

2.读寄存器时序

/**
* @brief 读取XL9555的16位IO值
* @param data:读取数据的存储区
* @retval ESP_OK:读取成功;其他:读取失败
*/
esp_err_t xl9555_read_Input_Value (uint16_t *data, uint8_t GPIO_Port)
{
esp_err_t ret = ESP_FAIL;
uint8_t tmp;
if((GPIO_Port & XL9555_GPIO_Port0) == 0x1)
{
ret = i2c_num0_read_byte(XL9555_ADDR, XL9555_INPUT_PORT0_REG, &tmp);
*data = tmp;
}
if((GPIO_Port & XL9555_GPIO_Port1) == 0x2)
{
ret = i2c_num0_read_byte(XL9555_ADDR, XL9555_INPUT_PORT1_REG, &tmp);
*data |= ((((uint16_t)tmp) << 8)& 0xFF00);
}
return ret;
}
esp_err_t i2c_num0_read_byte(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data)
{
esp_err_t ret = ESP_FAIL;
i2c_cmd_handle_t cmd = i2c_cmd_link_create(); //用于创建一个I2C命令链接,在发送或接收I2C数据时,需要先建立一个命令链,然后添加相应的命令
i2c_master_start(cmd); //向I2C命令链中添加开始信号
i2c_master_write_byte(cmd, (dev_addr << 1)|I2C_FLAG_WRITE, ACK_CHECK_EN); //向命令链中添加一个写设备地址和写命令的字节。
i2c_master_write_byte(cmd, reg_addr, ACK_CHECK_EN); //向命令链中添加写设备寄存器地址命令字符。
i2c_master_start(cmd); //向命令链发送起始信号
i2c_master_write_byte(cmd, (dev_addr << 1)|I2C_FLAG_READ, ACK_CHECK_EN); //向命令链发送设备地址和读命令的字符
i2c_master_read_byte(cmd, data, I2C_MASTER_LAST_NACK); //读取从机数据
i2c_master_stop(cmd); //发送停止信号
ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, 400/portTICK_PERIOD_MS); //开始发送命令
i2c_cmd_link_delete(cmd); //释放命令链接存储空间
return ret;
}

1449

被折叠的 条评论
为什么被折叠?



