Skip to main content
Visitor II
October 3, 2024
Question

Connect SN65DSI83 LCD to STM32F469

  • October 3, 2024
  • 4 replies
  • 5063 views

Hi, i'm developing a board with 7" lcd (LVDS) so i'm really hesitating about if is right to use a SN65DSI83 for this, my STM32F469IIT6 only have 2 DSI Lanes. I'm connecting the i2c lane from SN65DSI83 to i2c of STM, i just copied the circuit of cm4-baseboard-lvds-adapter (https://github.com/antmicro/cm4-baseboard-lvds-adapter) and adapted to mind. So i'm really new in this kind of applications and i don't know if i should first read the registers of SN65DSI83 and then change (i want to implement a logic that if the registers are correctly configured just read and pass but if these are not right, my stm32 write the registers) or if every time that i have turn on my circuit, the STM32 should configure all registers. So some one have a tutorial for write on the screen with the comand mode? I just make some changes but i think in the future will put only springs for my aplication. So if someone can help me with this o maybe there are some documentation that i had no reading.

    This topic has been closed for replies.

    4 replies

    Technical Moderator
    November 26, 2024

    Hello @Dallton96

     

    Firstly, I apologize for my late reply.

    I recommend you to look to some LCD_DSI examples in STM32CubeF4 firmware.

    Also, I think Introduction to DSI host on STM32 MCUs and MPUs application note can help you. This application note describes the DSI host interface on STM32 MCUs and MPUs and focuses on presenting different operating modes of the DSI host. It also provides practical examples on how to configure the DSI host depending on the operating mode

    I hope this help you.

    Thank you.

    Kaouthar

    Dallton96Author
    Visitor II
    January 20, 2025

    Hi @KDJEM.1 .

    I have tried with the configuration examples and just have config the SN65DSI83. Why i told you this is correctly configured? Because i tried with the test pattern and it works really ok. So some tutorial for config the DSI with screen parameters? Or maybe I'm configuring bad my STM32F469IIT6.... I don't know... If someone can help me, i will put the main code here.

    Main:

    #include "main.h"

    #include "dsihost.h"

    #include "i2c.h"

    #include "ltdc.h"

    #include "rtc.h"

    #include "sdio.h"

    #include "spi.h"

    #include "tim.h"

    #include "gpio.h"

     

    /* Private includes ----------------------------------------------------------*/

    /* USER CODE BEGIN Includes */

    #include "../../SN65DSI83/SN65DSI83_Lib.h"

    /* USER CODE END Includes */

     

    /* Private typedef -----------------------------------------------------------*/

    /* USER CODE BEGIN PTD */

     

    /* USER CODE END PTD */

     

    /* Private define ------------------------------------------------------------*/

    /* USER CODE BEGIN PD */

     

    /* USER CODE END PD */

     

    /* Private macro -------------------------------------------------------------*/

    /* USER CODE BEGIN PM */

     

    /* USER CODE END PM */

     

    /* Private variables ---------------------------------------------------------*/

     

    /* USER CODE BEGIN PV */

    __attribute__((section(".sram"))) uint32_t framebuffer[3800]; //Espacio de 1024 en la memoria RAM interna

     

    /* USER CODE END PV */

     

    /* Private function prototypes -----------------------------------------------*/

    void SystemClock_Config(void);

    /* USER CODE BEGIN PFP */

    void drawRegion(uint16_t startX, uint16_t startY, uint16_t endX, uint16_t endY, uint32_t color);

     

    /* USER CODE END PFP */

     

    /* Private user code ---------------------------------------------------------*/

    /* USER CODE BEGIN 0 */

     

    /* USER CODE END 0 */

     

    /**

    * @brief The application entry point.

    * @retval int

    */

    int main(void)

    {

     

    /* USER CODE BEGIN 1 */

     

    /* USER CODE END 1 */

     

    /* MCU Configuration--------------------------------------------------------*/

     

    /* Reset of all peripherals, Initializes the Flash interface and the Systick. */

    HAL_Init();

     

    /* USER CODE BEGIN Init */

     

    /* USER CODE END Init */

     

    /* Configure the system clock */

    SystemClock_Config();

     

    /* USER CODE BEGIN SysInit */

     

    /* USER CODE END SysInit */

     

    /* Initialize all configured peripherals */

    MX_GPIO_Init();

    MX_TIM2_Init();

    MX_RTC_Init();

    MX_I2C1_Init();

    MX_SPI2_Init();

    MX_SDIO_SD_Init();

    MX_DSIHOST_DSI_Init();

    MX_LTDC_Init();

    /* USER CODE BEGIN 2 */

    HAL_GPIO_WritePin(DSI_RST_GPIO_Port, DSI_RST_Pin, GPIO_PIN_SET);

    HAL_Delay(50);

    HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_4);

    HAL_Delay(50);

    __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_4, 0);

    HAL_Delay(50);

    __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_4, 500);

    HAL_Delay(50);

    HAL_GPIO_WritePin(DSI_RST_GPIO_Port, DSI_RST_Pin, GPIO_PIN_RESET);

    HAL_Delay(50);

    HAL_GPIO_WritePin(DSI_RST_GPIO_Port, DSI_RST_Pin, GPIO_PIN_SET);

    HAL_Delay(50);

    //SN65DSI83_TestPatern();

    SN65DSI83_Init();

     

    if(HAL_DSI_Start(&hdsi) != HAL_OK) {

    Error_Handler();

    }

     

    HAL_Delay(100);

    drawRegion(161, 35, 1180, 36, 0x000000FF);

     

    /* USER CODE END 2 */

     

    /* Infinite loop */

    /* USER CODE BEGIN WHILE */

    while (1)

    {

    //HAL_Delay(100);

    //drawRegion(160, 21, 1184, 22, 0x0000FF00);

    /* USER CODE END WHILE */

     

    /* USER CODE BEGIN 3 */

    }

    /* USER CODE END 3 */

    }

     

    /**

    * @brief System Clock Configuration

    * @retval None

    */

    void SystemClock_Config(void)

    {

    RCC_OscInitTypeDef RCC_OscInitStruct = {0};

    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

     

    /** Configure the main internal regulator output voltage

    */

    __HAL_RCC_PWR_CLK_ENABLE();

    __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

     

    /** Initializes the RCC Oscillators according to the specified parameters

    * in the RCC_OscInitTypeDef structure.

    */

    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE|RCC_OSCILLATORTYPE_LSE;

    RCC_OscInitStruct.HSEState = RCC_HSE_ON;

    RCC_OscInitStruct.LSEState = RCC_LSE_ON;

    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;

    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;

    RCC_OscInitStruct.PLL.PLLM = 4;

    RCC_OscInitStruct.PLL.PLLN = 180;

    RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;

    RCC_OscInitStruct.PLL.PLLQ = 8;

    RCC_OscInitStruct.PLL.PLLR = 2;

    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)

    {

    Error_Handler();

    }

     

    /** Activate the Over-Drive mode

    */

    if (HAL_PWREx_EnableOverDrive() != HAL_OK)

    {

    Error_Handler();

    }

     

    /** Initializes the CPU, AHB and APB buses clocks

    */

    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK

    |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;

    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;

    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;

    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;

    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

     

    if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)

    {

    Error_Handler();

    }

     

    /** Enables the Clock Security System

    */

    HAL_RCC_EnableCSS();

    }

     

    /* USER CODE BEGIN 4 */

     

    void drawRegion(uint16_t startX, uint16_t startY, uint16_t endX, uint16_t endY, uint32_t color) {

    // Validar límites

     

    // Configurar LTDC para la ventana activa

    LTDC_LayerCfgTypeDef layerCfg;

    layerCfg.WindowX0 = startX;

    layerCfg.WindowX1 = endX;

    layerCfg.WindowY0 = startY;

    layerCfg.WindowY1 = endY;

    layerCfg.PixelFormat = LTDC_PIXEL_FORMAT_RGB888;

    layerCfg.FBStartAdress = (uint32_t)framebuffer;

    layerCfg.Alpha = 255;

    layerCfg.Alpha0 = 0;

    layerCfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_CA;

    layerCfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_CA;

    layerCfg.ImageWidth = endX - startX + 1;

    layerCfg.ImageHeight = endY - startY + 1;

     

    HAL_LTDC_ConfigLayer(&hltdc, &layerCfg, 0);

     

    // Rellenar el framebuffer parcial con el color especificado

    for (uint16_t y = 0; y < (endY - startY + 1); y++) {

    for (uint16_t x = 0; x < (endX - startX + 1); x++) {

    framebuffer[x + (endY - startY)*y] = color; // Rellenar píxel

    }

    }

    // Actualizar la pantalla

    HAL_LTDC_Reload(&hltdc, LTDC_RELOAD_VERTICAL_BLANKING);

    }

    Graduate II
    January 21, 2025

    Not really any comments, or indication of parameters being worked from.

    What frequency are you clocking the LTDC

    What frequency are you clocking the DSI and lanes?

    Dallton96Author
    Visitor II
    January 21, 2025

    I'm sorry for no put the parameters, some days ago (in a Texas Instruments forum) read that when you have only SN65DSI83 and want to transmit in video mode should to configure the STM32 in non-burst mode with sync and i did some research so first I was traying with 60Hz but the frecuencies of lanebyteclock of my STM32 no reach to 77,4Mhz. Then I recalibrate the SN65DSI83 (with DSI Turner) to 30Hz. According to my calculations, I set the DSI PHY frecuency at 312Mhz and lanebyteclock at 39Mhz, Video Packet size at 128 Pixels, Number of chuncks at 8 and null packet size at 0.
    The parameters of my screen are here:
    HSync = 20
    HBP = 160
    Active Width = 1024
    HFP = 140
    VSync = 5
    VBP = 23
    Active Height = 600
    VFP = 7
    Horizontal Sync Polarity = Active Low
    Vertical Sync Polarity = Active Low
    Not Data Enable Polarity = Active Low
    Pixel Clock Polarity = Normal Input
    Here I attach de values that i put in the DSI Turner

    Dallton96_0-1737426995793.png

    Dallton96_1-1737427017745.png

    So what I'm looking for with the "drawRegion" function is to paint only a 50x50 square in any region of the screen, I set aside a portion of it in 2500 (uint32_t) RAM which I called framebuffer, I don't know if I'm going in the right direction. I didn't work with external RAM, because I only need to paint small regions of the screen, but if any of your recommendations tell me to put one in, then I would redesign the PCB.

    Dallton96Author
    Visitor II
    January 24, 2025

    Hi everyone who answered me, I was researching a little and trying with some values in the DSI configuration, so here is the values:

    Dallton96_0-1737682908063.pngDallton96_1-1737682960107.pngDallton96_2-1737682983250.pngDallton96_4-1737683033520.pngDallton96_5-1737683047225.png

    Dallton96_6-1737683111051.png

    But the result in the screen is not that i hope, the function should paint a rectangle in the screen, in the axe X: 120 pixels (from 0 to 119) and in the axe Y: 30 pixels (from 0 to 29).

    Someone can help me to configurate the right values?
    (I'm using EK79001 screen and SN65DSI83 from DSI to LVDS at 30Hz).