SDI
概述
环境需求
该示例的环境需求,可参考 环境需求。
硬件连线
将 P3_6 连接到Reset引脚。
将 P4_2 连接到 D0 引脚。
将 P4_1 连接到 D1 引脚。
将 P3_2 连接到 D2 引脚。
将 P3_3 连接到 D3 引脚。
将 P4_3 连接到 CS 引脚。
将 P4_0 连接到 CLK 引脚。
将 P0_5 连接到 TE 引脚。
配置选项
可以通过修改函数 rtk_lcd_hal_init()
中的参数 ABGR_color
来改变 LCD 屏幕上显示的颜色。
uint32_t ABGR_color = 0x0000FF00; rtk_lcd_hal_rect_fill(0, 0, 280, 456, ABGR_color);
当前默认值代表纯绿色。
编译和下载
该示例的编译和下载流程,可参考 编译和下载。
测试验证
屏幕刷新成功
屏幕将以 配置选项 中确定的特定颜色刷新。
代码介绍
该章节主要介绍示例中的初始化和相应功能实现的代码和流程说明。
源码路径
工程文件和源码路径如下:
工程路径:
sdk\samples\peripheral\lcdc\lcdc_qspi\proj
源码路径:
sdk\samples\peripheral\lcdc\lcdc_qspi\src
初始化
初始化流程包含在 rtk_lcd_hal_init()
中。
启用 LCDC 时钟并选择合适的时钟源。
/* config LCD dev info */
RCC_PeriphClockCmd(APBPeriph_DISP, APBPeriph_DISP_CLOCK, ENABLE);
//from XTAL SOURCE = 40M
PERIBLKCTRL_PERI_CLK->u_324.BITS_324.disp_ck_en = 1;
PERIBLKCTRL_PERI_CLK->u_324.BITS_324.disp_func_en = 1;
PERIBLKCTRL_PERI_CLK->u_324.BITS_324.r_disp_mux_clk_cg_en = 1;
//From PLL1, SOURCE = 100M
PERIBLKCTRL_PERI_CLK->u_324.BITS_324.r_disp_div_en = 1;
PERIBLKCTRL_PERI_CLK->u_324.BITS_324.r_disp_clk_src_sel0 = 0; //pll1_peri(0) or pll2(1, pll2 = 160M)
PERIBLKCTRL_PERI_CLK->u_324.BITS_324.r_disp_clk_src_sel1 = 1; //pll(1) or xtal(0)
PERIBLKCTRL_PERI_CLK->u_324.BITS_324.r_disp_div_sel = 1; //div
初始化所有将要使用的引脚。
Pad_Config(LCD_QSPI_RST, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_DISABLE, PAD_OUT_HIGH);
Pad_Config(LCD_QSPI_D0, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_DISABLE, PAD_OUT_HIGH);
Pad_Config(LCD_QSPI_D1, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_DISABLE, PAD_OUT_HIGH);
Pad_Config(LCD_QSPI_D2, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_DISABLE, PAD_OUT_HIGH);
Pad_Config(LCD_QSPI_D3, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_DISABLE, PAD_OUT_HIGH);
Pad_Config(LCD_QSPI_CS, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_DISABLE, PAD_OUT_HIGH);
Pad_Config(LCD_QSPI_CLK, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_DISABLE, PAD_OUT_HIGH);
Pad_Config(LCD_QSPI_TE, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_DISABLE, PAD_OUT_HIGH);
Pad_Dedicated_Config(LCD_QSPI_RST, ENABLE);
Pad_Dedicated_Config(LCD_QSPI_D0, ENABLE);
Pad_Dedicated_Config(LCD_QSPI_D1, ENABLE);
Pad_Dedicated_Config(LCD_QSPI_D2, ENABLE);
Pad_Dedicated_Config(LCD_QSPI_D3, ENABLE);
Pad_Dedicated_Config(LCD_QSPI_CS, ENABLE);
Pad_Dedicated_Config(LCD_QSPI_CLK, ENABLE);
Pad_Dedicated_Config(LCD_QSPI_TE, ENABLE);
确定输入和输出颜色格式,并选择 SDI 接口。启用 TE 信号。
LCDC_InitTypeDef lcdc_init = {0};
lcdc_init.LCDC_Interface = LCDC_IF_DBIC;
lcdc_init.LCDC_GroupSel = 1;
lcdc_init.LCDC_PixelInputFormat = LCDC_INPUT_RGB565;
lcdc_init.LCDC_PixelOutputFormat = LCDC_OUTPUT_RGB565;
lcdc_init.LCDC_PixelBitSwap = LCDC_SWAP_BYPASS;
lcdc_init.LCDC_TeEn = ENABLE;
lcdc_init.LCDC_TePolarity = LCDC_TE_EDGE_FALLING;
lcdc_init.LCDC_TeInputMux = LCDC_TE_LCD_INPUT;
lcdc_init.LCDC_DmaThreshold = 112;
LCDC_Init(&lcdc_init);
初始化 SDI 接口,选择时钟分频器、极性和相位。
LCDC_DBICCfgTypeDef dbic_init = {0};
dbic_init.DBIC_SPEED_SEL = 1;
dbic_init.SCPOL = DBIC_SCPOL_LOW;
dbic_init.SCPH = DBIC_SCPH_1Edge;
DBIC_Init(&dbic_init);
控制复位引脚完成 LCD 面板复位过程。
LCDC_LCD_SET_RST(false);
platform_delay_ms(100);
LCDC_LCD_SET_RST(true);
platform_delay_ms(120);
LCDC_LCD_SET_RST(false);
platform_delay_ms(50);
使用基本 SPI 协议发送命令和数据,这些命令和数据应参考 LCD 生产商的指导手册。
incna3311_cmd_param1(0xFE, 0x00);
incna3311_cmd_param1(0xC4, 0x80); /*set quad SPI mode*/
incna3311_cmd_param1(0x35, 0x00); /*set tear on*/
incna3311_cmd_param1(0x51, 0xff); /*write display brightness*/
incna3311_cmd_param1(0x53, 0x20); /*write display ctrl ,dimming*/
incna3311_cmd_param1(0x63, 0xFF); /*write HBM display brightness*/
功能实现
设置更新窗口
函数 rtk_lcd_hal_set_window
用于设置要更新的屏幕窗口。本示例演示了一个从点 (0,0) 开始,宽度为 280,高度为 456 的窗口:
通过向 LCD 面板发送命令设置窗口。使用窗口范围与命令一起构建数据包。
//水平范围
data[0] = xStart >> 8;
data[1] = xStart & 0xff;
data[2] = xEnd >> 8;
data[3] = xEnd & 0xff;
incna3311_cmd_param4(0x2A, data);
//垂直范围
data[0] = yStart >> 8;
data[1] = yStart & 0xff;
data[2] = yEnd >> 8;
data[3] = yEnd & 0xff;
incna3311_cmd_param4(0x2B, data);
通过 API
LCDC_AXIMUXMode()
将 LCDC 的 AXI 模式切换到LCDC_FW_MODE
,从而使能对 SDI 进行写入修改。
LCDC_AXIMUXMode(LCDC_FW_MODE);
设置帧数据传输的数据大小、地址和命令,然后将 LCDC 切换回
LCDC_HW_MODE
。
DBIC_CmdLength(1);
DBIC_AddrLength(3);
DBIC_TX_NDF(len_byte);
/* must push cmd and address to handler before SDI enable */
LCDC_SPICCmd(0x32);
LCDC_SPICAddr(0x002c00);
LCDC_AXIMUXMode(LCDC_HW_MODE);
DMA 配置
在初始化 SDI 接口后,还应初始化 DMA 以启用数据传输。该过程在 rtk_lcd_hal_clear_screen
中演示。
初始化 DMA 参数,包括数据大小、突发大小和源增量,通过初始化的 SDI 接口向 LCD 面板传输数据。在本示例中,使用单块模式。
LCDC_DMA_InitTypeDef LCDC_DMA_InitStruct = {0};
LCDC_DMA_StructInit(&LCDC_DMA_InitStruct);
LCDC_DMA_InitStruct.LCDC_DMA_ChannelNum = LCDC_DMA_CHANNEL_NUM;
LCDC_DMA_InitStruct.LCDC_DMA_DIR = LCDC_DMA_DIR_PeripheralToMemory;
LCDC_DMA_InitStruct.LCDC_DMA_SourceInc = LCDC_DMA_SourceInc_Inc;
LCDC_DMA_InitStruct.LCDC_DMA_DestinationInc = LCDC_DMA_DestinationInc_Fix;
LCDC_DMA_InitStruct.LCDC_DMA_SourceDataSize = LCDC_DMA_DataSize_Word;
LCDC_DMA_InitStruct.LCDC_DMA_DestinationDataSize = LCDC_DMA_DataSize_Word;
LCDC_DMA_InitStruct.LCDC_DMA_SourceMsize = LCDC_DMA_Msize_8;
LCDC_DMA_InitStruct.LCDC_DMA_DestinationMsize = LCDC_DMA_Msize_8;
LCDC_DMA_Init(LCDC_DMA_CHANNEL_INDEX, &LCDC_DMA_InitStruct);
数据传输
在初始化内部 DMA 后,数据传输准备就绪。该过程在 rtk_lcd_hal_clear_screen
中演示。
使用 API
LCDC_SetTxPixelLen()
确定每帧内应发送多少像素。
LCDC_SetTxPixelLen(280 * 456);
使用
LCDC_DmaCmd()
让 DMA 开始向内部 FIFO 搬运数据。
LCDC_DmaCmd(ENABLE);
通过调用 API
LCDC_AutoWriteCmd()
让 LCDC 开始从内部 FIFO 向选定的接口传输数据。
LCDC_AutoWriteCmd(ENABLE);
轮询 LCDC 的状态。在 DMA 和 SDI 返回空闲状态后,停止 LCDC 的使能状态。
while ((LCDC_HANDLER->DMA_FIFO_CTRL & LCDC_DMA_ENABLE) != RESET);//wait dma idle
LCDC_HANDLER_OPERATE_CTR_t handler_reg_0x14;
do
{
handler_reg_0x14.d32 = LCDC_HANDLER->OPERATE_CTR;
}
while (handler_reg_0x14.b.auto_write_start != RESET);
LCDC_Cmd(DISABLE);
LCDC_ClearDmaFifo();
LCDC_ClearTxPixelCnt();
LCDC_AXIMUXMode(LCDC_FW_MODE);