ESP32-DevKitC 开发板 + ESP32-LCDKit + 16位并口屏 st7796
Posted: Mon Oct 04, 2021 4:51 am
hi,大家好!
我手上有ESP32-DevKitC 开发板 + ESP32-LCDKit + 16位并口屏 st7796,按照SCH_ESP32-LCDKit_V1.1_20190218.pdf图纸连接,使用esp-iot-solution\examples\screen例子做测试,LCD为3.5寸,320X480,menuconfig里面也配置了相应的驱动。代码修改如下:
/* Screen Example
For other examples please check:
https://github.com/espressif/esp-iot-so ... r/examples
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_log.h"
#include "esp_task_wdt.h"
#include "board.h"
#include "screen_driver.h"
#include "img_array.h"
static const char *TAG = "screen example";
/**
* @brief Draw Mandelbrot Set on screen, A helpful site http://usefuljs.net/fractals/
*/
/** If you use a spi interface screen, set the USE_SPI_SCREEN to 1, otherwise use 8080 interface. */
#define USE_SPI_SCREEN 0
#define MAX_ZOOM 2500
#define ITERATION 128
static uint16_t g_color_table[ITERATION];
static scr_driver_t g_lcd;
static scr_info_t g_lcd_info;
static void generate_mandelbrot(scr_driver_t *lcd, uint16_t size_x, uint16_t size_y, int32_t offset_x, int32_t offset_y, uint16_t zoom, uint16_t *line_buffer)
{
uint8_t i;
uint16_t x, y;
float tmp1, tmp2;
float p_r, p_i;
float num_real, num_img;
float radius;
ESP_LOGI(TAG, "zoom = %d", zoom);
for (y = 0; y < size_y; y++) {
for (x = 0; x < size_x; x++) {
num_real = x - offset_x;
p_r = num_real = num_real / zoom;
num_img = y - offset_y;
p_i = num_img = num_img / zoom;
i = 0;
radius = 0;
if (0 == x && 0 == y) {
ESP_LOGI(TAG, "start(%f, %f)", num_real, num_img);
}
if (size_x - 1 == x && size_y - 1 == y) {
ESP_LOGI(TAG, "end (%f, %f)", num_real, num_img);
}
while ((i < ITERATION - 1) && (radius < 16)) {
// z = z^2 + c
tmp1 = num_real * num_real;
tmp2 = num_img * num_img;
num_img = 2 * num_real * num_img + p_i;
num_real = tmp1 - tmp2 + p_r;
radius = tmp1 + tmp2; // Modulus^2
i++;
}
if (NULL != line_buffer) {
line_buffer[x] = g_color_table;
} else {
lcd->draw_pixel(x, y, g_color_table);
}
}
if (NULL != line_buffer) {
lcd->draw_bitmap(0, y, g_lcd_info.width, 1, line_buffer);
}
}
}
static uint16_t rgb888_to_rgb565(uint8_t r, uint8_t g, uint8_t b)
{
return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
}
static void init_CLUT(uint16_t *clut)
{
uint32_t i = 0x00;
uint16_t red = 0, green = 0, blue = 0;
for (i = 0; i < ITERATION; i++) {
red = (i * 6 * 256 / ITERATION) % 256;
green = (i * 4 * 256 / ITERATION) % 256;
blue = (i * 8 * 256 / ITERATION) % 256;
clut = rgb888_to_rgb565(red, green, blue);
}
}
static void screen_clear(scr_driver_t *lcd, int color)
{
scr_info_t lcd_info;
lcd->get_info(&lcd_info);
uint16_t *buffer = malloc(lcd_info.width * sizeof(uint16_t));
if (NULL == buffer) {
for (size_t y = 0; y < lcd_info.height; y++) {
for (size_t x = 0; x < lcd_info.width; x++) {
lcd->draw_pixel(x, y, color);
}
}
} else {
for (size_t i = 0; i < lcd_info.width; i++) {
buffer = color;
}
for (int y = 0; y < lcd_info.height; y++) {
lcd->draw_bitmap(0, y, lcd_info.width, 1, buffer);
}
free(buffer);
}
}
static void lcd_bitmap_test(scr_driver_t *lcd)
{
scr_info_t lcd_info;
lcd->get_info(&lcd_info);
uint16_t *pixels = heap_caps_malloc((img_width * img_height) * sizeof(uint16_t), MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
if (NULL == pixels) {
ESP_LOGE(TAG, "Memory for bitmap is not enough");
return;
}
memcpy(pixels, img_array, (img_width * img_height) * sizeof(uint16_t));
lcd->draw_bitmap(0, 0, img_width, img_height, (uint16_t *)pixels);
heap_caps_free(pixels);
}
static void lcd_speed_test(scr_driver_t *lcd)
{
scr_info_t lcd_info;
lcd->get_info(&lcd_info);
uint32_t w = 240, h = 240;
w = lcd_info.width < w ? lcd_info.width : w;
h = lcd_info.height < h ? lcd_info.height : h;
const uint32_t buffer_size = w * h;
uint16_t *pixels = heap_caps_malloc(buffer_size * sizeof(uint16_t), MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
if (NULL == pixels) {
ESP_LOGE(TAG, "Memory for bitmap is not enough");
return;
}
esp_task_wdt_delete(xTaskGetIdleTaskHandleForCPU(xPortGetCoreID()));
const uint16_t color_table[] = {COLOR_RED, COLOR_GREEN, COLOR_BLUE, COLOR_YELLOW};
uint32_t times = 256;
uint64_t s;
uint64_t t1 = 0;
for (int i = 0; i < times; i++) {
for (int j = 0; j < buffer_size; j++) {
pixels[j] = color_table[i % 4];
}
s = esp_timer_get_time();
lcd->draw_bitmap(0, 0, w, h, pixels);
t1 += (esp_timer_get_time() - s);
}
t1 = t1 / 1000;
float time_per_frame = (float)t1 / (float)times;
float fps = (float)times * 1000.f / (float)t1;
float write_speed = sizeof(uint16_t) * buffer_size * times / 1024.0f / 1.0240f / (float)t1;
float factor = ((float)w * (float)h) / ((float)lcd_info.width * (float)lcd_info.height);
ESP_LOGI(TAG, "-------%s Test Result------", lcd_info.name);
if (w != lcd_info.width || h != lcd_info.height) {
ESP_LOGI(TAG, "@resolution 240x240 [time per frame=%.2fMS, fps=%.2f, speed=%.2fMB/s]", time_per_frame, fps, write_speed);
ESP_LOGI(TAG, "@resolution %ux%u infer to [time per frame=%.2fMS, fps=%.2f]",
lcd_info.width, lcd_info.height,
time_per_frame / factor, factor * fps);
} else {
ESP_LOGI(TAG, "@resolution %ux%u [time per frame=%.2fMS, fps=%.2f, speed=%.2fMB/s]", lcd_info.width, lcd_info.height, time_per_frame, fps, write_speed);
}
ESP_LOGI(TAG, "-------------------------------------");
esp_task_wdt_add(xTaskGetIdleTaskHandleForCPU(xPortGetCoreID()));
heap_caps_free(pixels);
}
void app_main(void)
{
esp_err_t ret = ESP_OK;
#if USE_SPI_SCREEN
iot_board_init();
spi_bus_handle_t spi_bus = iot_board_get_handle(BOARD_SPI2_ID);
scr_interface_spi_config_t spi_lcd_cfg = {
.spi_bus = spi_bus,
.pin_num_cs = BOARD_LCD_SPI_CS_PIN,
.pin_num_dc = BOARD_LCD_SPI_DC_PIN,
.clk_freq = BOARD_LCD_SPI_CLOCK_FREQ,
.swap_data = true,
};
scr_interface_driver_t *iface_drv;
scr_interface_create(SCREEN_IFACE_SPI, &spi_lcd_cfg, &iface_drv);
ret = scr_find_driver(SCREEN_CONTROLLER_ILI9341, &g_lcd);
if (ESP_OK != ret) {
return;
ESP_LOGE(TAG, "screen find failed");
}
scr_controller_config_t lcd_cfg = {
.interface_drv = iface_drv,
.pin_num_rst = BOARD_LCD_SPI_RESET_PIN,
.pin_num_bckl = BOARD_LCD_SPI_BL_PIN,
.rst_active_level = 0,
.bckl_active_level = 1,
.offset_hor = 0,
.offset_ver = 0,
.width = 240,
.height = 320,
.rotate = SCR_DIR_BTRL,
};
ret = g_lcd.init(&lcd_cfg);
#else
//iot_board_init();
i2s_lcd_config_t i2s_lcd_cfg = {
.data_width = BOARD_LCD_I2S_BITWIDTH,
.pin_data_num = {
BOARD_LCD_I2S_D0_PIN,
BOARD_LCD_I2S_D1_PIN,
BOARD_LCD_I2S_D2_PIN,
BOARD_LCD_I2S_D3_PIN,
BOARD_LCD_I2S_D4_PIN,
BOARD_LCD_I2S_D5_PIN,
BOARD_LCD_I2S_D6_PIN,
BOARD_LCD_I2S_D7_PIN,
BOARD_LCD_I2S_D8_PIN,
BOARD_LCD_I2S_D9_PIN,
BOARD_LCD_I2S_D10_PIN,
BOARD_LCD_I2S_D11_PIN,
BOARD_LCD_I2S_D12_PIN,
BOARD_LCD_I2S_D13_PIN,
BOARD_LCD_I2S_D14_PIN,
BOARD_LCD_I2S_D15_PIN,
},
.pin_num_cs = BOARD_LCD_I2S_CS_PIN,
.pin_num_wr = BOARD_LCD_I2S_WR_PIN,
.pin_num_rs = BOARD_LCD_I2S_RS_PIN,
.clk_freq = 20000000,
.i2s_port = I2S_NUM_0,
.buffer_size = 32000,
.swap_data = true,
};
scr_interface_driver_t *iface_drv;
scr_interface_create(SCREEN_IFACE_8080, &i2s_lcd_cfg, &iface_drv);
ret = scr_find_driver(SCREEN_CONTROLLER_ST7796, &g_lcd);
if (ESP_OK != ret) {
return;
ESP_LOGE(TAG, "screen find failed");
}
scr_controller_config_t lcd_cfg = {
.interface_drv = iface_drv,
.pin_num_rst = BOARD_LCD_I2S_RESET_PIN,
.pin_num_bckl = BOARD_LCD_I2S_BL_PIN,
.rst_active_level = 0,
.bckl_active_level = 1,
.offset_hor = 0,
.offset_ver = 0,
.width = 320,
.height = 480,
.rotate = SCR_SWAP_XY | SCR_MIRROR_Y, /** equal to SCR_DIR_BTLR */
};
ret = g_lcd.init(&lcd_cfg);
#endif
if (ESP_OK != ret) {
return;
ESP_LOGE(TAG, "screen initialize failed");
}
g_lcd.get_info(&g_lcd_info);
ESP_LOGI(TAG, "Screen name:%s | width:%d | height:%d", g_lcd_info.name, g_lcd_info.width, g_lcd_info.height);
screen_clear(&g_lcd, COLOR_ESP_BKGD);
vTaskDelay(pdMS_TO_TICKS(500));
/** Run test */
lcd_bitmap_test(&g_lcd);
vTaskDelay(pdMS_TO_TICKS(2000));
lcd_speed_test(&g_lcd);
vTaskDelay(pdMS_TO_TICKS(2000));
init_CLUT(g_color_table); /** Initialize color look up table */
/** Define an interesting point on the complex plane */
float real = -0.68481 + (g_lcd_info.width / 2 / (float)MAX_ZOOM);
float img = 0.380584 + (g_lcd_info.height / 2 / (float)MAX_ZOOM);
uint16_t *pixels = heap_caps_malloc(g_lcd_info.width * sizeof(uint16_t), MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
if (NULL == pixels) {
ESP_LOGE(TAG, "Memory for bitmap is not enough");
return;
}
float zoom;
while (1) {
for (zoom = 50; zoom <= MAX_ZOOM; zoom *= 1.1f) {
int32_t off_x = (real) * zoom;
int32_t off_y = (img) * zoom;
generate_mandelbrot(&g_lcd, g_lcd_info.width, g_lcd_info.height, g_lcd_info.width / 2 - off_x, g_lcd_info.height / 2 - off_y, zoom, pixels);
vTaskDelay(1); /** Delay one tick for feed task watchdog */
}
for (; zoom > 50; zoom /= 1.1f) {
int32_t off_x = (real) * zoom;
int32_t off_y = (img) * zoom;
generate_mandelbrot(&g_lcd, g_lcd_info.width, g_lcd_info.height, g_lcd_info.width / 2 - off_x, g_lcd_info.height / 2 - off_y, zoom, pixels);
vTaskDelay(1);
}
}
}
从运行日志情况看:
--- WARNING: GDB cannot open serial ports accessed as COMx
--- Using \\.\COM33 instead...
--- idf_monitor on \\.\COM33 115200 ---
--- Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---
ets Jul 29 2019 12:21:46
rst:0x1 (POWERON_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:6896
load:0x40078000,len:14292
ho 0 tail 12 room 4
load:0x40080400,len:3688
0x40080400: _init at ??:?
entry 0x40080678
I (29) boot: ESP-IDF v4.3 2nd stage bootloader
I (29) boot: compile time 23:04:34
I (29) boot: chip revision: 3
I (32) boot_comm: chip revision: 3, min. bootloader chip revision: 0
I (39) boot.esp32: SPI Speed : 40MHz
I (43) boot.esp32: SPI Mode : DIO
I (48) boot.esp32: SPI Flash Size : 2MB
I (53) boot: Enabling RNG early entropy source...
I (58) boot: Partition Table:
I (62) boot: ## Label Usage Type ST Offset Length
I (69) boot: 0 nvs WiFi data 01 02 00009000 00006000
I (76) boot: 1 phy_init RF data 01 01 0000f000 00001000
I (84) boot: 2 factory factory app 00 00 00010000 00100000
I (91) boot: End of partition table
I (95) boot_comm: chip revision: 3, min. application chip revision: 0
I (103) esp_image: segment 0: paddr=00010020 vaddr=3f400020 size=19934h (104756) map
I (151) esp_image: segment 1: paddr=0002995c vaddr=3ffb0000 size=02a00h ( 10752) load
I (155) esp_image: segment 2: paddr=0002c364 vaddr=40080000 size=03cb4h ( 15540) load
I (163) esp_image: segment 3: paddr=00030020 vaddr=400d0020 size=19cd0h (105680) map
I (205) esp_image: segment 4: paddr=00049cf8 vaddr=40083cb4 size=09c04h ( 39940) load
I (222) esp_image: segment 5: paddr=00053904 vaddr=50000000 size=00010h ( 16) load
I (230) boot: Loaded app from partition at offset 0x10000
I (230) boot: Disabling RNG early entropy source...
I (242) cpu_start: Pro cpu up.
I (242) cpu_start: Starting app cpu, entry point is 0x400811dc
0x400811dc: call_start_cpu1 at D:/esp/esp-idf/components/esp_system/port/cpu_start.c:141
I (0) cpu_start: App cpu up.
I (257) cpu_start: Pro cpu start user code
I (257) cpu_start: cpu freq: 240000000
I (257) cpu_start: Application information:
I (261) cpu_start: Project name: screen
I (266) cpu_start: App version: 87e76fd-dirty
I (271) cpu_start: Compile time: Oct 9 2021 23:03:55
I (278) cpu_start: ELF file SHA256: 32c61b9041962e0f...
I (283) cpu_start: ESP-IDF: v4.3
I (288) heap_init: Initializing. RAM available for dynamic allocation:
I (295) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (301) heap_init: At 3FFB33E0 len 0002CC20 (179 KiB): DRAM
I (308) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (314) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (321) heap_init: At 4008D8B8 len 00012748 (73 KiB): IRAM
I (328) spi_flash: detected chip: generic
I (331) spi_flash: flash io: dio
W (335) spi_flash: Detected size(8192k) larger than the size in the binary image header(2048k). Using the size in the binary image header.
I (349) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
I (364) ESP32_I2S_LCD: Enable I2S0
I (368) ESP32_I2S_LCD: lcd_buffer_size: 32000, lcd_dma_size: 4000, lcd_dma_node_cnt: 8
I (376) ESP32_I2S_LCD: i2s lcd driver init ok
I (493) lcd st7796: MADCTL=a8
I (493) screen example: Screen name:ST7796 | width:480 | height:320
I (5526) screen example: -------ST7796 Test Result------
I (5527) screen example: @resolution 240x240 [time per frame=4.48MS, fps=223.19, speed=24.52MB/s]
I (5532) screen example: @resolution 480x320 infer to [time per frame=11.95MS, fps=83.70]
I (5541) screen example: -------------------------------------
I (7547) screen example: zoom = 50
I (7547) screen example: start(-5.380000, -2.760000)
I (7852) screen example: end (4.200000, 3.620000)
I (7853) screen example: zoom = 55
I (7853) screen example: start(-4.945455, -2.472727)
I (8179) screen example: end (3.763636, 3.327273)
I (8180) screen example: zoom = 60
I (8180) screen example: start(-4.583333, -2.233333)
I (8525) screen example: end (3.400000, 3.083333)
I (8526) screen example: zoom = 66
I (8526) screen example: start(-4.227273, -1.984848)
I (8894) screen example: end (3.030303, 2.848485)
I (8896) screen example: zoom = 73
I (8896) screen example: start(-3.876712, -1.753425)
I (9294) screen example: end (2.684932, 2.616438)
I (9295) screen example: zoom = 80
I (9295) screen example: start(-3.587500, -1.562500)
I (9726) screen example: end (2.400000, 2.425000)
I (9727) screen example: zoom = 88
I (9727) screen example: start(-3.318182, -1.375000)
I (10197) screen example: end (2.125000, 2.250000)
I (10199) screen example: zoom = 97
I (10199) screen example: start(-3.061856, -1.206186)
I (10718) screen example: end (1.876289, 2.082474)
I (10719) screen example: zoom = 107
I (10719) screen example: start(-2.831776, -1.056075)
I (11298) screen example: end (1.644860, 1.925234)
I (11299) screen example: zoom = 117
I (11299) screen example: start(-2.641026, -0.923077)
也没有出现错误,但是屏没有正常显示
我手上有ESP32-DevKitC 开发板 + ESP32-LCDKit + 16位并口屏 st7796,按照SCH_ESP32-LCDKit_V1.1_20190218.pdf图纸连接,使用esp-iot-solution\examples\screen例子做测试,LCD为3.5寸,320X480,menuconfig里面也配置了相应的驱动。代码修改如下:
/* Screen Example
For other examples please check:
https://github.com/espressif/esp-iot-so ... r/examples
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_log.h"
#include "esp_task_wdt.h"
#include "board.h"
#include "screen_driver.h"
#include "img_array.h"
static const char *TAG = "screen example";
/**
* @brief Draw Mandelbrot Set on screen, A helpful site http://usefuljs.net/fractals/
*/
/** If you use a spi interface screen, set the USE_SPI_SCREEN to 1, otherwise use 8080 interface. */
#define USE_SPI_SCREEN 0
#define MAX_ZOOM 2500
#define ITERATION 128
static uint16_t g_color_table[ITERATION];
static scr_driver_t g_lcd;
static scr_info_t g_lcd_info;
static void generate_mandelbrot(scr_driver_t *lcd, uint16_t size_x, uint16_t size_y, int32_t offset_x, int32_t offset_y, uint16_t zoom, uint16_t *line_buffer)
{
uint8_t i;
uint16_t x, y;
float tmp1, tmp2;
float p_r, p_i;
float num_real, num_img;
float radius;
ESP_LOGI(TAG, "zoom = %d", zoom);
for (y = 0; y < size_y; y++) {
for (x = 0; x < size_x; x++) {
num_real = x - offset_x;
p_r = num_real = num_real / zoom;
num_img = y - offset_y;
p_i = num_img = num_img / zoom;
i = 0;
radius = 0;
if (0 == x && 0 == y) {
ESP_LOGI(TAG, "start(%f, %f)", num_real, num_img);
}
if (size_x - 1 == x && size_y - 1 == y) {
ESP_LOGI(TAG, "end (%f, %f)", num_real, num_img);
}
while ((i < ITERATION - 1) && (radius < 16)) {
// z = z^2 + c
tmp1 = num_real * num_real;
tmp2 = num_img * num_img;
num_img = 2 * num_real * num_img + p_i;
num_real = tmp1 - tmp2 + p_r;
radius = tmp1 + tmp2; // Modulus^2
i++;
}
if (NULL != line_buffer) {
line_buffer[x] = g_color_table;
} else {
lcd->draw_pixel(x, y, g_color_table);
}
}
if (NULL != line_buffer) {
lcd->draw_bitmap(0, y, g_lcd_info.width, 1, line_buffer);
}
}
}
static uint16_t rgb888_to_rgb565(uint8_t r, uint8_t g, uint8_t b)
{
return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
}
static void init_CLUT(uint16_t *clut)
{
uint32_t i = 0x00;
uint16_t red = 0, green = 0, blue = 0;
for (i = 0; i < ITERATION; i++) {
red = (i * 6 * 256 / ITERATION) % 256;
green = (i * 4 * 256 / ITERATION) % 256;
blue = (i * 8 * 256 / ITERATION) % 256;
clut = rgb888_to_rgb565(red, green, blue);
}
}
static void screen_clear(scr_driver_t *lcd, int color)
{
scr_info_t lcd_info;
lcd->get_info(&lcd_info);
uint16_t *buffer = malloc(lcd_info.width * sizeof(uint16_t));
if (NULL == buffer) {
for (size_t y = 0; y < lcd_info.height; y++) {
for (size_t x = 0; x < lcd_info.width; x++) {
lcd->draw_pixel(x, y, color);
}
}
} else {
for (size_t i = 0; i < lcd_info.width; i++) {
buffer = color;
}
for (int y = 0; y < lcd_info.height; y++) {
lcd->draw_bitmap(0, y, lcd_info.width, 1, buffer);
}
free(buffer);
}
}
static void lcd_bitmap_test(scr_driver_t *lcd)
{
scr_info_t lcd_info;
lcd->get_info(&lcd_info);
uint16_t *pixels = heap_caps_malloc((img_width * img_height) * sizeof(uint16_t), MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
if (NULL == pixels) {
ESP_LOGE(TAG, "Memory for bitmap is not enough");
return;
}
memcpy(pixels, img_array, (img_width * img_height) * sizeof(uint16_t));
lcd->draw_bitmap(0, 0, img_width, img_height, (uint16_t *)pixels);
heap_caps_free(pixels);
}
static void lcd_speed_test(scr_driver_t *lcd)
{
scr_info_t lcd_info;
lcd->get_info(&lcd_info);
uint32_t w = 240, h = 240;
w = lcd_info.width < w ? lcd_info.width : w;
h = lcd_info.height < h ? lcd_info.height : h;
const uint32_t buffer_size = w * h;
uint16_t *pixels = heap_caps_malloc(buffer_size * sizeof(uint16_t), MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
if (NULL == pixels) {
ESP_LOGE(TAG, "Memory for bitmap is not enough");
return;
}
esp_task_wdt_delete(xTaskGetIdleTaskHandleForCPU(xPortGetCoreID()));
const uint16_t color_table[] = {COLOR_RED, COLOR_GREEN, COLOR_BLUE, COLOR_YELLOW};
uint32_t times = 256;
uint64_t s;
uint64_t t1 = 0;
for (int i = 0; i < times; i++) {
for (int j = 0; j < buffer_size; j++) {
pixels[j] = color_table[i % 4];
}
s = esp_timer_get_time();
lcd->draw_bitmap(0, 0, w, h, pixels);
t1 += (esp_timer_get_time() - s);
}
t1 = t1 / 1000;
float time_per_frame = (float)t1 / (float)times;
float fps = (float)times * 1000.f / (float)t1;
float write_speed = sizeof(uint16_t) * buffer_size * times / 1024.0f / 1.0240f / (float)t1;
float factor = ((float)w * (float)h) / ((float)lcd_info.width * (float)lcd_info.height);
ESP_LOGI(TAG, "-------%s Test Result------", lcd_info.name);
if (w != lcd_info.width || h != lcd_info.height) {
ESP_LOGI(TAG, "@resolution 240x240 [time per frame=%.2fMS, fps=%.2f, speed=%.2fMB/s]", time_per_frame, fps, write_speed);
ESP_LOGI(TAG, "@resolution %ux%u infer to [time per frame=%.2fMS, fps=%.2f]",
lcd_info.width, lcd_info.height,
time_per_frame / factor, factor * fps);
} else {
ESP_LOGI(TAG, "@resolution %ux%u [time per frame=%.2fMS, fps=%.2f, speed=%.2fMB/s]", lcd_info.width, lcd_info.height, time_per_frame, fps, write_speed);
}
ESP_LOGI(TAG, "-------------------------------------");
esp_task_wdt_add(xTaskGetIdleTaskHandleForCPU(xPortGetCoreID()));
heap_caps_free(pixels);
}
void app_main(void)
{
esp_err_t ret = ESP_OK;
#if USE_SPI_SCREEN
iot_board_init();
spi_bus_handle_t spi_bus = iot_board_get_handle(BOARD_SPI2_ID);
scr_interface_spi_config_t spi_lcd_cfg = {
.spi_bus = spi_bus,
.pin_num_cs = BOARD_LCD_SPI_CS_PIN,
.pin_num_dc = BOARD_LCD_SPI_DC_PIN,
.clk_freq = BOARD_LCD_SPI_CLOCK_FREQ,
.swap_data = true,
};
scr_interface_driver_t *iface_drv;
scr_interface_create(SCREEN_IFACE_SPI, &spi_lcd_cfg, &iface_drv);
ret = scr_find_driver(SCREEN_CONTROLLER_ILI9341, &g_lcd);
if (ESP_OK != ret) {
return;
ESP_LOGE(TAG, "screen find failed");
}
scr_controller_config_t lcd_cfg = {
.interface_drv = iface_drv,
.pin_num_rst = BOARD_LCD_SPI_RESET_PIN,
.pin_num_bckl = BOARD_LCD_SPI_BL_PIN,
.rst_active_level = 0,
.bckl_active_level = 1,
.offset_hor = 0,
.offset_ver = 0,
.width = 240,
.height = 320,
.rotate = SCR_DIR_BTRL,
};
ret = g_lcd.init(&lcd_cfg);
#else
//iot_board_init();
i2s_lcd_config_t i2s_lcd_cfg = {
.data_width = BOARD_LCD_I2S_BITWIDTH,
.pin_data_num = {
BOARD_LCD_I2S_D0_PIN,
BOARD_LCD_I2S_D1_PIN,
BOARD_LCD_I2S_D2_PIN,
BOARD_LCD_I2S_D3_PIN,
BOARD_LCD_I2S_D4_PIN,
BOARD_LCD_I2S_D5_PIN,
BOARD_LCD_I2S_D6_PIN,
BOARD_LCD_I2S_D7_PIN,
BOARD_LCD_I2S_D8_PIN,
BOARD_LCD_I2S_D9_PIN,
BOARD_LCD_I2S_D10_PIN,
BOARD_LCD_I2S_D11_PIN,
BOARD_LCD_I2S_D12_PIN,
BOARD_LCD_I2S_D13_PIN,
BOARD_LCD_I2S_D14_PIN,
BOARD_LCD_I2S_D15_PIN,
},
.pin_num_cs = BOARD_LCD_I2S_CS_PIN,
.pin_num_wr = BOARD_LCD_I2S_WR_PIN,
.pin_num_rs = BOARD_LCD_I2S_RS_PIN,
.clk_freq = 20000000,
.i2s_port = I2S_NUM_0,
.buffer_size = 32000,
.swap_data = true,
};
scr_interface_driver_t *iface_drv;
scr_interface_create(SCREEN_IFACE_8080, &i2s_lcd_cfg, &iface_drv);
ret = scr_find_driver(SCREEN_CONTROLLER_ST7796, &g_lcd);
if (ESP_OK != ret) {
return;
ESP_LOGE(TAG, "screen find failed");
}
scr_controller_config_t lcd_cfg = {
.interface_drv = iface_drv,
.pin_num_rst = BOARD_LCD_I2S_RESET_PIN,
.pin_num_bckl = BOARD_LCD_I2S_BL_PIN,
.rst_active_level = 0,
.bckl_active_level = 1,
.offset_hor = 0,
.offset_ver = 0,
.width = 320,
.height = 480,
.rotate = SCR_SWAP_XY | SCR_MIRROR_Y, /** equal to SCR_DIR_BTLR */
};
ret = g_lcd.init(&lcd_cfg);
#endif
if (ESP_OK != ret) {
return;
ESP_LOGE(TAG, "screen initialize failed");
}
g_lcd.get_info(&g_lcd_info);
ESP_LOGI(TAG, "Screen name:%s | width:%d | height:%d", g_lcd_info.name, g_lcd_info.width, g_lcd_info.height);
screen_clear(&g_lcd, COLOR_ESP_BKGD);
vTaskDelay(pdMS_TO_TICKS(500));
/** Run test */
lcd_bitmap_test(&g_lcd);
vTaskDelay(pdMS_TO_TICKS(2000));
lcd_speed_test(&g_lcd);
vTaskDelay(pdMS_TO_TICKS(2000));
init_CLUT(g_color_table); /** Initialize color look up table */
/** Define an interesting point on the complex plane */
float real = -0.68481 + (g_lcd_info.width / 2 / (float)MAX_ZOOM);
float img = 0.380584 + (g_lcd_info.height / 2 / (float)MAX_ZOOM);
uint16_t *pixels = heap_caps_malloc(g_lcd_info.width * sizeof(uint16_t), MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
if (NULL == pixels) {
ESP_LOGE(TAG, "Memory for bitmap is not enough");
return;
}
float zoom;
while (1) {
for (zoom = 50; zoom <= MAX_ZOOM; zoom *= 1.1f) {
int32_t off_x = (real) * zoom;
int32_t off_y = (img) * zoom;
generate_mandelbrot(&g_lcd, g_lcd_info.width, g_lcd_info.height, g_lcd_info.width / 2 - off_x, g_lcd_info.height / 2 - off_y, zoom, pixels);
vTaskDelay(1); /** Delay one tick for feed task watchdog */
}
for (; zoom > 50; zoom /= 1.1f) {
int32_t off_x = (real) * zoom;
int32_t off_y = (img) * zoom;
generate_mandelbrot(&g_lcd, g_lcd_info.width, g_lcd_info.height, g_lcd_info.width / 2 - off_x, g_lcd_info.height / 2 - off_y, zoom, pixels);
vTaskDelay(1);
}
}
}
从运行日志情况看:
--- WARNING: GDB cannot open serial ports accessed as COMx
--- Using \\.\COM33 instead...
--- idf_monitor on \\.\COM33 115200 ---
--- Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---
ets Jul 29 2019 12:21:46
rst:0x1 (POWERON_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:6896
load:0x40078000,len:14292
ho 0 tail 12 room 4
load:0x40080400,len:3688
0x40080400: _init at ??:?
entry 0x40080678
I (29) boot: ESP-IDF v4.3 2nd stage bootloader
I (29) boot: compile time 23:04:34
I (29) boot: chip revision: 3
I (32) boot_comm: chip revision: 3, min. bootloader chip revision: 0
I (39) boot.esp32: SPI Speed : 40MHz
I (43) boot.esp32: SPI Mode : DIO
I (48) boot.esp32: SPI Flash Size : 2MB
I (53) boot: Enabling RNG early entropy source...
I (58) boot: Partition Table:
I (62) boot: ## Label Usage Type ST Offset Length
I (69) boot: 0 nvs WiFi data 01 02 00009000 00006000
I (76) boot: 1 phy_init RF data 01 01 0000f000 00001000
I (84) boot: 2 factory factory app 00 00 00010000 00100000
I (91) boot: End of partition table
I (95) boot_comm: chip revision: 3, min. application chip revision: 0
I (103) esp_image: segment 0: paddr=00010020 vaddr=3f400020 size=19934h (104756) map
I (151) esp_image: segment 1: paddr=0002995c vaddr=3ffb0000 size=02a00h ( 10752) load
I (155) esp_image: segment 2: paddr=0002c364 vaddr=40080000 size=03cb4h ( 15540) load
I (163) esp_image: segment 3: paddr=00030020 vaddr=400d0020 size=19cd0h (105680) map
I (205) esp_image: segment 4: paddr=00049cf8 vaddr=40083cb4 size=09c04h ( 39940) load
I (222) esp_image: segment 5: paddr=00053904 vaddr=50000000 size=00010h ( 16) load
I (230) boot: Loaded app from partition at offset 0x10000
I (230) boot: Disabling RNG early entropy source...
I (242) cpu_start: Pro cpu up.
I (242) cpu_start: Starting app cpu, entry point is 0x400811dc
0x400811dc: call_start_cpu1 at D:/esp/esp-idf/components/esp_system/port/cpu_start.c:141
I (0) cpu_start: App cpu up.
I (257) cpu_start: Pro cpu start user code
I (257) cpu_start: cpu freq: 240000000
I (257) cpu_start: Application information:
I (261) cpu_start: Project name: screen
I (266) cpu_start: App version: 87e76fd-dirty
I (271) cpu_start: Compile time: Oct 9 2021 23:03:55
I (278) cpu_start: ELF file SHA256: 32c61b9041962e0f...
I (283) cpu_start: ESP-IDF: v4.3
I (288) heap_init: Initializing. RAM available for dynamic allocation:
I (295) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (301) heap_init: At 3FFB33E0 len 0002CC20 (179 KiB): DRAM
I (308) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (314) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (321) heap_init: At 4008D8B8 len 00012748 (73 KiB): IRAM
I (328) spi_flash: detected chip: generic
I (331) spi_flash: flash io: dio
W (335) spi_flash: Detected size(8192k) larger than the size in the binary image header(2048k). Using the size in the binary image header.
I (349) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
I (364) ESP32_I2S_LCD: Enable I2S0
I (368) ESP32_I2S_LCD: lcd_buffer_size: 32000, lcd_dma_size: 4000, lcd_dma_node_cnt: 8
I (376) ESP32_I2S_LCD: i2s lcd driver init ok
I (493) lcd st7796: MADCTL=a8
I (493) screen example: Screen name:ST7796 | width:480 | height:320
I (5526) screen example: -------ST7796 Test Result------
I (5527) screen example: @resolution 240x240 [time per frame=4.48MS, fps=223.19, speed=24.52MB/s]
I (5532) screen example: @resolution 480x320 infer to [time per frame=11.95MS, fps=83.70]
I (5541) screen example: -------------------------------------
I (7547) screen example: zoom = 50
I (7547) screen example: start(-5.380000, -2.760000)
I (7852) screen example: end (4.200000, 3.620000)
I (7853) screen example: zoom = 55
I (7853) screen example: start(-4.945455, -2.472727)
I (8179) screen example: end (3.763636, 3.327273)
I (8180) screen example: zoom = 60
I (8180) screen example: start(-4.583333, -2.233333)
I (8525) screen example: end (3.400000, 3.083333)
I (8526) screen example: zoom = 66
I (8526) screen example: start(-4.227273, -1.984848)
I (8894) screen example: end (3.030303, 2.848485)
I (8896) screen example: zoom = 73
I (8896) screen example: start(-3.876712, -1.753425)
I (9294) screen example: end (2.684932, 2.616438)
I (9295) screen example: zoom = 80
I (9295) screen example: start(-3.587500, -1.562500)
I (9726) screen example: end (2.400000, 2.425000)
I (9727) screen example: zoom = 88
I (9727) screen example: start(-3.318182, -1.375000)
I (10197) screen example: end (2.125000, 2.250000)
I (10199) screen example: zoom = 97
I (10199) screen example: start(-3.061856, -1.206186)
I (10718) screen example: end (1.876289, 2.082474)
I (10719) screen example: zoom = 107
I (10719) screen example: start(-2.831776, -1.056075)
I (11298) screen example: end (1.644860, 1.925234)
I (11299) screen example: zoom = 117
I (11299) screen example: start(-2.641026, -0.923077)
也没有出现错误,但是屏没有正常显示