diff --git a/Power_Pico/BSP/LCD/lcd.c b/Power_Pico/BSP/LCD/lcd.c index 9cc3a3a..2ce1af7 100644 --- a/Power_Pico/BSP/LCD/lcd.c +++ b/Power_Pico/BSP/LCD/lcd.c @@ -15,7 +15,7 @@ extern osSemaphoreId_t DMA_SemaphoreHandle; void LCD_Fill(u16 xsta,u16 ysta,u16 xend,u16 yend,u16 color) { u16 i,j; - LCD_Address_Set(xsta+OFFSET_X, ysta+OFFSET_Y,xend-1+OFFSET_X, yend-1+OFFSET_Y);//设置显示范围 + LCD_Address_Set(xsta, ysta,xend-1, yend-1);//设置显示范围 for(i=ysta;iCR1 |= SPI_CR1_DFF; // 置位 DFF,启用 16 位数据帧 + __HAL_SPI_ENABLE(&hspi2); + // 3. 启动 DMA 传输 + HAL_SPI_Transmit_DMA(&hspi2, (uint8_t*)color_p, count); +} - LCD_Address_Set(xsta+OFFSET_X, ysta+OFFSET_Y, xend+OFFSET_X, yend+OFFSET_Y); +static void *lcd_ready_cb = NULL; - hspi2.Init.DataSize = SPI_DATASIZE_16BIT; - hspi2.Instance->CR1|=SPI_CR1_DFF; - HAL_SPI_Transmit_DMA(&hspi2,(uint8_t*)color_p,size); - while(__HAL_DMA_GET_COUNTER(&hdma_spi2_tx)!=0); +// 设置通知的回调函数 +void LCD_Set_Flush_Complete_Callback(void *cb) +{ + // 保存回调指针 + lcd_ready_cb = cb; +} - hspi2.Init.DataSize = SPI_DATASIZE_8BIT; - hspi2.Instance->CR1&=~SPI_CR1_DFF; +// DMA 传输完成中断回调 +void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi) +{ + if (hspi->Instance == SPI2) + { + // 1. 死等 SPI 总线发完最后 1 bit + while (hspi->Instance->SR & SPI_FLAG_BSY); + // 2. 安全切回 8-bit 模式 (为下一次发送命令做准备) + __HAL_SPI_DISABLE(hspi); + hspi->Instance->CR1 &= ~SPI_CR1_DFF; // 清除 DFF,回退到 8 位 + __HAL_SPI_ENABLE(hspi); + + // 3. 通知 LVGL 渲染结束,执行回调函数 + if (lcd_ready_cb) { + LCD_CallbackFunc_t func = (LCD_CallbackFunc_t)lcd_ready_cb; + func(); + } + } } /****************************************************************************** diff --git a/Power_Pico/BSP/LCD/lcd.h b/Power_Pico/BSP/LCD/lcd.h index 06d7a63..92374ed 100644 --- a/Power_Pico/BSP/LCD/lcd.h +++ b/Power_Pico/BSP/LCD/lcd.h @@ -2,8 +2,11 @@ #define __LCD_H #include "sys.h" +typedef void (*LCD_CallbackFunc_t)(void); // LCDDMAˢ»ص + void LCD_Fill(u16 xsta,u16 ysta,u16 xend,u16 yend,u16 color);//ָɫ -void LCD_Color_Render(u16 xsta,u16 ysta,u16 xend,u16 yend,u16 *color); +void LCD_Set_Flush_Complete_Callback(void *cb); +void LCD_Color_Render_Async(u16 xsta, u16 ysta, u16 xend, u16 yend, u16 *color_p); void LCD_DrawPoint(u16 x,u16 y,u16 color);//ָλûһ void LCD_DrawLine(u16 x1,u16 y1,u16 x2,u16 y2,u16 color);//ָλûһ void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2,u16 color);//ָλûһ diff --git a/Power_Pico/BSP/LCD/lcd_init.c b/Power_Pico/BSP/LCD/lcd_init.c index dcfb97b..5d9c77d 100644 --- a/Power_Pico/BSP/LCD/lcd_init.c +++ b/Power_Pico/BSP/LCD/lcd_init.c @@ -112,13 +112,13 @@ void LCD_WR_REG(u8 dat) ******************************************************************************/ void LCD_Address_Set(u16 x1,u16 y1,u16 x2,u16 y2) { - LCD_WR_REG(0x2a);//еַ - LCD_WR_DATA(x1); - LCD_WR_DATA(x2); - LCD_WR_REG(0x2b);//еַ - LCD_WR_DATA(y1); - LCD_WR_DATA(y2); - LCD_WR_REG(0x2c);//д + LCD_WR_REG(0x2a);//еַ + LCD_WR_DATA(x1 + OFFSET_X); + LCD_WR_DATA(x2 + OFFSET_X); + LCD_WR_REG(0x2b);//еַ + LCD_WR_DATA(y1 + OFFSET_Y); + LCD_WR_DATA(y2 + OFFSET_Y); + LCD_WR_REG(0x2c);//д } @@ -230,14 +230,20 @@ void LCD_Init(void) LCD_RES_Set(); HAL_Delay(100); + // 1. ˳˯ģʽ (Exit Sleep Mode) LCD_WR_REG(0x11); HAL_Delay(120); - LCD_WR_REG(0x36); + + // 2. ʾ (Memory Data Access Control) LCD_SetRotation(LCD_ROTATION); + // 3. ظʽ (Interface Pixel Format) + // 0x55 ʾ 16λɫ (RGB565)Ϊ0x66 (18λɫ)ɫ᲻ȷ LCD_WR_REG(0x3A); - LCD_WR_DATA8(0x05); + LCD_WR_DATA8(0x55); + // 4. Porch (ʱ) + // ɨǰʱ䣬ͨҪ޸ġ LCD_WR_REG(0xB2); LCD_WR_DATA8(0x0C); LCD_WR_DATA8(0x0C); @@ -245,31 +251,49 @@ void LCD_Init(void) LCD_WR_DATA8(0x33); LCD_WR_DATA8(0x33); + // 5. Gate (Gate Control) + // ɫʹؼVGHVGLѹӰĻĶԱȶȺӽǡ + // 0x35һȽͨõֵĻдֱĴŻ˸Գ޸ֵ LCD_WR_REG(0xB7); LCD_WR_DATA8(0x35); + // 6. VCOM (VCOM Setting) + // ɫʹؼǷdzҪIJֱӰʾرǶԱȶȺ˸ + // 0x19 һοֵ 0x10 0x30 ֮䳢ԣҵȶֵ LCD_WR_REG(0xBB); LCD_WR_DATA8(0x19); + // 7. LCM (LCM Control) LCD_WR_REG(0xC0); LCD_WR_DATA8(0x2C); + // 8. VDV VRH ʹ LCD_WR_REG(0xC2); LCD_WR_DATA8(0x01); + // 9. VRH (VRH Set) + // ɫʹؼӰѹ΢ĻȺ͹ġ LCD_WR_REG(0xC3); LCD_WR_DATA8(0x12); + // 10. VDV (VDV Set) + // ͨĬֵ LCD_WR_REG(0xC4); LCD_WR_DATA8(0x20); + // 11. ֡ʿ (Frame Rate Control) + // 0x0F ͨӦ 60Hz ҵˢʡĻ˸ԳԼСֵ0x14ӹġ LCD_WR_REG(0xC6); LCD_WR_DATA8(0x0F); + // 12. Դ (Power Control) LCD_WR_REG(0xD0); - LCD_WR_DATA8(0xA4); + LCD_WR_DATA8(0xA6); LCD_WR_DATA8(0xA1); + // 13. Gamma У (Positive Voltage Gamma Control) + // ɫʹؼǵɫͻҽױĵIJ֣ + // 14ֽڶ˴ӰĻҽߡ޸ЩֵıɫʵıͶȡԱȶȺ͹ƽȡ LCD_WR_REG(0xE0); LCD_WR_DATA8(0xD0); LCD_WR_DATA8(0x04); @@ -286,6 +310,8 @@ void LCD_Init(void) LCD_WR_DATA8(0x1F); LCD_WR_DATA8(0x23); + // 14. Gamma У (Negative Voltage Gamma Control) + // ɫʹؼGammaͬҪҪϵԴﵽЧ LCD_WR_REG(0xE1); LCD_WR_DATA8(0xD0); LCD_WR_DATA8(0x04); @@ -302,8 +328,10 @@ void LCD_Init(void) LCD_WR_DATA8(0x20); LCD_WR_DATA8(0x23); + // 15. ɫת (Display Inversion On) LCD_WR_REG(0x21); + // 16. ʾ (Display On) LCD_WR_REG(0x29); } diff --git a/Power_Pico/Middlewares/LVGL/porting/lv_port_disp.c b/Power_Pico/Middlewares/LVGL/porting/lv_port_disp.c index 8fa3f6d..39db2cd 100644 --- a/Power_Pico/Middlewares/LVGL/porting/lv_port_disp.c +++ b/Power_Pico/Middlewares/LVGL/porting/lv_port_disp.c @@ -46,6 +46,9 @@ static void disp_flush(lv_display_t * disp, const lv_area_t * area, uint8_t * px * STATIC VARIABLES **********************/ +// 1. 定义一个静态变量来保存当前的 driver 句柄 +static lv_display_t *g_current_disp_drv = NULL; + /********************** * MACROS **********************/ @@ -66,6 +69,7 @@ void lv_port_disp_init(void) * -----------------------------------*/ lv_display_t * disp = lv_display_create(MY_DISP_HOR_RES, MY_DISP_VER_RES); lv_display_set_flush_cb(disp, disp_flush); + g_current_disp_drv = disp; #define BUFFER_METHOD 1 #if BUFFER_METHOD == 1 /* Example 1 @@ -103,6 +107,13 @@ void lv_port_disp_init(void) * STATIC FUNCTIONS **********************/ +void lcd_flush_ready_callback(void) +{ + if (g_current_disp_drv != NULL) { + lv_display_flush_ready(g_current_disp_drv); + } +} + /*Initialize your display and the required peripherals.*/ static void disp_init(void) { @@ -110,6 +121,7 @@ static void disp_init(void) LCD_Init(); LCD_Fill(0,0, LCD_W, LCD_H, BLACK); LCD_Close_Light(); + LCD_Set_Flush_Complete_Callback(lcd_flush_ready_callback); } volatile bool disp_flush_enabled = true; @@ -142,12 +154,12 @@ static void disp_flush(lv_display_t * disp_drv, const lv_area_t * area, uint8_t last_rotation = current_rotation; // 更新上次状态 } if(disp_flush_enabled) { - LCD_Color_Render(area->x1,area->y1,area->x2,area->y2, (uint16_t *)px_map); + LCD_Color_Render_Async(area->x1,area->y1,area->x2,area->y2, (uint16_t *)px_map); } /*IMPORTANT!!! *Inform the graphics library that you are ready with the flushing*/ - lv_display_flush_ready(disp_drv); + // lv_display_flush_ready(disp_drv); } #else /*Enable this file at the top*/ diff --git a/Power_Pico/User/GUI/ui.c b/Power_Pico/User/GUI/ui.c index 20a76b0..2a59f6c 100644 --- a/Power_Pico/User/GUI/ui.c +++ b/Power_Pico/User/GUI/ui.c @@ -54,7 +54,7 @@ Page_t pages[] = { */ static void main_timer_cb(lv_timer_t * timer) { - // 1s 刷新一次全屏,防止有时候不知什么原因的LCD刷新错误(需要后续找到问题从根本解决) + // 1s 刷新一次全屏,防止有时候不知什么原因的LCD刷新错误(需要后续找到问题从根本解决不知是不是屏幕本身问题) ui_full_screen_refresh(lv_screen_active()); ui_GetElapsedTime_HMS(NULL, NULL, NULL); // 更新经过时间计数器 }