esp32课设记录(二)lcd屏显示文字与照片
取模软件链接:
链接: 百度网盘 请输入提取码 提取码: 1234
课设要求如图所示,因此需要在esp32显示文字和照片。在上个文章中我已经写了按键相关内容。这篇主要描述怎么显示文字和照片。我使用的是ESP-IDF库。
本项目使用的是基于ST7789驱动芯片的LCD屏幕,通过SPI接口与ESP32通信。这是一个彩色TFT显示屏,具有以下特点:
分辨率:128×160像素
色深:16位色(65536色)
通信方式:SPI(串行外设接口)
控制引脚定义:
#define LCD_PIN_SCL 5 // SPI时钟信号
#define LCD_PIN_SDA 4 // SPI数据信号
#define LCD_PIN_RES 0 // 复位信号
#define LCD_PIN_DC 3 // 数据/命令选择信号
#define LCD_PIN_CS 1 // 片选信号
#define LCD_PIN_BL 2 // 背光控制信号
初始化
感觉和stm32的标准库蛮像的。里面的函数都是ESP-IDF库自带的。
LCD的初始化过程非常关键,按照以下顺序执行:
1.配置背光为输出模式,输出高电平。
2. 配置并初始化SPI总线
各参数详细说明:
sclk_io_num:
指定用于SPI时钟信号的GPIO引脚号
该时钟信号同步数据传输,决定了通信速度
mosi_io_num:
Master Out Slave In,主设备输出/从设备输入
ESP32通过这根线发送数据到LCD
miso_io_num:
Master In Slave Out,主设备输入/从设备输出
设为-1表示不使用此功能
LCD显示通常是单向通信,不需要从LCD读取数据
quadwp_io_num & quadhd_io_num:
用于四线SPI模式的额外数据线
设为-1表示使用标准SPI而非四线模式
max_transfer_sz:
单次SPI传输的最大字节数
设置为整个屏幕的数据量:宽×高×每像素字节数
16位色彩深度,每像素2字节,故乘以2
3. 配置LCD面板IO
各参数详细说明:
dc_gpio_num = LCD_PIN_DC - 数据/命令选择线,区分发送给LCD的是命令还是数据
cs_gpio_num = LCD_PIN_CS - 片选信号线,当有多个SPI设备时,用于选择LCD
pclk_hz = LCD_PIXEL_CLOCK_HZ - 时钟频率,决定数据传输速率,此处为20MHz
spi_mode = 0 - SPI模式,定义时钟极性和相位:模式0:空闲时时钟为低,在上升沿采样
lcd_cmd_bits = 8 - 命令位宽,LCD控制命令的位数
lcd_param_bits = 8 - 参数位宽,命令参数的位数
trans_queue_depth = 10 - 传输队列深度,可以排队等待的传输请求数量,提高吞吐量
4. 创建ST7789面板控制器
.reset_gpio_num = LCD_PIN_RES
指定用于重置LCD控制器的GPIO引脚。初始化过程中,ESP32会通过这个引脚发送复位信号,使LCD控制器恢复到已知初始状态。通常是先将此引脚拉低一段时间(10-100ms),然后拉高,触发硬件复位。
.rgb_endian = LCD_RGB_ENDIAN_RGB
设置RGB颜色数据的字节顺序
LCD_RGB_ENDIAN_RGB:标准RGB格式,红色分量在高位
LCD_RGB_ENDIAN_BGR:BGR格式,蓝色分量在高位
.bits_per_pixel = 16
设置每个像素的位深度。值=16:表示使用RGB565颜色格式(红色5位,绿色6位,蓝色5位)。
数据结构:16位色模式下,每个像素占用2个字节内存。
显示能力:支持65536种颜色
5. 初始化面板并配置显示参数
6. 分配显示缓冲区并清空屏幕
// LCD相关句柄
esp_lcd_panel_handle_t panel_handle = NULL;
uint16_t *lcd_buffer = NULL;// 初始化背光,就是搞高电平ovo
void backlight_init(void)
{gpio_config_t io_conf = {.pin_bit_mask = (1ULL << LCD_PIN_BL),.mode = GPIO_MODE_OUTPUT,.pull_up_en = GPIO_PULLUP_DISABLE,.pull_down_en = GPIO_PULLDOWN_DISABLE,.intr_type = GPIO_INTR_DISABLE,};gpio_config(&io_conf);// 打开背光(根据接线可能需要调整电平)gpio_set_level(LCD_PIN_BL, 1);
}// 清除屏幕上的文本区域
void clear_text_area(uint16_t *buffer, int width, int height)
{// 使用黑色填充文本区域for (int y = 0; y < height; y++){for (int x = 0; x < width; x++){buffer[y * width + x] = 0x0000; // 黑色}}
}void lcd_init(void) {// 1. 初始化背光backlight_init();// 2. 配置并初始化SPI总线// SPI总线配置spi_bus_config_t buscfg = {.sclk_io_num = LCD_PIN_SCL,.mosi_io_num = LCD_PIN_SDA,.miso_io_num = -1, // 不使用MISO.quadwp_io_num = -1,.quadhd_io_num = -1,.max_transfer_sz = LCD_H_RES * LCD_V_RES * 2, // 16bit/pixel};ESP_ERROR_CHECK(spi_bus_initialize(LCD_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO));// 3. 配置LCD面板IOesp_lcd_panel_io_handle_t io_handle = NULL;esp_lcd_panel_io_spi_config_t io_config = {.dc_gpio_num = LCD_PIN_DC,.cs_gpio_num = LCD_PIN_CS,.pclk_hz = LCD_PIXEL_CLOCK_HZ,.lcd_cmd_bits = 8,.lcd_param_bits = 8,.spi_mode = 0,.trans_queue_depth = 10,};ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)LCD_SPI_HOST, &io_config, &io_handle));// 4. 创建ST7789面板控制器esp_lcd_panel_dev_config_t panel_config = {.reset_gpio_num = LCD_PIN_RES,.rgb_endian = LCD_RGB_ENDIAN_RGB, // 使用RGB格式.bits_per_pixel = 16,};// 5. 初始化面板并配置显示参数// 初始化LCD面板ESP_LOGI(TAG, "正在初始化LCD面板");ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle));// 初始化LCD面板ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle));ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle));// 应用正确的显示设置ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel_handle, false)); // 不交换XYESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, false, false)); // 不镜像ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel_handle, false)); // 不反转颜色// 开启显示ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true));// 6. 分配显示缓冲区并清空屏幕// 分配显示缓冲区lcd_buffer = heap_caps_malloc(LCD_H_RES * LCD_V_RES * sizeof(uint16_t), MALLOC_CAP_DMA);if (!lcd_buffer){ESP_LOGE(TAG, "内存分配失败");return;}// 清空屏幕clear_text_area(lcd_buffer, LCD_H_RES, LCD_V_RES);
}// 释放LCD资源
void lcd_deinit(void)
{if (lcd_buffer){free(lcd_buffer);lcd_buffer = NULL;}
}
显示图片
我的图片显示使用的是大端、rgb565、水平扫描。
用image2lcd软件,配置如图:
取模软件链接:
链接: 百度网盘 请输入提取码 提取码: 1234
可以先用这张测试图片测试,我是网上下载了一个三原色图并且加了个圈,只要这张图所有颜色显示对了,结果包对的!!!!
我在图片显示这边卡了很久很久,最后发现是大端小端的问题,这个一定要注意!!!!
小技巧:当图片一直颜色不对的时候,可以排列组合n种图片显示方式,比如rgb/bgr,大端/小端等等,每隔1s切换一次,最后看第几次显示的是对的。
把数据粘贴过去,变成单独文件。然后直接主函数调用就行。
#include "wyh_pic.h"const unsigned char gImage_wyh_pic[32768] = {0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,......
decode_image(gImage_wyh_pic, lcd_buffer, LCD_H_RES, LCD_V_RES);
显示汉字
用取模软件取模,我的设置是:阴码,逐行,逆向,十六进制,C51格式。
取模软件链接:
链接: 百度网盘 请输入提取码 提取码: 1234
由于我要显示的中文字符实在太多太多了,有大几十个,而且经常会有复用的情况。于是我用了一种简单高效的字库查表方式。
先定义一个结构体:
// 中文字符结构体
typedef struct
{uint16_t unicode; // Unicode编码const uint8_t *bitmap; // 16x16点阵数据
} chinese_char_t;
Unicode编码:每个汉字的唯一标识符,如"王"的Unicode是0x738B
点阵数据:16×16像素的点阵,每个汉字占用32字节(16行×每行2字节)
然后复制粘贴取模结果。看我右边预览就知道有多少中文字符了。比如:
static const uint8_t char_jie[] = {0x08, 0x01, 0x08, 0x02, 0xC8, 0x3F, 0x08, 0x00, 0xBF, 0x10, 0x08, 0x09, 0xE8, 0x7F, 0x08, 0x02,0x18, 0x02, 0xEC, 0x7F, 0x0B, 0x11, 0x88, 0x10, 0x08, 0x09, 0x08, 0x06, 0x8A, 0x19, 0x64, 0x20 /*"接",13*/
};
之后构建字符表:
static const chinese_char_t chinese_chars[] = {{0x5DF2, char_yi}, // 已{0x8FDE, char_lian}, // 连{0x63A5, char_jie}, // 接// ...更多字符
};#define NUM_CHINESE_CHARS (sizeof(chinese_chars) / sizeof(chinese_char_t))
//自动计算中文字库数组中包含的汉字数量
最后编写一个查询函数,输入unicode码就能找到汉字的取模结果
// 查找中文字符点阵数据
const uint8_t *get_chinese_char_bitmap(uint16_t unicode)
{for (int i = 0; i < NUM_CHINESE_CHARS; i++){if (chinese_chars[i].unicode == unicode){return chinese_chars[i].bitmap;}}return NULL; // 未找到对应字符
}
最后这样调用就行了
draw_string(lcd_buffer, 0, 0, "设备信息", 0xFFFF, LCD_H_RES);
我之后的功能函数会自动处理转换,可以看到相当方便,扩展也很简单。
功能函数
一些函数,适配屏幕,可以直接调用。主要包含中文显示,ASCII显示,图片显示功能。
// 显示屏参数
#define LCD_H_RES 128 // 水平分辨率
#define LCD_V_RES 160 // 垂直分辨率
#define LCD_PIXEL_CLOCK_HZ (20 * 1000 * 1000) // 20MHz SPI时钟
#define LCD_SPI_HOST SPI2_HOST// 添加图片尺寸常量
#define IMAGE_WIDTH 128 // 图片宽度
#define IMAGE_HEIGHT 128 // 图片高度// 字体设置
#define FONT_WIDTH 6 // 英文字符宽度
#define FONT_HEIGHT 8 // 英文字符高度
#define CHINESE_FONT_WIDTH 16 // 中文字符宽度
#define CHINESE_FONT_HEIGHT 16 // 中文字符高度
#define TEXT_LINE_MAX 19 // 最大行数 (160/8 - 1)
#define TEXT_COLUMN_MAX 21 // 最大列数 (128/6)// LCD相关句柄
extern esp_lcd_panel_handle_t panel_handle;
extern uint16_t *lcd_buffer;// 颜色格式转换函数 ,大端
uint16_t convert_color_format(uint8_t byte1, uint8_t byte2)
{return (byte1 << 8) | byte2;
}// 解码图像函数
void decode_image(const unsigned char *src_data, uint16_t *dest_buffer, int width, int height)
{// 使用定义的图片尺寸常量const int img_width = IMAGE_WIDTH;const int img_height = IMAGE_HEIGHT;// 清空缓冲区为黑色for (int i = 0; i < width * height; i++){dest_buffer[i] = 0x0000; // 黑色}// 根据显示屏和图像尺寸计算居中位置int start_x = (width - img_width) / 2;int start_y = (height - img_height) / 2;if (start_x < 0)start_x = 0;if (start_y < 0)start_y = 0;// 复制图像数据到缓冲区的居中位置for (int y = 0; y < img_height && y + start_y < height; y++){for (int x = 0; x < img_width && x + start_x < width; x++){// 计算源位置 - 水平扫描模式int src_pos = (y * img_width + x) * 2; // 每个像素2字节// 读取像素数据uint8_t byte1 = src_data[src_pos];uint8_t byte2 = src_data[src_pos + 1];// 转换颜色格式 - 使用正确的格式uint16_t pixel = convert_color_format(byte1, byte2);// 计算目标缓冲区位置int dest_pos = (y + start_y) * width + (x + start_x);// 写入像素数据dest_buffer[dest_pos] = pixel;}}
}// 绘制单个字符函数 (简单ASCII字体)
void draw_char(uint16_t *buffer, int x, int y, char ch, uint16_t color, int width)
{// 简单ASCII字体定义 (仅支持基本ASCII)// 这是一个非常简单的5x7字体,每个字节代表一行,每位代表一个像素static const unsigned char font5x7[][5] = {{0x00, 0x00, 0x00, 0x00, 0x00}, // 空格{0x00, 0x00, 0x5F, 0x00, 0x00}, // !{0x00, 0x07, 0x00, 0x07, 0x00}, // "{0x14, 0x7F, 0x14, 0x7F, 0x14}, // #{0x24, 0x2A, 0x7F, 0x2A, 0x12}, // ${0x23, 0x13, 0x08, 0x64, 0x62}, // %{0x36, 0x49, 0x55, 0x22, 0x50}, // &{0x00, 0x05, 0x03, 0x00, 0x00}, // '{0x00, 0x1C, 0x22, 0x41, 0x00}, // ({0x00, 0x41, 0x22, 0x1C, 0x00}, // ){0x08, 0x2A, 0x1C, 0x2A, 0x08}, // *{0x08, 0x08, 0x3E, 0x08, 0x08}, // +{0x00, 0x50, 0x30, 0x00, 0x00}, // ,{0x08, 0x08, 0x08, 0x08, 0x08}, // -{0x00, 0x60, 0x60, 0x00, 0x00}, // .{0x20, 0x10, 0x08, 0x04, 0x02}, // /{0x3E, 0x51, 0x49, 0x45, 0x3E}, // 0{0x00, 0x42, 0x7F, 0x40, 0x00}, // 1{0x42, 0x61, 0x51, 0x49, 0x46}, // 2{0x21, 0x41, 0x45, 0x4B, 0x31}, // 3{0x18, 0x14, 0x12, 0x7F, 0x10}, // 4{0x27, 0x45, 0x45, 0x45, 0x39}, // 5{0x3C, 0x4A, 0x49, 0x49, 0x30}, // 6{0x01, 0x71, 0x09, 0x05, 0x03}, // 7{0x36, 0x49, 0x49, 0x49, 0x36}, // 8{0x06, 0x49, 0x49, 0x29, 0x1E}, // 9{0x00, 0x36, 0x36, 0x00, 0x00}, // :{0x00, 0x56, 0x36, 0x00, 0x00}, // ;{0x00, 0x08, 0x14, 0x22, 0x41}, // <{0x14, 0x14, 0x14, 0x14, 0x14}, // ={0x41, 0x22, 0x14, 0x08, 0x00}, // >{0x02, 0x01, 0x51, 0x09, 0x06}, // ?{0x32, 0x49, 0x79, 0x41, 0x3E}, // @{0x7E, 0x11, 0x11, 0x11, 0x7E}, // A{0x7F, 0x49, 0x49, 0x49, 0x36}, // B{0x3E, 0x41, 0x41, 0x41, 0x22}, // C{0x7F, 0x41, 0x41, 0x22, 0x1C}, // D{0x7F, 0x49, 0x49, 0x49, 0x41}, // E{0x7F, 0x09, 0x09, 0x01, 0x01}, // F{0x3E, 0x41, 0x41, 0x49, 0x3A}, // G{0x7F, 0x08, 0x08, 0x08, 0x7F}, // H{0x00, 0x41, 0x7F, 0x41, 0x00}, // I{0x20, 0x40, 0x41, 0x3F, 0x01}, // J{0x7F, 0x08, 0x14, 0x22, 0x41}, // K{0x7F, 0x40, 0x40, 0x40, 0x40}, // L{0x7F, 0x02, 0x04, 0x02, 0x7F}, // M{0x7F, 0x04, 0x08, 0x10, 0x7F}, // N{0x3E, 0x41, 0x41, 0x41, 0x3E}, // O{0x7F, 0x09, 0x09, 0x09, 0x06}, // P{0x3E, 0x41, 0x51, 0x21, 0x5E}, // Q{0x7F, 0x09, 0x19, 0x29, 0x46}, // R{0x46, 0x49, 0x49, 0x49, 0x31}, // S{0x01, 0x01, 0x7F, 0x01, 0x01}, // T{0x3F, 0x40, 0x40, 0x40, 0x3F}, // U{0x1F, 0x20, 0x40, 0x20, 0x1F}, // V{0x7F, 0x20, 0x18, 0x20, 0x7F}, // W{0x63, 0x14, 0x08, 0x14, 0x63}, // X{0x03, 0x04, 0x78, 0x04, 0x03}, // Y{0x61, 0x51, 0x49, 0x45, 0x43}, // Z{0x00, 0x00, 0x7F, 0x41, 0x41}, // [{0x02, 0x04, 0x08, 0x10, 0x20}, // '\'{0x41, 0x41, 0x7F, 0x00, 0x00}, // ]{0x04, 0x02, 0x01, 0x02, 0x04}, // ^{0x40, 0x40, 0x40, 0x40, 0x40}, // _{0x00, 0x01, 0x02, 0x04, 0x00}, // `{0x20, 0x54, 0x54, 0x54, 0x78}, // a{0x7F, 0x48, 0x44, 0x44, 0x38}, // b{0x38, 0x44, 0x44, 0x44, 0x20}, // c{0x38, 0x44, 0x44, 0x48, 0x7F}, // d{0x38, 0x54, 0x54, 0x54, 0x18}, // e{0x08, 0x7E, 0x09, 0x01, 0x02}, // f{0x08, 0x14, 0x54, 0x54, 0x3C}, // g{0x7F, 0x08, 0x04, 0x04, 0x78}, // H{0x00, 0x44, 0x7D, 0x40, 0x00}, // i{0x20, 0x40, 0x44, 0x3D, 0x00}, // j{0x00, 0x7F, 0x10, 0x28, 0x44}, // k{0x00, 0x41, 0x7F, 0x40, 0x00}, // l{0x7C, 0x04, 0x18, 0x04, 0x78}, // m{0x7C, 0x08, 0x04, 0x04, 0x78}, // n{0x38, 0x44, 0x44, 0x44, 0x38}, // o{0x7C, 0x14, 0x14, 0x14, 0x08}, // p{0x08, 0x14, 0x14, 0x18, 0x7C}, // q{0x7C, 0x08, 0x04, 0x04, 0x08}, // r{0x48, 0x54, 0x54, 0x54, 0x20}, // s{0x04, 0x3F, 0x44, 0x40, 0x20}, // t{0x3C, 0x40, 0x40, 0x20, 0x7C}, // u{0x1C, 0x20, 0x40, 0x20, 0x1C}, // v{0x3C, 0x40, 0x30, 0x40, 0x3C}, // w{0x44, 0x28, 0x10, 0x28, 0x44}, // x{0x0C, 0x50, 0x50, 0x50, 0x3C}, // y{0x44, 0x64, 0x54, 0x4C, 0x44}, // z{0x00, 0x08, 0x36, 0x41, 0x00}, // {{0x00, 0x00, 0x7F, 0x00, 0x00}, // |{0x00, 0x41, 0x36, 0x08, 0x00}, // }{0x08, 0x08, 0x2A, 0x1C, 0x08}, // →{0x08, 0x1C, 0x2A, 0x08, 0x08} // ←};// 确保字符在有效范围内if (ch < ' ' || ch > '~' + 2)ch = '?';// 计算在字体数组中的索引int idx = ch - ' ';// 在指定位置绘制字符for (int row = 0; row < 7; row++){for (int col = 0; col < 5; col++){if (font5x7[idx][col] & (1 << row)){// 如果这个像素需要绘制int pos = (y + row) * width + (x + col);if (pos < width * LCD_V_RES){buffer[pos] = color;}}}}
}// 绘制中文字符函数 (16x16点阵)
void draw_chinese_char(uint16_t *buffer, int x, int y, uint16_t unicode, uint16_t color, int width)
{// 获取字符点阵数据const uint8_t *bitmap = get_chinese_char_bitmap(unicode);if (bitmap == NULL){// 如果找不到字符,绘制一个方块表示缺失for (int row = 0; row < 16; row++){for (int col = 0; col < 16; col++){if (row == 0 || row == 15 || col == 0 || col == 15){int pos = (y + row) * width + (x + col);if (pos < width * LCD_V_RES){buffer[pos] = color;}}}}return;}// 绘制16x16点阵 - 修改为低位在前的模式for (int row = 0; row < 16; row++){for (int col = 0; col < 16; col++){// 计算点阵中的位置,每行2个字节uint8_t byte = bitmap[row * 2 + col / 8];uint8_t bit = col % 8; // 修改为低位在前(从低位到高位)if (byte & (1 << bit)){// 如果这个像素需要绘制int pos = (y + row) * width + (x + col);if (pos < width * LCD_V_RES){buffer[pos] = color;}}}}
}// 修改字符串绘制函数以支持中文
void draw_string(uint16_t *buffer, int x, int y, const char *str, uint16_t color, int width)
{int cursor_x = x;// 使用中文字符高度作为统一行高int line_height = CHINESE_FONT_HEIGHT;while (*str){// 处理换行if (*str == '\n'){cursor_x = x;y += line_height;if (y >= LCD_V_RES - line_height){break; // 超出屏幕底部}str++;continue;}// 检查是否是UTF-8编码的中文if ((*str & 0xE0) == 0xE0 && (*(str + 1) & 0x80) && (*(str + 2) & 0x80)){// 3字节UTF-8,提取Unicode码点uint16_t unicode = (((*str & 0x0F) << 12) |((*(str + 1) & 0x3F) << 6) |(*(str + 2) & 0x3F));// 绘制中文字符draw_chinese_char(buffer, cursor_x, y, unicode, color, width);cursor_x += CHINESE_FONT_WIDTH; // 使用常量而非硬编码值str += 3; // 跳过3个UTF-8字节// 检查是否需要换行if (cursor_x >= width - CHINESE_FONT_WIDTH){cursor_x = x;y += line_height; // 使用统一行高if (y >= LCD_V_RES - line_height){break; // 超出屏幕底部}}}else{// ASCII字符draw_char(buffer, cursor_x, y, *str, color, width);cursor_x += FONT_WIDTH;str++;// 检查是否需要换行if (cursor_x >= width - FONT_WIDTH){cursor_x = x;y += line_height; // 使用统一行高而非FONT_HEIGHTif (y >= LCD_V_RES - line_height){break; // 超出屏幕底部}}}}
}
main函数集合
LCD显示遵循以下基本流程:
1.初始化LCD
2.清空缓冲区
3.向缓冲区绘制内容
4.将缓冲区内容刷新到LCD
void display_example(void)
{// 1. 初始化LCD(通常在app_main开始时调用一次)lcd_init();// 2. 清空屏幕缓冲区clear_text_area(lcd_buffer, LCD_H_RES, LCD_V_RES);// 3. 向缓冲区绘制内容// 3.1 显示英文文本 - 参数:缓冲区、x坐标、y坐标、文本、颜色、屏幕宽度draw_string(lcd_buffer, 0, 0, "Hello World!", 0xFFFF, LCD_H_RES); // 白色文字// 3.2 显示中文文本(自动处理UTF-8编码)draw_string(lcd_buffer, 0, FONT_HEIGHT + 2, "你好,世界!", 0xFFFF, LCD_H_RES);// 3.3 显示带颜色的文本 - 0xF800是红色(RGB565格式)draw_string(lcd_buffer, 0, FONT_HEIGHT*2 + 4, "Red Text", 0xF800, LCD_H_RES);// 3.4 在特定位置显示内容(例如底部)draw_string(lcd_buffer, 0, LCD_V_RES - FONT_HEIGHT - 2, "Bottom Text", 0x07E0, LCD_H_RES); // 绿色// 4. 将缓冲区内容刷新到LCD显示esp_lcd_panel_draw_bitmap(panel_handle, 0, 0, LCD_H_RES, LCD_V_RES, lcd_buffer);// 等待2秒vTaskDelay(2000 / portTICK_PERIOD_MS);// 显示图片示例clear_text_area(lcd_buffer, LCD_H_RES, LCD_V_RES);decode_image(gImage_wyh_pic, lcd_buffer, LCD_H_RES, LCD_V_RES);esp_lcd_panel_draw_bitmap(panel_handle, 0, 0, LCD_H_RES, LCD_V_RES, lcd_buffer);// 等待2秒vTaskDelay(2000 / portTICK_PERIOD_MS);// 显示图片并在图片上添加文字clear_text_area(lcd_buffer, LCD_H_RES, LCD_V_RES);decode_image(gImage_wyh_pic, lcd_buffer, LCD_H_RES, LCD_V_RES);// 在图片上方添加标题(黑色背景白色文字,更容易看清)for (int y = 0; y < FONT_HEIGHT + 4; y++) {for (int x = 0; x < LCD_H_RES; x++) {lcd_buffer[y * LCD_H_RES + x] = 0x0000; // 黑色背景}}draw_string(lcd_buffer, 0, 2, "带标题的图片", 0xFFFF, LCD_H_RES);// 刷新显示esp_lcd_panel_draw_bitmap(panel_handle, 0, 0, LCD_H_RES, LCD_V_RES, lcd_buffer);
}
成功!示例
下一篇会介绍mqtt。