Mercurial > ~darius > hgwebdir.cgi > stm32test
diff lcd.c @ 7:9404b9869c27
Make the LCD panel work (timings, GPIOE clock needs to be on, etc)
Factor out LCD init (needs more work)
author | Daniel O'Connor <darius@dons.net.au> |
---|---|
date | Sun, 22 Jan 2012 17:10:51 +1030 |
parents | efa2c22266e3 |
children | 58d76cf522ff |
line wrap: on
line diff
--- a/lcd.c Sat Jan 14 11:42:24 2012 +1030 +++ b/lcd.c Sun Jan 22 17:10:51 2012 +1030 @@ -3,13 +3,13 @@ * ~/projects/STM32Strive/奋斗STM32开发板例程/奋斗STM32开发板例程/奋斗STM32开发板MINI/STM32奋斗版ucOS II V2.86 uCGUI 3.9 DEMO-V2/STM32奋斗版ucOS II V2.86 uCGUI 3.9 DEMO * * Schematics - * Main board ~/Downloads/Strive\ Mini\ STM32\ Schematic.pdf - * LCD board ~/Downloads/Strive Mini LCD STM32 Schematic.pdf - * MCU reference manual - * ~/Downloads/CD00171190.pdf - * MCU Data sheet (pinout) - * ~/Downloads/CD00191185.pdf - * LCD data sheet + * Main board docs/Strive\ Mini\ STM32\ Schematic.pdf + * LCD board docs/Strive Mini LCD STM32 Schematic.pdf + * MCU reference manual docs/CD00171190.pdf + * MCU Data sheet (pinout) docs/CD00191185.pdf + * LCD controller data sheet docs/ili9325-v0.35.pdf + * LCD controller app notes docs/ILI9325AN_V0.22.pdf + * XXX: not sure what panel is connected * */ /* LCD board MCU @@ -44,7 +44,7 @@ 29 D1 PD15/FSMC_D1 30 D9 PE12/FSMC_D9 31 D0 PD14/FSMC_D0 - 32 D14 PD9/FSMC_D9 + 32 D14 PD9/FSMC_D14 33 NC 34 D8 PE11/FSMC_D8 35 NC @@ -59,6 +59,8 @@ #include "stm32f10x.h" #include "lcd.h" +static void LCD_Doinit(void); + #define Bank1_LCD_C ((uint32_t)0x60000000) /* Register Address */ #define Bank1_LCD_D ((uint32_t)0x60020000) /* Data Address */ @@ -85,15 +87,25 @@ } void +LCD_WR_StartData(uint16_t x, uint16_t y) { + LCD_WR_Reg(0x20, x); + LCD_WR_Reg(0x21, y); + *(__IO uint16_t *)(Bank1_LCD_C) = 0x22; /* Start GRAM write */ +} + +void LCD_WR_Data(uint16_t val) { *(__IO uint16_t *)(Bank1_LCD_D) = val; } -/* Callers imply this is in milliseconds but that seems unlikely */ +/* This is a bit rough and ready */ void Delay(__IO uint32_t nCount) { + __IO uint32_t i; + for(; nCount != 0; nCount--) - ; + for (i = 0; i < 3900; i++) + ; } uint8_t @@ -221,16 +233,18 @@ FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure; FSMC_NORSRAMTimingInitTypeDef p; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; - uint16_t id; /* Enable FSMC clock */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE); + /* Enable alternate function IO clock */ + RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); + /* Enable GPIOD clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); - /* Enable alternate function IO clock */ - RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); + /* Enable GPIOD clock */ + RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE); /* Configures LCD Control lines (FSMC Pins) in alternate function Push-Pull mode. * @@ -238,7 +252,8 @@ * PD10(D15), PD11(A16/RS) PD14(D0), PD15(D1) */ GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7 | - GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_14 | GPIO_Pin_15); + GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | + GPIO_Pin_14 | GPIO_Pin_15); GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOD, &GPIO_InitStructure); @@ -246,8 +261,9 @@ /* PE7(D4), PE8(D5), PE9(D6), PE10(D7), PE11(D8), PE12(D9), PE13(D10), * PE14(D11), PE15(D12) */ - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | - GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; + GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | + GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | + GPIO_Pin_15); GPIO_Init(GPIOE, &GPIO_InitStructure); /* Configure backlight control (PD13/FSMC_A18 remapped to TIM4_CH2) */ @@ -291,23 +307,23 @@ GPIO_Init(GPIOE, &GPIO_InitStructure); /* Configures the Parallel interface (FSMC) for LCD (Parallel mode) */ - /* FSMC_Bank1_NORSRAM4 timing configuration */ - p.FSMC_AddressSetupTime = 1; - p.FSMC_AddressHoldTime = 0; - p.FSMC_DataSetupTime = 2; + /* Timing configuration */ + p.FSMC_AddressSetupTime = 5; + p.FSMC_AddressHoldTime = 5; + p.FSMC_DataSetupTime = 5; p.FSMC_BusTurnAroundDuration = 0; p.FSMC_CLKDivision = 0; p.FSMC_DataLatency = 0; p.FSMC_AccessMode = FSMC_AccessMode_A; - /* FSMC_Bank1_NORSRAM4 configured as follows: + /* FSMC_Bank1_NORSRAM1 configured as follows: - Data/Address MUX = Disable - Memory Type = SRAM - Data Width = 16bit - Write Operation = Enable - Extended Mode = Disable - Asynchronous Wait = Disable */ - FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM4; + FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM1; FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable; FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM; FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b; @@ -322,105 +338,10 @@ FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable; FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p; FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p; - FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure); - /* Enable FSMC_Bank1_NORSRAM4 */ - FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM4, ENABLE); - - /* Initialise LCD panel */ - - /* Pull reset pin low */ - GPIO_ResetBits(GPIOE, GPIO_Pin_1); - Delay(0xafff); - GPIO_SetBits(GPIOE, GPIO_Pin_1); - Delay(0xafff); - - id = LCD_RD_Reg(0x00); - if (id != 0x9325) { - printf("LCD ID doesn't match, expected 0x9325 got 0x%x\r\n", id); - return; - } - - LCD_WR_Reg(0x00e3, 0x3008); /* Set internal timing */ - LCD_WR_Reg(0x00e7, 0x0012); /* Set internal timing */ - LCD_WR_Reg(0x00ef, 0x1231); /* Set internal timing */ - LCD_WR_Reg(0x0000, 0x0001); /* Start Oscillation */ - LCD_WR_Reg(0x0001, 0x0100); /* set SS and SM bit */ - LCD_WR_Reg(0x0002, 0x0700); /* set 1 line inversion */ - - LCD_WR_Reg(0x0003, 0x1030); /* set GRAM write direction and BGR = 0, 262K colours, 1 transfers/pixel. */ - LCD_WR_Reg(0x0004, 0x0000); /* Resize register */ - LCD_WR_Reg(0x0008, 0x0202); /* set the back porch and front porch */ - LCD_WR_Reg(0x0009, 0x0000); /* set non-display area refresh cycle ISC[3:0] */ - LCD_WR_Reg(0x000a, 0x0000); /* FMARK function */ - LCD_WR_Reg(0x000c, 0x0000); /* RGB interface setting */ - LCD_WR_Reg(0x000d, 0x0000); /* Frame marker Position */ - LCD_WR_Reg(0x000f, 0x0000); /* RGB interface polarity */ - - /* Power On sequence */ - LCD_WR_Reg(0x0010, 0x0000); /* SAP, BT[3:0], AP, DSTB, SLP, STB */ - LCD_WR_Reg(0x0011, 0x0007); /* DC1[2:0], DC0[2:0], VC[2:0] */ - LCD_WR_Reg(0x0012, 0x0000); /* VREG1OUT voltage */ - LCD_WR_Reg(0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */ - Delay(200); /* Dis-charge capacitor power voltage */ - LCD_WR_Reg(0x0010, 0x1690); /* SAP, BT[3:0], AP, DSTB, SLP, STB */ - LCD_WR_Reg(0x0011, 0x0227); /* R11h = 0x0221 at VCI = 3.3V, DC1[2:0], DC0[2:0], VC[2:0] */ - Delay(50); /* Delay 50ms */ - LCD_WR_Reg(0x0012, 0x001c); /* External reference voltage= Vci; */ - Delay(50); /* Delay 50ms */ - LCD_WR_Reg(0x0013, 0x1800); /* R13 = 1200 when R12 = 009D; VDV[4:0] for VCOM amplitude */ - LCD_WR_Reg(0x0029, 0x001c); /* R29 = 000C when R12 = 009D; VCM[5:0] for VCOMH */ - LCD_WR_Reg(0x002b, 0x000d); /* Frame Rate = 91Hz */ - Delay(50); /* Delay 50ms */ - LCD_WR_Reg(0x0020, 0x0000); /* GRAM horizontal Address */ - LCD_WR_Reg(0x0021, 0x0000); /* GRAM Vertical Address */ - - /* Adjust the Gamma Curve */ - LCD_WR_Reg(0x0030, 0x0007); - LCD_WR_Reg(0x0031, 0x0302); - LCD_WR_Reg(0x0032, 0x0105); - LCD_WR_Reg(0x0035, 0x0206); - LCD_WR_Reg(0x0036, 0x0808); - LCD_WR_Reg(0x0037, 0x0206); - LCD_WR_Reg(0x0038, 0x0504); - LCD_WR_Reg(0x0039, 0x0007); - LCD_WR_Reg(0x003c, 0x0105); - LCD_WR_Reg(0x003d, 0x0808); - - /* Set GRAM area */ - LCD_WR_Reg(0x0050, 0x0000); /* Horizontal GRAM Start Address */ - LCD_WR_Reg(0x0051, 0x00ef); /* Horizontal GRAM End Address */ - LCD_WR_Reg(0x0052, 0x0000); /* Vertical GRAM Start Address */ - LCD_WR_Reg(0x0053, 0x013f); /* Vertical GRAM Start Address */ - LCD_WR_Reg(0x0060, 0xa700); /* Gate Scan Line */ - LCD_WR_Reg(0x0061, 0x0001); /* NDL,VLE, REV */ - LCD_WR_Reg(0x006a, 0x0000); /* set scrolling line */ - - /* Partial Display Control */ - LCD_WR_Reg(0x0080, 0x0000); - LCD_WR_Reg(0x0081, 0x0000); - LCD_WR_Reg(0x0082, 0x0000); - LCD_WR_Reg(0x0083, 0x0000); - LCD_WR_Reg(0x0084, 0x0000); - LCD_WR_Reg(0x0085, 0x0000); - - /* Panel Control */ - LCD_WR_Reg(0x0090, 0x0010); - LCD_WR_Reg(0x0092, 0x0000); - LCD_WR_Reg(0x0093, 0x0003); - LCD_WR_Reg(0x0095, 0x0110); - LCD_WR_Reg(0x0097, 0x0000); - LCD_WR_Reg(0x0098, 0x0000); - LCD_WR_Reg(0x0007, 0x0133); /* 262K colour and display ON */ - - /* Fill panel with white */ - LCD_WR_Reg(0x20, 0); - LCD_WR_Reg(0x21, 0x013f); - *(__IO uint16_t *)(Bank1_LCD_C) = 34; - for (uint32_t i = 0; i < 320 * 240; i++) { - LCD_WR_Data(0xffff); - } + /* Enable FSMC_Bank1_NORSRAM1 */ + FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE); /* Configure touch screen controller * @@ -470,6 +391,7 @@ /* SPI1 enable */ SPI_Cmd(SPI1, ENABLE); + LCD_Doinit(); } void @@ -485,3 +407,128 @@ TIM_OC2Init(TIM4, &TIM_OCInitStructure); } + +static void +LCD_Doinit(void) { + uint16_t id; + + /* Initialise LCD panel */ + + /* Pull reset pin low */ + Delay(1); + GPIO_ResetBits(GPIOE, GPIO_Pin_1); + Delay(10); + GPIO_SetBits(GPIOE, GPIO_Pin_1); + Delay(50); + + id = LCD_RD_Reg(0x00); + if (id != 0x9325) { + printf("LCD ID doesn't match, expected 0x9325 got 0x%x\r\n", id); + return; + } + printf("LCD ID matches\r\n"); + + LCD_WR_Reg(0x00e3, 0x3008); /* Set internal timing (not documented) */ + LCD_WR_Reg(0x00e7, 0x0012); /* Set internal timing (not documented) */ + LCD_WR_Reg(0x00ef, 0x1231); /* Set internal timing (not documented) */ + LCD_WR_Reg(0x0000, 0x0001); /* Start Oscillation */ + Delay(50); + LCD_WR_Reg(0x0001, 0x0100); /* set SS (S720 -> S1) */ + LCD_WR_Reg(0x0002, 0x0700); /* set line inversion (B/C + EOR) */ + LCD_WR_Reg(0x0004, 0x0000); /* no resizing */ + LCD_WR_Reg(0x0008, 0x0202); /* set the back porch and front porch (2 lines each) */ + LCD_WR_Reg(0x0009, 0x0000); /* set non-display area refresh cycle ISC[3:0] */ + LCD_WR_Reg(0x000a, 0x0000); /* FMARK function */ + + LCD_WR_Reg(0x000c, 0x0000); /* RGB ctl - Internal clock, 18bit interface */ + LCD_WR_Reg(0x000d, 0x0000); /* Frame marker Position */ + LCD_WR_Reg(0x000f, 0x0000); /* RGB interface polarity */ + + /* Power On sequence */ + LCD_WR_Reg(0x0010, 0x0000); /* SAP, BT[3:0], AP, DSTB, SLP, STB */ + LCD_WR_Reg(0x0011, 0x0007); /* DC1[2:0], DC0[2:0], VC[2:0] */ + LCD_WR_Reg(0x0012, 0x0000); /* VREG1OUT voltage */ + LCD_WR_Reg(0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */ + Delay(200); /* Dis-charge capacitor power voltage */ + LCD_WR_Reg(0x0010, 0x1690); /* SAP, BT[3:0], AP, DSTB, SLP, STB */ + LCD_WR_Reg(0x0011, 0x0227); /* R11h = 0x0221 at VCI = 3.3V, DC1[2:0], DC0[2:0], VC[2:0] */ + Delay(50); /* Delay 50ms */ + LCD_WR_Reg(0x0012, 0x001c); /* External reference voltage= Vci; */ + Delay(50); /* Delay 50ms */ + LCD_WR_Reg(0x0013, 0x1800); /* R13 = 1200 when R12 = 009D; VDV[4:0] for VCOM amplitude */ + LCD_WR_Reg(0x0029, 0x001c); /* R29 = 000C when R12 = 009D; VCM[5:0] for VCOMH */ + LCD_WR_Reg(0x002b, 0x000d); /* Frame Rate = 91Hz */ + Delay(50); /* Delay 50ms */ + + /* Set GRAM area */ + LCD_WR_Reg(0x0050, 0x0000); /* Horizontal GRAM Start Address */ + LCD_WR_Reg(0x0051, 0x00ef); /* Horizontal GRAM End Address */ + LCD_WR_Reg(0x0052, 0x0000); /* Vertical GRAM Start Address */ + LCD_WR_Reg(0x0053, 0x013f); /* Vertical GRAM Start Address */ + + LCD_WR_Reg(0x0060, 0xa700); /* Gate Scan Line, drive G320 -> G1 */ + LCD_WR_Reg(0x0061, 0x0003); /* VLE & REV */ + LCD_WR_Reg(0x006a, 0x0000); /* set scrolling line */ + + /* Partial Display Control */ + LCD_WR_Reg(0x0080, 0x0000); /* Image 1 */ + LCD_WR_Reg(0x0081, 0x0000); + LCD_WR_Reg(0x0082, 0x0000); + LCD_WR_Reg(0x0083, 0x0000); /* Image 2 */ + LCD_WR_Reg(0x0084, 0x0000); + LCD_WR_Reg(0x0085, 0x0000); + + /* Panel Control */ + LCD_WR_Reg(0x0090, 0x0010); + LCD_WR_Reg(0x0092, 0x0000); + LCD_WR_Reg(0x0093, 0x0003); + LCD_WR_Reg(0x0095, 0x0110); + LCD_WR_Reg(0x0097, 0x0000); /* Undocumented */ + LCD_WR_Reg(0x0098, 0x0000); /* Undocumented */ + + LCD_WR_Reg(0x0007, 0x0133); /* Display on, 262k colour mode (vs 8) */ + + LCD_WR_Reg(0x0003, 0x1030); /* set GRAM write direction and enable BGR, 64K colours, 1 transfers/pixel. */ + + /* Adjust the Gamma Curve */ + LCD_WR_Reg(0x0030, 0x0006); + LCD_WR_Reg(0x0031, 0x0101); + LCD_WR_Reg(0x0032, 0x0003); + LCD_WR_Reg(0x0035, 0x0106); + LCD_WR_Reg(0x0036, 0x0b02); + LCD_WR_Reg(0x0037, 0x0302); + LCD_WR_Reg(0x0038, 0x0707); + LCD_WR_Reg(0x0039, 0x0007); + LCD_WR_Reg(0x003c, 0x0600); + LCD_WR_Reg(0x003d, 0x020b); + + fputs("Testing\r\n", stdout); + LCD_WR_StartData(0, 0); + LCD_WR_Data(0xa5a5); + LCD_WR_Data(0x5a5a); + LCD_WR_StartData(0, 0); + if ((id = LCD_RD_Data(1)) != 0xa5a5) + printf("Expected 0xa5a5 got 0x%04x\r\n", id); + + if ((id = LCD_RD_Data(0)) != 0x5a5a) + printf("Expected 0x5a5a got 0x%04x\r\n", id); + + fputs("Filling\r\n", stdout); + /* Fill panel */ + LCD_WR_StartData(0, 0); + +#define RGB24_565(R, G, B) (((((R) >> 3) & 0x1f) << 11) | ((((G) >> 2) & 0x3f) << 5) | (((B) >> 3) & 0x1f)) + + for (int x = 0; x < 320; x++) { + for (int y = 0; y < 240; y++) { + if (((x / 5) % 3) == 0) + LCD_WR_Data(RGB24_565(255, 0, 0)); + else if (((x / 5) % 3) == 1) + LCD_WR_Data(RGB24_565(0, 255, 0)); + else + LCD_WR_Data(RGB24_565(0, 0, 255)); + } + } + +} +