2026-07-06 11:10:43 +08:00
|
|
|
#include "lcd.h"
|
|
|
|
|
#include "lcd_font.h"
|
|
|
|
|
#include "../App/config.h"
|
|
|
|
|
#include "intrins.h"
|
|
|
|
|
|
|
|
|
|
// RM69310 屏幕接口引脚
|
|
|
|
|
sbit LCD_RST = P1^0; // 硬件复位
|
|
|
|
|
sbit LCD_DCX = P1^1; // 数据/命令选择
|
|
|
|
|
sbit LCD_SDI = P1^4; // SPI 数据输入 (MOSI)
|
|
|
|
|
sbit LCD_SCL = P1^5; // SPI 时钟 (SCLK)
|
|
|
|
|
sbit LCD_CS = P1^6; // SPI 片选 (CS)
|
|
|
|
|
|
|
|
|
|
// SGM3833 电源芯片控制脚
|
|
|
|
|
sbit SGM_CTRL = P3^4;
|
|
|
|
|
|
|
|
|
|
// External delay functions defined in main.c
|
|
|
|
|
extern void Delay_ms(u16 ms);
|
|
|
|
|
extern void Delay10us(void);
|
|
|
|
|
|
|
|
|
|
void SGM_SendPulse(u8 pulse_cnt)
|
|
|
|
|
{
|
|
|
|
|
u8 i;
|
|
|
|
|
SGM_CTRL = 0;
|
|
|
|
|
Delay_ms(5); // 确保进入关断/复位状态 (tOFF)
|
|
|
|
|
SGM_CTRL = 1;
|
|
|
|
|
Delay_ms(5); // 确保充分初始化 (tINIT >= 300us)
|
|
|
|
|
for(i = 0; i < pulse_cnt; i++)
|
|
|
|
|
{
|
|
|
|
|
SGM_CTRL = 0;
|
|
|
|
|
Delay10us();
|
|
|
|
|
SGM_CTRL = 1;
|
|
|
|
|
Delay10us();
|
|
|
|
|
}
|
|
|
|
|
SGM_CTRL = 1;
|
|
|
|
|
Delay_ms(5); // 确保数据稳定存储 (tSTORE >= 80us)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SPI_SendData(u8 dat)
|
|
|
|
|
{
|
|
|
|
|
u8 i;
|
|
|
|
|
for(i = 0; i < 8; i++)
|
|
|
|
|
{
|
|
|
|
|
LCD_SCL = 0;
|
|
|
|
|
if(dat & 0x80)
|
|
|
|
|
LCD_SDI = 1;
|
|
|
|
|
else
|
|
|
|
|
LCD_SDI = 0;
|
|
|
|
|
_nop_();
|
|
|
|
|
LCD_SCL = 1;
|
|
|
|
|
_nop_();
|
|
|
|
|
dat <<= 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WriteComm(u8 cmd)
|
|
|
|
|
{
|
|
|
|
|
LCD_CS = 0;
|
|
|
|
|
LCD_DCX = 0; // 命令模式
|
|
|
|
|
SPI_SendData(cmd);
|
|
|
|
|
LCD_CS = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WriteData(u8 dat)
|
|
|
|
|
{
|
|
|
|
|
LCD_CS = 0;
|
|
|
|
|
LCD_DCX = 1; // 数据模式
|
|
|
|
|
SPI_SendData(dat);
|
|
|
|
|
LCD_CS = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LCD_Reset(void)
|
|
|
|
|
{
|
|
|
|
|
LCD_RST = 1;
|
|
|
|
|
Delay_ms(10);
|
|
|
|
|
LCD_RST = 0;
|
|
|
|
|
Delay_ms(20);
|
|
|
|
|
LCD_RST = 1;
|
|
|
|
|
Delay_ms(120);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LCD_Init(void)
|
|
|
|
|
{
|
|
|
|
|
// Configure LCD pins as push-pull output
|
|
|
|
|
P1M1 &= ~((1<<0) | (1<<1) | (1<<4) | (1<<5) | (1<<6));
|
|
|
|
|
P1M0 |= ((1<<0) | (1<<1) | (1<<4) | (1<<5) | (1<<6));
|
|
|
|
|
|
|
|
|
|
// Configure P3.4 (SGM_CTRL) as push-pull output
|
|
|
|
|
P3M1 &= ~(1 << 4);
|
|
|
|
|
P3M0 |= (1 << 4);
|
|
|
|
|
|
|
|
|
|
SGM_CTRL = 1;
|
|
|
|
|
LCD_CS = 1;
|
|
|
|
|
LCD_SCL = 1;
|
|
|
|
|
LCD_RST = 1;
|
|
|
|
|
LCD_DCX = 1;
|
|
|
|
|
|
|
|
|
|
LCD_Reset();
|
|
|
|
|
|
|
|
|
|
// 寄存器配置(源自 Truly 信利官方初始化配置)
|
|
|
|
|
WriteComm(0xFE);WriteData(0x01);
|
|
|
|
|
WriteComm(0x04);WriteData(0xa0); // SPI write ram enable
|
|
|
|
|
WriteComm(0x05);WriteData(0x70); // 128RGB
|
|
|
|
|
WriteComm(0x06);WriteData(0x3C); // NL = 240 line
|
|
|
|
|
WriteComm(0x25);WriteData(0x06); // normal mode: gamma1
|
|
|
|
|
WriteComm(0x26);WriteData(0x80); // T1A = 280
|
|
|
|
|
WriteComm(0x27);WriteData(0x12); // normal mode VBP = 12
|
|
|
|
|
WriteComm(0x28);WriteData(0x12); // normal mode VFP = 8
|
|
|
|
|
WriteComm(0x2A);WriteData(0x06); // idle mode: gamma1
|
|
|
|
|
WriteComm(0x2B);WriteData(0x80); // T1B = 280
|
|
|
|
|
WriteComm(0x2D);WriteData(0x12); // idle mode VBP = 12
|
|
|
|
|
WriteComm(0x2F);WriteData(0x12); // idle mode VFP = 8
|
|
|
|
|
WriteComm(0x37);WriteData(0x0C); // precharge to VGSP
|
|
|
|
|
WriteComm(0x6D);WriteData(0x18); // skip frame VGMP and VGSP regulator off
|
|
|
|
|
WriteComm(0x29);WriteData(0x01); // normal mode skip frame off
|
|
|
|
|
WriteComm(0x30);WriteData(0x43); // idle mode skip frame = 60/2 = 30Hz
|
|
|
|
|
WriteComm(0x0E);WriteData(0x83); // AVDD = 5.6V normal mode
|
|
|
|
|
WriteComm(0x0F);WriteData(0x83); // AVDD = 5.6V idle mode
|
|
|
|
|
WriteComm(0x10);WriteData(0x71); // AVDD = 3xVCI
|
|
|
|
|
WriteComm(0x11);WriteData(0xb3); // VCL = -2xVCI
|
|
|
|
|
WriteComm(0x12);WriteData(0xb3); // VCL = -2xVCI
|
|
|
|
|
WriteComm(0x13);WriteData(0x80); // VGH = AVDD normal mode
|
|
|
|
|
WriteComm(0x14);WriteData(0x80); // VGH = AVDD idle mode
|
|
|
|
|
WriteComm(0x15);WriteData(0x81); // VGL = VCL - VCI normal mode
|
|
|
|
|
WriteComm(0x16);WriteData(0x81); // VGL = VCL - VCI idle mode
|
|
|
|
|
WriteComm(0x18);WriteData(0x66); // VGHR = 6V normal/idle mode
|
|
|
|
|
WriteComm(0x19);WriteData(0x44); // VGLR = -6V normal/idle mode
|
|
|
|
|
WriteComm(0x1E);WriteData(0x02); // Switch EQ on
|
|
|
|
|
WriteComm(0x5B);WriteData(0x10); // VREFN5 on
|
|
|
|
|
WriteComm(0x62);WriteData(0x19); // VREFN5 = -3V normal mode
|
|
|
|
|
WriteComm(0x63);WriteData(0x19); // VREFN5 = -3V idle mode
|
|
|
|
|
WriteComm(0x70);WriteData(0x55); // display off SD to AVDD
|
|
|
|
|
WriteComm(0x1D);WriteData(0x02); // Switch EQ on
|
|
|
|
|
WriteComm(0x89);WriteData(0x18); // VGMP = 5.5V
|
|
|
|
|
WriteComm(0x8A);WriteData(0xb9); // VGSP = 2V
|
|
|
|
|
WriteComm(0x8B);WriteData(0x01); // VGMP VGSP high byte
|
|
|
|
|
WriteComm(0x8C);WriteData(0x10); // VGMP = 5.4V
|
|
|
|
|
WriteComm(0x8D);WriteData(0x90); // VGSP = 2V
|
|
|
|
|
WriteComm(0x8E);WriteData(0x01); // VGMP VGSP high byte
|
|
|
|
|
WriteComm(0x6E);WriteData(0x0A); // MIPI interface off
|
|
|
|
|
WriteComm(0x6A);WriteData(0x05); // MUX
|
|
|
|
|
WriteComm(0x3A);WriteData(0x08); // T1_sd
|
|
|
|
|
WriteComm(0x3B);WriteData(0x00); // Tp_sd
|
|
|
|
|
WriteComm(0x3D);WriteData(0x16); // Th_sd
|
|
|
|
|
WriteComm(0x3F);WriteData(0x27); // Tsw_sd
|
|
|
|
|
WriteComm(0x40);WriteData(0x0F); // Thsw_sd
|
|
|
|
|
WriteComm(0x41);WriteData(0x0D); // Thsd_sd
|
|
|
|
|
|
|
|
|
|
WriteComm(0x42);WriteData(0x14); // Mux 142536
|
|
|
|
|
WriteComm(0x43);WriteData(0x41);
|
|
|
|
|
WriteComm(0x44);WriteData(0x25);
|
|
|
|
|
WriteComm(0x45);WriteData(0x52);
|
|
|
|
|
WriteComm(0x46);WriteData(0x36);
|
|
|
|
|
WriteComm(0x47);WriteData(0x63);
|
|
|
|
|
WriteComm(0x48);WriteData(0x14);
|
|
|
|
|
WriteComm(0x49);WriteData(0x41);
|
|
|
|
|
WriteComm(0x4A);WriteData(0x25);
|
|
|
|
|
WriteComm(0x4B);WriteData(0x52);
|
|
|
|
|
WriteComm(0x4C);WriteData(0x36);
|
|
|
|
|
WriteComm(0x4D);WriteData(0x63);
|
|
|
|
|
WriteComm(0x4E);WriteData(0x14); // Data R1R2G1G2B1B2
|
|
|
|
|
WriteComm(0x4F);WriteData(0x41);
|
|
|
|
|
WriteComm(0x50);WriteData(0x25);
|
|
|
|
|
WriteComm(0x51);WriteData(0x52);
|
|
|
|
|
WriteComm(0x52);WriteData(0x36);
|
|
|
|
|
WriteComm(0x53);WriteData(0x63);
|
|
|
|
|
WriteComm(0x54);WriteData(0x14);
|
|
|
|
|
WriteComm(0x55);WriteData(0x41);
|
|
|
|
|
WriteComm(0x56);WriteData(0x25);
|
|
|
|
|
WriteComm(0x57);WriteData(0x52);
|
|
|
|
|
WriteComm(0x58);WriteData(0x36);
|
|
|
|
|
WriteComm(0x59);WriteData(0x63);
|
|
|
|
|
|
|
|
|
|
WriteComm(0x66);WriteData(0x90); // idle mode internal power
|
|
|
|
|
WriteComm(0x67);WriteData(0x40); // internal power delay 1 frame off
|
|
|
|
|
WriteComm(0x72);WriteData(0x1A); // internal OVDD = 4.6V
|
|
|
|
|
WriteComm(0x73);WriteData(0x07); // internal OVSS = -2V
|
|
|
|
|
WriteComm(0x74);WriteData(0x0C); // OVDD power from AVDD
|
|
|
|
|
WriteComm(0x6A);WriteData(0x3D); // swire 61=0x3D pulse
|
|
|
|
|
WriteComm(0x6B);WriteData(0x29); // swire 41=0x29 pulse
|
|
|
|
|
|
|
|
|
|
WriteComm(0xFE);WriteData(0x04);
|
|
|
|
|
WriteComm(0x5E);WriteData(0x01);
|
|
|
|
|
WriteComm(0x5F);WriteData(0xB8);
|
|
|
|
|
WriteComm(0x60);WriteData(0xBB);
|
|
|
|
|
WriteComm(0x61);WriteData(0xBB);
|
|
|
|
|
WriteComm(0x62);WriteData(0xBB);
|
|
|
|
|
WriteComm(0x76);WriteData(0xBB);
|
|
|
|
|
WriteComm(0x77);WriteData(0x3B);
|
|
|
|
|
WriteComm(0x78);WriteData(0x92);
|
|
|
|
|
WriteComm(0x79);WriteData(0xBB);
|
|
|
|
|
WriteComm(0x7A);WriteData(0xBB);
|
|
|
|
|
|
|
|
|
|
WriteComm(0x00);WriteData(0xDC); // SN_CK1
|
|
|
|
|
WriteComm(0x01);WriteData(0x00);
|
|
|
|
|
WriteComm(0x02);WriteData(0x02);
|
|
|
|
|
WriteComm(0x03);WriteData(0x00);
|
|
|
|
|
WriteComm(0x04);WriteData(0x08);
|
|
|
|
|
WriteComm(0x05);WriteData(0x01);
|
|
|
|
|
WriteComm(0x06);WriteData(0x70);
|
|
|
|
|
WriteComm(0x07);WriteData(0x0A);
|
|
|
|
|
WriteComm(0x08);WriteData(0x00);
|
|
|
|
|
|
|
|
|
|
WriteComm(0x09);WriteData(0xDC); // SN_CK2
|
|
|
|
|
WriteComm(0x0a);WriteData(0x00);
|
|
|
|
|
WriteComm(0x0b);WriteData(0x02);
|
|
|
|
|
WriteComm(0x0C);WriteData(0x00);
|
|
|
|
|
WriteComm(0x0D);WriteData(0x08);
|
|
|
|
|
WriteComm(0x0E);WriteData(0x00);
|
|
|
|
|
WriteComm(0x0F);WriteData(0x70);
|
|
|
|
|
WriteComm(0x10);WriteData(0x0A);
|
|
|
|
|
WriteComm(0x11);WriteData(0x00);
|
|
|
|
|
|
|
|
|
|
WriteComm(0x12);WriteData(0xCC); // EM_CK1
|
|
|
|
|
WriteComm(0x13);WriteData(0x00);
|
|
|
|
|
WriteComm(0x14);WriteData(0x02);
|
|
|
|
|
WriteComm(0x15);WriteData(0x00);
|
|
|
|
|
WriteComm(0x16);WriteData(0x20);
|
|
|
|
|
WriteComm(0x17);WriteData(0x00);
|
|
|
|
|
WriteComm(0x18);WriteData(0x28);
|
|
|
|
|
WriteComm(0x19);WriteData(0x26);
|
|
|
|
|
WriteComm(0x1A);WriteData(0x00);
|
|
|
|
|
|
|
|
|
|
WriteComm(0x1B);WriteData(0xCC); // EM_CK2
|
|
|
|
|
WriteComm(0x1C);WriteData(0x00);
|
|
|
|
|
WriteComm(0x1D);WriteData(0x02);
|
|
|
|
|
WriteComm(0x1E);WriteData(0x00);
|
|
|
|
|
WriteComm(0x1F);WriteData(0x20);
|
|
|
|
|
WriteComm(0x20);WriteData(0x01);
|
|
|
|
|
WriteComm(0x21);WriteData(0x28);
|
|
|
|
|
WriteComm(0x22);WriteData(0x26);
|
|
|
|
|
WriteComm(0x23);WriteData(0x00);
|
|
|
|
|
|
|
|
|
|
WriteComm(0x4C);WriteData(0x89); // SN_STV
|
|
|
|
|
WriteComm(0x4D);WriteData(0x00);
|
|
|
|
|
WriteComm(0x4E);WriteData(0x01);
|
|
|
|
|
WriteComm(0x4F);WriteData(0x00);
|
|
|
|
|
WriteComm(0x50);WriteData(0x01);
|
|
|
|
|
WriteComm(0x51);WriteData(0xBB);
|
|
|
|
|
WriteComm(0x52);WriteData(0xBB);
|
|
|
|
|
|
|
|
|
|
WriteComm(0x53);WriteData(0xCA); // EM_STV
|
|
|
|
|
WriteComm(0x54);WriteData(0x00);
|
|
|
|
|
WriteComm(0x55);WriteData(0x03);
|
|
|
|
|
WriteComm(0x56);WriteData(0x00);
|
|
|
|
|
WriteComm(0x58);WriteData(0x00);
|
|
|
|
|
WriteComm(0x59);WriteData(0x00);
|
|
|
|
|
WriteComm(0x65);WriteData(0x45); // 04
|
|
|
|
|
WriteComm(0x66);WriteData(0x0C); // 03
|
|
|
|
|
WriteComm(0x67);WriteData(0x00); // 10
|
|
|
|
|
|
|
|
|
|
WriteComm(0xFE);WriteData(0x01); // ID
|
|
|
|
|
WriteComm(0xE5);WriteData(0x00);
|
|
|
|
|
WriteComm(0xE6);WriteData(0x10);
|
|
|
|
|
WriteComm(0xE7);WriteData(0x31);
|
|
|
|
|
|
|
|
|
|
WriteComm(0xFE);WriteData(0x00); // 切换到 Page 0
|
|
|
|
|
WriteComm(0xC4);WriteData(0x80);
|
|
|
|
|
WriteComm(0x2A);WriteData(0x00);WriteData(0x04);WriteData(0x00);WriteData(0x7B); // 设置列
|
|
|
|
|
|
|
|
|
|
// 显式设置 16 位像素格式 (COLMOD = 0x75)
|
|
|
|
|
WriteComm(0x3A);WriteData(0x75);
|
|
|
|
|
|
|
|
|
|
WriteComm(0x11);WriteData(0x00); // 退出睡眠
|
|
|
|
|
Delay_ms(150);
|
|
|
|
|
|
|
|
|
|
WriteComm(0x29);WriteData(0x00); // 开启显示
|
|
|
|
|
Delay_ms(20);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LCD_SetWindow(u16 x_start, u16 x_end, u16 y_start, u16 y_end)
|
|
|
|
|
{
|
|
|
|
|
WriteComm(0x2A);
|
|
|
|
|
WriteData((u8)(x_start >> 8));
|
|
|
|
|
WriteData((u8)(x_start & 0xFF));
|
|
|
|
|
WriteData((u8)(x_end >> 8));
|
|
|
|
|
WriteData((u8)(x_end & 0xFF));
|
|
|
|
|
|
|
|
|
|
WriteComm(0x2B);
|
|
|
|
|
WriteData((u8)(y_start >> 8));
|
|
|
|
|
WriteData((u8)(y_start & 0xFF));
|
|
|
|
|
WriteData((u8)(y_end >> 8));
|
|
|
|
|
WriteData((u8)(y_end & 0xFF));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LCD_Clear(u16 color)
|
|
|
|
|
{
|
|
|
|
|
u16 i, j;
|
|
|
|
|
LCD_SetWindow(4, 123, 0, 239);
|
|
|
|
|
WriteComm(0x2C);
|
|
|
|
|
for(i = 0; i < 120; i++)
|
|
|
|
|
{
|
|
|
|
|
for(j = 0; j < 240; j++)
|
|
|
|
|
{
|
|
|
|
|
WriteData((u8)(color >> 8));
|
|
|
|
|
WriteData((u8)(color & 0xFF));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LCD_FillRect(u16 x, u16 y, u16 w, u16 h, u16 color)
|
|
|
|
|
{
|
|
|
|
|
u16 i, count;
|
|
|
|
|
u8 ch = (u8)(color >> 8);
|
|
|
|
|
u8 cl = (u8)(color & 0xFF);
|
|
|
|
|
LCD_SetWindow(x + 4, x + w - 1 + 4, y, y + h - 1);
|
|
|
|
|
WriteComm(0x2C);
|
|
|
|
|
count = w * h;
|
|
|
|
|
for(i = 0; i < count; i++)
|
|
|
|
|
{
|
|
|
|
|
WriteData(ch);
|
|
|
|
|
WriteData(cl);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LCD_DrawRectBorder(u16 x, u16 y, u16 w, u16 h, u16 color)
|
|
|
|
|
{
|
|
|
|
|
LCD_FillRect(x, y, w, 1, color);
|
|
|
|
|
LCD_FillRect(x, y + h - 1, w, 1, color);
|
|
|
|
|
LCD_FillRect(x, y, 1, h, color);
|
|
|
|
|
LCD_FillRect(x + w - 1, y, 1, h, color);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LCD_DrawMonoBitmap(u16 x, u16 y, u16 w, u16 h, unsigned char code *bmp, u16 color, u16 bg_color)
|
|
|
|
|
{
|
|
|
|
|
u16 r, c;
|
|
|
|
|
u16 byte_width = (w + 7) / 8;
|
|
|
|
|
u8 ch = (u8)(color >> 8);
|
|
|
|
|
u8 cl = (u8)(color & 0xFF);
|
|
|
|
|
u8 bgh = (u8)(bg_color >> 8);
|
|
|
|
|
u8 bgl = (u8)(bg_color & 0xFF);
|
|
|
|
|
|
|
|
|
|
LCD_SetWindow(x + 4, x + w - 1 + 4, y, y + h - 1);
|
|
|
|
|
WriteComm(0x2C);
|
|
|
|
|
for(r = 0; r < h; r++)
|
|
|
|
|
{
|
|
|
|
|
for(c = 0; c < w; c++)
|
|
|
|
|
{
|
|
|
|
|
u16 byte_idx = r * byte_width + (c / 8);
|
|
|
|
|
u8 bit_shift = 7 - (c % 8);
|
|
|
|
|
if(bmp[byte_idx] & (1 << bit_shift))
|
|
|
|
|
{
|
|
|
|
|
WriteData(ch);
|
|
|
|
|
WriteData(cl);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
WriteData(bgh);
|
|
|
|
|
WriteData(bgl);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LCD_ShowChar8x16(u16 x, u16 y, char ch, u16 color, u16 bg_color)
|
|
|
|
|
{
|
|
|
|
|
u8 r, c;
|
|
|
|
|
u8 char_idx = ch - 0x20;
|
|
|
|
|
u8 f_h = (u8)(color >> 8);
|
|
|
|
|
u8 f_l = (u8)(color & 0xFF);
|
|
|
|
|
u8 b_h = (u8)(bg_color >> 8);
|
|
|
|
|
u8 b_l = (u8)(bg_color & 0xFF);
|
|
|
|
|
|
|
|
|
|
if(ch < 0x20 || ch > 0x7E) return;
|
|
|
|
|
|
|
|
|
|
LCD_SetWindow(x + 4, x + 8 - 1 + 4, y, y + 16 - 1);
|
|
|
|
|
WriteComm(0x2C);
|
|
|
|
|
for(r = 0; r < 16; r++)
|
|
|
|
|
{
|
|
|
|
|
u8 line = FONT_8x16[char_idx][r];
|
|
|
|
|
for(c = 0; c < 8; c++)
|
|
|
|
|
{
|
|
|
|
|
if(line & (0x80 >> c))
|
|
|
|
|
{
|
|
|
|
|
WriteData(f_h);
|
|
|
|
|
WriteData(f_l);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
WriteData(b_h);
|
|
|
|
|
WriteData(b_l);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LCD_ShowString(u16 x, u16 y, char *str, u16 color, u16 bg_color)
|
|
|
|
|
{
|
|
|
|
|
while(*str)
|
|
|
|
|
{
|
|
|
|
|
LCD_ShowChar8x16(x, y, *str, color, bg_color);
|
|
|
|
|
x += 8;
|
|
|
|
|
str++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LCD_ShowStringCentered(u16 y, char *str, u16 color, u16 bg_color)
|
|
|
|
|
{
|
|
|
|
|
u16 len = 0;
|
|
|
|
|
char *p = str;
|
|
|
|
|
while(*p++) len++;
|
|
|
|
|
if(len * 8 >= 120)
|
|
|
|
|
LCD_ShowString(0, y, str, color, bg_color);
|
|
|
|
|
else
|
|
|
|
|
LCD_ShowString((120 - len * 8) / 2, y, str, color, bg_color);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LCD_ShowChar16x32(u16 x, u16 y, char ch, u16 color, u16 bg_color)
|
|
|
|
|
{
|
|
|
|
|
u8 r, c, i, j;
|
|
|
|
|
u8 char_idx = ch - 0x20;
|
|
|
|
|
u8 f_h = (u8)(color >> 8);
|
|
|
|
|
u8 f_l = (u8)(color & 0xFF);
|
|
|
|
|
u8 b_h = (u8)(bg_color >> 8);
|
|
|
|
|
u8 b_l = (u8)(bg_color & 0xFF);
|
|
|
|
|
|
|
|
|
|
if(ch < 0x20 || ch > 0x7E) return;
|
|
|
|
|
|
|
|
|
|
LCD_SetWindow(x + 4, x + 16 - 1 + 4, y, y + 32 - 1);
|
|
|
|
|
WriteComm(0x2C);
|
|
|
|
|
for(r = 0; r < 16; r++)
|
|
|
|
|
{
|
|
|
|
|
u8 line = FONT_8x16[char_idx][r];
|
|
|
|
|
for(i = 0; i < 2; i++)
|
|
|
|
|
{
|
|
|
|
|
for(c = 0; c < 8; c++)
|
|
|
|
|
{
|
|
|
|
|
u8 val_bit = (line & (0x80 >> c));
|
|
|
|
|
for(j = 0; j < 2; j++)
|
|
|
|
|
{
|
|
|
|
|
if(val_bit)
|
|
|
|
|
{
|
|
|
|
|
WriteData(f_h);
|
|
|
|
|
WriteData(f_l);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
WriteData(b_h);
|
|
|
|
|
WriteData(b_l);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LCD_ShowString16x32(u16 x, u16 y, char *str, u16 color, u16 bg_color)
|
|
|
|
|
{
|
|
|
|
|
while(*str)
|
|
|
|
|
{
|
|
|
|
|
LCD_ShowChar16x32(x, y, *str, color, bg_color);
|
|
|
|
|
x += 16;
|
|
|
|
|
str++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LCD_ShowString16x32Centered(u16 y, char *str, u16 color, u16 bg_color)
|
|
|
|
|
{
|
|
|
|
|
u16 len = 0;
|
|
|
|
|
char *p = str;
|
|
|
|
|
while(*p++) len++;
|
|
|
|
|
if(len * 16 >= 120)
|
|
|
|
|
LCD_ShowString16x32(0, y, str, color, bg_color);
|
|
|
|
|
else
|
|
|
|
|
LCD_ShowString16x32((120 - len * 16) / 2, y, str, color, bg_color);
|
|
|
|
|
}
|
2026-07-10 10:04:40 +08:00
|
|
|
|
2026-07-10 10:47:51 +08:00
|
|
|
// Touched to align with doc updates V3
|