搜索
bottom↓
回复: 0

《DNESP32S3使用指南-IDF版_V1.6》第三十三章 RGB显示屏实验

[复制链接]

出0入234汤圆

发表于 昨天 11:24 | 显示全部楼层 |阅读模式
2.jpg
1)实验平台:正点原子ESP32S3开发板
2)购买链接:https://detail.tmall.com/item.htm?id=768499342659
3)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-347618-1-1.html
4)正点原子官方B站:https://space.bilibili.com/394620890
5)正点原子手把手教你学ESP32S3快速入门视频教程:https://www.bilibili.com/video/BV1sH4y1W7Tc
6)正点原子FPGA交流群:132780729
1.png
3.png

第三十三章 RGB显示屏实验

       ESP32-S3的LCD_CAM控制器由独立的LCD模块和Camera模块组成。LCD模块主要用于发送并行视频数据信号,支持多种接口时序,如RGB、MOTO6800和I8080。而Camera模块则用于接收并行视频数据信号,支持DVP 8-/16-bit模式。在本章节中,我们将首先介绍正点原子的RGBLCD显示屏的参数和功能参数,然后详细介绍LCD_CAM控制器的LCD模块,该模块用于驱动RGBLCD接口。
       本章分为如下几个小节:
       33.1 RGBLCD和LCD模块接口简介
       33.2 硬件设计
       33.3 程序设计
       33.4 下载验证

       33.1 RGBLCD和LCD模块接口简介

       33.1.1 RGBLCD简介
       RGBLCD是基于一组特定的同步信号,该同步信号指示在哪里开始和停止帧。帧缓冲区分配在ESP侧。因为在这种情况下我们不需要安装任何IO接口驱动程序,所以这使得驱动程序的安装步骤极大简化了。接下来我们就简单介绍一些RGBLCD的驱动。

       1,RGBLCD的信号线
       RGBLCD的信号线如表33.1.1.1所示:

1.png
表33.1.1.1 RGBLCD信号线

       一般的RGB屏都有如表33.1.1.1所示的信号线,有24根颜色数据线(RGB各8根,即RGB888格式),这样可以表示最多1600W色,DE、VS、HS和DCLK,用于控制数据传输。

       2,RGBLCD的驱动模式
       RGB屏一般有2种驱动模式:DE模式和HV模式。DE模式使用DE信号来确定有效数据(DE为高/低时,数据有效),而HV模式,则需要行同步和场同步,来表示扫描的行和列。
       DE模式和HV模式的行扫描时序图(以800*480的LCD面板为例),如图33.1.1.1所示:

第三十三章 RGB显示屏实验897.png
图33.1.1.1 DE/HV模式行扫描时序图

       从图中可以看出,DE和HV模式,时序基本一样,DEN模式需要提供DE信号(DEN),而HV模式,则无需DE信号。图中的HSD即HS信号,用于行同步,注意:在DE模式下面,是可以不用HS信号的,即不接HS信号,液晶照样可以正常工作。
       图中的thpw为水平同步有效信号脉宽,用于表示一行数据的开始;thb为水平后廊,表示从水平有效信号开始,到有效数据输出之间的像素时钟个数;thfp为水平前廊,表示一行数据结束后,到下一个水平同步信号开始之前的像素时钟个数。
       图33.1.1.1仅是一行数据的扫描,输出800个像素点数据,而液晶面板总共有480行,这就还需要一个垂直扫描时序图,如图33.1.1.2所示:

第三十三章 RGB显示屏实验1224.png
图33.1.1.2 垂直扫描时序图

       图中的VSD就是垂直同步信号,HSD就是水平同步信号,DE为数据使能信号。如图可知,一个垂直扫描,刚好就是480个有效的DE脉冲信号,每一个DE时钟周期,扫描一行,总共扫描480行,完成一帧数据的显示。这就是800*480的LCD面板扫描时序,其他分辨率的LCD面板,时序类似。
       图中的tvpw为垂直同步有效信号脉宽,用于表示一帧数据的开始;tvb为垂直后廊,表示垂直同步信号以后的无效行数,tvfp为垂直前廊,表示一帧数据输出结束后,到下一个垂直同步信号开始之前的无效行数;这几个时间同样在配置LTDC的时候,需要进行设置。

       3,正点原子 RGBLCD模块
       正点原子目前提供大家五款 RGBLCD 模块:ATK-4342(4.3寸,480*272)、ATK-4384(4.3寸,800*480) ATK-7084(7寸,800*480)、 ATK-7016(7 寸,1024*600)和ATK-1018(10.1 寸,1280*800),这里我们以 ATK-7084 为例,给大家介绍。该模块的接口原理图如图 33.1.1.3 所示:

第三十三章 RGB显示屏实验1713.png
图33.1.1.3 RGBLCD模块对外接口原理图

       图中 J3就是对外接口,是一个 40PIN 的 FPC 座( 0.5mm 间距),通过 FPC 线,可以连接到ESP32-S3 开发板的RGB接口上面,从而实现和ESP32-S3的连接。该接口十分完善,采用 RGB888 格式,并支持 DE&HV 模式,还支持触摸屏(电阻/电容)和背光控制。右侧的几个电阻,并不是都焊接的,而是可以用户自己选择。默认情况, R1 和 R6 焊接,设置 LCD_LR和 LCD_UD,控制 LCD 的扫描方向,是从左到右,从上到下(横屏看)。而 LCD_R7/G7/B7 则用来设置 LCD 的 ID,由于 RGBLCD 没有读写寄存器,也就没有所谓的 ID,这里我们通过在模块上面,控制 R7/G7/B7 的上/下拉,来自定义 LCD 模块的 ID,帮助 MCU 判断当前 LCD 面板的分辨率和相关参数,以提高程序兼容性。这几个位的设置关系如表 33.1.1.2 所示:

2.png
表33.1.1.2正点原子 RGBLCD模块ID对应关系

       这样我们在程序里面,读取 LCD_R7/G7/B7,得到 M0:M2 的值,从而判断 RGBLCD 模块的型号,并执行不同的配置,即可实现不同 LCD模块的兼容。
       更详细的RGB屏相关内容,可以参考正点原子提供的《ATK-MD0430R模块用户手册_V1.0》和《ATK-MD0430R模块使用说明_V1.0》,在这两个手册中,已经详细说明了RGB的工作原理及相关参数信息。

       33.1.2 LCD模块接口简介
       本小节主要介绍LCD_CAM控制器的LCD模块,至于CAMERA模块讲解,作者会在摄像头章节中涉及,下面我们来看一下LCD模块的结构框架。

第三十三章 RGB显示屏实验2667.png
图33.1.2.1 LCD_CAM控制器结构框架

       这个系统的LCD模块(即上图的下方部分)包括以下模块:一个独立的发送控制单元(LCD_Ctrl),用于控制LCD的发送;一个发送异步FIFO(Async Tx FIFO),用于与外部设备交互,发送数据;一个LCD_Clock Generator时钟生成模块,用于生成对应模块的时钟;以及一个格式转换模块,即RGB/YCbCr Converter,用于各种格式的视频数据互相转换。这些模块协同工作,确保系统能够高效、稳定地处理和传输并行视频数据信号。
       需要读者注意的是:LCD_CAM的所有信号均需要经过GPIO交换矩阵映射到芯片管脚。更多信息请参考章节6 IO MUX和GPIO 交换矩阵(GPIO, IO MUX)。

       1,LCD模块信号描述
       LCD模块信号对应了上图右下角的几个信号,它们的具体作用如下所示。

3.png
表33.1.2.1 LCD模块信号描述

       在启动LCD模块时,信号的位宽是一个关键参数。根据所接入的LCD的位宽,N的值会有所不同。如果使用RGBLCD接口连接,并且位宽为16位,则N的值为15。相反,如果接入的LCD使用8位的位宽,则N的值为7。因此,根据LCD的位宽,可以确定N的具体值。

       2,LCD时钟选择
       从上图可以清晰地看到,LCD模块的时钟由三个不同的时钟源提供,它们分别是XTAL_CLK、PLL_D2_CLK和PLL_F160M_CLK。LCD模块的时钟源选择模式是由寄存器LCD_CAM_LCD_CLOCK_REG中的LCD_CAM_LCD_CLK_SEL位决定的。最后,LCD_Clock Generator时钟生成模块负责生成LCD模块所需的时钟,即上图中的LCD_CLK。
       下图是LCD时钟选择与计算框图。

第三十三章 RGB显示屏实验3684.png
图33.1.2.2 LCD时钟选择与计算框图

       LCD_CLK 的频率 fLCD_CLK 与分频器时钟源频率 fLCD_CLK_S 间的关系如下:

第三十三章 RGB显示屏实验3759.png

       其中,2<=N<=256,N对应为LCD_CAM_LCD_CLOCK_REG寄存器中LCD_CAM_LCD_CLKM_DIV_NUM的值。LCD模块的像素时钟PCLK为LCD_PCLK信号,由LCD_CLK分频获得。计算公式如下:

第三十三章 RGB显示屏实验3877.png

       其中,MO由寄存器LCD_CAM_LCD_CLK_EQU_SYSCLK和LCD_CAM_LCD_CLKCNT_N决定。最终我们得到了LCD_PCLK时钟,该时钟经过分频得到了像素时钟 LCD_PCLK。
       如果读者想了解更多的LCD模块知识,可参考《esp32-s3_technical_reference_manual_cn.pdf》技术手册29章节内容。

       33.2 硬件设计

       33.2.1 例程功能
       本章实验功能简介:本实验利用ESP32-S3开发板的RGB接口来驱动RGB屏,RGBLCD模块的接口在核心板上,通过40P的FPC排线连接RGBLCD模块,实现RGBLCD模块的驱动和显示,下载成功后,按下复位之后,就可以看到RGBLCD模块不停的显示一些信息并不断切换底色。同时,屏幕上会显示LCD的ID。需要注意的是:DNESP32S3开发板的RGB例程仅支持4.3寸的RGB显示屏。

       33.2.2 硬件资源

       1. LED灯
              LED-IO1

       2. XL9555
              IIC_SDA-IO41
              IIC_SCL-IO42

       3. RGBLCD
              LCD_BL-IO1_3(XL9555)
              LCD_DE-IO4
              LCD_VSYNC-NC
              LCD_HSYNC-NC
              LCD_PCLK-IO5
              LCD_R3-IO45
              LCD_R4-IO48
              LCD_R5-IO47
              LCD_R6-IO21
              LCD_R7-IO14
              LCD_G2-IO10
              LCD_G3-IO9
              LCD_G4-IO46
              LCD_G5-IO3
              LCD_G6-IO8
              LCD_G7-IO18
              LCD_B3-IO17
              LCD_B4-IO16
              LCD_B5-IO15
              LCD_B6-IO7
              LCD_B7-IO6

       33.2.3 原理图
       RGB接口与ESP32-S3的连接关系,如下图所示:

第三十三章 RGB显示屏实验4646.png
图33.2.3.1 RGB接口与ESP32-S3的连接电路图

       33.3 程序设计

       33.3.1 程序流程图
       程序流程图能帮助我们更好的理解一个工程的功能和实现的过程,对学习和设计工程有很好的主导作用。下面看看本实验的程序流程图:

第三十三章 RGB显示屏实验4790.png
图33.3.1.1 RGB实验程序流程图

       33.3.2 RGB-LCD函数解析
       ESP-IDF提供了一套API来配置RGB。要使用此功能,需要导入必要的头文件:
  1. #include "esp_lcd_panel_ops.h"
  2. #include "esp_lcd_panel_rgb.h"
复制代码
       接下来,作者将介绍一些常用的ESP32-S3中的RGB函数,这些函数的描述及其作用如下:

       1,创建RGB对象
       该函数通过配置结构体参数的方式将参数以指针的方式传进,该函数原型如下所示:
  1. esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t
  2.                                 *rgb_panel_config,
  3.                                 esp_lcd_panel_handle_t *ret_panel);
复制代码
       该函数的形参描述如下表所示:

4.png
表33.3.2.1 esp_lcd_new_rgb_panel()函数形参描述

       该函数的返回值描述,如下表所示:

5.png
表33.3.2.2 函数esp_lcd_new_rgb_panel ()返回值描述

       该函数使用esp_lcd_rgb_panel_config_t类型的结构体变量传入,该结构体的定义如下:

6.png
表33.3.2.3 esp_lcd_rgb_panel_config_t结构体参数值描述

       完成上述结构体参数配置之后,可以将结构传递给 esp_lcd_new_rgb_panel () 函数,用以实例化RGB。

       2,复位RGB屏幕
       在创建RGB屏幕对象后需要进行RGB屏幕复位,该函数原型如下所示:
  1. esp_err_t esp_lcd_panel_reset(esp_lcd_panel_handle_t panel);
复制代码
       该函数的形参描述如下表所示:

7.png
表33.3.2.4 esp_lcd_panel_reset ()函数形参描述

       该函数的返回值描述,如下表所示:

8.png
表33.3.2.5 函数esp_lcd_panel_reset ()返回值描述

       3,初始化RGB屏幕
       通过上两个步骤的配置,可以对屏幕进行初始化了,该函数原型如下所示:
  1. esp_err_t esp_lcd_panel_init(esp_lcd_panel_handle_t panel);
复制代码
       该函数的形参描述如下表所示:

9.png
表33.3.2.6 esp_lcd_panel_init ()函数形参描述

       该函数的返回值描述,如下表所示:

10.png
表33.3.2.7 函数esp_lcd_panel_init ()返回值描述

       33.3.3 RGB-LCD驱动解析
       在IDF版的23_rgb例程中,作者23_rgb\components\BSP路径下新增了一个RGB文件夹,分别用于存放ltdc.c、ltdc.h以及ltdcfont.h这三个文件。其中,ltdc.h和ltdc.h文件负责声明RGB相关的函数和变量并存放了LTDC 字库,而ltdc.c文件则实现了RGB的驱动代码。下面,我们将详细解析这三个文件的实现内容。

       1,ltdc.h文件
       该文件下定义了屏幕需要用到的一些重要参数,比如引脚定义,RGB颜色的十六进制值以及屏幕横向纵向的方向参数等。
  1. /* RGB_BL */
  2. #define LCD_BL(x)       do { x ?                                 \
  3.                              xl9555_pin_write(LCD_BL_IO, 1):     \
  4.                              xl9555_pin_write(LCD_BL_IO, 0);     \
  5.                         } while(0)


  6. /* RGBLCD引脚 */
  7. #define GPIO_LCD_DE     (GPIO_NUM_4)
  8. #define GPIO_LCD_VSYNC  (GPIO_NUM_NC)
  9. #define GPIO_LCD_HSYNC  (GPIO_NUM_NC)
  10. #define GPIO_LCD_PCLK   (GPIO_NUM_5)

  11. #define GPIO_LCD_R3     (GPIO_NUM_45)
  12. #define GPIO_LCD_R4     (GPIO_NUM_48)
  13. #define GPIO_LCD_R5     (GPIO_NUM_47)
  14. #define GPIO_LCD_R6     (GPIO_NUM_21)
  15. #define GPIO_LCD_R7     (GPIO_NUM_14)

  16. #define GPIO_LCD_G2     (GPIO_NUM_10)
  17. #define GPIO_LCD_G3     (GPIO_NUM_9)
  18. #define GPIO_LCD_G4     (GPIO_NUM_46)
  19. #define GPIO_LCD_G5     (GPIO_NUM_3)
  20. #define GPIO_LCD_G6     (GPIO_NUM_8)
  21. #define GPIO_LCD_G7     (GPIO_NUM_18)

  22. #define GPIO_LCD_B3     (GPIO_NUM_17)
  23. #define GPIO_LCD_B4     (GPIO_NUM_16)
  24. #define GPIO_LCD_B5     (GPIO_NUM_15)
  25. #define GPIO_LCD_B6     (GPIO_NUM_7)
  26. #define GPIO_LCD_B7     (GPIO_NUM_6)


  27. /* 常用画笔颜色 */
  28. #define WHITE           0xFFFF      /* 白色 */
  29. #define BLACK           0x0000      /* 黑色 */
  30. #define RED             0xF800      /* 红色 */
  31. #define GREEN           0x07E0      /* 绿色 */
  32. #define BLUE            0x001F      /* 蓝色 */
  33. #define MAGENTA         0xF81F      /* 品红色/紫红色 = BLUE + RED */
  34. #define YELLOW          0xFFE0      /* 黄色 = GREEN + RED */
  35. #define CYAN            0x07FF      /* 青色 = GREEN + BLUE */  


  36. /* LCD LTDC重要参数集 */
  37. typedef struct  
  38. {
  39. /* LTDC面板的宽度,固定参数,不随显示方向改变,如果为0,说明没有任何RGB屏接入 */
  40.     uint32_t pwidth;        
  41.     uint32_t pheight;       /* LTDC面板的高度,固定参数,不随显示方向改变 */
  42.     uint16_t hsw;           /* 水平同步宽度 */
  43.     uint16_t vsw;           /* 垂直同步宽度 */
  44.     uint16_t hbp;           /* 水平后廊 */
  45.     uint16_t vbp;           /* 垂直后廊 */
  46.     uint16_t hfp;           /* 水平前廊 */
  47.     uint16_t vfp;           /* 垂直前廊  */
  48.     uint8_t activelayer;    /* 当前层编号:0/1 */
  49.     uint8_t dir;            /* 0,竖屏;1,横屏; */
  50.     uint16_t id;            /* LTDC ID */
  51.     uint32_t pclk_hz;       /* 设置像素时钟 */
  52.     uint16_t width;         /* LTDC宽度 */
  53.     uint16_t height;        /* LTDC高度 */
  54. } _ltdc_dev;

  55. /* LTDC参数 */
  56. extern _ltdc_dev ltdcdev;   /* 管理LTDC重要参数 */

  57. extern esp_lcd_panel_handle_t panel_handle;
复制代码

       2,ltdc.c文件
       该文件下便是实现RGB屏幕的驱动函数了。由于代码过长,笔者仅整理出部分代码粘贴至此,详细内容请各位读者进入工程界面进行理解与学习。
  1. static const char *TAG = "ltdc";
  2. esp_lcd_panel_handle_t panel_handle = NULL;                   /* RGBLCD句柄 */

  3. /* 定义portMUX_TYPE类型的自旋锁变量,用于临界区保护 */
  4. static portMUX_TYPE my_spinlock = portMUX_INITIALIZER_UNLOCKED;     
  5. uint32_t g_back_color  = 0xFFFF;                              /* 背景色 */

  6. /* 管理LTDC重要参数 */
  7. _ltdc_dev ltdcdev;

  8. /**
  9. * @brief       LTDC读取面板ID
  10. * @note        利用LCD RGB线的最高位(R7,G7,B7)来识别面板ID
  11. *              PG6 = R7(M0); PI2 = G7(M1); PI7 = B7(M2);
  12. *              M2:M1:M0
  13. *              0 :0 :0     4.3 寸480*272  RGB屏,ID = 0X4342
  14. *              1 :0 :0     4.3 寸800*480  RGB屏,ID = 0X4384
  15. * @param       无
  16. * @retval      0, 非法;
  17. *              其他, LCD ID
  18. */
  19. uint16_t ltdc_panelid_read(void)
  20. {
  21.     uint8_t idx = 0;
  22.     gpio_config_t gpio_init_struct = {0};

  23.     gpio_init_struct.intr_type = GPIO_INTR_DISABLE;         /* 失能引脚中断 */
  24.     gpio_init_struct.mode = GPIO_MODE_INPUT;                /* 输入输出模式 */
  25.     gpio_init_struct.pull_up_en = GPIO_PULLUP_ENABLE;       /* 使能上拉 */
  26.     gpio_init_struct.pull_down_en = GPIO_PULLDOWN_DISABLE;  /* 失能下拉 */
  27.     gpio_init_struct.pin_bit_mask = 1ull << GPIO_LCD_B7;
  28.     gpio_config(&gpio_init_struct);                         /* 配置GPIO */

  29.     gpio_init_struct.pin_bit_mask = 1ull << GPIO_LCD_R7 || 1ull << GPIO_LCD_G7;
  30.     gpio_config(&gpio_init_struct);                         /* 配置GPIO */

  31.     idx  = (uint8_t)gpio_get_level(GPIO_LCD_R7);            /* 读取M0 */
  32.     idx |= (uint8_t)gpio_get_level(GPIO_LCD_G7) << 1;       /* 读取M1 */
  33.     idx |= (uint8_t)gpio_get_level(GPIO_LCD_B7) << 2;       /* 读取M2 */

  34.     switch (idx)
  35.     {
  36.         case 0 :
  37.             return 0X4342;                          /* 4.3寸屏, 480*272分辨率 */
  38.         case 4 :
  39.             return 0X4384;                          /* 4.3寸屏, 800*480分辨率 */
  40.         default :
  41.             return 0;
  42.     }
  43. }

  44. /**
  45. * @brief       初始化ltdc
  46. * @param       无
  47. * @retval      无
  48. */
  49. void ltdc_init(void)
  50. {
  51.     panel_handle = NULL;
  52.     ltdcdev.id = ltdc_panelid_read();           /* 读取LCD面板ID */

  53.     if (ltdcdev.id == 0X4342)                   /* 4.3寸屏, 480*272 RGB屏 */
  54.     {
  55.         ltdcdev.pwidth = 480;                   /* 面板宽度,单位:像素 */
  56.         ltdcdev.pheight = 272;                  /* 面板高度,单位:像素 */
  57.         ltdcdev.hsw = 1;                        /* 水平同步宽度 */
  58.         ltdcdev.vsw = 1;                        /* 垂直同步宽度 */
  59.         ltdcdev.hbp = 40;                       /* 水平后廊 */
  60.         ltdcdev.vbp = 8;                        /* 垂直后廊 */
  61.         ltdcdev.hfp = 5;                        /* 水平前廊 */
  62.         ltdcdev.vfp = 8;                        /* 垂直前廊 */
  63.         ltdcdev.pclk_hz = 9 * 1000 * 1000;      /* 设置像素时钟 9Mhz */
  64.     }
  65.     else if (ltdcdev.id == 0X4384)
  66.     {
  67.         ltdcdev.pwidth = 800;                   /* 面板宽度,单位:像素 */
  68.         ltdcdev.pheight = 480;                  /* 面板高度,单位:像素 */
  69.         ltdcdev.hbp = 88;                       /* 水平后廊 */
  70.         ltdcdev.hfp = 40;                       /* 水平前廊 */
  71.         ltdcdev.hsw = 48;                       /* 水平同步宽度 */
  72.         ltdcdev.vbp = 32;                       /* 垂直后廊 */
  73.         ltdcdev.vfp = 13;                       /* 垂直前廊 */
  74.         ltdcdev.vsw = 3;                        /* 垂直同步宽度 */
  75.         ltdcdev.pclk_hz = 18 * 1000 * 1000;     /* 设置像素时钟 18Mhz */
  76.     }

  77.     /* 配置RGB参数 */
  78.     esp_lcd_rgb_panel_config_t panel_config = { /* RGBLCD配置结构体 */
  79.         .data_width = 16,                       /* 数据宽度为16位 */
  80.         .psram_trans_align = 64,                /* 在PSRAM中分配的缓冲区的对齐 */
  81.         .clk_src = LCD_CLK_SRC_PLL160M,         /* RGBLCD外设时钟源 */
  82.         .disp_gpio_num = GPIO_NUM_NC,           /* 用于显示控制信号,不使用设为-1 */
  83.         .pclk_gpio_num = GPIO_LCD_PCLK,         /* PCLK信号引脚 */
  84.         .hsync_gpio_num = GPIO_NUM_NC,          /* HSYNC信号引脚,DE模式可不使用 */
  85.         .vsync_gpio_num = GPIO_NUM_NC,          /* VSYNC信号引脚,DE模式可不使用 */
  86.         .de_gpio_num = GPIO_LCD_DE,             /* DE信号引脚 */
  87.         .data_gpio_nums = {                     /* 数据线引脚 */
  88.             GPIO_LCD_B3, GPIO_LCD_B4, GPIO_LCD_B5, GPIO_LCD_B6, GPIO_LCD_B7,
  89.             GPIO_LCD_G2, GPIO_LCD_G3, GPIO_LCD_G4, GPIO_LCD_G5, GPIO_LCD_G6, GPIO_LCD_G7,
  90.             GPIO_LCD_R3, GPIO_LCD_R4, GPIO_LCD_R5, GPIO_LCD_R6, GPIO_LCD_R7,
  91.         },
  92.         .timings = {                            /* RGBLCD时序参数 */
  93.             .pclk_hz = ltdcdev.pclk_hz,         /* 像素时钟频率 */
  94.             .h_res = ltdcdev.pwidth,            /* 水平分辨率,即一行中的像素数 */
  95.             .v_res = ltdcdev.pheight,           /* 垂直分辨率,即帧中的行数 */

  96. /* 水平后廊,hsync和行活动数据开始之间的PCLK数 */
  97.             .hsync_back_porch = ltdcdev.hbp,
  98. /* 水平前廊,活动数据结束和下一个hsync之间的PCLK数 */
  99.             .hsync_front_porch = ltdcdev.hfp,   
  100.             .hsync_pulse_width = ltdcdev.vsw,   /* 垂直同步宽度,单位:行数 */
  101. /* 垂直后廊,vsync和帧开始之间的无效行数 */
  102.             .vsync_back_porch = ltdcdev.vbp,
  103. /* 垂直前廊,帧结束和下一个vsync之间的无效行数 */
  104.             .vsync_front_porch = ltdcdev.vfp,
  105.             .vsync_pulse_width = ltdcdev.hsw,   /* 水平同步宽度,单位:PCLK周期 */
  106.             .flags.pclk_active_neg = true,      /* RGB数据在下降沿计时 */
  107.         },
  108.         .flags.fb_in_psram = true,              /* 在PSRAM中分配帧缓冲区 */

  109. /* 解决写spiflash时,抖动问题 */
  110.         .bounce_buffer_size_px = (ltdcdev.id == 0X4384) ? 480 * 10 : 272 * 10,  
  111.     };

  112.     /* 创建RGB对象 */
  113.     esp_lcd_new_rgb_panel(&panel_config, &panel_handle);
  114.     /* 复位RGB屏 */
  115.     ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle));
  116.     /* 初始化RGB */
  117.     ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle));
  118.     /* 设置横屏 */
  119.     ltdc_display_dir(1);
  120.     /* 清除屏幕为颜色 */
  121.     ltdc_clear(WHITE);
  122.     /* 打开背光 */
  123.     LCD_BL(1);
  124. }


  125. /**
  126. * @brief       清除屏幕
  127. * @param       color:清除的颜色
  128. * @retval      无
  129. */
  130. void ltdc_clear(uint16_t color)
  131. {
  132.     uint16_t *buffer = heap_caps_malloc(ltdcdev.width * sizeof(uint16_t), MALLOC_CAP_INTERNAL |
  133.                                         MALLOC_CAP_8BIT);

  134.     if (NULL == buffer)
  135.     {
  136.         ESP_LOGE(TAG, "Memory for bitmap is not enough");
  137.     }
  138.     else
  139.     {
  140.         for (uint16_t i = 0; i < ltdcdev.width; i++)
  141.         {
  142.             buffer = color;
  143.         }
  144.         
  145.         for (uint16_t y = 0; y < ltdcdev.height; y++)
  146.         {/*使用taskENTER_CRITICAL()和taskEXIT_CRITICAL()保护画点过程,禁止任务调度*/
  147.             taskENTER_CRITICAL(&my_spinlock);   /* 屏蔽中断 */
  148.             esp_lcd_panel_draw_bitmap(panel_handle,
  149.                                                                            0,
  150.                                                                            y,
  151.                                                                            ltdcdev.width,
  152.                                                                            y + 1,
  153.                                                                            buffer);

  154.             taskEXIT_CRITICAL(&my_spinlock);    /* 重新使能中断 */
  155.         }
  156.         
  157.         heap_caps_free(buffer);
  158.     }
  159. }
复制代码

       33.3.4 CMakeLists.txt文件
       打开本实验BSP下的CMakeLists.txt文件,其内容如下所示:
  1. set(src_dirs
  2.             IIC
  3.             LED
  4.             XL9555
  5.             RGBLCD)

  6. set(include_dirs
  7.             IIC
  8.             LED
  9.             XL9555
  10.             RGBLCD)

  11. set(requires
  12.             driver
  13.             esp_lcd
  14.             esp_common
  15.             log)

  16. idf_component_register(SRC_DIRS ${src_dirs}
  17. INCLUDE_DIRS ${include_dirs} REQUIRES ${requires})

  18. component_compile_options(-ffast-math -O3 -Wno-error=format=-Wno-format)
复制代码
       上述的红色标注部分驱动需要由开发者自行添加,以确保RGB屏幕驱动能够顺利集成到构建系统中。这一步骤是必不可少的,它确保了RGB驱动的正确性和可用性,为后续的开发工作提供了坚实的基础。

       33.3.5 实验应用代码
       打开main/main.c文件,该文件定义了工程入口函数,名为app_main。该函数代码如下。
  1. i2c_obj_t i2c0_master;

  2. /**
  3. * @brief       程序入口
  4. * @param       无
  5. * @retval      无
  6. */
  7. void app_main(void)
  8. {
  9.     uint8_t x = 0;
  10.     uint8_t lcd_id[12];
  11.     esp_err_t ret;
  12.    
  13.     ret = nvs_flash_init();                            /* 初始化NVS */

  14. if (ret == ESP_ERR_NVS_NO_FREE_PAGES ||
  15. ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
  16.     {
  17.         ESP_ERROR_CHECK(nvs_flash_erase());
  18.         ret = nvs_flash_init();
  19.     }

  20.     led_init();                                        /* 初始化LED */
  21.     i2c0_master = iic_init(I2C_NUM_0);                 /* 初始化IIC0 */
  22.     xl9555_init(i2c0_master);                          /* IO扩展芯片初始化 */
  23.     ltdc_init();                                       /* RGB屏初始化 */

  24.     sprintf((char *)lcd_id, "LCD ID:%04X", ltdcdev.id);/*将ID打印到lcd_id数组*/

  25.     while (1)
  26.     {
  27.         switch (x)
  28.         {
  29.             case 0:
  30.                 ltdc_clear(WHITE);
  31.                 break;

  32.             case 1:
  33.                 ltdc_clear(BLACK);
  34.                 break;

  35.             case 2:
  36.                 ltdc_clear(BLUE);
  37.                 break;

  38.             case 3:
  39.                 ltdc_clear(RED);
  40.                 break;

  41.             case 4:
  42.                 ltdc_clear(MAGENTA);
  43.                 break;

  44.             case 5:
  45.                 ltdc_clear(GREEN);
  46.                 break;

  47.             case 6:
  48.                 ltdc_clear(CYAN);
  49.                 break;

  50.             case 7:
  51.                 ltdc_clear(YELLOW);
  52.                 break;
  53.         }

  54.         ltdc_show_string(10, 40, 240, 32, 32, "ESP32S3", RED);
  55.         ltdc_show_string(10, 80, 240, 24, 24, "LTDC TEST", RED);
  56.         ltdc_show_string(10, 110, 240, 16, 16, "ATOM@ALIENTEK", RED);
  57.         ltdc_show_string(10, 130, 240, 16, 16, (char *)lcd_id, RED);/* LCD ID */

  58.         x++;

  59.         if (x == 8)
  60.         {
  61.             x = 0;
  62.         }

  63.         vTaskDelay(1000);
  64.     }
  65. }
复制代码
       main函数功能主要是显示一些固定的字符,字体大小包括32*16、24*12、16*8和12*6四种,同时显示RGB-LCD驱动IC的型号,然后不停的切换背景颜色,每1s切换一次。其中我们用到一个sprintf的函数,该函数用法同printf,只是sprintf把打印内容输出到指定的内存区间上,最终在死循环中通过ltdc_show_strinig函数进行屏幕显示,sprintf的详细用法,请百度学习。

       33.4 下载验证
       在初始化完RGB-LCD屏幕后,便在RGB-LCD上显示一些本实验的相关信息,随后便每间隔1000毫秒就更换一次RGB-LCD屏幕显示的背景色。

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-27 20:20

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表