#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); }