Hi,
I have the following ili9341 lcd
The display is connected as described:
/** * ILI9341 <--> LAUNCHXL-F28069M interconnect * ILI9341 LAUNCHXL-F28069M InitSpiaGpio * ------------------------------------------------------------- * SDO(MISO) J2(14) 1SPI_SO (GPIO17) (SPISOMIA) * LED J4(34) GPIO (GPIO13) * SCK J1(7) 1SPI_CLK (GPIO18) (SPICLKA) * SDI(MOSI) J2(15) 1SPI_SI (GPIO16) (SPISIMOA) * DC J2(18) GPIO (GPIO44) * RESET J1(8) GPIO (GPIO22) * CS J2(19) 1SPI_CS (GPIO19) (SPISTEA) * GND * VCC */
I have the following code to drive the LCD:
void init_spi_ili9341(void) { EALLOW; /** * Enable internal pull-up for the selected pins * Pull-ups can be enabled or disabled by the user. * This will enable the pullups for the specified pins. */ GpioCtrlRegs.GPAPUD.bit.GPIO16 = 0; /* pull-up on GPIO16 (SPISIMOA) */ GpioCtrlRegs.GPAPUD.bit.GPIO17 = 0; /* pull-up on GPIO17 (SPISOMIA) */ GpioCtrlRegs.GPAPUD.bit.GPIO18 = 0; /* pull-up on GPIO18 (SPICLKA) */ GpioCtrlRegs.GPAPUD.bit.GPIO19 = 0; /* pull-up on GPIO19 (SPISTEA) */ /** * Set qualification for selected pins to asynch only * This will select asynch (no qualification) for the selected pins. */ GpioCtrlRegs.GPAQSEL2.bit.GPIO16 = 3; /* Asynch input GPIO16 (SPISIMOA) */ GpioCtrlRegs.GPAQSEL2.bit.GPIO17 = 3; /* Asynch input GPIO17 (SPISOMIA) */ GpioCtrlRegs.GPAQSEL2.bit.GPIO18 = 3; /* Asynch input GPIO18 (SPICLKA) */ GpioCtrlRegs.GPAQSEL2.bit.GPIO19 = 3; /* Asynch input GPIO19 (SPISTEA) */ /** * Configure SPI-A pins using GPIO regs * This specifies which of the possible GPIO pins will be SPI functional * pins. */ GpioCtrlRegs.GPAMUX2.bit.GPIO16 = 1; /* Configure GPIO16 as SPISIMOA */ GpioCtrlRegs.GPAMUX2.bit.GPIO17 = 1; /* Configure GPIO17 as SPISOMIA */ GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 1; /* Configure GPIO18 as SPICLKA */ GpioCtrlRegs.GPAMUX2.bit.GPIO19 = 1; /* Configure GPIO19 as SPISTEA */ EDIS; } void init_spi(void) { SpiaRegs.SPICCR.bit.SPISWRESET = 0; /* Reset SPI */ SpiaRegs.SPIPRI.bit.TRIWIRE = 0; /* SPI 4 wire MODE enabled */ SpiaRegs.SPICCR.bit.SPICHAR = 0x7; /* 8 bits */ SpiaRegs.SPICCR.bit.CLKPOLARITY = 0; /* CPOL = 0 */ SpiaRegs.SPICTL.bit.MASTER_SLAVE = 1; /* Master */ SpiaRegs.SPICTL.bit.CLK_PHASE = 0; /* CPHA = 0, normal mode */ SpiaRegs.SPICTL.bit.TALK = 1; /* enable transmission */ SpiaRegs.SPISTS.all = 0x0000; /* clear status flags */ SpiaRegs.SPIBRR = 0x0063; /* Baud Rate */ SpiaRegs.SPIFFTX.bit.SPIFFENA = 1; /* FIFO enhancement enabled */ SpiaRegs.SPIFFTX.bit.SPIRST = 1; /* FIFO can resume Rx/Tx */ SpiaRegs.SPIFFCT.all = 0x00; /* no delays */ SpiaRegs.SPIPRI.bit.FREE = 1; /* Free run */ SpiaRegs.SPICCR.bit.SPISWRESET = 1; /* Enable SPI */ SpiaRegs.SPIFFTX.bit.TXFIFO = 1; /* Re enable TX FIFO */ SpiaRegs.SPIFFRX.bit.RXFIFORESET = 1; /* Re enable RX FIFO */ } /** * ILI9341 <--> LAUNCHXL-F28069M interconnect * ILI9341 LAUNCHXL-F28069M InitSpiaGpio * ------------------------------------------------------------- * SDO(MISO) J2(14) 1SPI_SO (GPIO17) (SPISOMIA) * LED J4(34) GPIO (GPIO13) * SCK J1(7) 1SPI_CLK (GPIO18) (SPICLKA) * SDI(MOSI) J2(15) 1SPI_SI (GPIO16) (SPISIMOA) * DC J2(18) GPIO (GPIO44) * RESET J1(8) GPIO (GPIO22) * CS J2(19) 1SPI_CS (GPIO19) (SPISTEA) * GND * VCC */ int spi_wr(Uint8 data) { Uint16 rd, tmp = data << 8; SpiaRegs.SPITXBUF = tmp; /* master TX data */ while (SpiaRegs.SPIFFRX.bit.RXFFST != 1); /* wait for data Rx */ rd = SpiaRegs.SPIRXBUF; /* Read Rx data */ if (rd != tmp) return -1; return 0; } int spi_wr16(Uint16 data) { Uint16 rd, tmp; tmp = (data >> 8) << 8; /* MSB first, left aligned */ SpiaRegs.SPITXBUF = tmp; while (SpiaRegs.SPIFFRX.bit.RXFFST != 1); rd = SpiaRegs.SPIRXBUF; if (rd != tmp) return -1; tmp = (data & 0xff) << 8; /* LSB next, left aligned */ SpiaRegs.SPITXBUF = tmp; while (SpiaRegs.SPIFFRX.bit.RXFFST != 1); rd = SpiaRegs.SPIRXBUF; if (rd != tmp) return -1; return 0; } void lcd_cmd(Uint8 cmd) { /** * D/CX bit is “low”, the transmission byte is interpreted * as a command byte. */ GpioDataRegs.GPBCLEAR.bit.GPIO44 = 1; /* pull down D/C pin */ spi_wr(cmd); GpioDataRegs.GPBSET.bit.GPIO44 = 1; /* pull up D/C pin */ } void lcd_dat(Uint8 *data, Uint32 len) { Uint32 i; for (i = 0; i < len; i++) spi_wr(data[i]); } void lcd_pixels(Uint16 color, Uint32 count) { Uint16 i; for (i = 0; i < count; i++) spi_wr16(color); } const Uint8 ili9341_init[] = { // Power control A 6, LCD_POWERA, 0x39, 0x2C, 0x00, 0x34, 0x02, // Power control B 4, LCD_POWERB, 0x00, 0xC1, 0x30, // Driver timing control A 4, LCD_DTCA, 0x85, 0x00, 0x78, // Driver timing control B 3, LCD_DTCB, 0x00, 0x00, // Power on sequence control 5, LCD_POWER_SEQ, 0x64, 0x03, 0x12, 0x81, // Pump ratio control 2, LCD_PRC, 0x20, // Power control 1 2, LCD_POWER1, 0x23, // Power control 2 2, LCD_POWER2, 0x10, // VCOM control 1 3, LCD_VCOM1, 0x3E, 0x28, // VCOM cotnrol 2 2, LCD_VCOM2, 0x86, // Memory access control 2, LCD_MAC, 0x48, // Pixel format set 2, LCD_PIXEL_FORMAT, 0x55, // Frame rate control 3, LCD_FRMCTR1, 0x00, 0x18, // Display function control 4, LCD_DFC, 0x08, 0x82, 0x27, // 3Gamma function disable 2, LCD_3GAMMA_EN, 0x00, // Column Address 5, LCD_COLUMN_ADDR, 0x00, 0x00, 0x00, 0xEF, // Page Address 5, LCD_PAGE_ADDR, 0x00, 0x00, 0x01, 0x3F, // Gamma curve selected 2, LCD_GAMMA, 0x01, // Set positive gamma 16, LCD_PGAMMA, 0x0F, 0x29, 0x24, 0x0C, 0x0E, 0x09, 0x4E, 0x78, 0x3c, 0x09, 0x13, 0x05, 0x17, 0x11, 0x00, 16, LCD_NGAMMA, 0x00, 0x16, 0x1b, 0x04, 0x11, 0x07, 0x31, 0x33, 0x42, 0x05, 0x0c, 0x0a, 0x28, 0x2f, 0x0F, 0 }; void lcd_init(void) { Uint8 count; Uint8 *address = (Uint8 *) ili9341_init; while (1) { count = *(address++); if (count-- == 0) break; lcd_cmd(*(address++)); lcd_dat(address, count); address += count; } } void lcd_reset(void) { GpioDataRegs.GPACLEAR.bit.GPIO22 = 1; /* RESET = 0 */ DELAY_US(10000); /* wait 10ms */ GpioDataRegs.GPASET.bit.GPIO22 = 1; /* RESET = 1 */ DELAY_US(50000); /* wait 50mS */ } void lcd_standby(void) { lcd_cmd(LCD_SLEEP_OUT); /* 0x11 */ DELAY_US(150000); /* Wait 150mS */ lcd_cmd(LCD_DISPLAY_ON); /* 0x29 */ } void lcd_orientation(Uint8 pos) { lcd_cmd(LCD_MAC); lcd_dat(&pos, 1); } static void lcd_set_window(Uint16 x1, Uint16 y1, Uint16 x2, Uint16 y2) { lcd_cmd(LCD_COLUMN_ADDR); /* 0x2a */ spi_wr16(x1); /* Start Column */ spi_wr16(x2); /* End Column */ lcd_cmd(LCD_PAGE_ADDR); /* 0x2b */ spi_wr16(y1); /* Start Page */ spi_wr16(y2); /* End Page */ } // width = 0, is 1 pixel wide // height = 0, is 1 pixel high void lcd_window_fill(Uint16 x_start, Uint16 y_start, Uint16 width, Uint16 height, Uint16 color) { Uint32 pixels = width * height; lcd_set_window(x_start, y_start, (Uint16) (x_start + width - 1), (Uint16) (y_start + height - 1)); lcd_cmd(LCD_GRAM); /* 0x2c */ lcd_pixels(color, pixels); } void main(void) { InitSysCtrl(); /* PLL, WatchDog, Peripheral Clk's */ init_spi_ili9341(); /* setup gpio for ili9341 spi */ DINT; /* Disable all CPU interrupts */ IER = 0x0000; /* Clear all CPU interrupts */ IFR = 0x0000; InitPieCtrl(); InitPieVectTable(); EALLOW; /* disable pullups */ GpioCtrlRegs.GPAPUD.bit.GPIO13 = 1; /* disable pullup for Backlight */ GpioCtrlRegs.GPAPUD.bit.GPIO22 = 1; /* disable pullup for RESET */ GpioCtrlRegs.GPBPUD.bit.GPIO44 = 1; /* disable pullup for D/C */ /* configure as GPIO */ GpioCtrlRegs.GPAMUX1.bit.GPIO13 = 0; /* GPIO::Backlight LED */ GpioCtrlRegs.GPAMUX2.bit.GPIO22 = 0; /* GPIO::RESET */ GpioCtrlRegs.GPBMUX1.bit.GPIO44 = 0; /* GPIO::D/C */ /* configure as output */ GpioCtrlRegs.GPADIR.bit.GPIO13 = 1; /* Output::Backlight */ GpioCtrlRegs.GPADIR.bit.GPIO22 = 1; /* Output::Reset */ GpioCtrlRegs.GPBDIR.bit.GPIO44 = 1; /* Output::D/C */ EDIS; /* set default states */ GpioDataRegs.GPASET.bit.GPIO22 = 1; /* RESET default HIGH (Release) */ GpioDataRegs.GPBSET.bit.GPIO44 = 1; /* D/C default HIGH (Data MODE) */ GpioDataRegs.GPASET.bit.GPIO13 = 1; /* Display Backlight ON */ /* LCD RESET */ lcd_reset(); /* Force LCD Hard RESET */ GpioDataRegs.GPACLEAR.bit.GPIO13 = 1; /* Enable Backlight after Init */ init_spi(); /* Initialize SPI peripheral */ lcd_standby(); /* Display ON, standby */ lcd_init(); /* Display fully configured */ lcd_orientation(LANDSCAPE); /* Display orientation */ GpioDataRegs.GPASET.bit.GPIO13 = 1; /* Backlight::ON */ lcd_window_fill(0, 0, 320, 240, 0x7e0); /* clear screen (Green) */ while (1) {} }
The waveforms SPI_WR looks thus:
and the SPIWR16 looks thus:
I've been expecting the display to be filled with GREEN, but display seems void of anything:
The display is actually white, but the camera makes the LCD appear bluish.
Given that nothing is visible on the display that I've written to it, but when the SPI Clk Phase is changed from
SpiaRegs.SPICTL.bit.CLK_PHASE = 0; /* CPHA = 0, normal mode */
to
SpiaRegs.SPICTL.bit.CLK_PHASE = 1; /* SPICLK delayed by one half-cycle */
Now the display appears thus:
I wonder whether anything is wrong with my spi writes. If not, wondering what else could be wrong ? Though the window area which is filled is not as expected, the color is exactly what was expected. The LCD command/data sequence has been working exactly as expected on a STM32 Cortex M3 previously.
Also the ILI9341 SDO line should be sending the data back to the Master ? But can't see that either ?
The ILI9341 appears to use a Normal CLK Phase, but the display doesn't seem to like that; Unless there is an issue with my SPI writes.
I am slightly lost here. Can someone help, please ?
Thanks,
Manu