这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 【ESP-IDF】使用ESP-IDF驱动IO拓展芯片XL9533点亮屏幕

共3条 1/1 1 跳转至

【ESP-IDF】使用ESP-IDF驱动IO拓展芯片XL9533点亮屏幕

工程师
2025-09-23 16:21:41     打赏

简介

在上一篇文章中https://forum.eepw.com.cn/thread/394839/1/#1 我们详细介绍了和分析了IO拓展芯片XL9535QF24。那么本章节我们尝试使用ESP-IDF将它驱动起来。 然后之后再尝试修改摄像头的驱动程序中的reset按键来尝试驱动摄像头。 (突然发现还是一个比较麻烦的事情,摄像头上已经挂载了一个I2C了,现在还不确定两个是不是一个PIN占用。我感觉还是自己画一个摄像头拓展版好点,太麻烦了)image.png

首先,在上述原理图中可以看到ILI9341的背光主要是由LCD_BLK 控制的。

image.png所以只需要控制XL9535的00口输出高电平即可点亮这个屏幕来看到效果。 于是我花了一点时间写了一下驱动文件。

#ifndef XL9535_H
#define XL9535_H
#include "sdkconfig.h"
#include "driver/i2c_master.h"
#include "esp_log.h"

#ifdef __cplusplus
extern "C"
{
#endif

// I2C Configuration
#define SCL_IO_PIN CONFIG_I2C_MASTER_SCL
#define SDA_IO_PIN CONFIG_I2C_MASTER_SDA
#define MASTER_FREQUENCY CONFIG_I2C_MASTER_FREQUENCY
#define PORT_NUMBER -1

// XL9535 Register Addresses
#define XL9535_I2C_ADDR (0x20)
#define XL9535_REG_INPUT_PORT (0x00)
#define XL9535_REG_INPUT_PORT2 (0x01)
#define XL9535_REG_OUTPUT_PORT (0x02)
#define XL9535_REG_OUTPUT_PORT2 (0x03)
#define XL9535_REG_POLARITY (0x04)
#define XL9535_REG_POLARITY2 (0x05)
#define XL9535_REG_CONFIG (0x06)
#define XL9535_REG_CONFIG2 (0x07)

    typedef enum
    {
        XL9535_CONFIG_1 = 0x06,
        XL9535_CONFIG_2 = 0x07
    } xl9535_config_type_t;

    typedef struct
    {
        xl9535_config_type_t config_type; // 配置寄存器类型
        const uint8_t *value;             // 指向2字节配置值
        size_t value_len;                 // 配置值长度
    } xl9535_config_select_t;

    typedef enum
    {
        XL9535_PORT_1 = 0x02,
        XL9535_PORT_2 = 0x03,
    } xl9535_port_type_t;

    typedef struct
    {
        xl9535_port_type_t port_type; // 端口寄存器类型
        const uint8_t *value;         // 指向端口数据
        size_t value_len;             // 数据长度
    } xl9535_port_select_t;

    void XL9535_Init(void);

    void XL9535_configure(const xl9535_config_select_t *config);

    void XL9535_write_port(const xl9535_port_select_t *port);

#ifdef __cplusplus
}
#endif

#endif // XL9535_H

其中上述主要有三个函数,第一个是用来初始化的。第二个则是根据结构体来配置寄存器是输入还是输出。 然后第三个函数则是给寄存器写对应的值。从而来控制输出寄存器的输出。

#include "xl9535.h"
#include <string.h>
#include <stdio.h>

i2c_device_config_t dev_cfg;
i2c_master_dev_handle_t dev_handle;

void XL9535_Init(void)
{
    i2c_master_bus_config_t i2c_bus_config = {
        .clk_source = I2C_CLK_SRC_DEFAULT,
        .i2c_port = PORT_NUMBER,
        .scl_io_num = SCL_IO_PIN,
        .sda_io_num = SDA_IO_PIN,
        .glitch_ignore_cnt = 7,
    };
    i2c_master_bus_handle_t bus_handle;

    ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_config, &bus_handle));

    printf("I2C 扫描开始...\n");

    for (uint8_t addr = 1; addr < 0x7F; addr++)
    {
        esp_err_t ret = i2c_master_probe(bus_handle, addr, 100);
        if (ret == ESP_OK)
        {
            printf("0x%02X ", addr);
        }
    }
    printf("\n扫描完成,5秒后重试...\n");

    dev_cfg.dev_addr_length = I2C_ADDR_BIT_LEN_7;
    dev_cfg.device_address = 0x20;
    dev_cfg.scl_speed_hz = 100000;

    ESP_ERROR_CHECK(i2c_master_bus_add_device(bus_handle, &dev_cfg, &dev_handle));
    printf("已添加设备,开始读取数据...\n");
}

void XL9535_configure(const xl9535_config_select_t *config)
{
    assert(config != NULL);
    assert(config->value != NULL);
    assert(config->value_len == 2);
    uint8_t direction_buffer[3] = {config->config_type, config->value[0], config->value[1]};
    esp_err_t ret = i2c_master_transmit(dev_handle, direction_buffer, sizeof(direction_buffer), 1000);

    if (ret == ESP_OK)
    {
        printf("初始化控制寄存器成功\n");
    }
    else
    {
        printf("数据发送失败,错误码: %d\n", ret);
    }
}

void XL9535_write_port(const xl9535_port_select_t *port)
{
    assert(port != NULL);
    assert(port->value != NULL);
    assert(port->value_len > 0);

    uint8_t buffer[port->value_len + 1];
    buffer[0] = port->port_type;
    memcpy(&buffer[1], port->value, port->value_len);

    esp_err_t ret = i2c_master_transmit(dev_handle, buffer, sizeof(buffer), 1000);

    if (ret == ESP_OK)
    {
        printf("初始化端口成功\n");
    }
    else
    {
        printf("数据发送失败,错误码: %d\n", ret);
    }
}

对应的函数实现如上所示。 通过上述的原理图得知BLK的控制脚是00,所以我们只需要在LSB写入1即可,即0x01。所以对应的主程序如下所示。

/*
 * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
 *
 * SPDX-License-Identifier: Unlicense OR CC0-1.0
 */
#include <string.h>
#include <stdio.h>
#include "sdkconfig.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/i2c_master.h"
#include "xl9535.h"

#define SCL_IO_PIN CONFIG_I2C_MASTER_SCL
#define SDA_IO_PIN CONFIG_I2C_MASTER_SDA
#define MASTER_FREQUENCY CONFIG_I2C_MASTER_FREQUENCY
#define PORT_NUMBER -1

void app_main(void)
{
    XL9535_Init();

    // 配置 config1
    uint8_t config_val[2] = {0x00, 0x00};
    xl9535_config_select_t config = {
        .config_type = XL9535_CONFIG_1,
        .value = config_val,
        .value_len = 2};
    XL9535_configure(&config);

    // 写端口1
    uint8_t port_val[2] = {0x01, 0x00};
    xl9535_port_select_t port = {
        .port_type = XL9535_PORT_1,
        .value = port_val,
        .value_len = 2};
    XL9535_write_port(&port);

    while (1)
    {
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

这样的话就可以成功的通过IO拓展芯片来点亮屏幕了。 效果如下所示。

微信图片_20250923161628_36_211.jpg

附件:

IO-XL9535.zip




关键词: XL9535     ESP-IDF     IO拓展芯片    

院士
2025-09-23 22:11:59     打赏
2楼

看着esp-idf就是普普通通的样子嘛!



专家
2025-09-24 09:10:31     打赏
3楼

谢谢分享


共3条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]