Skip to main content
Graduate
February 27, 2024
Solved

STM32H7B3I -DK unable to activate LCD - screen through registers

  • February 27, 2024
  • 7 replies
  • 6974 views

Please I need someone to review the code I wrote I double checked few times but am probably missing some info and configuration. I want to display red color on display module by only setting bits in the register. Here is the provided code. Someone please help I am working on a homework project.

#include <stdint.h>
#include "stm32h7b3xxq.h"
#include "reg_util.h"
#include "main.h"

void SystemClockSetup(void);
void VcoreSetup(void);
void LTDC_Peripheral_Init(void);
void LTDC_Peripheral_Setup(void);

int main(void)
{
 HAL_Init();
 SystemClockSetup();
 VcoreSetup();
 LTDC_Peripheral_Init();
 LTDC_Peripheral_Setup();

 /*Loop forever */
 for (;;);
}

void VcoreSetup(void)
{
 	//Povecaj wait states i latency

 FLASH->ACR |= (3 << 4);
 FLASH->ACR |= 0b0111;

 	//Disable SMP
 	//PWR -> CR3 &= ~(PWR_CR3_SMPSEN);

 	//Disable Bypass
 	//PWR -> CR3 &= ~(PWR_CR3_BYPASS);

 	//Wait for ACTVOSRDY bit
 	//while(!REG_READ_BIT(PWR -> CSR1,PWR_CSR1_ACTVOSRDY_Pos));

 	//Povisi voltage na VOS0;
 PWR->SRDCR |= (3 << 14);

 	//Wait for VOSRDY bit
 	//while(!REG_READ_BIT(PWR -> SRDCR,PWR_SRDCR_VOSRDY_Pos));

 	//Enable PLL1
 RCC->CR |= RCC_CR_PLL1ON;

 	//Wait for PLL stabilization
 while (!REG_READ_BIT(RCC->CR, RCC_CR_PLL1RDY_Pos));

 	//PLL as the main clock
 RCC->CFGR |= 3;	// pll1_p_ck je main clock

 	//Wait for confirmation

 while (!((RCC->CFGR >> 3) &(0x3) == (0x3)));

 	//Enable PLL3
 RCC->CR |= RCC_CR_PLL3ON;

 	//Wait for PLL stabilization
 while (!REG_READ_BIT(RCC->CR, RCC_CR_PLL3RDY_Pos));

 	//Omoguci clock za LTDC na APB3 busu
 RCC->APB3ENR |= RCC_APB3ENR_LTDCEN;

}

void SystemClockSetup(void)
{
 	//System Clock je HSI 64 MHz (default)

 	//DIVM1 i DIVM3 prescaler za smanjivanje frekvencije na 8 MHz
 RCC->PLLCKSELR |= RCC_PLLCKSELR_DIVM1_3;
 RCC->PLLCKSELR |= RCC_PLLCKSELR_DIVM3_3;

 	//Disable pll2 divider
 RCC->PLLCKSELR &= ~(32 << 12);	//Disable PLL2

 	//Ja koristim pll3_r_ck i pll1_p_ck, ostale ugasiti
 RCC->PLLCFGR &= ~(RCC_PLLCFGR_DIVQ1EN);	//Disable Q1 divider
 RCC->PLLCFGR &= ~(RCC_PLLCFGR_DIVR1EN);	//Disable R1 divider

 RCC->PLLCFGR &= ~(RCC_PLLCFGR_DIVP3EN);	//Disable P3 divider
 RCC->PLLCFGR &= ~(RCC_PLLCFGR_DIVQ3EN);	//Disable Q3 divider

 	//Choose input VCO frequency range 8 - 16 MHz
 RCC->PLLCFGR |= RCC_PLLCFGR_PLL1RGE_3;
 RCC->PLLCFGR |= RCC_PLLCFGR_PLL3RGE_3;

 	//Za PLL1 trebam pomnožiti sa 69(70 zapravo) i podijeliti sa 2(default state)
 RCC->PLL1DIVR |= 69;

 	//Pomnozi sa 17(18 zapravo) i podijeli sa 15(zapravo 16) 8 * 18/7 = 9 MHz za lcd driver na display modulu
 RCC->PLL3DIVR |= 17;	//Množenje sa 18
 RCC->PLL3DIVR |= (15 << 24);	// Dijeljenje sa 16;

 	//Namjesti Prescalere za PLL1 APB3 bus da bude max outan tj. 140 MHz
 RCC->CDCFGR1 |= RCC_CDCFGR1_CDPPRE_2;	//sys_clk / 2 = 140 MHz

}

void LTDC_Peripheral_Init(void)
{
 	//Enable AHB peripheral I,J,K ports
 RCC->AHB4ENR |= RCC_AHB4ENR_GPIOIEN;	// LCD_CLK, LCD_HSYNC, LCD_VSYNC
 RCC->AHB4ENR |= RCC_AHB4ENR_GPIOJEN;	//
 RCC->AHB4ENR |= RCC_AHB4ENR_GPIOKEN;	// LCD_DE

 	//Enable all 24 pins as Alternate functions
 GPIOI->MODER &= ~(GPIO_MODER_MODE12_0);	//PIN 12, LCD_HSYNC
 GPIOI->MODER &= ~(GPIO_MODER_MODE13_0);	//PIN 13, LCD_VSYNC
 GPIOI->MODER &= ~(GPIO_MODER_MODE14_0);	//PIN 14, LCD_CLK
 GPIOI->MODER &= ~(GPIO_MODER_MODE15_0);	//PIN 15, R0

 GPIOJ->MODER &= ~(GPIO_MODER_MODE0_0);	//PIN 0, R1
 GPIOJ->MODER &= ~(GPIO_MODER_MODE1_0);	//PIN 1, R2
 GPIOJ->MODER &= ~(GPIO_MODER_MODE2_0);	//PIN 2 R3
 GPIOJ->MODER &= ~(GPIO_MODER_MODE3_0);	//PIN 3 R4
 GPIOJ->MODER &= ~(GPIO_MODER_MODE4_0);	//PIN 4 R5
 GPIOJ->MODER &= ~(GPIO_MODER_MODE5_0);	//PIN 5 R6
 GPIOJ->MODER &= ~(GPIO_MODER_MODE6_0);	//PIN 6 R7
 GPIOJ->MODER &= ~(GPIO_MODER_MODE7_0);	//PIN 7 G0
 GPIOJ->MODER &= ~(GPIO_MODER_MODE8_0);	//PIN 8 G1
 GPIOJ->MODER &= ~(GPIO_MODER_MODE9_0);	//PIN 9 G2
 GPIOJ->MODER &= ~(GPIO_MODER_MODE10_0);	//PIN 10 G3
 GPIOJ->MODER &= ~(GPIO_MODER_MODE11_0);	//PIN 11 G4
 GPIOJ->MODER &= ~(GPIO_MODER_MODE12_0);	//PIN 12 B0
 GPIOJ->MODER &= ~(GPIO_MODER_MODE13_0);	//PIN 13 B1
 GPIOJ->MODER &= ~(GPIO_MODER_MODE14_0);	//PIN 14 B2
 GPIOJ->MODER &= ~(GPIO_MODER_MODE15_0);	//PIN 15 B3

 GPIOK->MODER &= ~(GPIO_MODER_MODE0_0);	//PIN 0 G5
 GPIOK->MODER &= ~(GPIO_MODER_MODE1_0);	//PIN 1 G6
 GPIOK->MODER &= ~(GPIO_MODER_MODE2_0);	//PIN 2 G7
 GPIOK->MODER &= ~(GPIO_MODER_MODE3_0);	//PIN 3 B4
 GPIOK->MODER &= ~(GPIO_MODER_MODE4_0);	//PIN 4 B5
 GPIOK->MODER &= ~(GPIO_MODER_MODE5_0);	//PIN 5 B6
 GPIOK->MODER &= ~(GPIO_MODER_MODE6_0);	//PIN 6 B7
 GPIOK->MODER &= ~(GPIO_MODER_MODE7_0);	//PIN 7 LCD_DE

 	//Set peripherals to AF14 so it could be configured for LCD-TFT
 GPIOI->AFR[1] |= (14 << GPIO_AFRH_AFSEL12_Pos);
 GPIOI->AFR[1] |= (14 << GPIO_AFRH_AFSEL13_Pos);
 GPIOI->AFR[1] |= (14 << GPIO_AFRH_AFSEL14_Pos);
 GPIOI->AFR[1] |= (14 << GPIO_AFRH_AFSEL15_Pos);

 GPIOJ->AFR[0] |= (14 << GPIO_AFRL_AFSEL0_Pos);
 GPIOJ->AFR[0] |= (14 << GPIO_AFRL_AFSEL1_Pos);
 GPIOJ->AFR[0] |= (14 << GPIO_AFRL_AFSEL2_Pos);
 GPIOJ->AFR[0] |= (14 << GPIO_AFRL_AFSEL3_Pos);
 GPIOJ->AFR[0] |= (14 << GPIO_AFRL_AFSEL4_Pos);
 GPIOJ->AFR[0] |= (14 << GPIO_AFRL_AFSEL5_Pos);
 GPIOJ->AFR[0] |= (14 << GPIO_AFRL_AFSEL6_Pos);
 GPIOJ->AFR[0] |= (14 << GPIO_AFRL_AFSEL7_Pos);
 GPIOJ->AFR[1] |= (14 << GPIO_AFRH_AFSEL8_Pos);
 GPIOJ->AFR[1] |= (14 << GPIO_AFRH_AFSEL9_Pos);
 GPIOJ->AFR[1] |= (14 << GPIO_AFRH_AFSEL10_Pos);
 GPIOJ->AFR[1] |= (14 << GPIO_AFRH_AFSEL11_Pos);
 GPIOJ->AFR[1] |= (14 << GPIO_AFRH_AFSEL12_Pos);
 GPIOJ->AFR[1] |= (14 << GPIO_AFRH_AFSEL13_Pos);
 GPIOJ->AFR[1] |= (14 << GPIO_AFRH_AFSEL14_Pos);
 GPIOJ->AFR[1] |= (14 << GPIO_AFRH_AFSEL15_Pos);

 GPIOK->AFR[0] |= (14 << GPIO_AFRL_AFSEL0_Pos);
 GPIOK->AFR[0] |= (14 << GPIO_AFRL_AFSEL1_Pos);
 GPIOK->AFR[0] |= (14 << GPIO_AFRL_AFSEL2_Pos);
 GPIOK->AFR[0] |= (14 << GPIO_AFRL_AFSEL3_Pos);
 GPIOK->AFR[0] |= (14 << GPIO_AFRL_AFSEL4_Pos);
 GPIOK->AFR[0] |= (14 << GPIO_AFRL_AFSEL5_Pos);
 GPIOK->AFR[0] |= (14 << GPIO_AFRL_AFSEL6_Pos);
 GPIOK->AFR[0] |= (14 << GPIO_AFRL_AFSEL7_Pos);

 	//Set every Pin to have Very high speed (OSPEEDR)
 GPIOI->OSPEEDR |= (3 << GPIO_OSPEEDR_OSPEED12_Pos);
 GPIOI->OSPEEDR |= (3 << GPIO_OSPEEDR_OSPEED13_Pos);
 GPIOI->OSPEEDR |= (3 << GPIO_OSPEEDR_OSPEED14_Pos);
 GPIOI->OSPEEDR |= (3 << GPIO_OSPEEDR_OSPEED15_Pos);

 GPIOJ->OSPEEDR |= (3 << GPIO_OSPEEDR_OSPEED0_Pos);
 GPIOJ->OSPEEDR |= (3 << GPIO_OSPEEDR_OSPEED1_Pos);
 GPIOJ->OSPEEDR |= (3 << GPIO_OSPEEDR_OSPEED2_Pos);
 GPIOJ->OSPEEDR |= (3 << GPIO_OSPEEDR_OSPEED3_Pos);
 GPIOJ->OSPEEDR |= (3 << GPIO_OSPEEDR_OSPEED4_Pos);
 GPIOJ->OSPEEDR |= (3 << GPIO_OSPEEDR_OSPEED5_Pos);
 GPIOJ->OSPEEDR |= (3 << GPIO_OSPEEDR_OSPEED6_Pos);
 GPIOJ->OSPEEDR |= (3 << GPIO_OSPEEDR_OSPEED7_Pos);
 GPIOJ->OSPEEDR |= (3 << GPIO_OSPEEDR_OSPEED8_Pos);
 GPIOJ->OSPEEDR |= (3 << GPIO_OSPEEDR_OSPEED9_Pos);
 GPIOJ->OSPEEDR |= (3 << GPIO_OSPEEDR_OSPEED10_Pos);
 GPIOJ->OSPEEDR |= (3 << GPIO_OSPEEDR_OSPEED11_Pos);
 GPIOJ->OSPEEDR |= (3 << GPIO_OSPEEDR_OSPEED12_Pos);
 GPIOJ->OSPEEDR |= (3 << GPIO_OSPEEDR_OSPEED13_Pos);
 GPIOJ->OSPEEDR |= (3 << GPIO_OSPEEDR_OSPEED14_Pos);
 GPIOJ->OSPEEDR |= (3 << GPIO_OSPEEDR_OSPEED15_Pos);

 GPIOK->OSPEEDR |= (3 << GPIO_OSPEEDR_OSPEED0_Pos);
 GPIOK->OSPEEDR |= (3 << GPIO_OSPEEDR_OSPEED1_Pos);
 GPIOK->OSPEEDR |= (3 << GPIO_OSPEEDR_OSPEED2_Pos);
 GPIOK->OSPEEDR |= (3 << GPIO_OSPEEDR_OSPEED3_Pos);
 GPIOK->OSPEEDR |= (3 << GPIO_OSPEEDR_OSPEED4_Pos);
 GPIOK->OSPEEDR |= (3 << GPIO_OSPEEDR_OSPEED5_Pos);
 GPIOK->OSPEEDR |= (3 << GPIO_OSPEEDR_OSPEED6_Pos);
 GPIOK->OSPEEDR |= (3 << GPIO_OSPEEDR_OSPEED7_Pos);

}

void LTDC_Peripheral_Setup(void)
{
 	//Set Hsync and Vsync in LTDC_SSCR
 LTDC->SSCR |= ((20 - 1) << LTDC_SSCR_VSH_Pos);	//Vsync
 LTDC->SSCR |= ((30 - 1) << LTDC_SSCR_HSW_Pos);	//Wsync

 	//Back porch configuration
 LTDC->BPCR |= ((20 + 12 - 1) << LTDC_BPCR_AVBP_Pos);	//Vsync + VBP
 LTDC->BPCR |= ((43 + 30 - 1) << LTDC_BPCR_AHBP_Pos);	//Hsync + HBP

 	//Active width and height configuration
 LTDC->AWCR |= ((20 + 12 + 272 - 1) << LTDC_AWCR_AAH_Pos);	//Active height
 LTDC->AWCR |= ((43 + 30 + 480 - 1) << LTDC_AWCR_AAW_Pos);	//Active weight

 	//Total width configuration
 LTDC->TWCR |= ((20 + 12 + 272 + 4 - 1) << LTDC_TWCR_TOTALH_Pos);	//Total height
 LTDC->TWCR |= ((43 + 30 + 480 + 8 - 1) << LTDC_TWCR_TOTALW_Pos);	//Total weight

 	//Configure color red

 LTDC->BCCR |= (0xFF UL << LTDC_BCCR_BCRED_Pos);

 	//Enable LTDC peripheral
 LTDC->GCR |= (1 << 0);
}
    This topic has been closed for replies.
    Best answer by mƎALLEm

    You need to download the all package from this link

    Then go to this path: \Projects\STM32H7B3I-DK\Examples\LTDC

    7 replies

    ST Employee
    February 28, 2024

    You may refer to an example for this board:

    STM32CubeH7/Projects/STM32H7B3I-DK/Examples/LTDC at master · STMicroelectronics/STM32CubeH7 · GitHub

     

    after the example is OK for your board, you may translate the source code to your desired style - only setting bits in the register.

    richiAuthor
    Graduate
    February 28, 2024

    Maybe a *** question but repo does not have the classic "Code<>" button where I can just copy the URL. Is there any other way to download the code?

    richi_0-1709125832063.png

     

    mƎALLEmAnswer
    Technical Moderator
    February 28, 2024

    You need to download the all package from this link

    Then go to this path: \Projects\STM32H7B3I-DK\Examples\LTDC

    Technical Moderator
    February 28, 2024

    Hello,

    It's a very painful task to check this kind of code (direct access to the registers).

    As stated by @jiangfan , you need to run the example(s) provided in CubeH7 then you can inspire from it and finally doing optimization by a direct access to the registers.

    PS: next time use  </> button to insert the code for readability.

    Thank you.

    Technical Moderator
    February 28, 2024

    @richi I sent the code through a code beautifier for you and inserted it as code with </> as suggested by @mƎALLEm. It's much easier to read, don't you think?

    Technical Moderator
    February 28, 2024

    @Peter BENSCH indeed but he needs to start by using HAL before going to direct access to the registers. Analyzing each bit (set/reset) in each register with different peripherals needs a huge time to analyze.

    I suggest him to start with HAL. If he faces issues, he can post the code as it will be easy to analyze.

    Technical Moderator
    February 28, 2024

    How you did open the project?

    This is what you have to get as view:

    SofLit_0-1709130745885.png

    You need to have "IDE" label in blue square on the project view.

    richiAuthor
    Graduate
    February 28, 2024

    I did manage to load it into workspace, but when I tried to build I get this error , in which folder should I paste that header file? 

    richi_0-1709134165624.png

     

    Technical Moderator
    February 29, 2024

    Sorry I didn't understand what you copied? and why you copied it?

    You need to have the all package and build the project (out of the box) from here: STM32Cube_FW_H7_VX.Y.0\Projects\STM32H7B3I-DK\Examples\LTDC\LTDC_Display_2Layers\STM32CubeIDE\

     No need to copy or move any file!

    Technical Moderator
    March 1, 2024

    Please re-download the package from here and build the project as it is .. There is no problems with the projects.

    Also try to shorten the path to the projects from your drive root for example copy your STM32CubeH7 package directly under C: as Windows uses a path length limitation.

    Technical Moderator
    March 1, 2024

    @richi The firmware library uses relative paths and expects .c/.h files to be located at a specific relative position. So you cannot simply copy an example from the firmware structure and expect everything to be compilable.

    Have you tested the examples directly from the directory structure recommended by @mƎALLEm , i.e. without copying them anywhere?

    richiAuthor
    Graduate
    March 1, 2024

    I did , they out of the box cannot be built because they throw errors that stm32h7xx.h is missing 

    richi_0-1709330862336.png

     

    Technical Moderator
    March 2, 2024

    I can see from your screenshot that you are neither working in the unchanged directory structure nor using a short path as suggested by @mƎALLEm. As long as you do not implement this, you will always have problems.

    richiAuthor
    Graduate
    March 3, 2024

    richi_0-1709459815422.png

    I must say that I dont understand what does it mean to "test the examples directly from the directory structure". I tried to go File >> Open Projects from File System choose the LTDC_2Layers directory , but then I am unable to build the project. If I go to LTDC_2Layers and click on the .project file it imports my project in Cube , I build it and the above picture is the result. I changed relative path in C: but error persists.

     

    Technical Moderator
    March 4, 2024

    Hello,

    When CubeMx suggested you to download the H7 library did you do it?

    You need to have the H7 cube package on this path <user>\STM32Cube\Repository\STM32Cube_FW_H7_VX.YY.ZZ

    No need to import the project from File >> Open Projects . Simply open the project by clicking .project file.