diff --git a/include/derivative.h b/include/derivative.h index b4363a4..301db3d 100644 --- a/include/derivative.h +++ b/include/derivative.h @@ -14,6 +14,18 @@ #define PI 3.1415926 #define BIT(x) (1UL << (x)) +#define GPIO_OUT(port, pin, mode) \ + { \ + GPIO##port->PDDR |= BIT(pin); \ + PORT##port->PCR[pin] |= PORT_PCR_MUX(mode); \ + } + +#define GPIO_IN(port, pin, mode) \ + { \ + GPIO##port->PDDR &= ~BIT(pin); \ + PORT##port->PCR[pin] |= PORT_PCR_MUX(mode); \ + PORT##port->PCR[pin] |= PORT_PCR_PE(0x1); \ + } extern uint32_t CORCLK; extern uint32_t BUSCLK; diff --git a/include/tftlcd.h b/include/tftlcd.h new file mode 100644 index 0000000..669ccd3 --- /dev/null +++ b/include/tftlcd.h @@ -0,0 +1,111 @@ +/* + TFT LCD Driver + Screen: Z280IT002 + Driver: ILI9341 + + Commands: 8-bit + Arguments: + GRAM: 16-bit + Others: 8-bit + + Memory: 320 * 240 * 18 / 8 = 172800 bytes + RGB Interface: (maunal p. 45, Chapter 7.2.1) + 16 bit mode (RGB565): + D0: NC + D1 - D5: blue + D6 - D11: green + D12: NC + D13 - D17: red + + Pins: + CS: Chip Selection + WR: WRite signal + RD: ReaD signal + RS: data or command + DB: Data (8 pin * 2) + only use 0-7 to send data +*/ +#pragma once + +#include "derivative.h" + +typedef unsigned char uchar; + +// LCD function 1 enable +#define USE_HORIZONTAL 1 // 横屏 +#define LCD_FAST_IO 1 // 快速IO + +// LCD size +#if USE_HORIZONTAL == 1 +#define LCD_W 320 +#define LCD_H 240 +#else +#define LCD_W 240 +#define LCD_H 320 +#endif + +/* + LCD Control Pins Definition + LCD_CS -> PTB9 片选 低有效 + LCD_RS -> PTB8 命令/数据 低命令 高数据 + LCD_WR -> PTB11 写 低有效 + LCD_RD -> PTB10 读 低有效 + LCD_RST -> PTE31 复位 低有效 + LCD_BL -> PTA19 背光 低亮 高灭 +*/ +#define LCD_CS_SET (GPIOB->PDOR |= BIT(9)) +#define LCD_CS_CLR (GPIOB->PDOR &= ~BIT(9)) +#define LCD_RS_SET (GPIOB->PDOR |= BIT(8)) +#define LCD_RS_CLR (GPIOB->PDOR &= ~BIT(8)) +#define LCD_WR_SET (GPIOB->PDOR |= BIT(11)) +#define LCD_WR_CLR (GPIOB->PDOR &= ~BIT(11)) +#define LCD_RD_SET (GPIOB->PDOR |= BIT(10)) +#define LCD_RD_CLR (GPIOB->PDOR &= ~BIT(10)) +#define LCD_RST_SET (GPIOE->PDOR |= BIT(31)) +#define LCD_RST_CLR (GPIOE->PDOR &= ~BIT(31)) +#define LCD_BL_SET (GPIOA->PDOR |= BIT(19)) +#define LCD_BL_CLR (GPIOA->PDOR &= ~BIT(19)) + +// PTD 0~7 数据线 +#define DATAOUT(x) GPIOD->PDOR = (x & 0xff) // 数据输出 +#define DATAIN GPIOD->PDIR // 数据输入 + +// Commands +#define LCD_COL_WR 0x2A // write column address, maunal p. 110 (Chapter 8.2.20) +#define LCD_PAGE_WR 0x2B // write page address, maunal p. 112 (Chapter 8.2.21) +#define LCD_RAM_WR 0x2C // write RAM, maunal p. 114 (Chapter 8.2.22) +#define LCD_RAM_AC 0x36 // Memory Access Control, manual p. 127 (Chapter 8.2.29) + +// 画笔颜色 +#define RED 0xF800 +#define GREEN 0x07E0 +#define BLUE 0x001F +#define WHITE 0xFFFF +#define BLACK 0x0000 +#define YELLOW 0xFFE0 +#define BRED 0XF81F +#define GRED 0XFFE0 +#define GBLUE 0X07FF +#define MAGENTA 0xF81F +#define CYAN 0x7FFF +#define BROWN 0XBC40 // 棕色 +#define BRRED 0XFC07 // 棕红色 +#define GRAY 0X8430 // 灰色 + +#define DARKBLUE 0X01CF // 深蓝色 +#define LIGHTBLUE 0X7D7C // 浅蓝色 +#define GRAYBLUE 0X5458 // 灰蓝色 + +#define LIGHTGREEN 0X841F // 浅绿色 +#define LIGHTGRAY 0XEF5B // 浅灰色(PANNEL) +#define LGRAY 0XC618 // 浅灰色(PANNEL),窗体背景色 + +#define LGRAYBLUE 0XA651 // 浅灰蓝色(中间层颜色) +#define LBBLUE 0X2B12 // 浅棕蓝色(选择条目的反色) + +void LCD_RESET(); +void LCD_Init(); +void LCD_S_XY(uint16_t x, uint16_t y); +void LCD_S_Rec(uint16_t xs, uint16_t xe, uint16_t ys, uint16_t ye); +void LCD_D_Point(uint16_t x, uint16_t y, uint16_t color); +void LCD_Clear(uint16_t color); \ No newline at end of file diff --git a/main.c b/main.c index 8ba9a92..e964d62 100644 --- a/main.c +++ b/main.c @@ -1,5 +1,6 @@ #include "derivative.h" #include "systick.h" +#include "tftlcd.h" #include "uart.h" #include #include @@ -9,6 +10,7 @@ int main(void) { SysTick_Config(CORCLK / 1000); // Period of systick timer : 1ms uart_init(UART_MSG, 9600); // Initialize UART1 with PC uart_rie_enable(UART_MSG); // Enable UART1 receive interrupt + LCD_Init(); // Initialize LCD uart_printf(UART_MSG, "System Clock: %lu\r\n", CORCLK); uart_printf(UART_MSG, "Bus Clock: %lu\r\n", BUSCLK); diff --git a/src/tftlcd.c b/src/tftlcd.c new file mode 100644 index 0000000..186e7df --- /dev/null +++ b/src/tftlcd.c @@ -0,0 +1,239 @@ +#include "systick.h" +#include "tftlcd.h" + +// 画笔颜色 背景颜色 +unsigned int POINT_COLOR = 0x0000, BACK_COLOR = 0xFFFF; +unsigned int DeviceCode; + +void LCD_RESET() { + LCD_RST_CLR; + delay_ms(100); + LCD_RST_SET; +} + +// 写寄存器 -> RS = 0 +// what is the difference between set LCD_WR_CLR before and after output +static void LCD_WR_REG(uint8_t reg) { + LCD_RS_CLR; + LCD_CS_CLR; + DATAOUT(reg); + LCD_WR_CLR; + LCD_WR_SET; + LCD_CS_SET; +} + +// 写数据 -> RS = 1 - 8bit +static void LCD_WR_DATA(uchar data) { + LCD_RS_SET; + LCD_CS_CLR; + DATAOUT(data); + LCD_WR_CLR; + LCD_WR_SET; + LCD_CS_SET; +} + +// 写数据 -> RS = 1 - 16bit +static void LCD_WR_DATA_16BIT(uint16_t data) { + LCD_WR_DATA(data >> 8); + LCD_WR_DATA(data & 0xff); +} + +// 写寄存器和数据 - 8bit +static void LCD_WR_REG_DATA(uint8_t reg, uchar data) { + LCD_WR_REG(reg); + LCD_WR_DATA(data); +} + +// 写寄存器和数据 - 16bit +static void LCD_WR_REG_DATA_16BIT(uint8_t reg, uint16_t data) { + LCD_WR_REG(reg); + LCD_WR_DATA_16BIT(data); +} + +// // 写GRAM prepare +// static void LCD_WR_RAM_Prepare() { LCD_WR_REG(LCD_RAM_WR); } + +// // 写GRAM 16-bit +// static void LCD_WR_RAM(uint16_t rgb) { +// LCD_WR_DATA(rgb >> 8); +// LCD_WR_DATA(rgb); +// } + +// 读寄存器 +static uchar LCD_RD_REG(uint8_t reg) { + uchar tmp; + LCD_WR_REG(reg); + + for (uint8_t i = 0; i < 8; i++) GPIO_IN(D, i, 1); + + LCD_RS_SET; + LCD_CS_CLR; + LCD_RD_CLR; + tmp = DATAIN; + LCD_RD_SET; + LCD_CS_SET; + + for (uint8_t i = 0; i < 8; i++) GPIO_OUT(D, i, 1); + + return tmp; +} + +void LCD_Init() { + // Enable Clock + SIM->SCGC5 |= SIM_SCGC5_PORTA_MASK // PTA19 : Back Light (BL) + | SIM_SCGC5_PORTB_MASK // PTB0 - PTB3 : coordinates, PTB8 - PTB11 : RS, CS, RD, WR + | SIM_SCGC5_PORTC_MASK // PTC16 - PTC17 : X-Y In + | SIM_SCGC5_PORTD_MASK // PTD0 - PTD7: data + | SIM_SCGC5_PORTE_MASK; // PTE31 : ReSeT (RST) + + // Set GPIO + GPIO_OUT(A, 19, 1); // Back Light + GPIO_OUT(E, 31, 1); // ReSeT (RST) + GPIO_OUT(B, 16, 1); // Y-IN + GPIO_OUT(B, 17, 1); // X-IN + for (uint8_t i = 0; i < 4; i++) GPIO_OUT(B, i, 1); + for (uint8_t i = 8; i < 12; i++) GPIO_OUT(B, i, 1); + for (uint8_t i = 0; i < 8; i++) GPIO_OUT(D, i, 1); + + LCD_RESET(); + delay_ms(50); + LCD_WR_REG_DATA(0x00, 0x0001); // Software Reset + delay_ms(50); + DeviceCode = LCD_RD_REG(0x04); // Read display identification information 0x04 + + // Driver + LCD_WR_REG(0xCF); + LCD_WR_DATA(0x00); + LCD_WR_DATA(0xD9); + LCD_WR_DATA(0X30); + + LCD_WR_REG(0xED); + LCD_WR_DATA(0x64); + LCD_WR_DATA(0x03); + LCD_WR_DATA(0X12); + LCD_WR_DATA(0X81); + + LCD_WR_REG(0xE8); + LCD_WR_DATA(0x85); + LCD_WR_DATA(0x10); + LCD_WR_DATA(0x78); + + LCD_WR_REG(0xCB); + LCD_WR_DATA(0x39); + LCD_WR_DATA(0x2C); + LCD_WR_DATA(0x00); + LCD_WR_DATA(0x34); + LCD_WR_DATA(0x02); + + LCD_WR_REG(0xF7); + LCD_WR_DATA(0x20); + + LCD_WR_REG(0xEA); + LCD_WR_DATA(0x00); + LCD_WR_DATA(0x00); + + LCD_WR_REG(0xC0); // Power control + LCD_WR_DATA(0x21); // VRH[5:0] + + LCD_WR_REG(0xC1); // Power control + LCD_WR_DATA(0x12); // SAP[2:0];BT[3:0] + + LCD_WR_REG(0xC5); // VCM control + LCD_WR_DATA(0x32); + LCD_WR_DATA(0x3C); + + LCD_WR_REG(0xC7); // VCM control2 + LCD_WR_DATA(0XC1); + + LCD_WR_REG(LCD_RAM_AC); + LCD_WR_DATA(0x88); // 0x88: MY = 1, MX = MV = 0 从左到右 从下到上, BGR = 1s + + LCD_WR_REG(0x3A); + LCD_WR_DATA(0x55); + + LCD_WR_REG(0xB1); + LCD_WR_DATA(0x00); + LCD_WR_DATA(0x18); + + LCD_WR_REG(0xB6); // Display Function Control + LCD_WR_DATA(0x0A); + LCD_WR_DATA(0xA2); + + LCD_WR_REG(0xF2); // 3Gamma Function Disable + LCD_WR_DATA(0x00); + + LCD_WR_REG(0x26); // Gamma curve selected + LCD_WR_DATA(0x01); + + LCD_WR_REG(0xE0); // Set Gamma + LCD_WR_DATA(0x0F); + LCD_WR_DATA(0x20); + LCD_WR_DATA(0x1E); + LCD_WR_DATA(0x09); + LCD_WR_DATA(0x12); + LCD_WR_DATA(0x0B); + LCD_WR_DATA(0x50); + LCD_WR_DATA(0XBA); + LCD_WR_DATA(0x44); + LCD_WR_DATA(0x09); + LCD_WR_DATA(0x14); + LCD_WR_DATA(0x05); + LCD_WR_DATA(0x23); + LCD_WR_DATA(0x21); + LCD_WR_DATA(0x00); + + LCD_WR_REG(0XE1); // Set Gamma + LCD_WR_DATA(0x00); + LCD_WR_DATA(0x19); + LCD_WR_DATA(0x19); + LCD_WR_DATA(0x00); + LCD_WR_DATA(0x12); + LCD_WR_DATA(0x07); + LCD_WR_DATA(0x2D); + LCD_WR_DATA(0x28); + LCD_WR_DATA(0x3F); + LCD_WR_DATA(0x02); + LCD_WR_DATA(0x0A); + LCD_WR_DATA(0x08); + LCD_WR_DATA(0x25); + LCD_WR_DATA(0x2D); + LCD_WR_DATA(0x0F); + + LCD_WR_REG(0x11); // Exit Sleep + delay_ms(120); + LCD_WR_REG(0x29); // Display on + + LCD_BL_CLR; // Back Light On + LCD_Clear(WHITE); +} + +void LCD_S_XY(uint16_t x, uint16_t y) { + LCD_WR_REG_DATA_16BIT(LCD_PAGE_WR, x); + LCD_WR_REG_DATA_16BIT(LCD_COL_WR, y); +} + +// Set a rectangle area +void LCD_S_Rec(uint16_t xs, uint16_t xe, uint16_t ys, uint16_t ye) { + LCD_WR_REG(LCD_PAGE_WR); + LCD_WR_DATA_16BIT(xs); + LCD_WR_DATA_16BIT(xe); + + LCD_WR_REG(LCD_COL_WR); + LCD_WR_DATA_16BIT(ys); + LCD_WR_DATA_16BIT(ye); +} + +void LCD_D_Point(uint16_t x, uint16_t y, uint16_t color) { + LCD_S_XY(x, y); + LCD_WR_REG_DATA_16BIT(LCD_RAM_WR, color); +} + +void LCD_Clear(uint16_t color) { + // LCD_S_Rec(0, LCD_W - 1, 0, LCD_H - 1); + // for (uint32_t i = 0; i < LCD_W * LCD_H; i++) LCD_WR_DATA_16BIT(color); + for (uint16_t i = 0; i < LCD_W; i++) + for (uint16_t j = 0; j < LCD_H; j++) { + LCD_S_XY(i, j); + LCD_WR_REG_DATA_16BIT(LCD_RAM_WR, color); + } +}