当前位置: 首页 > news >正文

SOC-ESP32S3部分:20-SPISPI屏幕驱动

飞书文档https://x509p6c8to.feishu.cn/wiki/RyLFwXd6ViBfi9kUe17cHPeAnhj

ESP32-S3 有4个SPI接口

– 2 个 SPI 接口用于连接 flash 和 RAM

– 2 个通用 SPI 接口

具体如下:

• SPI0,供 ESP32-S3 的 GDMA 控制器与 Cache 访问封装内或封装外 flash/PSRAM
• SPI1,供 CPU 访问封装内或封装外 flash/PSRAM
• SPI2,通用 SPI 控制器,通过 GDMA 分配 DMA 通道进行访问
• SPI3,通用 SPI 控制器,通过 GDMA 分配 DMA 通道进行访问

SPI0 SPI1 控制器主要供内部使用以访问外部 flash PSRAM,应用部分一般使用SPI2SPI3

关于GPIO选择:

SPI0、SPI1:

如果使用模组,或者参考模组原理图设计,SPI0/1:GPIO26 ~ GPIO32 通常用于 SPI flash 和 PSRAM,不推荐用于其他用途。当使用八线 flash 或八线 PSRAM 或同时使用两者时,GPIO33 ~ GPIO37 会连接到 SPI-IO4 ~ SPI-IO7 和 SPIDQS。因此,对于内嵌 ESP32-S3R8 或 ESP32-S3R8V 芯片的开发板,GPIO33 ~ GPIO37 也不推荐用于其他用途。

SPI2、SPI3:

可通过 GPIO 交换矩阵可配置使用任意 GPIO 管脚。

SPI传输事务属性由总线配置结构体 spi_bus_config_t、设备配置结构体 spi_device_interface_config_t 和传输事务配置结构体 spi_transaction_t 共同决定。

ESP32 IDF库的SPI主设备驱动程序的API使用流程大致如下

  • 初始化SPI总线:使用spi_bus_initialize()函数初始化SPI总线。这个函数需要一个spi_bus_config_t结构体,该结构体包含了SPI总线的配置信息,如时钟速度、数据模式等。
  • 添加SPI设备:使用spi_bus_add_device()函数将SPI设备添加到SPI总线上。这个函数需要一个spi_device_interface_config_t结构体,该结构体包含了SPI设备的配置信息,如片选信号、时钟极性和相位等。
  • 创建SPI事务:创建一个spi_transaction_t结构体,该结构体定义了一个SPI事务。一个事务包括一个命令阶段和一个数据阶段。在命令阶段,主设备会发送一个命令给从设备。在数据阶段,主设备和从设备会交换数据。
  • 发送SPI事务:使用spi_device_transmit()函数发送SPI事务。这个函数会阻塞,直到事务完成。如果你希望在发送事务后立即返回,可以使用spi_device_queue_trans()函数将事务添加到队列中,然后使用spi_device_get_trans_result()函数获取事务的结果。
  • 移除SPI设备:当不再需要与SPI设备通信时,可以使用spi_bus_remove_device()函数将设备从SPI总线上移除。
  • 释放SPI总线:最后,使用spi_bus_free()函数释放SPI总线。

初始化SPI总线

spi_bus_initialize 函数用于初始化指定的 SPI 主机设备,并根据提供的配置信息设置 SPI 总线的参数

esp_err_t spi_bus_initialize(spi_host_device_t host_id, const spi_bus_config_t *bus_config, int dma_chan);
参数说明
spi_host_device_t host_id:
SPI 主机设备编号,表示要初始化的 SPI 主机。常见的主机编号包括:
typedef enum {SPI1_HOST=0,    ///< SPI1SPI2_HOST=1,    ///< SPI2SPI3_HOST=2,    ///< SPI3
} spi_host_device_t;const spi_bus_config_t *bus_config:
这个结构体定义了 SPI 总线的引脚配置、最大传输大小等参数。int dma_chan :
DMA 通道编号,用于指定 SPI 传输使用的 DMA 通道。常见的选项包括:
typedef enum {SPI_DMA_DISABLED = 0,     //不开启DMASPI_DMA_CH1      = 1,     ///DMA通道1SPI_DMA_CH2      = 2,     //DMA通道2SPI_DMA_CH_AUTO  = 3,     //自动分配 DMA 通道。
} spi_common_dma_t;spi_bus_config_t 字段说明
miso_io_num:SPI 总线的 MISO(Master In Slave Out)引脚编号。
mosi_io_num:SPI 总线的 MOSI(Master Out Slave In)引脚编号。
sclk_io_num:SPI 总线的 SCLK(Serial Clock)引脚编号。SCLK 引脚用于提供时钟信号,同步数据传输。
quadwp_io_num:SPI 总线的 QuadWP(Quad Write Protect)引脚编号。用于四线 SPI 模式中的写保护功能。值为 -1 表示不使用该引脚。
quadhd_io_num:SPI 总线的 QuadHD(Quad Hold)引脚编号。用于四线 SPI 模式中的保持功能。值为 -1 表示不使用该引脚。
max_transfer_sz:SPI 总线的最大传输大小(以字节为单位)。这个参数用于限制单次 SPI 传输的最大数据量。

使用参考:

    spi_bus_config_t buscfg = {.miso_io_num = PIN_NUM_MISO,.mosi_io_num = PIN_NUM_MOSI,.sclk_io_num = PIN_NUM_CLK,.quadwp_io_num = -1,.quadhd_io_num = -1,.max_transfer_sz = 320,};ret = spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO);

添加SPI设备

spi_bus_add_device 函数用于将一个新的 SPI 设备添加到指定的 SPI 主机上。

esp_err_t spi_bus_add_device(spi_host_device_t host_id, const spi_device_interface_config_t *dev_config, spi_device_handle_t *out_handle);
参数说明
spi_host_device_t host_id:
SPI 主机设备编号,表示要添加设备的 SPI 主机。const spi_device_interface_config_t *dev_config:
这个结构体定义了设备的时钟速度、模式、引脚配置、传输队列大小等参数。spi_device_handle_t *out_handle:
输出参数,用于返回新添加的 SPI 设备的句柄。通过这个句柄可以对设备进行后续操作,如发送和接收数据。spi_device_interface_config_t 是用于配置 SPI 设备接口参数的结构体。
字段说明
command_bits: 默认命令阶段的位数(0-16) 8 表示命令阶段使用 8 位。
address_bits: 默认地址阶段的位数(0-64)。16 表示地址阶段使用 16 位。
dummy_bits: 在地址和数据阶段之间插入的虚拟位数。
clock_speed_hz:SPI 总线的时钟速度(以Hz为单位)。时钟速度决定了 SPI 传输的数据速率。
mode:SPI 模式(CPOL 和 CPHA 的组合)。常见的 SPI 模式包括:
0: CPOL = 0, CPHA = 0
1: CPOL = 0, CPHA = 1
2: CPOL = 1, CPHA = 0
3: CPOL = 1, CPHA = 1
clock_source: 选择 SPI 时钟源,默认为 SPI_CLK_SRC_DEFAULT。
spics_io_num:SPI 总线的片选CS(Chip Select)引脚编号。CS 引脚用于选择特定的 SPI 从设备。
flags: SPI_DEVICE_* 标志的按位或组合,详见下方spi_device_interface_config_t结构体。
queue_size:SPI 传输队列的大小。
pre_cb:在传输开始前调用的回调函数。
post_cb: 在传输完成后调用的回调函数。spi_device_interface_config_tflags 字段用于设置各种标志位,以控制 SPI 设备的行为。
以下是对每个标志位的详细解释:
SPI_DEVICE_TXBIT_LSBFIRST:
在传输命令、地址和数据时,使用最低有效位(LSB)优先而不是默认的最高有效位(MSB)优先。
.flags = SPI_DEVICE_TXBIT_LSBFIRST表示在传输时使用 LSB 优先。SPI_DEVICE_RXBIT_LSBFIRST:
在接收数据时,使用最低有效位(LSB)优先而不是默认的最高有效位(MSB)优先。
.flags = SPI_DEVICE_RXBIT_LSBFIRST表示在接收时使用 LSB 优先。SPI_DEVICE_BIT_LSBFIRST:
在传输和接收数据时都使用最低有效位(LSB)优先。SPI_DEVICE_3WIRE:
使用 MOSI(也称为 SPID)引脚进行数据的发送和接收,而不是使用单独的 MISO 引脚。
示例:.flags = SPI_DEVICE_3WIRE表示使用 3 线 SPI 模式。SPI_DEVICE_POSITIVE_CS:
在传输期间使 CS 信号为高电平(正电平),而不是默认的低电平(负电平)。SPI_DEVICE_HALFDUPLEX:
半双工模式。SPI_DEVICE_CLK_AS_CS:
在 CS 信号激活时输出时钟信号。

使用参考1:

  • 用于 LCD 显示器。
  • 设置了 10 MHz 的时钟速度。
  • 使用指定的 CS 引脚。
  • 可以队列 7 个事务。
  • 使用 lcd_spi_pre_transfer_callback 处理 D/C 线。
    spi_device_interface_config_t devcfg = {.clock_speed_hz = 10 * 1000 * 1000,     //Clock out at 10 MHz.mode = 0,                              //SPI mode 0.spics_io_num = PIN_NUM_CS,             //CS pin.queue_size = 7,                        //We want to be able to queue 7 transactions at a time.pre_cb = lcd_spi_pre_transfer_callback, //Specify pre-transfer callback to handle D/C line};spi_device_handle_t spi;ret = spi_bus_add_device(SPI2_HOST, &devcfg, &spi);

使用参考2: 

  • 用于SPI接口的EEPROM,EEPROM和一般SPI设备有点不同,操作时需带设备地址、读写地址、读写数据。
  • 使用SPI接口的EEPROM 的时钟频率。
  • 不使用硬件 CS 引脚,通过回调函数手动控制 CS 引脚。
  • 只能队列 1 个事务。
  • 使用半双工模式。
  • 使用 cs_highcs_low 回调函数控制 CS 引脚。
  • 设置输入延迟,以适应 EEPROM 的输出延迟。
    spi_device_interface_config_t devcfg = {.command_bits = 10,.clock_speed_hz = EEPROM_CLK_FREQ,.mode = 0,         .spics_io_num = -1,.queue_size = 1,.flags = SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_POSITIVE_CS,.pre_cb = cs_high,.post_cb = cs_low,.input_delay_ns = EEPROM_INPUT_DELAY_NS,  //the EEPROM output the data half a SPI clock behind.};spi_device_handle_t spi;ret = spi_bus_add_device(SPI2_HOST, &devcfg, &spi);

传输配置

使用 spi_device_polling_transmit 函数可以进行 SPI 数据传输:

esp_err_t SPI_MASTER_ISR_ATTR spi_device_polling_transmit(spi_device_handle_t handle, spi_transaction_t* trans_desc);
参数说明
spi_device_handle_t handle:
说明:指向 SPI 设备的句柄。这个句柄是通过 spi_bus_add_device 函数创建的。spi_transaction_t* trans_desc:
说明:指向 spi_transaction_t 结构体的指针,包含 SPI 传输的详细信息。

spi_transaction_t 结构体用于配置和描述一次 SPI 传输的详细参数。通过设置这些参数,可以精确控制 SPI 传输的各个阶段,包括命令、地址、数据的发送和接收。

字段说明
flags: 按位或的 SPI_TRANS_* 标志,用于设置传输的各种选项。
.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA表示使用 tx_data 和 rx_data 直接发送和接收数据。cmd: 命令数据,长度由 spi_device_interface_config_t 中的 command_bits 设置。
.cmd = 0x0123如果 command_bits 设置为 12,则实际发送的命令为 0x0123 的低 12 位。addr: 地址数据,长度由 spi_device_interface_config_t 中的 address_bits 设置。
.addr = 0x123400如果 address_bits 设置为 24,则实际发送的地址为 0x123400 的低 24 位。length: 总数据长度(以位为单位),包括命令、地址和数据部分。
rxlength: 接收数据的总长度(以位为单位),如果设置为 0,则默认等于 length。tx_buffer 和 tx_data: 发送数据缓冲区或直接发送的数据。
tx_buffer:: 指向发送缓冲区的指针,如果不需要 MOSI 阶段,则设置为 NULL。
tx_data: 如果设置了 SPI_TRANS_USE_TXDATA 标志,则直接从这个变量发送数据。rx_buffer 和 rx_data: 接收数据缓冲区或直接接收的数据。
rx_buffer:: 指向接收缓冲区的指针,如果不需要 MISO 阶段,则设置为 NULL。如果使用 DMA,则数据按 4 字节对齐。
rx_data:: 如果设置了 SPI_TRANS_USE_RXDATA 标志,则直接将数据接收到这里。
user: 用户定义的变量,可以用于存储事务 ID 或其他自定义信息。

spi_transaction_t 结构体中,flags 字段用于设置各种标志位,以控制 SPI 传输的详细行为。

标志位定义
SPI_TRANS_MODE_DIO:
在 2 位模式下传输/接收数据(双 I/O 模式)。SPI_TRANS_MODE_QIO:
在 4 位模式下传输/接收数据(四 I/O 模式)。SPI_TRANS_USE_RXDATA:
将接收到的数据存储在 spi_transaction_t 结构体的 rx_data 成员中,而不是存储在 rx_buffer 指向的内存中。SPI_TRANS_USE_TXDATA:
使用 spi_transaction_t 结构体的 tx_data 成员发送数据,而不是使用 tx_buffer 指向的内存。SPI_TRANS_MODE_DIOQIO_ADDR:
在地址阶段也使用 SPI_TRANS_MODE_DIO 或 SPI_TRANS_MODE_QIO 模式传输地址。
.flags = SPI_TRANS_MODE_DIO | SPI_TRANS_MODE_DIOQIO_ADDR表示在命令和地址阶段都使用 2 位模式。SPI_TRANS_VARIABLE_CMD:
使用 spi_transaction_ext_t 结构体中的 command_bits 字段,而不是 spi_device_interface_config_t 中的默认值。SPI_TRANS_VARIABLE_ADDR:
使用 spi_transaction_ext_t 结构体中的 address_bits 字段,而不是 spi_device_interface_config_t 中的默认值。SPI_TRANS_VARIABLE_DUMMY:
使用 spi_transaction_ext_t 结构体中的 dummy_bits 字段,而不是 spi_device_interface_config_t 中的默认值。SPI_TRANS_CS_KEEP_ACTIVE:
在数据传输完成后保持 CS 信号保持激活状态。SPI_TRANS_MULTILINE_CMD:
在命令阶段使用与数据阶段相同的多线数据线(否则,命令阶段只使用一条数据线)。SPI_TRANS_MODE_OCT:
在 8 位模式下传输/接收数据。SPI_TRANS_MULTILINE_ADDR:
在地址阶段也使用与数据阶段相同的多线数据线(否则,地址阶段只使用一条数据线)。
.flags = SPI_TRANS_MODE_DIO | SPI_TRANS_MULTILINE_ADDR表示在命令和地址阶段都使用 2 位模式。SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL:
默认情况下,驱动程序会自动重新分配 DMA 缓冲区以满足硬件对齐或 DMA 能力的要求。设置此标志可以禁用此功能,需要手动处理对齐问题,否则驱动程序会返回 ESP_ERR_INVALID_ARG 错误。
.flags = SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL表示手动处理 DMA 缓冲区对齐。
模式命令位宽地址位宽数据位宽传输事务标志信号总线 IO 设置标志信号
普通 SPI 模式11100
双线输出模式112SPI_TRANS_MODE_DIOSPICOMMON_BUSFLAG_DUAL
双线 I/O 模式122SPI_TRANS_MODE_DIO SPI_TRANS_MULTILINE_ADDRSPICOMMON_BUSFLAG_DUAL
四线输出模式114SPI_TRANS_MODE_QIOSPICOMMON_BUSFLAG_QUAD
四线 I/O 模式144SPI_TRANS_MODE_QIO SPI_TRANS_MULTILINE_ADDRSPICOMMON_BUSFLAG_QUAD
八线输出模式118SPI_TRANS_MODE_OCTSPICOMMON_BUSFLAG_OCTAL
OPI 模式888SPI_TRANS_MODE_OCT SPI_TRANS_MULTILINE_ADDR SPI_TRANS_MULTILINE_CMDSPICOMMON_BUSFLAG_OCTAL

使用参考:

通过tx_buffer和rx_buffer发送&接收:spi_transaction_t t;memset(&t, 0, sizeof(t));      // 初始化事务结构体t.length = 8 * 4;              // 传输数据长度为 4 字节(32 位)t.rxlength = 8 * 4;            // 接收数据长度为 4 字节(32 位)t.tx_buffer = (void *)"Data";  // 发送缓冲区uint8_t rx_data[4];            // 接收缓冲区t.rx_buffer = (void *)rx_data;esp_err_t ret = spi_device_polling_transmit(spi_handle, &t);通过rx_data接收:   spi_transaction_t t = {.rxlength = 8,                      // 接收数据长度为 8 位(1 字节).flags = SPI_TRANS_USE_RXDATA,      // 使用 rx_data 字段来存储接收数据.user = ctx,                        // 用户上下文数据};esp_err_t err = spi_device_polling_transmit(spi, &t);*out_data = t.rx_data[0];
通过tx_data发送:    spi_transaction_t t = {.cmd = CMD_WRITE | (addr & ADDR_MASK),  // 命令和地址,例如SPI EEPROM的写入操作.length = 8,                            // 发送数据长度为 8 位(1 字节).flags = SPI_TRANS_USE_TXDATA,          // 使用 tx_data 字段来发送数据.tx_data = {data},                      // 发送的数据.user = ctx,                            // 用户上下文数据};err = spi_device_polling_transmit(ctx->spi, &t);

最终代码参考:

esp-idf/examples/peripherals/spi_master/hd_eeprom

esp-idf/examples/peripherals/spi_master/lcd

这部分代码只是参考,不能在板卡上面跑哦,需要在板卡上面运行的,可以看下方的SPI屏幕驱动部分

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "driver/spi_master.h"
#include "driver/gpio.h"
#include "esp_log.h"// 定义 SPI 引脚
#define SPI_HOST     SPI2_HOST  // 使用 SPI2 主机
#define PIN_NUM_MISO 12  // MISO 引脚
#define PIN_NUM_MOSI 13  // MOSI 引脚
#define PIN_NUM_CLK  14  // SCLK 引脚
#define PIN_NUM_CS   15  // CS 引脚static const char *TAG = "SPI_EXAMPLE";  // 日志标签void app_main(void) {// 配置 SPI 总线spi_bus_config_t buscfg = {.miso_io_num = PIN_NUM_MISO,  // MISO 引脚.mosi_io_num = PIN_NUM_MOSI,  // MOSI 引脚.sclk_io_num = PIN_NUM_CLK,   // SCLK 引脚.quadwp_io_num = -1,          // 不使用 WP 引脚.quadhd_io_num = -1,          // 不使用 HD 引脚.max_transfer_sz = 4094,      // 最大传输大小为 4094 字节};// 初始化 SPI 总线ESP_ERROR_CHECK(spi_bus_initialize(SPI_HOST, &buscfg, 1));// 配置 SPI 设备spi_device_interface_config_t devcfg = {.clock_speed_hz = 10 * 1000 * 1000,  // 时钟速度为 10 MHz.mode = 0,                           // SPI 模式 0.spics_io_num = PIN_NUM_CS,          // CS 引脚.queue_size = 7,                     // 队列大小为 7,可以同时排队 7 个事务};// 初始化 SPI 设备spi_device_handle_t spi_handle;ESP_ERROR_CHECK(spi_bus_add_device(SPI_HOST, &devcfg, &spi_handle));// 准备 SPI 事务spi_transaction_t t;memset(&t, 0, sizeof(t));  // 初始化事务结构体t.length = 8 * 4;          // 传输数据长度为 4 字节(32 位)t.rxlength = 8 * 4;        // 接收数据长度为 4 字节(32 位)t.tx_buffer = (void *)"Data";  // 发送缓冲区uint8_t rx_data[4];        // 接收缓冲区t.rx_buffer = (void *)rx_data;// 执行 SPI 事务esp_err_t ret = spi_device_polling_transmit(spi_handle, &t);if (ret == ESP_OK) {ESP_LOGD(TAG, "SPI transaction successful");ESP_LOGD(TAG, "Received data: %s\n", rx_data);} else {ESP_LOGD(TAG, "SPI transaction failed: %s\n", esp_err_to_name(ret));}// 清理资源spi_bus_remove_device(spi_handle);  // 移除 SPI 设备spi_bus_free(SPI_HOST);             // 释放 SPI 总线
}

SPI屏幕

SPI屏幕使用的驱动芯片是ST7789,这个驱动芯片支持的分辨率是240*320,据厂家手册说明可知,由于是异形屏幕,屏幕的分辨率是172*320,所以驱动芯片左右两边分别有34列((240-172)/2) = 34是没有接到屏幕的,所以我们设置显示地址是,要偏移34列,屏幕接线部分如下:

从原理图可知:

SPI SCLK为GPIO_NUM_16
SPI MOSI为GPIO_NUM_17
SPI MISO不需要
LCD_DC为GPIO_NUM_21
LCD_RST为GPIO_NUM_18
LCD_CS为GPIO_NUM_15
背光IO为GPIO_NUM_2,背光有效电平为低电平(低电平点亮)

所以最终代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "driver/spi_master.h"
#include "driver/gpio.h"// 定义LCD使用的SPI主机
#define LCD_HOST SPI2_HOST// 定义SPI接口的引脚
#define PIN_NUM_MISO GPIO_NUM_NC
#define PIN_NUM_MOSI GPIO_NUM_17
#define PIN_NUM_CLK GPIO_NUM_16
#define PIN_NUM_CS GPIO_NUM_15// 定义LCD控制引脚
#define PIN_NUM_DC GPIO_NUM_21
#define PIN_NUM_RST GPIO_NUM_18
#define PIN_NUM_BCKL GPIO_NUM_2// 定义背光开启时的电平
#define LCD_BK_LIGHT_ON_LEVEL 0#define USE_HORIZONTAL 0 //设置横屏或者竖屏显示 0或1为竖屏 2或3为横屏
#if USE_HORIZONTAL == 0 || USE_HORIZONTAL == 1
#define EXAMPLE_LCD_H_RES 172
#define EXAMPLE_LCD_V_RES 320
#else
#define EXAMPLE_LCD_H_RES 320
#define EXAMPLE_LCD_V_RES 172
#endif#define WHITE 0xFFFF
#define BLACK 0x0000
#define BLUE 0x001F
#define BRED 0XF81Fconst unsigned char gImage_1[3200] = { /* 0X10,0X10,0X00,0X28,0X00,0X28,0X01,0X1B, */0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF7,0XBE,0XFF,0XFF,0XFF,0XDE,0XC6,0X38,0X8C,0X92,0X6B,0X8E,0X6B,0X6E,0X7C,0X10,0XAD,0X96,0XE7,0X3C,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XEF,0X5D,0X9D,0X15,0X63,0X4F,0X42,0X6C,0X32,0X0A,0X29,0X88,0X19,0X46,0X19,0X25,0X21,0X45,0X31,0XE8,0X6B,0X8E,0XC6,0X38,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XA5,0X36,0X53,0X10,0X4B,0X10,0X53,0X51,0X4B,0X0F,0X3A,0X6C,0X31,0XE9,0X21,0X67,0X19,0X25,0X10,0XE4,0X08,0XA3,0X00,0X62,0X08,0X83,0X52,0XCB,0XD6,0X9A,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0X3C,0X63,0X70,0X63,0XB3,0X7C,0XB8,0X63,0XF5,0X43,0X11,0X32,0X4D,0X29,0XEA,0X21,0X88,0X19,0X26,0X19,0X05,0X19,0X05,0X11,0X04,0X11,0X04,0X10,0XE4,0X00,0X83,0X08,0XA3,0X8C,0X72,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XDE,0XDB,0X3A,0X4B,0X42,0XF0,0X6C,0X35,0X4B,0X54,0X32,0XB1,0X2A,0X2E,0X21,0XEB,0X21,0XA9,0X19,0X67,0X19,0X05,0X11,0X04,0X11,0X04,0X11,0X04,0X11,0X04,0X11,0X04,0X19,0X05,0X10,0XE4,0X00,0X42,0X73,0XAF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XEF,0X5D,0X32,0X09,0X32,0X4C,0X4B,0X10,0X32,0X8F,0X2A,0X4F,0X2A,0X2E,0X19,0XCC,0X19,0X89,0X21,0X89,0X19,0X47,0X19,0X05,0X11,0X04,0X11,0X04,0X10,0XC4,0X10,0XC4,0X11,0X04,0X11,0X04,0X11,0X04,0X10,0XE4,0X00,0X42,0X84,0X31,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X52,0XEC,0X19,0X47,0X32,0X4C,0X2A,0X0B,0X21,0XEC,0X21,0XEC,0X22,0X0C,0X5B,0X91,0X4A,0XEE,0X11,0X06,0X19,0X26,0X19,0X04,0X10,0XE4,0X10,0XE4,0X29,0XA7,0X21,0X66,0X08,0XA3,0X19,0X05,0X11,0X04,0X11,0X04,0X10,0XE4,0X00,0X82,0XBD,0XF7,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XA5,0X35,0X08,0X83,0X21,0X88,0X21,0X88,0X21,0X89,0X21,0XAA,0X21,0X8A,0X42,0X6B,0X8C,0X71,0XFF,0XFF,0X8C,0X72,0X08,0X83,0X11,0X04,0X08,0XC4,0X42,0X29,0XDE,0XFB,0XEF,0X5D,0X5A,0XEC,0X08,0X83,0X11,0X04,0X11,0X04,0X11,0X04,0X08,0X83,0X31,0XE8,0XFF,0XDF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF7,0XBE,0X31,0XC7,0X10,0XC4,0X19,0X25,0X19,0X26,0X19,0X47,0X19,0X47,0X29,0XA8,0X52,0X8A,0X4A,0X28,0XAD,0X55,0XFF,0XFF,0X31,0XE8,0X08,0XA3,0X19,0X05,0X6B,0X4D,0X6B,0X4D,0XFF,0XFF,0XEF,0X7D,0X21,0X45,0X10,0XC4,0X11,0X04,0X11,0X04,0X11,0X04,0X00,0X62,0XAD,0X76,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XB5,0X96,0X00,0X62,0X11,0X04,0X19,0X04,0X11,0X05,0X19,0X05,0X08,0XC4,0X4A,0X8B,0XB5,0XB6,0XEF,0X5D,0XBD,0XF7,0XFF,0XFF,0X6B,0X8E,0X00,0X62,0X42,0X29,0X5A,0XAA,0X42,0X08,0XFF,0XFF,0XFF,0XFF,0X52,0XCC,0X08,0X83,0X11,0X04,0X11,0X04,0X11,0X04,0X08,0XA3,0X52,0XAD,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0X1C,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X63,0X4E,0X00,0X62,0X11,0X04,0X11,0X04,0X11,0X04,0X10,0XE4,0X00,0X62,0X63,0X8E,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X73,0XCF,0X00,0X01,0X9C,0XF3,0X63,0X2C,0XB5,0X96,0XFF,0XFF,0XFF,0XFF,0X5B,0X2D,0X00,0X83,0X11,0X04,0X11,0X04,0X11,0X04,0X10,0XE4,0X21,0X67,0XEF,0X3D,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XBD,0XF8,0XB5,0XB7,0XEF,0X9E,0X52,0XCB,0X94,0XB3,0XFF,0XFF,0XFF,0XFF,0XFF,0XDF,0X31,0XE8,0X08,0XA3,0X11,0X04,0X11,0X04,0X11,0X04,0X11,0X04,0X08,0XA3,0X42,0X49,0XF7,0XFF,0XF7,0XFF,0XFF,0XFF,0XFF,0XFF,0X4A,0X6A,0X00,0X01,0X84,0X72,0XFF,0XFF,0XFF,0XFF,0XF7,0XFF,0XEF,0XDF,0X3A,0X09,0X08,0XA3,0X11,0X04,0X11,0X04,0X11,0X04,0X11,0X04,0X11,0X05,0XBE,0X18,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X7B,0XF0,0X00,0X62,0X31,0XE8,0X31,0XC7,0X00,0X41,0XA5,0X35,0XFF,0XFF,0XEF,0X5D,0X21,0X46,0X10,0XC4,0X11,0X04,0X11,0X04,0X11,0X04,0X11,0X04,0X10,0XE4,0X08,0XA3,0X9D,0X76,0XF7,0XFF,0XFF,0XFF,0XAD,0XB7,0X08,0XA3,0X08,0XA3,0X31,0XC7,0XE7,0X9E,0XF7,0XFF,0XF7,0XFF,0XA5,0X76,0X08,0XA3,0X10,0XE4,0X11,0X04,0X11,0X04,0X11,0X04,0X11,0X05,0X11,0X05,0XA5,0X35,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XDE,0XDB,0X29,0XA7,0X00,0X83,0X10,0XC4,0X10,0XC4,0X10,0XC4,0XE7,0X1C,0XEF,0X9E,0X11,0X05,0X10,0XE4,0X11,0X04,0X11,0X04,0X11,0X04,0X11,0X04,0X19,0X04,0X08,0XC4,0X10,0XE5,0X6B,0XD1,0X6B,0XD1,0X08,0XC5,0X00,0X64,0X08,0XA5,0X00,0X43,0X32,0X2B,0X9D,0X77,0X84,0XB3,0X19,0X25,0X10,0XC4,0X11,0X04,0X11,0X04,0X11,0X04,0X11,0X04,0X19,0X25,0X09,0X26,0X9D,0X35,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X73,0XAF,0X00,0X62,0X19,0X04,0X19,0X05,0X00,0X82,0X5B,0X0D,0X9B,0X8E,0X10,0X62,0X11,0X05,0X11,0X04,0X11,0X04,0X19,0X04,0X10,0XE4,0X00,0X85,0X11,0X05,0X39,0XC4,0X5A,0X81,0X7B,0X40,0X9C,0X22,0XAC,0X43,0XA4,0X03,0X9B,0X83,0X72,0X82,0X49,0X82,0X18,0XC2,0X00,0XA4,0X00,0XC5,0X10,0XE4,0X19,0X04,0X11,0X04,0X19,0X05,0X19,0X47,0X11,0X67,0X5A,0XEC,0XFF,0XBE,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XDF,0XDE,0XDB,0X10,0XC4,0X10,0XE4,0X11,0X04,0X11,0X05,0X18,0XA4,0XC0,0X01,0X88,0X83,0X00,0XE4,0X19,0X05,0X19,0X04,0X08,0XC5,0X21,0X44,0X83,0X43,0XD5,0X23,0XFE,0X42,0XFE,0XE4,0XFF,0X27,0XFF,0X07,0XFE,0XA4,0XFE,0X64,0XFE,0X03,0XFD,0XA3,0XFC,0XE2,0XEC,0X42,0XB3,0X83,0X62,0X24,0X10,0XE5,0X08,0XC4,0X19,0X04,0X19,0X26,0X19,0XA8,0X21,0X87,0X90,0X00,0XBC,0XD3,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XDF,0XFF,0XFF,0X7C,0X10,0X00,0X42,0X19,0X05,0X11,0X05,0X28,0X83,0XD0,0X01,0XF8,0X44,0X48,0XA3,0X00,0XE4,0X08,0XC5,0X5A,0X44,0XED,0X02,0XFD,0XE2,0XFE,0X02,0XFE,0X66,0XFF,0X74,0XFF,0XB8,0XFF,0X73,0XF6,0XE7,0XF6,0XA6,0XF6,0X45,0XF5,0XA4,0XFC,0XC3,0XFC,0X62,0XFC,0XC2,0XFC,0XC2,0XCB,0XE3,0X49,0XC4,0X11,0X06,0X19,0X88,0X01,0X87,0X90,0XA4,0XF8,0X01,0X9A,0XEC,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF7,0XBE,0X31,0XE8,0X00,0X83,0X09,0X05,0X40,0X82,0XC0,0X01,0XF8,0X23,0XF0,0X85,0X48,0XA3,0X00,0XA4,0X5A,0X44,0XFD,0X02,0XCC,0X23,0XDC,0XC2,0XFE,0X04,0XFE,0X28,0XF6,0X48,0XF6,0X46,0XF6,0X24,0XF5,0XE4,0XFD,0X64,0XFC,0XE3,0XFC,0X62,0XFC,0XC2,0XE4,0X02,0XDC,0X02,0XFC,0XE2,0X7A,0XA4,0X01,0X48,0X01,0X67,0X78,0XC4,0XF8,0X24,0XF8,0X02,0XB0,0X84,0XE7,0X7D,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XDE,0XDB,0X19,0X25,0X00,0XA3,0X38,0XC4,0XE0,0X02,0XD8,0X22,0XF8,0X44,0XF8,0XA6,0X78,0XA4,0X00,0X63,0X21,0X43,0X72,0X83,0X39,0X83,0X9B,0X82,0XF5,0X21,0XFD,0X61,0XFD,0X22,0XFC,0XE2,0XFC,0XA2,0XFC,0X42,0XFC,0X42,0XFC,0X42,0XAB,0X22,0X41,0X83,0X92,0XC3,0X52,0X04,0X01,0X26,0X19,0X25,0X98,0XA4,0XF8,0X44,0XF8,0X23,0XF8,0X02,0XD0,0XA4,0XEF,0X9E,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XD6,0X9A,0X29,0X87,0X00,0XA5,0XB8,0X43,0XF8,0X22,0XE0,0X23,0XF8,0X65,0XF8,0XE8,0XC9,0X07,0X48,0X83,0X00,0X42,0X00,0XA3,0X00,0X84,0X29,0X63,0X7A,0XA2,0XB3,0X62,0XCB,0XA2,0XD3,0X62,0XBB,0X02,0X8A,0X82,0X39,0X83,0X00,0XA4,0X00,0XE5,0X00,0XE5,0X08,0XE5,0X60,0XC4,0XD8,0X64,0XF8,0X44,0XF8,0X24,0XF8,0X23,0XF8,0X02,0X88,0X83,0XC6,0XDB,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0X3D,0X5B,0X50,0X31,0X08,0XE8,0X23,0XF8,0X43,0XF0,0X44,0XF8,0X65,0XF9,0X09,0XF9,0XAB,0XD1,0X89,0X89,0X06,0X48,0XA3,0X18,0X42,0X00,0X02,0X00,0X42,0X00,0X61,0X00,0X82,0X00,0X62,0X00,0X62,0X00,0X83,0X20,0XA3,0X50,0XC4,0X88,0XA5,0XD8,0X85,0XF8,0X65,0XF8,0X44,0XF8,0X44,0XF8,0X23,0XF8,0X23,0XD0,0X03,0X10,0X82,0X29,0XC7,0XEF,0X5D,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X32,0X6C,0X38,0XA5,0XD8,0X02,0XF8,0X23,0XF8,0X65,0XF8,0X66,0XF8,0XA7,0XF9,0X4A,0XFA,0X0C,0XFA,0X4D,0XEA,0X4C,0XD2,0X0B,0XB9,0XA9,0XB1,0X68,0XA9,0X47,0XB1,0X27,0XB9,0X07,0XD1,0X07,0XE8,0XE7,0XF8,0XC7,0XF8,0XA7,0XF8,0X65,0XF8,0X65,0XF8,0X44,0XF8,0X23,0XF8,0X03,0XD0,0X02,0X28,0XA3,0X09,0X05,0X08,0XC4,0X5A,0XEC,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XDE,0XFB,0X19,0X05,0X00,0XC4,0X41,0XA7,0XC0,0XE6,0XF8,0X03,0XF8,0X86,0XF8,0XA7,0XF8,0X87,0XF8,0X86,0XF8,0XC7,0XF9,0X29,0XF9,0X8A,0XF9,0XAB,0XF9,0XAB,0XF9,0X8B,0XF9,0X6A,0XF9,0X29,0XF9,0X08,0XF8,0XC7,0XF8,0XA6,0XF8,0X86,0XF8,0X65,0XF8,0X64,0XF8,0X23,0XF0,0X02,0XB1,0X06,0X29,0X25,0X00,0XE4,0X10,0XE4,0X19,0X25,0X19,0X25,0X9D,0X14,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XAD,0X96,0X00,0X62,0X08,0X82,0X95,0X35,0XCE,0XBA,0XA2,0X8B,0XD0,0X44,0XF8,0X25,0XF8,0X87,0XF8,0XA7,0XF8,0XC7,0XF8,0XA7,0XF8,0X87,0XF8,0X86,0XF8,0X86,0XF8,0X86,0XF8,0X87,0XF8,0XA7,0XF8,0XA7,0XF8,0XA6,0XF8,0X85,0XF8,0X65,0XF8,0X64,0XF0,0X24,0XB8,0X64,0X93,0X0D,0XB6,0XBB,0X63,0XCF,0X08,0X83,0X11,0X04,0X10,0XE4,0X21,0X66,0X3A,0X49,0XEF,0X5D,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X94,0XD3,0X00,0X42,0X10,0XE4,0XCE,0XBB,0XFF,0XFF,0XE7,0XBE,0XB5,0X76,0XAA,0XCC,0XC1,0X07,0XE0,0X45,0XF8,0X45,0XF8,0X46,0XF8,0X66,0XF8,0X86,0XF8,0X86,0XF8,0X86,0XF8,0X86,0XF8,0X65,0XF8,0X45,0XF8,0X65,0XE8,0X65,0XD0,0X44,0XA8,0X43,0X88,0X01,0X90,0X82,0XD7,0X3C,0XEF,0XFF,0X95,0X55,0X08,0X83,0X11,0X04,0X11,0X04,0X19,0X05,0X19,0X46,0X94,0XB3,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X94,0XB3,0X00,0X41,0X21,0X86,0XDF,0X5D,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XDF,0XC6,0X7A,0XB4,0XD3,0XB3,0X4E,0XC2,0X2A,0XD1,0X68,0XE0,0XE6,0XE8,0XA6,0XE8,0XA5,0XE8,0XA5,0XD8,0XE6,0XC9,0X88,0XA9,0X06,0XA8,0X22,0XA8,0X02,0XA0,0X00,0XC8,0X00,0XD8,0X00,0XE5,0XF7,0XE7,0XFF,0XAD,0XF8,0X10,0XC4,0X10,0XE4,0X11,0X04,0X10,0XE4,0X11,0X05,0X4A,0X8B,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XA5,0X55,0X00,0X41,0X29,0XA7,0XDF,0X5D,0XF7,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XEF,0XFF,0XDF,0X7D,0XCE,0XDB,0XCE,0X59,0XCD,0XF8,0XCD,0XD7,0XC5,0XF7,0XCE,0X79,0XBE,0XFB,0XA2,0XAB,0XF0,0X03,0XF8,0X45,0XD0,0X42,0XE8,0X43,0XF0,0X00,0XD4,0X72,0XDF,0XFF,0XAE,0X39,0X10,0XE4,0X10,0XE4,0X11,0X04,0X10,0XE4,0X11,0X05,0X29,0X87,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XCE,0X59,0X08,0X83,0X21,0X46,0XD7,0X1C,0XF7,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XEF,0XFF,0XBA,0X8B,0XF8,0X04,0XF8,0X45,0XE0,0X62,0XF0,0X44,0XF8,0X00,0XDB,0X8E,0XDF,0XFF,0XA5,0XF8,0X10,0XC4,0X10,0XE4,0X10,0XE4,0X11,0X04,0X10,0XE4,0X19,0X25,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF7,0XBE,0X29,0X87,0X08,0X83,0XB6,0X39,0XF7,0XFF,0XF7,0XDF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XBE,0XBA,0X4A,0XF8,0X03,0XF8,0X45,0XF8,0X64,0XF8,0X44,0XF8,0X00,0XE3,0X6E,0XD7,0XFF,0X8C,0XF4,0X08,0X83,0X11,0X04,0X10,0XE4,0X10,0XE4,0X10,0XE4,0X19,0X05,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X73,0XEF,0X00,0X00,0X84,0X72,0XEF,0XFF,0XEF,0XBE,0XFF,0XDF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE7,0XDF,0XBA,0X8B,0XF8,0X03,0XF8,0X45,0XF8,0X45,0XF8,0X23,0XF8,0X00,0XD4,0XD3,0XD7,0XFF,0X5B,0X4E,0X00,0X21,0X3A,0X29,0XA5,0X55,0X08,0X83,0X10,0XC4,0X19,0X25,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XDE,0XFB,0X08,0XA3,0X31,0XE8,0XDF,0X9E,0XE7,0X9E,0XEF,0XBF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF7,0XFF,0XBC,0X51,0XE0,0X02,0XF8,0X03,0XF0,0X03,0XE0,0X43,0XC2,0XEC,0XCF,0X7E,0XBE,0XFC,0X21,0X46,0X00,0X21,0X94,0XD3,0XFF,0XFF,0X84,0X51,0X00,0X00,0X29,0X87,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X84,0X51,0X00,0X00,0X8C,0XF4,0XEF,0XFF,0XE7,0X9E,0XEF,0XBF,0XFF,0XDF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XDF,0X3D,0XBD,0X55,0XBC,0X52,0XBC,0X72,0XB5,0XB7,0XC7,0X5D,0XDF,0XFF,0X6B,0XF0,0X00,0X00,0X3A,0X09,0XF7,0XBF,0XFF,0XFF,0XFF,0XFF,0X9D,0X14,0XA5,0X55,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X4A,0XAC,0X08,0XA4,0XBE,0XBB,0XE7,0XDF,0XE7,0X7E,0XEF,0XBE,0XF7,0XDF,0XFF,0XDF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XDF,0XF7,0XDF,0XEF,0XFF,0XDF,0XDF,0XD7,0XBF,0XD7,0X9E,0XDF,0XDF,0XA5,0XD8,0X08,0X83,0X11,0X26,0XD6,0XDB,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XEE,0X79,0XDC,0X8B,0X31,0X21,0X21,0XA9,0XCF,0X3D,0XDF,0XBF,0XDF,0X7E,0XE7,0X9E,0XEF,0XBE,0XEF,0XBF,0XF7,0XDF,0XF7,0XDF,0XF7,0XDF,0XF7,0XDF,0XF7,0XDF,0XEF,0XBF,0XEF,0XBE,0XE7,0X9E,0XDF,0X7E,0XD7,0X5E,0XD7,0X5E,0XDF,0XDF,0XB6,0X9A,0X19,0X26,0X08,0X42,0XA3,0XED,0XFF,0XBF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XDD,0X74,0XDB,0XC0,0XFE,0X00,0XEE,0X42,0X42,0X02,0X21,0X89,0XB6,0X7B,0XDF,0XDF,0XD7,0X7E,0XDF,0X7E,0XDF,0X7E,0XE7,0X9E,0XE7,0X9E,0XE7,0X9E,0XE7,0X9E,0XE7,0X9E,0XDF,0X7E,0XDF,0X7E,0XD7,0X5D,0XD7,0X5D,0XDF,0X9E,0XE7,0XFF,0XA5,0XF8,0X11,0X07,0X18,0XE3,0XC5,0X02,0XFD,0X60,0XD3,0XE6,0XEE,0XDB,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF7,0X9E,0XBA,0X84,0XFC,0XC1,0XFE,0X42,0XFE,0X82,0XFE,0XA2,0X83,0X81,0X21,0X45,0X74,0X74,0XC7,0X5E,0XDF,0XDF,0XD7,0X7E,0XD7,0X5E,0XD7,0X5D,0XD7,0X5E,0XD7,0X5E,0XD7,0X5D,0XD7,0X5D,0XD7,0X5E,0XDF,0X9E,0XE7,0XFF,0XC7,0X3D,0X63,0XF1,0X08,0X84,0X52,0X42,0XE6,0X26,0XFF,0X29,0XFE,0X86,0XF3,0XE0,0XC3,0X6A,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XDE,0X18,0XD2,0XC1,0XFD,0XA2,0XFE,0X22,0XFE,0X42,0XFE,0X42,0XFE,0X62,0XD4,0XE2,0X6A,0X41,0X42,0X49,0X74,0X53,0XA6,0X3B,0XC7,0X3E,0XD7,0XBF,0XD7,0XBF,0XD7,0XBF,0XDF,0XBF,0XD7,0XBF,0XC7,0X3E,0XA6,0X1A,0X63,0XF2,0X29,0XA7,0X41,0X82,0XB4,0X22,0XFE,0X62,0XFE,0X83,0XFE,0XAA,0XFF,0X0F,0XFD,0X67,0XBA,0X63,0XEF,0X3C,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE6,0X9A,0XD2,0X80,0XFD,0X21,0XFD,0XC2,0XF5,0XE2,0XF5,0XC2,0XF5,0X82,0XFD,0X82,0XFD,0X62,0XDC,0X61,0X9B,0X21,0X6A,0X84,0X6A,0XE9,0X63,0X2C,0X63,0XAF,0X74,0X11,0X63,0X6E,0X63,0X2C,0X5A,0X89,0X52,0X04,0X7A,0X81,0XCB,0XC2,0XFC,0XE2,0XFD,0X62,0XFD,0X82,0XFD,0XC2,0XFD,0XC2,0XFD,0XE4,0XFD,0X24,0XCA,0X62,0XE7,0X1C,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XCC,0XB1,0XD2,0X81,0XF3,0XC0,0XFC,0XC1,0XFD,0X02,0XFD,0X02,0XFC,0XE2,0XFC,0XC2,0XFC,0XC2,0XFC,0X81,0XFB,0X80,0XC9,0XC0,0X81,0XA4,0XAD,0X35,0XCE,0X59,0X9C,0X71,0X81,0X21,0XDA,0X00,0XFB,0XA1,0XFC,0X82,0XFC,0XA2,0XFC,0X82,0XFC,0XA2,0XFD,0X02,0XFD,0X22,0XFC,0XE2,0XFC,0X00,0XDA,0X60,0XCC,0X90,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XDE,0X59,0XC4,0X0D,0XCB,0X06,0XD2,0XE4,0XDB,0X03,0XDB,0X03,0XDA,0XE3,0XD2,0XC3,0XC2,0XA4,0XB3,0X09,0XBC,0XD2,0XF7,0X9E,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XE6,0XFB,0XB4,0X0E,0XBA,0XA6,0XD2,0X83,0XE2,0XE3,0XEB,0X02,0XEB,0X22,0XE3,0X22,0XDB,0X03,0XD2,0XE4,0XC3,0X6A,0XD5,0XB6,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,};spi_device_handle_t spi;/* 向LCD发送一个命令。使用spi_device_polling_transmit函数,该函数会等待传输完成。*/
void lcd_cmd(const uint8_t cmd)
{esp_err_t ret;spi_transaction_t t;// D/C线需要设置为0,表示发送命令gpio_set_level(PIN_NUM_DC, 0);gpio_set_level(PIN_NUM_CS, 0);// 初始化事务结构体memset(&t, 0, sizeof(t));// 命令长度为8位t.length = 8;// 要发送的命令数据t.tx_buffer = &cmd;// 发送命令ret = spi_device_polling_transmit(spi, &t);// 确保发送成功assert(ret == ESP_OK);gpio_set_level(PIN_NUM_CS, 1);gpio_set_level(PIN_NUM_DC, 1);
}void lcd_data8(const uint8_t data)
{esp_err_t ret;spi_transaction_t t;// D/C线需要设置为1,表示发送数据gpio_set_level(PIN_NUM_CS, 0);gpio_set_level(PIN_NUM_DC, 1);// 初始化事务结构体memset(&t, 0, sizeof(t));// 数据长度(位)t.length = 8;// 要发送的数据t.tx_buffer = &data;// 发送数据ret = spi_device_polling_transmit(spi, &t);// 确保发送成功assert(ret == ESP_OK);gpio_set_level(PIN_NUM_CS, 1);
}void lcd_data16(const uint16_t data)
{uint16_t send_data;// 大端模式:直接发送原始数据// send_data = data;// // 小端模式:交换字节顺序send_data = (data << 8) | (data >> 8);esp_err_t ret;spi_transaction_t t;// D/C线需要设置为1,表示发送数据gpio_set_level(PIN_NUM_CS, 0);gpio_set_level(PIN_NUM_DC, 1);// 初始化事务结构体memset(&t, 0, sizeof(t));// 数据长度(位)t.length = 16;// 要发送的数据t.tx_buffer = &send_data;// 发送数据ret = spi_device_polling_transmit(spi, &t);// 确保发送成功assert(ret == ESP_OK);gpio_set_level(PIN_NUM_CS, 1);
}// 初始化LCD
void lcd_init()
{// 初始化非SPI的GPIO引脚gpio_config_t io_conf = {};// 配置DC、RST和BCKL引脚io_conf.pin_bit_mask = ((1ULL << PIN_NUM_DC) | (1ULL << PIN_NUM_RST) | (1ULL << PIN_NUM_BCKL));// 设置为输出模式io_conf.mode = GPIO_MODE_OUTPUT;// 启用上拉电阻io_conf.pull_up_en = true;// 应用GPIO配置gpio_config(&io_conf);// 复位LCDgpio_set_level(PIN_NUM_RST, 0);vTaskDelay(100 / portTICK_PERIOD_MS);gpio_set_level(PIN_NUM_RST, 1);vTaskDelay(100 / portTICK_PERIOD_MS);// 检测LCD类型printf("LCD ST7789V initialization.\n");// 使用ST7789V的初始化命令lcd_cmd(0x11);lcd_cmd(0x36);if (USE_HORIZONTAL == 0)lcd_data8(0x00);else if (USE_HORIZONTAL == 1)lcd_data8(0xC0);else if (USE_HORIZONTAL == 2)lcd_data8(0x70);elselcd_data8(0xA0);lcd_cmd(0x3A);lcd_data8(0x05);lcd_cmd(0xB2);lcd_data8(0x0C);lcd_data8(0x0C);lcd_data8(0x00);lcd_data8(0x33);lcd_data8(0x33);lcd_cmd(0xB7);lcd_data8(0x35);lcd_cmd(0xBB);lcd_data8(0x35);lcd_cmd(0xC0);lcd_data8(0x2C);lcd_cmd(0xC2);lcd_data8(0x01);lcd_cmd(0xC3);lcd_data8(0x13);lcd_cmd(0xC4);lcd_data8(0x20);lcd_cmd(0xC6);lcd_data8(0x0F);lcd_cmd(0xD0);lcd_data8(0xA4);lcd_data8(0xA1);lcd_cmd(0xD6);lcd_data8(0xA1);lcd_cmd(0xE0);lcd_data8(0xF0);lcd_data8(0x00);lcd_data8(0x04);lcd_data8(0x04);lcd_data8(0x04);lcd_data8(0x05);lcd_data8(0x29);lcd_data8(0x33);lcd_data8(0x3E);lcd_data8(0x38);lcd_data8(0x12);lcd_data8(0x12);lcd_data8(0x28);lcd_data8(0x30);lcd_cmd(0xE1);lcd_data8(0xF0);lcd_data8(0x07);lcd_data8(0x0A);lcd_data8(0x0D);lcd_data8(0x0B);lcd_data8(0x07);lcd_data8(0x28);lcd_data8(0x33);lcd_data8(0x3E);lcd_data8(0x36);lcd_data8(0x14);lcd_data8(0x14);lcd_data8(0x29);lcd_data8(0x32);lcd_cmd(0x21);lcd_cmd(0x11);vTaskDelay(120 / portTICK_PERIOD_MS);lcd_cmd(0x29);// 启用背光gpio_set_level(PIN_NUM_BCKL, LCD_BK_LIGHT_ON_LEVEL);
}/*** @brief 设置绘制的起始和结束地址* x1,x2 设置列的起始和结束地址* y1,y2 设置行的起始和结束地址*/
void lcd_address_set(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
{if (USE_HORIZONTAL == 0){lcd_cmd(0x2a);       // 列地址设置lcd_data16(x1 + 34); // 偏移34是因为屏幕驱动芯片是240*320,但是屏幕尺寸是172*320,左右会有34的黑边lcd_data16(x2 + 34);lcd_cmd(0x2b); // 行地址设置lcd_data16(y1);lcd_data16(y2);lcd_cmd(0x2c); // 储存器写}else if (USE_HORIZONTAL == 1){lcd_cmd(0x2a); // 列地址设置lcd_data16(x1 + 34);lcd_data16(x2 + 34);lcd_cmd(0x2b); // 行地址设置lcd_data16(y1);lcd_data16(y2);lcd_cmd(0x2c); // 储存器写}else if (USE_HORIZONTAL == 2){lcd_cmd(0x2a); // 列地址设置lcd_data16(x1);lcd_data16(x2);lcd_cmd(0x2b); // 行地址设置lcd_data16(y1 + 34);lcd_data16(y2 + 34);lcd_cmd(0x2c); // 储存器写}else{lcd_cmd(0x2a); // 列地址设置lcd_data16(x1);lcd_data16(x2);lcd_cmd(0x2b); // 行地址设置lcd_data16(y1 + 34);lcd_data16(y2 + 34);lcd_cmd(0x2c); // 储存器写}
}/*** @brief 在指定区域填充颜色* xsta,ysta   起始坐标* xend,yend   终止坐标* color       要填充的颜色*/
void lcd_fill(uint16_t xsta, uint16_t ysta, uint16_t xend, uint16_t yend, uint16_t color)
{uint16_t i, j;lcd_address_set(xsta, ysta, xend - 1, yend - 1); // 设置显示范围for (i = ysta; i < yend; i++){for (j = xsta; j < xend; j++){lcd_data16(color);}}
}void lcd_draw_point(uint16_t x, uint16_t y, uint16_t color)
{lcd_address_set(x, y, x, y); // 设置光标位置lcd_data16(color);
}void lcd_draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
{uint16_t t;int xerr = 0, yerr = 0, delta_x, delta_y, distance;int incx, incy, uRow, uCol;delta_x = x2 - x1; // 计算坐标增量delta_y = y2 - y1;uRow = x1; // 画线起点坐标uCol = y1;if (delta_x > 0)incx = 1; // 设置单步方向else if (delta_x == 0)incx = 0; // 垂直线else{incx = -1;delta_x = -delta_x;}if (delta_y > 0)incy = 1;else if (delta_y == 0)incy = 0; // 水平线else{incy = -1;delta_y = -delta_y;}if (delta_x > delta_y)distance = delta_x; // 选取基本增量坐标轴elsedistance = delta_y;for (t = 0; t < distance + 1; t++){lcd_draw_point(uRow, uCol, color); // 画点xerr += delta_x;yerr += delta_y;if (xerr > distance){xerr -= distance;uRow += incx;}if (yerr > distance){yerr -= distance;uCol += incy;}}
}void lcd_draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2,uint16_t color)
{lcd_draw_line(x1,y1,x2,y1,color);lcd_draw_line(x1,y1,x1,y2,color);lcd_draw_line(x1,y2,x2,y2,color);lcd_draw_line(x2,y1,x2,y2,color);
}void lcd_draw_picture(uint16_t x,uint16_t y,uint16_t length,uint16_t width,const uint8_t pic[])
{uint16_t i,j;uint32_t k=0;lcd_address_set(x,y,x+length-1,y+width-1);for(i=0;i<length;i++){for(j=0;j<width;j++){lcd_data8(pic[k*2]);lcd_data8(pic[k*2+1]);k++;}}          
}// 主函数,程序入口
void app_main(void)
{esp_err_t ret;// SPI总线配置结构体spi_bus_config_t buscfg = {.miso_io_num = PIN_NUM_MISO,.mosi_io_num = PIN_NUM_MOSI,.sclk_io_num = PIN_NUM_CLK,.quadwp_io_num = -1,.quadhd_io_num = -1,.max_transfer_sz = EXAMPLE_LCD_H_RES * EXAMPLE_LCD_V_RES * 2,};// SPI设备接口配置结构体spi_device_interface_config_t devcfg = {.clock_speed_hz = 10 * 1000 * 1000, // 时钟频率为10MHz.mode = 0,                          // SPI模式0.spics_io_num = PIN_NUM_CS,         // CS引脚.queue_size = 7,                    // 一次最多可以排队7个事务};// 初始化SPI总线ret = spi_bus_initialize(LCD_HOST, &buscfg, SPI_DMA_CH_AUTO);// 检查初始化结果ESP_ERROR_CHECK(ret);// 将LCD设备添加到SPI总线ret = spi_bus_add_device(LCD_HOST, &devcfg, &spi);// 检查添加设备结果ESP_ERROR_CHECK(ret);// 初始化LCDlcd_init(spi);while (1){lcd_fill(0, 0, EXAMPLE_LCD_H_RES, EXAMPLE_LCD_V_RES, WHITE);vTaskDelay(1000 / portTICK_PERIOD_MS);lcd_fill(0, 0, EXAMPLE_LCD_H_RES, EXAMPLE_LCD_V_RES, BLUE);vTaskDelay(1000 / portTICK_PERIOD_MS);lcd_fill(0, 0, EXAMPLE_LCD_H_RES, EXAMPLE_LCD_V_RES, BRED);vTaskDelay(1000 / portTICK_PERIOD_MS);lcd_draw_rectangle(10,50,100,150,BLUE);vTaskDelay(1000 / portTICK_PERIOD_MS);lcd_draw_picture(10,200,40,40,gImage_1);vTaskDelay(1000 / portTICK_PERIOD_MS);}
}

相关文章:

  • 【Docker管理工具】部署Docker管理面板DweebUI
  • 鲲鹏Arm+麒麟V10,国产化信创 K8s 离线部署保姆级教程
  • 鸿蒙OSUniApp页面切换动效实战:打造流畅精致的转场体验#三方框架 #Uniapp
  • InnoDB引擎逻辑存储结构及架构
  • 【图像处理基石】如何进行图像畸变校正?
  • 面试中的项目经验考查:如何让实战经历成为你的决胜王牌
  • 下载即转化的商业密码:解析华为应用商店CPD广告的智能投放逻辑
  • Ubuntu下实现nginx反向代理
  • 基于SpringBoot的商家销售管理网站的设计与实现
  • ubuntu20.04安装教程(图文详解)
  • 历年中南大学计算机保研上机真题
  • LeetCode hot100-8
  • Ubuntu 22.04 上使用 Docker 安装 RagFlow
  • ass字幕嵌入mp4带偏移
  • Ubuntu 下同名文件替换后编译链接到旧内容的现象分析
  • 实验分享|基于sCMOS相机科学成像技术的耐高温航空涂层材料损伤检测实验
  • leetcode hot100刷题日记——29.合并两个有序链表
  • 历年武汉大学计算机保研上机真题
  • USB充电检测仪-2.USB充电检测仪硬件设计
  • 解决访问网站提示“405 很抱歉,由于您访问的URL有可能对网站造成安全威胁,您的访问被阻断”问题
  • 新手怎么做自己网站广告/关键词有哪些?
  • 移动互联网开发作业/seo 网站排名
  • 滁州做网站电话号码/百度培训
  • 织梦网站怎样做防护/网络推广的方法有
  • 乐清网站只做/最新足球新闻头条
  • 开发一个app要多久/武汉百度快照优化排名