feat: LCD Driver
This commit is contained in:
parent
0a5bcc9e02
commit
397e4f0894
@ -14,6 +14,18 @@
|
|||||||
|
|
||||||
#define PI 3.1415926
|
#define PI 3.1415926
|
||||||
#define BIT(x) (1UL << (x))
|
#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 CORCLK;
|
||||||
extern uint32_t BUSCLK;
|
extern uint32_t BUSCLK;
|
||||||
|
111
include/tftlcd.h
Normal file
111
include/tftlcd.h
Normal file
@ -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);
|
2
main.c
2
main.c
@ -1,5 +1,6 @@
|
|||||||
#include "derivative.h"
|
#include "derivative.h"
|
||||||
#include "systick.h"
|
#include "systick.h"
|
||||||
|
#include "tftlcd.h"
|
||||||
#include "uart.h"
|
#include "uart.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -9,6 +10,7 @@ int main(void) {
|
|||||||
SysTick_Config(CORCLK / 1000); // Period of systick timer : 1ms
|
SysTick_Config(CORCLK / 1000); // Period of systick timer : 1ms
|
||||||
uart_init(UART_MSG, 9600); // Initialize UART1 with PC
|
uart_init(UART_MSG, 9600); // Initialize UART1 with PC
|
||||||
uart_rie_enable(UART_MSG); // Enable UART1 receive interrupt
|
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, "System Clock: %lu\r\n", CORCLK);
|
||||||
uart_printf(UART_MSG, "Bus Clock: %lu\r\n", BUSCLK);
|
uart_printf(UART_MSG, "Bus Clock: %lu\r\n", BUSCLK);
|
||||||
|
239
src/tftlcd.c
Normal file
239
src/tftlcd.c
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user