SF32 驱动ST77916

参考 SF32快速点屏指南
代码如下

/**
  ******************************************************************************
  * @file   ST77916.c
  * @author Sifli software development team
  * @brief   This file includes the LCD driver for ST77916 LCD.
  * @attention
  ******************************************************************************
*/
/**
 * @attention
 * Copyright (c) 2019 - 2022,  Sifli Technology
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form, except as embedded into a Sifli integrated circuit
 *    in a product or a software update for such product, must reproduce the above
 *    copyright notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * 3. Neither the name of Sifli nor the names of its contributors may be used to endorse
 *    or promote products derived from this software without specific prior written permission.
 *
 * 4. This software, with or without modification, must only be used with a
 *    Sifli integrated circuit.
 *
 * 5. Any software provided in binary form under this license must not be reverse
 *    engineered, decompiled, modified and/or disassembled.
 *
 * THIS SOFTWARE IS PROVIDED BY SIFLI TECHNOLOGY "AS IS" AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL SIFLI TECHNOLOGY OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include <rtthread.h>
#include "string.h"
#include "board.h"
#include "drv_io.h"
#include "drv_lcd.h"

#include "log.h"









#define ROW_OFFSET (0x00)
#define COL_OFFSET (0x00)

/**
  * @brief ST77916 chip IDs
  */
#define THE_LCD_ID                  0x61977

/**
  * @brief  ST77916 Size
  */
#define  THE_LCD_PIXEL_WIDTH    ((uint16_t)360)
#define  THE_LCD_PIXEL_HEIGHT   ((uint16_t)360)






/**
  * @brief  ST77916 Registers
  */
#define REG_LCD_ID             0xDB /*Read ID1 , Read ID2 DBh  ,  Read ID3  DCh*/
#define REG_POWER_MODE         0x09
#define REG_SLEEP_IN           0x10 /* Dispaly Sleep  IN*/
#define REG_SLEEP_OUT          0x11 /* Dispaly Sleep  OUT*/
#define REG_PARTIAL_DISPLAY    0x12
#define REG_DISPLAY_INVERSION  0x21
#define REG_DISPLAY_OFF        0x28 /* Display Off*/
#define REG_DISPLAY_ON         0x29 /* Display On */
#define REG_WRITE_RAM          0x2C
#define REG_READ_RAM           0x2E
#define REG_CASET              0x2A
#define REG_RASET              0x2B
#define REG_SWRESET            0x01

#define REG_TEARING_EFFECT     0x35

#define REG_IDLE_MODE_OFF      0x38
#define REG_IDLE_MODE_ON       0x39
#define REG_COLOR_MODE         0x3A
#define REG_WBRIGHT            0x51
#define REG_MACTL              0x36





#define REG_VDV_VRH_EN         0xC2
#define REG_VDV_SET            0xC4














#define DEBUG

#ifdef DEBUG
    #define DEBUG_PRINTF(...)   LOG_I(__VA_ARGS__)
#else
    #define DEBUG_PRINTF(...)
#endif

static void LCD_WriteReg(LCDC_HandleTypeDef *hlcdc, uint16_t LCD_Reg, uint8_t *Parameters, uint32_t NbParameters);
static uint32_t LCD_ReadData(LCDC_HandleTypeDef *hlcdc, uint16_t RegValue, uint8_t ReadSize);
static uint32_t LCD_ESDCehck(LCDC_HandleTypeDef *hlcdc);
static void LCD_TimeoutDbg(LCDC_HandleTypeDef *hlcdc);
static void LCD_TimeoutReset(LCDC_HandleTypeDef *hlcdc);




#define QAD_SPI_ITF LCDC_INTF_SPI_DCX_4DATA
/**
 * @brief 
 * 
 */
static LCDC_InitTypeDef lcdc_int_cfg =
{
    .lcd_itf = QAD_SPI_ITF,
    .freq = 60000000,
    .color_mode = LCDC_PIXEL_FORMAT_RGB565,

    .cfg = {
        .spi = {
            .dummy_clock = 1,  //fixme : dafult : 0
#ifdef LCD_ST77916_VSYNC_ENABLE
            .syn_mode = HAL_LCDC_SYNC_VER, //open TE
#else            
            .syn_mode = HAL_LCDC_SYNC_DISABLE,
#endif
            .vsyn_polarity = 1,
            //default_vbp=2, frame rate=82, delay=115us,
            //TODO: use us to define delay instead of cycle, delay_cycle=115*48
            .vsyn_delay_us = 0,   //fixme : dafult : 100
            .hsyn_num = 0,        //fixme : dafult : 100
        },
    },


};


#define MAX_CMD_LEN 16
#if 1
static const uint8_t lcd_init_cmds[][MAX_CMD_LEN] =
{
    {0xF0,1, 0x28},
    {0xF2,1, 0x28},
    {0x73,1, 0xF0},
    {0x7C,1, 0xD1},
    {0x83,1, 0xE0},
    {0x84,1, 0x61},
    {0xF2,1, 0x82},
    {0xF0,1, 0x00},
    {0xF0,1, 0x01},
    {0xF1,1, 0x01},
    {0xB0,1, 0x40},
    {0xB1,1, 0x33},
    {0xB2,1, 0x26},
    {0xB4,1, 0x66},
    {0xB5,1, 0x44},
    {0xB6,1, 0xA5},
    {0xB7,1, 0x40},
    {0xB8,1, 0x8C},
    {0xBA,1, 0x00},
    {0xBB,1, 0x08},
    {0xBC,1, 0x08},
    {0xBD,1, 0x00},
    {0xC0,1, 0x80},
    {0xC1,1, 0x10},
    {0xC2,1, 0x37},
    {0xC3,1, 0x80},
    {0xC4,1, 0x10},
    {0xC5,1, 0x37},
    {0xC6,1, 0xA9},
    {0xC7,1, 0x41},
    {0xC8,1, 0x01},
    {0xC9,1, 0xA9},
    {0xCA,1, 0x41},
    {0xCB,1, 0x01},
    {0xCD,1, 0x7F},
    {0xD0,1, 0x91},
    {0xD1,1, 0x68},
    {0xD2,1, 0x68},
  
    { 0xF5,2,0x00, 0xA5},
    {0xF1, 1,0x10},
    {0xF0, 1,0x00},
    {0xF0, 1,0x02},
  
    {0xE0,14,
    0xF0 , 0x06,
    0x0B , 0x09,
    0x09 , 0x16,
    0x32 , 0x44,
    0x4A , 0x37,
    0x13 , 0x13,
    0x2E , 0x34},
  
    {0xE1,   14,
  
    0xF0 , 0x06,
    0x0B , 0x09,
    0x08 , 0x05,
    0x32 , 0x33,
    0x49 , 0x17,
    0x13 , 0x13,
    0x2E , 0x34},
  
    {0X35,1, 0X00},
    {0xF0,1, 0x10},
    {0xF3,1, 0x10},
    {0xE0,1, 0x0A},
    {0xE1,1, 0x00},
    {0xE2,1, 0x00},
    {0xE3,1, 0x00},
    {0xE4,1, 0xE0},
    {0xE5,1, 0x06},
    {0xE6,1, 0x21},
    {0xE7,1, 0x00},
    {0xE8,1, 0x05},
    {0xE9,1, 0xF2},
    {0xEA,1, 0xDF},
    {0xEB,1, 0x80},
    {0xEC,1, 0x26},
    {0xED,1, 0x14},
    {0xEE,1, 0xFF},
    {0xEF,1, 0x00},
    {0xF8,1, 0xFF},
    {0xF9,1, 0x00},
    {0xFA,1, 0x00},
    {0xFB,1, 0x30},
    {0xFC,1, 0x00},
    {0xFD,1, 0x00},
    {0xFE,1, 0x00},
    {0xFF,1, 0x00},
    {0x60,1, 0x42},
    {0x61,1, 0xE0},
    {0x62,1, 0x40},
    {0x63,1, 0x40},
    {0x64,1, 0x02},
    {0x65,1, 0x00},
    {0x66,1, 0x40},
    {0x67,1, 0x03},
    {0x68,1, 0x00},
    {0x69,1, 0x00},
    {0x6A,1, 0x00},
    {0x6B,1, 0x00},
    {0x70,1, 0x42},
    {0x71,1, 0xE0},
    {0x72,1, 0x40},
    {0x73,1, 0x40},
    {0x74,1, 0x02},
    {0x75,1, 0x00},
    {0x76,1, 0x40},
    {0x77,1, 0x03},
    {0x78,1, 0x00},
    {0x79,1, 0x00},
    {0x7A,1, 0x00},
    {0x7B,1, 0x00},
    {0x80,1, 0x48},
    {0x81,1, 0x00},
    {0x82,1, 0x05},
    {0x83,1, 0x02},
    {0x84,1, 0xDD},
    {0x85,1, 0x00},
    {0x86,1, 0x00},
    {0x87,1, 0x00},
    {0x88,1, 0x48},
    {0x89,1, 0x00},
    {0x8A,1, 0x07},
    {0x8B,1, 0x02},
    {0x8C,1, 0xDF},
    {0x8D,1, 0x00},
    {0x8E,1, 0x00},
    {0x8F,1, 0x00},
    {0x90,1, 0x48},
    {0x91,1, 0x00},
    {0x92,1, 0x09},
    {0x93,1, 0x02},
    {0x94,1, 0xE1},
    {0x95,1, 0x00},
    {0x96,1, 0x00},
    {0x97,1, 0x00},
    {0x98,1, 0x48},
    {0x99,1, 0x00},
    {0x9A,1, 0x0B},
    {0x9B,1, 0x02},
    {0x9C,1, 0xE3},
    {0x9D,1, 0x00},
    {0x9E,1, 0x00},
    {0x9F,1, 0x00},
    {0xA0,1, 0x48},
    {0xA1,1, 0x00},
    {0xA2,1, 0x04},
    {0xA3,1, 0x02},
    {0xA4,1, 0xDC},
    {0xA5,1, 0x00},
    {0xA6,1, 0x00},
    {0xA7,1, 0x00},
    {0xA8,1, 0x48},
    {0xA9,1, 0x00},
    {0xAA,1, 0x06},
    {0xAB,1, 0x02},
    {0xAC,1, 0xDE},
    {0xAD,1, 0x00},
    {0xAE,1, 0x00},
    {0xAF,1, 0x00},
    {0xB0,1, 0x48},
    {0xB1,1, 0x00},
    {0xB2,1, 0x08},
    {0xB3,1, 0x02},
    {0xB4,1, 0xE0},
    {0xB5,1, 0x00},
    {0xB6,1, 0x00},
    {0xB7,1, 0x00},
    {0xB8,1, 0x48},
    {0xB9,1, 0x00},
    {0xBA,1, 0x0A},
    {0xBB,1, 0x02},
    {0xBC,1, 0xE2},
    {0xBD,1, 0x00},
    {0xBE,1, 0x00},
    {0xBF,1, 0x00},
    {0xC0,1, 0x22},
    {0xC1,1, 0x98},
    {0xC2,1, 0x65},
    {0xC3,1, 0x74},
    {0xC4,1, 0x47},
    {0xC5,1, 0x56},
    {0xC6,1, 0x00},
    {0xC7,1, 0xBA},
    {0xC8,1, 0xAB},
    {0xC9,1, 0x33},
    {0xD0,1, 0x11},
    {0xD1,1, 0x98},
    {0xD2,1, 0x65},
    {0xD3,1, 0x74},
    {0xD4,1, 0x47},
    {0xD5,1, 0x56},
    {0xD6,1, 0x00},
    {0xD7,1, 0xBA},
    {0xD8,1, 0xAB},
    {0xD9,1, 0x33},
    {0xF3,1, 0x01},
    {0xF0,1, 0x00},
    {0x21,1, 0x00},
    {0x3A,1, 0x55},
    {0x11,1, 0x00},

};

//Display 1, color bar to check LCD ok.
static const uint8_t bist_cmds[][MAX_CMD_LEN] =
{
    {0xf0, 1,  0xa5},
    {0xb0, 1,  0xa5},
    {0xcc, 9, 0x40, 0x00, 0x3f, 0x01, 0x06, 0x06, 0x55, 0x55, 0x00},
};
#else
static const uint8_t lcd_init_cmds[][MAX_CMD_LEN] =
{
    { 0xf0, 1,  0xc3},
    { 0xf0, 1,  0x96},
    { 0xf0, 1,  0xa5},
    { 0xe9, 1,  0x20},
    { 0xe7, 4,  0x80, 0x77, 0x1f, 0xcc},
    { 0xc1, 4,  0x77, 0x07, 0xcf, 0x16},
    { 0xc2, 4,  0x77, 0x07, 0xcf, 0x16},
    { 0xc3, 4,  0x22, 0x02, 0x22, 0x04},
    { 0xc4, 4,  0x22, 0x02, 0x22, 0x04},
    { 0xc5, 1,  0xed},
    { 0xe0, 14, 0x87, 0x09, 0x0c, 0x06, 0x05, 0x03, 0x29, 0x32, 0x49, 0x0f, 0x1b, 0x17, 0x2a, 0x2f},
    { 0xe1, 14, 0x87, 0x09, 0x0c, 0x06, 0x05, 0x03, 0x29, 0x32, 0x49, 0x0f, 0x1b, 0x17, 0x2a, 0x2f},
    { 0xe5, 14, 0xbe, 0xf5, 0xb1, 0x22, 0x22, 0x25, 0x10, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22},
    { 0xe6, 14, 0xbe, 0xf5, 0xb1, 0x22, 0x22, 0x25, 0x10, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22},
    { 0xec, 2,  0x40, 0x03},
    { 0x36, 1,  0x0c},
    { 0x3a, 1,  0x05},  //0x07-rgb888  05-rgb565
    { 0xb2, 1,  0x00},
    { 0xb3, 1,  0x01},
    { 0xb4, 1,  0x00},
    { 0xb5, 4,  0x00, 0x08, 0x00, 0x08},
    { 0xa5, 9,  0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x2a, 0x8a, 0x02},
    { 0xa6, 9,  0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x2a, 0x8a, 0x02},
    { 0xba, 7,  0x0a, 0x5a, 0x23, 0x10, 0x25, 0x02, 0x00},
    { 0xbb, 8,  0x00, 0x30, 0x00, 0x2c, 0x82, 0x87, 0x18, 0x00},
    { 0xbc, 8,  0x00, 0x30, 0x00, 0x2c, 0x82, 0x87, 0x18, 0x00},
    { 0xbd, 11, 0xa1, 0xb2, 0x2b, 0x1a, 0x56, 0x43, 0x34, 0x65, 0xff, 0xff, 0x0f}



};

//Display  color bar to check LCD ok.
static const uint8_t bist_cmds[][MAX_CMD_LEN] =
{
    {0xb0, 1,  0xa5},
    {0xcc, 9, 0x40, 0x00, 0x3f, 0x00, 0x14, 0x14, 0x20, 0x20, 0x03},
};

#endif









/**
  * @brief  spi read/write mode
  * @param  enable: false - write spi mode |  true - read spi mode
  * @retval None
  */
static void LCD_ReadMode(LCDC_HandleTypeDef *hlcdc, bool enable)
{
    if (HAL_LCDC_IS_SPI_IF(lcdc_int_cfg.lcd_itf))
    {
        if (enable)
        {
            HAL_LCDC_SetFreq(hlcdc, 4000000); //read mode min cycle 300ns
        }
        else
        {
            HAL_LCDC_SetFreq(hlcdc, lcdc_int_cfg.freq); //Restore normal frequency
        }
    }
}

/**
  * @brief  Power on the LCD.
  * @param  None
  * @retval None
  */
static void LCD_Init(LCDC_HandleTypeDef *hlcdc)
{
    uint8_t   parameter[14];
    memcpy(&hlcdc->Init, &lcdc_int_cfg, sizeof(LCDC_InitTypeDef));
    HAL_LCDC_Init(hlcdc);
#if 1
    BSP_LCD_Reset(1);//Reset LCD
    LCD_DRIVER_DELAY_MS(100);
    BSP_LCD_Reset(0);
    LCD_DRIVER_DELAY_MS(120);
    BSP_LCD_Reset(1);
    LCD_DRIVER_DELAY_MS(120);

#else
    
    // software_reset
    LCD_WriteReg(hlcdc, REG_SWRESET, (uint8_t *)NULL, 0);
    LCD_DRIVER_DELAY_MS(120);
#endif


    for (int i = 0; i < sizeof(lcd_init_cmds) / MAX_CMD_LEN; i++)
    {
        //rt_kprintf("write %d,cmd=0x%x,len=%d\n",i,(int)lcd_init_cmds[i][0], (int)lcd_init_cmds[i][1]);
        //HAL_DBG_print_data((char*)&(lcd_init_cmds[i][2]),0,(int)lcd_init_cmds[i][1]);
        LCD_WriteReg(hlcdc, lcd_init_cmds[i][0], (uint8_t *)&lcd_init_cmds[i][2], lcd_init_cmds[i][1]);

    }


#ifdef LCD_ST77916_VSYNC_ENABLE
    LCD_DRIVER_DELAY_MS(80);
    rt_kprintf("Enable V-Blanking TE signal\n");
    // 启用 TE 指令
    parameter[0] = 0x01; // 00h: VSYNC Only , 01h:VSYNC&HSYNC
    LCD_WriteReg(hlcdc, REG_TEARING_EFFECT, parameter, 1);
#endif
    LCD_DRIVER_DELAY_MS(100);
    // tag:...................
    parameter[0] = 0x00; 
    LCD_WriteReg(hlcdc, REG_DISPLAY_ON, parameter, 1); /*  Display On */


//tag:............
#if 0
    HAL_LCDC_SetROIArea(hlcdc, 0, 0, LCD_HOR_RES_MAX - 1, LCD_VER_RES_MAX - 1);

    {
        uint32_t data;

        data = LCD_ReadData(hlcdc, REG_LCD_ID, 4);
        DEBUG_PRINTF("ST77916_ReadID 0x%x \n", data);


        data = LCD_ReadData(hlcdc, REG_POWER_MODE, 4);
        DEBUG_PRINTF("ST77916_ReadPowerMode 0x%x \n", data);
    }
#endif
}

/**
  * @brief  Disables the Display.
  * @param  None
  * @retval LCD Register Value.
  */
static uint32_t LCD_ReadID(LCDC_HandleTypeDef *hlcdc)
{
    uint32_t data;

    data = LCD_ReadData(hlcdc, REG_LCD_ID, 4);
    DEBUG_PRINTF("ST77916_ReadID 0x%x \n", data);
    // data = ((data << 1) >> 8) & 0xFFFFFF;

if (data)
{
    DEBUG_PRINTF("LCD module use ST77916 IC \n");
    data = THE_LCD_ID;
}
    return THE_LCD_ID;
}

/**
  * @brief  Enables the Display.
  * @param  None
  * @retval None
  */
static void LCD_DisplayOn(LCDC_HandleTypeDef *hlcdc)
{
    /* Display On */
    LCD_WriteReg(hlcdc, REG_SLEEP_OUT, (uint8_t *)NULL, 0);
    /* Wait for 120ms */
    LCD_DRIVER_DELAY_MS(100);
}

/**
  * @brief  Disables the Display.
  * @param  None
  * @retval None
  */
static void LCD_DisplayOff(LCDC_HandleTypeDef *hlcdc)
{
    /* Display Off */
    LCD_WriteReg(hlcdc, REG_SLEEP_IN, (uint8_t *)NULL, 0);
    /* Wait for 120ms */
    LCD_DRIVER_DELAY_MS(100);
}
/**
 * @brief set display windown
 * 
 */
static void LCD_SetRegion(LCDC_HandleTypeDef *hlcdc, uint16_t Xpos0, uint16_t Ypos0, uint16_t Xpos1, uint16_t Ypos1)
{
    /*
        0x2A & 0X2B is invalid for ST77916
    */
   uint8_t   parameter[4];

   //Set LCDC clip area
   HAL_LCDC_SetROIArea(hlcdc, Xpos0, Ypos0, Xpos1, Ypos1);

   Xpos0 += COL_OFFSET;
   Xpos1 += COL_OFFSET;

   Ypos0 += ROW_OFFSET;
   Ypos1 += ROW_OFFSET;


   parameter[0] = (Xpos0) >> 8;
   parameter[1] = (Xpos0) & 0xFF;
   parameter[2] = (Xpos1) >> 8;
   parameter[3] = (Xpos1) & 0xFF;
   LCD_WriteReg(hlcdc, REG_CASET, parameter, 4);

   parameter[0] = (Ypos0) >> 8;
   parameter[1] = (Ypos0) & 0xFF;
   parameter[2] = (Ypos1) >> 8;
   parameter[3] = (Ypos1) & 0xFF;
   LCD_WriteReg(hlcdc, REG_RASET, parameter, 4);


}

/**
  * @brief  Writes pixel.
  * @param  Xpos: specifies the X position.
  * @param  Ypos: specifies the Y position.
  * @param  RGBCode: the RGB pixel color
  * @retval None
  */
static void LCD_WritePixel(LCDC_HandleTypeDef *hlcdc, uint16_t Xpos, uint16_t Ypos, const uint8_t *RGBCode)
{
    uint8_t data = 0;

    rt_kprintf("\n ST77916_WritePixel xpos=%d, ypos=%d\n", Xpos, Ypos);

    if ((Xpos >= THE_LCD_PIXEL_WIDTH) || (Ypos >= THE_LCD_PIXEL_HEIGHT))
    {
        return;
    }

    /* Set Cursor */
    LCD_SetRegion(hlcdc, Xpos, Ypos, Xpos, Ypos);
    LCD_WriteReg(hlcdc, REG_WRITE_RAM, (uint8_t *)RGBCode, 2);
}

#if 0

void ST77916_WriteMultiplePixels_mcu(LCDC_HandleTypeDef *hlcdc, const uint8_t *RGBCode, uint16_t Xpos0, uint16_t Ypos0, uint16_t Xpos1, uint16_t Ypos1)
{
    uint32_t size;
    if ((Xpos0 >= THE_LCD_PIXEL_WIDTH) || (Ypos0 >= THE_LCD_PIXEL_HEIGHT)
            || (Xpos1 >= THE_LCD_PIXEL_WIDTH) || (Ypos1 >= THE_LCD_PIXEL_HEIGHT))
    {
        return;
    }

    if ((Xpos0 > Xpos1) || (Ypos0 > Ypos1))
    {
        return;
    }
    if (LCDC_INTF_SPI_DCX_4DATA_AUX == lcdc_int_cfg.lcd_itf)
    {
        HAL_LCDC_LayerSetData(hlcdc, HAL_LCDC_LAYER_DEFAULT, (uint8_t *)RGBCode, Xpos0, Ypos0, Xpos1, Ypos1);


        while (1)
        {
            /*

                1line data   ----(must > 40us, include Vporch line)------> 1line data

                1 frame      ------(must > 1ms)--------------->   1 frame

            */
            HAL_LCDC_WriteU32Reg(hlcdc, 0xDE006100, 0, 0);
            HAL_Delay_us(40); //Must delay 40us

            for (uint32_t back_porch = 7; back_porch > 0; back_porch--)
            {
                HAL_LCDC_WriteU32Reg(hlcdc, 0xDE006000, 0, 0);
                HAL_Delay_us(40);//Must delay 40us
            }

            for (uint16_t row = Ypos0; row < Ypos1; row++)
            {
                HAL_LCDC_SetROIArea(hlcdc, Xpos0, row, Xpos1, row);
                HAL_LCDC_SendLayerData2Reg_IT(hlcdc, 0xDE006000, 4);
                //Must delay 40us
            }


            for (uint32_t front_porch = 8; front_porch > 0; front_porch--)
            {
                HAL_LCDC_WriteU32Reg(hlcdc, 0xDE006000, 0, 0);
                HAL_Delay_us(40);  //Must delay 40us
            }

            LCD_DRIVER_DELAY_MS(1); //Must delay 1ms
        }

    }
    else
    {
        HAL_LCDC_LayerSetData(hlcdc, HAL_LCDC_LAYER_DEFAULT, (uint8_t *)RGBCode, Xpos0, Ypos0, Xpos1, Ypos1);
        HAL_LCDC_SendLayerData2Reg_IT(hlcdc, REG_WRITE_RAM, 1);
    }

}
#endif
 
//tag: 02-20 20:07:11:930    [101034] E/drv.lcd lcd_task: draw_core timeout

static void LCD_WriteMultiplePixels(LCDC_HandleTypeDef *hlcdc, const uint8_t *RGBCode, uint16_t Xpos0, uint16_t Ypos0, uint16_t Xpos1, uint16_t Ypos1)
{
    uint32_t size;
    HAL_LCDC_LayerSetData(hlcdc, HAL_LCDC_LAYER_DEFAULT, (uint8_t *)RGBCode, Xpos0, Ypos0, Xpos1, Ypos1);


    if (QAD_SPI_ITF == lcdc_int_cfg.lcd_itf)
    {
        HAL_LCDC_SendLayerData2Reg_IT(hlcdc, ((0x32 << 24) | (REG_WRITE_RAM << 8)), 4);
    }
    else
    {
        HAL_LCDC_SendLayerData2Reg_IT(hlcdc, REG_WRITE_RAM, 1);
    }
}


// fixme :ZhouMo Modify 2025-02-25
/**
  * @brief  Writes  to the selected LCD register.
  * @param  LCD_Reg: address of the selected register.
  * @retval None
  */
static void LCD_WriteReg(LCDC_HandleTypeDef *hlcdc, uint16_t LCD_Reg, uint8_t *Parameters, uint32_t NbParameters)
{

    if (QAD_SPI_ITF == lcdc_int_cfg.lcd_itf)
    {
        uint32_t cmd;

        cmd = (0x02 << 24) | (LCD_Reg << 8);

        if (0 != NbParameters)
        {
            /* Send command's parameters if any */
            HAL_LCDC_WriteU32Reg(hlcdc, cmd, Parameters, NbParameters);
        }
        else
        {
            uint32_t v = 0;
            HAL_LCDC_WriteU32Reg(hlcdc, cmd, (uint8_t *)&v, 1);
        }
    }
    else
    {
        HAL_LCDC_WriteU8Reg(hlcdc, LCD_Reg, Parameters, NbParameters);
    }


}


/**
  * @brief  Reads the selected LCD Register.
  * @param  RegValue: Address of the register to read
  * @param  ReadSize: Number of bytes to read
  * @retval LCD Register Value.
  */
static uint32_t LCD_ReadData(LCDC_HandleTypeDef *hlcdc, uint16_t RegValue, uint8_t ReadSize)
{
    uint32_t rd_data = 0;

    LCD_ReadMode(hlcdc, true);
    if (0)
    {
    }
    else if (QAD_SPI_ITF == lcdc_int_cfg.lcd_itf)
    {
        HAL_LCDC_ReadU32Reg(hlcdc, ((0x03 << 24) | (RegValue << 8)), (uint8_t *)&rd_data, ReadSize);
    }
    else
    {
        HAL_LCDC_ReadU8Reg(hlcdc, RegValue, (uint8_t *)&rd_data, ReadSize);
    }
    LCD_ReadMode(hlcdc, false);
    return rd_data;
}


// or
static uint32_t LCD_ReadPixel(LCDC_HandleTypeDef *hlcdc, uint16_t Xpos, uint16_t Ypos)
{
    return 0;
}


static void LCD_SetColorMode(LCDC_HandleTypeDef *hlcdc, uint16_t color_mode)
{
    uint8_t parameter[2];

    switch (color_mode)
    {
    case RTGRAPHIC_PIXEL_FORMAT_RGB565:
        /* Color mode 16bits/pixel */
        parameter[0] = 0x55;
        lcdc_int_cfg.color_mode = LCDC_PIXEL_FORMAT_RGB565;
        break;

    case RTGRAPHIC_PIXEL_FORMAT_RGB888:
        parameter[0] = 0x66;
        lcdc_int_cfg.color_mode = LCDC_PIXEL_FORMAT_RGB888;
        break;

    default:
        return; // unsupport
        break;
    }

    LCD_WriteReg(hlcdc, REG_COLOR_MODE, parameter, 1);

    uint32_t data = LCD_ReadData(hlcdc, 0xc, 1);
    DEBUG_PRINTF("\nST77916color_format 0x%x \n", data);

    HAL_LCDC_SetOutFormat(hlcdc, lcdc_int_cfg.color_mode);
}
/**
 * @brief 
 * 
 * @param hlcdc 
 * @param br 
 */
static void LCD_SetBrightness(LCDC_HandleTypeDef *hlcdc, uint8_t br)
{

    LOG_I("Set lcdlight %d", br);
    uint8_t bright = (uint8_t)((uint16_t)UINT8_MAX * br / 100);
    //LCD_WriteReg(hlcdc, REG_WBRIGHT, &br, 1);

    rt_device_t device = rt_device_find("lcdlight");
    if (device)
    {
        rt_err_t err = rt_device_open(device, RT_DEVICE_OFLAG_RDWR);
        uint8_t val = br;
        rt_device_write(device, 0, &val, 1);
        rt_device_close(device);
    }
    else
    {
        LOG_E("Can't find device lcdlight!");
    }

}


static void LCD_Rotate(LCDC_HandleTypeDef *hlcdc, LCD_DrvRotateTypeDef degree)
{
    uint8_t parameter;
#if defined(LCDC_SUPPORT_V_MIRROR)&&!defined(LCDC_SUPPORT_H_MIRROR)
    if (LCD_ROTATE_180_DEGREE == degree)
    {
        parameter = 0 << 7; //MY
        parameter = 0 << 6; //MX
        LCD_WriteReg(hlcdc, REG_MACTL, &parameter, 1);
    }
    else
    {
        parameter = 0 << 7; //MY
        parameter = 1 << 6; //MX
        LCD_WriteReg(hlcdc, REG_MACTL, &parameter, 1);
    }
#endif /* LCDC_SUPPORT_H_MIRROR */
}




static const LCD_DrvOpsDef ST77916_drv =
{
    LCD_Init,
    LCD_ReadID,
    LCD_DisplayOn,
    LCD_DisplayOff,

    LCD_SetRegion,
    LCD_WritePixel,
    LCD_WriteMultiplePixels,

    LCD_ReadPixel,

    LCD_SetColorMode,
    LCD_SetBrightness,
    NULL,
    NULL,
    LCD_Rotate,

};

LCD_DRIVER_EXPORT2(ST77916, THE_LCD_ID, &lcdc_int_cfg,
                   &ST77916_drv, 1);








/************************ (C) COPYRIGHT Sifli Technology *******END OF FILE****/

自行添加宏

6 个赞

大佬可以给讲解以下如何接线么

链接:mahjong_red_dragon:的教程里有接线顺序

1 个赞