Files
stc32g128k/Docs/60_coding/mod-lcd.md

139 lines
4.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 编码实现 - LCD 显示与字模驱动 (Docs/60_coding/mod-lcd.md)
本文件对应 LCD 驱动与字模渲染的具体编码实现细节。
## 1. 对应代码源文件
* [Drivers/lcd.c](file:///c:/workfile/105/stc32g12k128/Drivers/lcd.c) (LCD 初始化、SPI 数据写、画图画字函数)
* [Drivers/lcd.h](file:///c:/workfile/105/stc32g12k128/Drivers/lcd.h) (管脚接口与画图画字声明)
* [Drivers/lcd_font.h](file:///c:/workfile/105/stc32g12k128/Drivers/lcd_font.h) (ASCII 8x16 点阵字模与图标数据)
## 2. 关键代码片段与逻辑实现
### 2.1 局部窗口设置 (X/Y轴偏移量修正)
`lcd.c` 中配置窗口时,需要将坐标对齐到 ST7789V 在 135x240 面板下的实际 GRAM 范围,加入 X 轴 52 像素、Y 轴 40 像素的偏差:
```c
void LCD_SetWindow(u16 x1, u16 y1, u16 x2, u16 y2) {
x1 += 52;
x2 += 52;
y1 += 40;
y2 += 40;
LCD_WriteCmd(0x2A); // Column Address Set
LCD_WriteData(x1 >> 8);
LCD_WriteData(x1 & 0xFF);
LCD_WriteData(x2 >> 8);
LCD_WriteData(x2 & 0xFF);
LCD_WriteCmd(0x2B); // Row Address Set
LCD_WriteData(y1 >> 8);
LCD_WriteData(y1 & 0xFF);
LCD_WriteData(y2 >> 8);
LCD_WriteData(y2 & 0xFF);
}
```
### 2.2 电池图标与动态百分比 (包含充电 + 后缀) 渲染
`main.c` 的时钟页面刷新中,获取当前百分比及充电状态,动态绘制到状态栏:
```c
void UI_ShowClockPage(SystemState state, u8 hour, u8 min) {
char bat_str[10];
u8 bat_val = Read_Battery_Percent();
bit charging = Is_Charging();
LCD_Clear(COLOR_BLACK);
// 充电状态判定与百分比字符串格式化
if (charging) {
// 充电时显示 + 号后缀,如 "85%+"
if (bat_val >= 100) {
bat_str[0] = '1'; bat_str[1] = '0'; bat_str[2] = '0'; bat_str[3] = '%'; bat_str[4] = '+'; bat_str[5] = '\0';
} else {
bat_str[0] = '0' + (bat_val / 10);
bat_str[1] = '0' + (bat_val % 10);
bat_str[2] = '%';
bat_str[3] = '+';
bat_str[4] = '\0';
}
// X 坐标向左平移 8 像素 (X=69) 以确保和电池图标 (X=107) 之间有 6px 以上的安全间距
LCD_ShowString(69, 24, bat_str, COLOR_GRAY, COLOR_BLACK);
} else {
// 未充电正常显示百分比,如 "85%"
if (bat_val >= 100) {
bat_str[0] = '1'; bat_str[1] = '0'; bat_str[2] = '0'; bat_str[3] = '%'; bat_str[4] = '\0';
} else {
bat_str[0] = '0' + (bat_val / 10);
bat_str[1] = '0' + (bat_val % 10);
bat_str[2] = '%';
bat_str[3] = '\0';
}
LCD_ShowString(77, 24, bat_str, COLOR_GRAY, COLOR_BLACK);
}
// 绘制电池位图图标
LCD_ShowImage(107, 27, 20, 10, bmp_battery_20x10, COLOR_GRAY, COLOR_BLACK);
// ...
}
```
### 2.3 字模百分号偏置
`lcd_font.h` 的 ASCII 字符数组中,百分号 `%`(十进制 37十六进制 0x25的字模通过在字模绘制时向上平移 2 像素对齐普通数字的下基准线。
### 2.4 水平居中渲染实现
`lcd.c` 中,字符串居中函数需修改宽度限制参数为 `135` 像素:
```c
void LCD_ShowStringCentered(u16 y, char *str, u16 color, u16 bg_color) {
u16 len = 0;
char *p = str;
while(*p++) len++;
if(len * 8 >= 135)
LCD_ShowString(0, y, str, color, bg_color);
else
LCD_ShowString((135 - len * 8) / 2, y, str, color, bg_color);
}
```
### 2.5 绑定界面 ID 渲染实现
`main.c` 中通过 `FormatHex` 接口将 `bracelet_factory_id` 转换为十六进制字符串,并显示在绑定界面的底部:
```c
void UI_ShowBindingPage(void) {
char id_str[15];
// 渲染背景与图标
// ...
// 绘制手环自身的出厂 ID
FormatHex(bracelet_factory_id, id_str);
LCD_ShowStringCentered(180, id_str, COLOR_GRAY, COLOR_BLACK);
}
### 2.6 对码确认与序号微调页渲染
`main.c` 中通过以下方式渲染可供按键微调的数字后缀界面:
```c
void UI_ShowPairConfirmPage(u8 type, u8 selected_suffix) {
char num_buf[10];
LCD_Clear(COLOR_BLACK);
LCD_ShowStringCentered(40, "v RECU", COLOR_GREEN, COLOR_BLACK);
// 根据类型渲染 32x32 图标
// ...
// 居中显示预设名称前缀
LCD_ShowStringCentered(135, sensor_prefixes[type], COLOR_WHITE, COLOR_BLACK);
// 拼接成带选框的 "[ 02 ]" 格式字符串并高亮居中渲染
num_buf[0] = '[';
num_buf[1] = ' ';
num_buf[2] = ' ';
num_buf[3] = '0' + (selected_suffix / 10);
num_buf[4] = '0' + (selected_suffix % 10);
num_buf[5] = ' ';
num_buf[6] = ' ';
num_buf[7] = ']';
num_buf[8] = '\0';
LCD_ShowStringCentered(165, num_buf, COLOR_CYAN, COLOR_BLACK);
}
<!-- Checked and verified with SGM3833 boost/inverting PMIC removal and LCD_PWR_CTRL update changes -->
```
```