Page 1 of 1

当LCD和外部FLASH共用SPI总线时如何实现同步?

Posted: Mon May 18, 2026 10:56 am
by BitFu2027
ESP32-C3模块,LCD和外部FLASH共用了SPI2,Lcd使用lcd_panel 驱动,读写FLASH时总是出错,如果停掉LCD就正常,说明这两个使用SPI总线时冲突了,下面是相关的代码:

Code: Select all

 esp_lcd_panel_io_spi_config_t io_config = {
        .dc_gpio_num = EXAMPLE_PIN_NUM_LCD_DC,
        .cs_gpio_num = EXAMPLE_PIN_NUM_LCD_CS,
        .pclk_hz = EXAMPLE_LCD_PIXEL_CLOCK_HZ,
        .lcd_cmd_bits = EXAMPLE_LCD_CMD_BITS,
        .lcd_param_bits = EXAMPLE_LCD_PARAM_BITS,
        .spi_mode = 0,
        .trans_queue_depth = 10,
        .on_color_trans_done = example_notify_lvgl_flush_ready,
        .user_ctx = &disp_drv,
    };
    // Attach the LCD to the SPI bus
    ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)LCD_HOST, &io_config, &io_handle));

这个是是安装SPI传输完成后的回调函数

Code: Select all

    disp_drv.hor_res = EXAMPLE_LCD_H_RES;
    disp_drv.ver_res = EXAMPLE_LCD_V_RES;
    disp_drv.flush_cb = example_lvgl_flush_cb;
    disp_drv.drv_update_cb = example_lvgl_port_update_callback;
    disp_drv.draw_buf = &disp_buf;
    disp_drv.user_data = panel_handle;
    lv_disp_t *disp = lv_disp_drv_register(&disp_drv);

Code: Select all

uint8_t spi_bus_lcd_busy(void)
{
    return g_lcdTransDown;
}

static void example_lvgl_flush_cb(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map)
{
    myspi_lock();
    g_lcdTransDown=1;  // LCD 传输开始
    esp_lcd_panel_handle_t panel_handle = (esp_lcd_panel_handle_t) drv->user_data;
    int offsetx1 = area->x1;
    int offsetx2 = area->x2;
    int offsety1 = area->y1;
    int offsety2 = area->y2;
    // copy a buffer's content to a specific area of the display
    esp_lcd_panel_draw_bitmap(panel_handle, offsetx1, offsety1, offsetx2 + 1, offsety2 + 1, color_map);
    myspi_unlock();  // 立即释放锁,让 Flash 操作可以获取
}
读写flash部分

Code: Select all

void ext_flash_read(uint32_t addr ,uint8_t *buf,uint32_t len)
{
    // 先等待当前 LCD 传输完成
    spi_bus_wait_lcd_idle();
    xSemaphoreTake(spi_bus_mutex, portMAX_DELAY);
    esp_err_t err=esp_flash_read(ext_flash,buf, addr, len);
    if (err != ESP_OK)
    {
        ESP_LOGE(TAG, "读取FLASH失败: %s (0x%x)", esp_err_to_name(err), err);
    }
    xSemaphoreGive(spi_bus_mutex);
}

void ext_flash_write(uint32_t addr, uint8_t *buf,uint32_t len)
{
    // 先等待当前 LCD 传输完成
    spi_bus_wait_lcd_idle();
    xSemaphoreTake(spi_bus_mutex, portMAX_DELAY);

    esp_err_t err;
    if(addr % 4096 ==0)
    {
        err = esp_flash_erase_region(ext_flash, addr, 4096);
        if (err != ESP_OK) 
        {
            ESP_LOGE(TAG, "擦除失败: %s", esp_err_to_name(err));
            xSemaphoreGive(spi_bus_mutex);
            return;
        }
    }
    err= esp_flash_write(ext_flash,buf,addr,len);
    if(err!=ESP_OK)
    {
        ESP_LOGE(TAG,"写入FLASH失败: %s (0x%x)", esp_err_to_name(err), err);
    }

    xSemaphoreGive(spi_bus_mutex);
}
想请教的是传输完成回调函数on_color_trans_done 一定是在中断中调用吗?这个中断和外部的读写FLash功能,使用哪种同步合适呢?