简介
在上一篇文章中https://forum.eepw.com.cn/thread/394839/1/#1 我们详细介绍了和分析了IO拓展芯片XL9535QF24。那么本章节我们尝试使用ESP-IDF将它驱动起来。 然后之后再尝试修改摄像头的驱动程序中的reset按键来尝试驱动摄像头。 (突然发现还是一个比较麻烦的事情,摄像头上已经挂载了一个I2C了,现在还不确定两个是不是一个PIN占用。我感觉还是自己画一个摄像头拓展版好点,太麻烦了)
首先,在上述原理图中可以看到ILI9341的背光主要是由LCD_BLK 控制的。
所以只需要控制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拓展芯片来点亮屏幕了。 效果如下所示。
附件: