/* Display a text message on the TFT with ILI9340 * * This program initializes the ILI9340 controller of a QVGA TFT * display then shows a text message. * */ #include "stm32f4xx.h" #define TFTWIDTH 240 #define TFTHEIGHT 320 // Color definitions #define BLACK 0x0000 #define BLUE 0x001F #define RED 0xF800 #define GREEN 0x07E0 #define CYAN 0x07FF #define MAGENTA 0xF81F #define YELLOW 0xFFE0 #define WHITE 0xFFFF // font table const uint8_t font5x7[][6]= { {0x00, 0x00, 0x00, 0x00, 0x00} // 20 ,{0x00, 0x00, 0xBE, 0x00, 0x00} // 21 ! ,{0x00, 0x0E, 0x00, 0x0E, 0x00} // 22 " ,{0x28, 0xFE, 0x28, 0xFE, 0x28} // 23 # ,{0x48, 0x54, 0xFE, 0x54, 0x24} // 24 $ ,{0x46, 0x26, 0x10, 0xC8, 0xC4} // 25 % ,{0x6C, 0x92, 0xAA, 0x44, 0xA0} // 26 & ,{0x00, 0x0A, 0x06, 0x00, 0x00} // 27 ' ,{0x00, 0x38, 0x44, 0x82, 0x00} // 28 ( ,{0x00, 0x82, 0x44, 0x38, 0x00} // 29 ) ,{0x28, 0x10, 0x7C, 0x10, 0x28} // 2a * ,{0x10, 0x10, 0x7C, 0x10, 0x10} // 2b + ,{0x00, 0xA0, 0x60, 0x00, 0x00} // 2c ,{0x10, 0x10, 0x10, 0x10, 0x10} // 2d - ,{0x00, 0xC0, 0xC0, 0x00, 0x00} // 2e . ,{0x40, 0x20, 0x10, 0x08, 0x04} // 2f / ,{0x7C, 0xA2, 0x92, 0x8A, 0x7C} // 30 0 ,{0x00, 0x84, 0xFE, 0x80, 0x00} // 31 1 ,{0x84, 0xC2, 0xA2, 0x92, 0x8C} // 32 2 ,{0x42, 0x82, 0x8A, 0x96, 0x62} // 33 3 ,{0x30, 0x28, 0x24, 0xFE, 0x20} // 34 4 ,{0x4E, 0x8A, 0x8A, 0x8A, 0x72} // 35 5 ,{0x78, 0x94, 0x92, 0x92, 0x60} // 36 6 ,{0x02, 0xE2, 0x12, 0x0A, 0x06} // 37 7 ,{0x6C, 0x92, 0x92, 0x92, 0x6C} // 38 8 ,{0x0C, 0x92, 0x92, 0x52, 0x3C} // 39 9 ,{0x00, 0x6C, 0x6C, 0x00, 0x00} // 3a : ,{0x00, 0xAC, 0x6C, 0x00, 0x00} // 3b ; ,{0x10, 0x28, 0x44, 0x82, 0x00} // 3c < ,{0x28, 0x28, 0x28, 0x28, 0x28} // 3d = ,{0x00, 0x82, 0x44, 0x28, 0x10} // 3e > ,{0x04, 0x02, 0xA2, 0x12, 0x0C} // 3f ? ,{0x64, 0x92, 0xF2, 0x82, 0x7C} // 40 @ ,{0xFC, 0x22, 0x22, 0x22, 0xFC} // 41 A ,{0xFE, 0x92, 0x92, 0x92, 0x6C} // 42 B ,{0x7C, 0x82, 0x82, 0x82, 0x44} // 43 C ,{0xFE, 0x82, 0x82, 0x44, 0x38} // 44 D ,{0xFE, 0x92, 0x92, 0x92, 0x82} // 45 E ,{0xFE, 0x12, 0x12, 0x12, 0x02} // 46 F ,{0x7C, 0x82, 0x92, 0x92, 0xF4} // 47 G ,{0xFE, 0x10, 0x10, 0x10, 0xFE} // 48 H ,{0x00, 0x82, 0xFE, 0x82, 0x00} // 49 I ,{0x40, 0x80, 0x82, 0x7E, 0x02} // 4a J ,{0xFE, 0x10, 0x28, 0x44, 0x82} // 4b K ,{0xFE, 0x80, 0x80, 0x80, 0x80} // 4c L ,{0xFE, 0x04, 0x18, 0x04, 0xFE} // 4d M ,{0xFE, 0x08, 0x10, 0x20, 0xFE} // 4e N ,{0x7C, 0x82, 0x82, 0x82, 0x7C} // 4f O ,{0xFE, 0x12, 0x12, 0x12, 0x0C} // 50 P ,{0x7C, 0x82, 0xA2, 0x42, 0xBC} // 51 Q ,{0xFE, 0x12, 0x32, 0x52, 0x8C} // 52 R ,{0x8C, 0x92, 0x92, 0x92, 0x62} // 53 S ,{0x02, 0x02, 0xFE, 0x02, 0x02} // 54 T ,{0x7E, 0x80, 0x80, 0x80, 0x7E} // 55 U ,{0x3E, 0x40, 0x80, 0x40, 0x3E} // 56 V ,{0x7E, 0x80, 0x70, 0x80, 0x7E} // 57 W ,{0xC6, 0x28, 0x10, 0x28, 0xC6} // 58 X ,{0x0E, 0x10, 0xE0, 0x10, 0x0E} // 59 Y ,{0xC2, 0xA2, 0x92, 0x8A, 0x86} // 5a Z ,{0x00, 0xFE, 0x82, 0x82, 0x00} // 5b [ ,{0x04, 0x08, 0x10, 0x20, 0x40} // 5c '\' ,{0x00, 0x82, 0x82, 0xFE, 0x00} // 5d ] ,{0x08, 0x04, 0x02, 0x04, 0x08} // 5e ^ ,{0x80, 0x80, 0x80, 0x80, 0x80} // 5f _ ,{0x00, 0x02, 0x04, 0x08, 0x00} // 60 ` ,{0x40, 0xA8, 0xA8, 0xA8, 0xF0} // 61 a ,{0xFE, 0x90, 0x88, 0x88, 0x70} // 62 b ,{0x70, 0x88, 0x88, 0x88, 0x40} // 63 c ,{0x70, 0x88, 0x88, 0x90, 0xFE} // 64 d ,{0x70, 0xA8, 0xA8, 0xA8, 0x30} // 65 e ,{0x10, 0xFC, 0x12, 0x02, 0x04} // 66 f ,{0x18, 0xA4, 0xA4, 0xA4, 0x7C} // 67 g ,{0xFE, 0x10, 0x08, 0x08, 0xF0} // 68 h ,{0x00, 0x88, 0xFA, 0x80, 0x00} // 69 i ,{0x40, 0x80, 0x88, 0x7A, 0x00} // 6a j ,{0xFE, 0x20, 0x50, 0x88, 0x00} // 6b k ,{0x00, 0x82, 0xFE, 0x80, 0x00} // 6c l ,{0xF8, 0x08, 0x30, 0x08, 0xF0} // 6d m ,{0xF8, 0x10, 0x08, 0x08, 0xF0} // 6e n ,{0x70, 0x88, 0x88, 0x88, 0x70} // 6f o ,{0xF8, 0x28, 0x28, 0x28, 0x10} // 70 p ,{0x10, 0x28, 0x28, 0x30, 0xF8} // 71 q ,{0xF8, 0x10, 0x08, 0x08, 0x10} // 72 r ,{0x90, 0xA8, 0xA8, 0xA8, 0x40} // 73 s ,{0x08, 0x7E, 0x88, 0x80, 0x40} // 74 t ,{0x78, 0x80, 0x80, 0x40, 0xF8} // 75 u ,{0x38, 0x40, 0x80, 0x40, 0x38} // 76 v ,{0x78, 0x80, 0x60, 0x80, 0x78} // 77 w ,{0x88, 0x50, 0x20, 0x50, 0x88} // 78 x ,{0x18, 0xA0, 0xA0, 0xA0, 0x78} // 79 y ,{0x88, 0xC8, 0xA8, 0x98, 0x88} // 7a z ,{0x00, 0x10, 0x6C, 0x82, 0x00} // 7b { ,{0x00, 0x00, 0xFE, 0x00, 0x00} // 7c | ,{0x00, 0x82, 0x6C, 0x10, 0x00} // 7d } ,{0x20, 0x10, 0x10, 0x20, 0x10} // 7e ~ ,{0x00, 0x1C, 0x14, 0x1C, 0x00} // 7f degree }; #define FONTWIDTH 6 #define FONTHEIGHT 8 #define ILI9340_SLPOUT 0x11 #define ILI9340_GAMMASET 0x26 #define ILI9340_DISPON 0x29 #define ILI9340_CASET 0x2A #define ILI9340_PASET 0x2B #define ILI9340_RAMWR 0x2C #define ILI9340_MADCTL 0x36 #define ILI9340_MADCTL_MX 0x40 #define ILI9340_MADCTL_BGR 0x08 #define ILI9340_PIXFMT 0x3A #define ILI9340_FRMCTR1 0xB1 #define ILI9340_DFUNCTR 0xB6 #define ILI9340_PWCTR1 0xC0 #define ILI9340_PWCTR2 0xC1 #define ILI9340_VMCTR1 0xC5 #define ILI9340_VMCTR2 0xC7 #define ILI9340_GMCTRP1 0xE0 #define ILI9340_GMCTRN1 0xE1 #define ILI9340_setCommand() GPIOA->BSRR = 0x08000000; /* make DC PA11 low */ #define ILI9340_setData() GPIOA->BSRR = 0x00000800; /* make DC PA11 high */ #define ILI9340_assertSS() GPIOC->BSRR = 0x00020000; /* assert /SS PC1 */ #define ILI9340_deassertSS() GPIOC->BSRR = 0x00000002; /* deassert /SS PC1 */ #define ILI9340_reset() ; /* make RESET P2.6 low */ #define ILI9340_dereset() ; /* make RESET P2.6 high */ void SPI_init(void); void SPI_write(unsigned char data); void ILI9340_hardReset(void); void ILI9340_command(uint8_t command); void ILI9340_data(uint8_t data); void ILI9340_blockData(int32_t n, uint16_t color); void delayMs(int32_t n); void ILI9340_setWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1); void ILI9340_init(void); void ILI9340_drawChar(uint8_t c, uint16_t x, uint16_t y, uint16_t fcolor, uint16_t bcolor); void ILI9340_drawCharBig(uint8_t c, uint16_t x, uint16_t y, uint16_t fcolor, uint16_t bcolor, uint8_t m); void ILI9340_drawString(uint8_t* s, uint16_t x, uint16_t y, uint16_t fcolor, uint16_t bcolor, uint8_t m); void ILI9340_drawPixel(uint16_t x, uint16_t y, uint16_t color); int32_t main(void) { uint32_t ulx = 0, uly = 0, lrx = TFTWIDTH, lry = TFTHEIGHT; uint16_t color = BLUE; uint32_t w = ulx - lrx; uint32_t h = uly - lry; ILI9340_init(); ILI9340_setWindow(ulx, uly, lrx, lry); ILI9340_blockData(w * h, color); // Landscape ILI9340_command(0x36); ILI9340_data(0xD8); ILI9340_drawString((uint8_t*)"STM32 NUCLEO-64", 20, 60, RED, YELLOW, 3); ILI9340_drawString((uint8_t*)"on EduBase V2", 20, 90, YELLOW, BLUE, 3); while(1) { } } /* draw a character */ void ILI9340_drawChar(uint8_t c, uint16_t x, uint16_t y, uint16_t fcolor, uint16_t bcolor) { for (int i = 0; i < FONTWIDTH; i++) { uint8_t byte = font5x7[c - ' '][i]; uint16_t xx = x + i; for (int j = 0; j < FONTHEIGHT; j++) { uint16_t yy = y + j; ILI9340_drawPixel(yy, xx, byte & (1 << j) ? fcolor : bcolor); } } } /* draw a big character */ void ILI9340_drawCharBig(uint8_t c, uint16_t x, uint16_t y, uint16_t fcolor, uint16_t bcolor, uint8_t m) { for (int i = 0; i < FONTWIDTH; i++) { uint8_t byte = font5x7[c - ' '][i]; for (int n = 0; n < m; n++) { uint16_t xx = x + i * m + n; for (int j = 0; j < FONTHEIGHT; j++) { uint16_t yy = y + j * m; for (int k = 0; k < m; k++) { ILI9340_drawPixel(yy + k, xx, byte & (1 << j) ? fcolor : bcolor); } } } } } /* draw a string of big characters */ void ILI9340_drawString(uint8_t* s, uint16_t x, uint16_t y, uint16_t fcolor, uint16_t bcolor, uint8_t m) { while (*s != 0) { ILI9340_drawCharBig(*s, x, y, fcolor, bcolor, m); s++; x += FONTWIDTH * m; } } /* draw a pixel */ void ILI9340_drawPixel(uint16_t x, uint16_t y, uint16_t color) { if((x < 1) ||(x >= TFTWIDTH) || (y < 1) || (y >= TFTHEIGHT)) return; ILI9340_setWindow(x, y, x + 1, y + 1); ILI9340_blockData(1, color); } /* Initialize SPI for TFT controller */ void SPI_init(void) { RCC->AHB1ENR |= 1; /* enable GPIOA clock */ RCC->AHB1ENR |= 4; /* enable GPIOC clock */ RCC->APB2ENR |= 0x1000; /* enable SPI1 clock */ /* PORTA 5, 7 for SPI1 MOSI and SCLK */ GPIOA->MODER &= ~0x0000CC00; /* clear pin mode */ GPIOA->MODER |= 0x00008800; /* set pin alternate mode */ GPIOA->AFR[0] &= ~0xF0F00000; /* clear alt mode */ GPIOA->AFR[0] |= 0x50500000; /* set alt mode SPI1 */ /* PC1 as GPIO output for SPI slave select */ GPIOC->MODER &= ~0x0000000C; /* clear pin mode */ GPIOC->MODER |= 0x00000004; /* set pin output mode */ /* PA11 as GPIO output for TFT Command/Data select */ GPIOA->MODER &= ~0x00C00000; /* clear pin mode */ GPIOA->MODER |= 0x00400000; /* set pin output mode */ SPI1->CR1 = 0x31F; SPI1->CR2 = 0; SPI1->CR1 |= 0x40; /* enable SPI1 module */ } /* write data to SPI */ void SPI_write(unsigned char data) { ILI9340_assertSS(); /* assert slave select */ SPI1->DR = data; /* write data */ while (SPI1->SR & 0x80) {} /* wait for transmission done */ ILI9340_deassertSS(); /* deassert slave select */ } /* hardware reset of TFT controller */ void ILI9340_hardReset(void) { delayMs(2000); ILI9340_reset(); delayMs(1); ILI9340_dereset(); delayMs(2000); } /* send a command to TFT controller */ void ILI9340_command(uint8_t command) { ILI9340_setCommand(); ILI9340_assertSS(); SPI_write(command); ILI9340_deassertSS(); } /* send a data to TFT controller */ void ILI9340_data(uint8_t data) { ILI9340_setData(); ILI9340_assertSS(); SPI_write(data); ILI9340_deassertSS(); } /* send a block of data to TFT controller */ void ILI9340_blockData(int32_t n, uint16_t color) { ILI9340_setData(); ILI9340_assertSS(); while (n--) { SPI_write(color >> 8); SPI_write(color & 0xFF); } ILI9340_deassertSS(); } /* set a window in the display to receive data */ void ILI9340_setWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { ILI9340_command(ILI9340_CASET); // Column addr set ILI9340_data(x0 >> 8); // XSTART ILI9340_data(x0 & 0xFF); ILI9340_data(x1 >> 8); // XEND ILI9340_data(x1 & 0xFF); ILI9340_command(ILI9340_PASET); // Row addr set ILI9340_data(y0>>8); // YSTART ILI9340_data(y0); ILI9340_data(y1>>8); // YEND ILI9340_data(y1); ILI9340_command(ILI9340_RAMWR); // write to RAM } /* initialize the TFT controller */ void ILI9340_init(void) { SPI_init(); ILI9340_hardReset(); ILI9340_command(0xEF); ILI9340_data(0x03); ILI9340_data(0x80); ILI9340_data(0x02); ILI9340_command(0xCF); ILI9340_data(0x00); ILI9340_data(0xC1); ILI9340_data(0x30); ILI9340_command(0xED); ILI9340_data(0x64); ILI9340_data(0x03); ILI9340_data(0x12); ILI9340_data(0x81); ILI9340_command(0xE8); ILI9340_data(0x85); ILI9340_data(0x00); ILI9340_data(0x78); ILI9340_command(0xCB); ILI9340_data(0x39); ILI9340_data(0x2C); ILI9340_data(0x00); ILI9340_data(0x34); ILI9340_data(0x02); ILI9340_command(0xF7); ILI9340_data(0x20); ILI9340_command(0xEA); ILI9340_data(0x00); ILI9340_data(0x00); ILI9340_command(ILI9340_PWCTR1); //Power control ILI9340_data(0x23); //VRH[5:0] ILI9340_command(ILI9340_PWCTR2); //Power control ILI9340_data(0x10); //SAP[2:0];BT[3:0] ILI9340_command(ILI9340_VMCTR1); //VCM control ILI9340_data(0x3e); ILI9340_data(0x28); ILI9340_command(ILI9340_VMCTR2); //VCM control2 ILI9340_data(0x86); ILI9340_command(ILI9340_MADCTL); // Memory Access Control ILI9340_data(ILI9340_MADCTL_MX | ILI9340_MADCTL_BGR); ILI9340_command(ILI9340_PIXFMT); ILI9340_data(0x55); ILI9340_command(ILI9340_FRMCTR1); ILI9340_data(0x00); ILI9340_data(0x18); ILI9340_command(ILI9340_DFUNCTR); // Display Function Control ILI9340_data(0x08); ILI9340_data(0x82); ILI9340_data(0x27); ILI9340_command(0xF2); // 3Gamma Function Disable ILI9340_data(0x00); ILI9340_command(ILI9340_GAMMASET); //Gamma curve selected ILI9340_data(0x01); ILI9340_command(ILI9340_GMCTRP1); //Set Gamma ILI9340_data(0x0F); ILI9340_data(0x31); ILI9340_data(0x2B); ILI9340_data(0x0C); ILI9340_data(0x0E); ILI9340_data(0x08); ILI9340_data(0x4E); ILI9340_data(0xF1); ILI9340_data(0x37); ILI9340_data(0x07); ILI9340_data(0x10); ILI9340_data(0x03); ILI9340_data(0x0E); ILI9340_data(0x09); ILI9340_data(0x00); ILI9340_command(ILI9340_GMCTRN1); //Set Gamma ILI9340_data(0x00); ILI9340_data(0x0E); ILI9340_data(0x14); ILI9340_data(0x03); ILI9340_data(0x11); ILI9340_data(0x07); ILI9340_data(0x31); ILI9340_data(0xC1); ILI9340_data(0x48); ILI9340_data(0x08); ILI9340_data(0x0F); ILI9340_data(0x0C); ILI9340_data(0x31); ILI9340_data(0x36); ILI9340_data(0x0F); ILI9340_command(ILI9340_SLPOUT); //Exit Sleep delayMs(120); ILI9340_command(ILI9340_DISPON); //Display on } /* 16 MHz SYSCLK */ void delayMs(int n) { int i; for (; n > 0; n--) for (i = 0; i < 3195; i++) ; }