diff --git a/AGENTS.md b/AGENTS.md index 1951199..c928865 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -15,6 +15,8 @@ STM32CubeMX 生成的项目,使用 **Keil MDK-ARM V5.32** 工具链。 - `hz16_data.c/h` — CJK 16×16 字库 - `STM32F103C8T6/Drivers/BSP/AT24C02/` — AT24C02 EEPROM 驱动 - `at24c02.c/h` — I2C 读写(字节/页/连续,自动跨页) +- `STM32F103C8T6/User/` — 用户应用代码 + - `menu.c/h` — 菜单系统(LCD参数显示、按键调节、EEPROM存储) ## 硬件配置 - **MCU**: STM32F103C8T6 (LQFP48, 72MHz, 64KB Flash, 20KB RAM) @@ -33,39 +35,30 @@ STM32CubeMX 生成的项目,使用 **Keil MDK-ARM V5.32** 工具链。 ## 初始化顺序(main.c) ``` HAL_Init → SystemClock_Config → MX_GPIO → MX_DMA → MX_USART1 → MX_SPI2 -→ MX_TIM4 → MX_ADC1 → MX_TIM3 +→ MX_TIM4 → MX_ADC1 → MX_TIM3 → MX_I2C1 → button_driver_init() → st7735s_init() → lcd_* draw → TIM3 PWM start (PA6~PB1) → TIM4 Base start (TRGO→ADC) → ADC injected start +→ AT24C02 scan → menu_init() ``` -## ADC 采坑记录(不可从 CubeMX 重新生成时光靠设置) -- **ADC 时钟**: SystemClock_Config 初始为 PCLK2/2=36MHz(超 14MHz 规格),必须在 `USER CODE SysInit` 中手动改为 `/6`: - ```c - RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_ADCPRE) | RCC_CFGR_ADCPRE_DIV6; - ``` -- **TIM4_TRGO 触发 ADC(当前方案)**: CubeMX 中 TIM4 无任何 PWM 通道,生成的 `MasterOutputTrigger` 为 `TIM_TRGO_RESET` → TRGO 无脉冲。必须在 `USER CODE TIM4_Init 2` 中写寄存器: - ```c - TIM4->CR2 = (TIM4->CR2 & ~TIM_CR2_MMS) | TIM_CR2_MMS_1; /* TRGO = Update */ - ``` - 启动时用 `HAL_TIM_Base_Start(&htim4)` 即可。 -- **旧方案(已废弃)**: TIM3_CH4 触发 ADC 已废弃(PB8/PB9 改为 I2C)。 +## CubeMX 生成代码注意事项 +- **TIM4_TRGO**: CubeMX 已正确生成 `TIM_TRGO_UPDATE`(`tim.c:125`),无需手动写寄存器。若从 `.ioc` 重新生成,检查 `sMasterConfig.MasterOutputTrigger` 是否仍为 `TIM_TRGO_UPDATE`。 +- **ADC 时钟**: CubeMX 已通过 HAL 配置 `RCC_ADCPCLK2_DIV6`(`adc.c:221`),无需手动改 `RCC->CFGR`。若重新生成,验证 `PeriphClkInit.AdcClockSelection` 是否为 `RCC_ADCPCLK2_DIV6`(必须 ≤14MHz)。 +- **SPI2 模式**: CubeMX 已配置 Mode 3(CPOL=HIGH, CPHA=2EDGE),见 `spi.c:45-46`。重新生成时确认 `CLKPolarity=HIGH, CLKPhase=2EDGE`。 ## printf 无 MicroLIB 在 `usart.c` 的 USER CODE 区通过 `#pragma import(__use_no_semihosting)` + `_sys_exit()` + `_ttywrch()` + `struct __FILE` + `FILE __stdout` 实现。Keil 取消勾选 Use MicroLIB 即可。 -## SPI 注意事项 -- LCD (ST7735S) 使用**硬件SPI2**(PB13 SCK, PB15 MOSI),18MHz,**Mode 3**(CPOL=HIGH, CPHA=2EDGE) -- 若通过 CubeMX 重新生成 `spi.c`,务必在 SPI2 配置中设置 Clock Polarity=High, Clock Phase=2 Edge -- CS(PB11)、DC(PB10)、RST(PB12) 为 GPIO 控制 - ## LCD 字库生成(tools/font_gen.py) -- Python + Pillow 渲染,使用 `C:\ProgramData\anaconda3\python.exe` -- ASCII 8×16(默认):`python font_gen.py` -- CJK 16×16(按需):`python font_gen.py --cjk --string "你的汉字" --output STM32F103C8T6/Drivers/BSP/LCD/hz16_data` -- ASCII 默认参数:`--font simsun --size 56 --threshold 64 --scale 4` -- CJK 默认参数:`--font simsun --size 48 --threshold 50 --scale 3` +- Python + Pillow,使用 `python font_gen.py`(Windows 下默认系统 Python) +- **仅生成 CJK 字库**,ASCII 字库 `lcd_data.c` 已手动维护 +- CJK 16×16(按需): + ``` + python tools/font_gen.py --cjk --string "你的汉字" --output STM32F103C8T6/Drivers/BSP/LCD/hz16_data + ``` + - 默认参数:`--font simsun --size 48 --scale 3`,Otsu 自适应阈值 + - CJK 无等宽替代字体,必须用 simsun - ASCII `_` 下划线手动设为 `0x7F`(GDI 无法可靠提取) -- 输出目录 `MDK-ARM\STM32F103C8T6\` 已 gitignore ## 代码规范 - **遵循**: `嵌入式C语言代码规范(V1.0).md` diff --git a/STM32F103C8T6/Core/Src/main.c b/STM32F103C8T6/Core/Src/main.c index 883d71b..4bea882 100644 --- a/STM32F103C8T6/Core/Src/main.c +++ b/STM32F103C8T6/Core/Src/main.c @@ -33,6 +33,7 @@ #include "st7735s.h" #include "lcd.h" #include "at24c02.h" +#include "menu.h" /* USER CODE END Includes */ @@ -91,9 +92,6 @@ int main(void) SystemClock_Config(); /* USER CODE BEGIN SysInit */ - /* ADC 时钟预分频:PCLK2 / 6 = 72/6 = 12MHz */ - /* 默认 /2=36MHz 超过 14MHz 规格,ADC 无法正常工作 */ - RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_ADCPRE) | RCC_CFGR_ADCPRE_DIV6; /* USER CODE END SysInit */ /* Initialize all configured peripherals */ @@ -143,63 +141,40 @@ int main(void) /* 启动 ADC 注入组(TIM4 每触发一次,自动采一轮 PA0~PA3) */ HAL_ADCEx_InjectedStart(&hadc1); - /* === AT24C02 EEPROM 测试 === */ - { - uint8_t wbuf[] = {0x11, 0x22, 0x33, 0x44, 0x55}; - uint8_t rbuf[8]; - int i, ret; - - ret = at24c02_scan(); - if (ret == AT24C02_OK) { - lcd_draw_string(0, 64, "AT24C02 OK", COLOR_GREEN, COLOR_BLACK); - } else { - lcd_draw_string(0, 64, "AT24C02 FAIL", COLOR_RED, COLOR_BLACK); - } - - /* 在地址 0 写入 5 个字节 */ - ret = at24c02_write_buf(0, wbuf, 5); - printf("AT24C02 write: %d\r\n", ret); - - /* 从地址 0 读回 8 个字节 */ - ret = at24c02_read_buf(0, rbuf, 8); - printf("AT24C02 read[%d]:", ret); - for (i = 0; i < 8; i++) { - printf(" %02X", rbuf[i]); - } - printf("\r\n"); - - /* 验证 */ - lcd_draw_string(0, 80, "EEPROM:", COLOR_WHITE, COLOR_BLACK); - for (i = 0; i < 5; i++) { - if (rbuf[i] != wbuf[i]) { - printf("AT24C02 ERR: addr %d expect %02X got %02X\r\n", - i, wbuf[i], rbuf[i]); - break; - } - } - if (i == 5) { - printf("AT24C02 verify OK\r\n"); - } + /* AT24C02 检测 */ + if (at24c02_scan() == AT24C02_OK) { + lcd_draw_string(0, 80, "AT24C02 OK", COLOR_GREEN, COLOR_BLACK); + } else { + lcd_draw_string(0, 80, "AT24C02 FAIL", COLOR_RED, COLOR_BLACK); } + /* 进入菜单界面 */ + menu_init(); + /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ + uint32_t tick_last = 0; while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ - HAL_Delay(1000); - HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin); + /* 菜单按键处理(每帧必须频繁调用) */ + menu_process(); - /* 读取 ADC 注入组结果(TIM4 以 1kHz 触发,每秒打印一次最新值) */ - uint16_t adc0 = HAL_ADCEx_InjectedGetValue(&hadc1, ADC_INJECTED_RANK_1); - uint16_t adc1 = HAL_ADCEx_InjectedGetValue(&hadc1, ADC_INJECTED_RANK_2); - uint16_t adc2 = HAL_ADCEx_InjectedGetValue(&hadc1, ADC_INJECTED_RANK_3); - uint16_t adc3 = HAL_ADCEx_InjectedGetValue(&hadc1, ADC_INJECTED_RANK_4); - printf("ADC: %4d %4d %4d %4d\r\n", adc0, adc1, adc2, adc3); + /* 每秒执行一次:LED翻转 + ADC打印 */ + if (HAL_GetTick() - tick_last >= 1000) { + tick_last = HAL_GetTick(); + HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin); + + uint16_t adc0 = HAL_ADCEx_InjectedGetValue(&hadc1, ADC_INJECTED_RANK_1); + uint16_t adc1 = HAL_ADCEx_InjectedGetValue(&hadc1, ADC_INJECTED_RANK_2); + uint16_t adc2 = HAL_ADCEx_InjectedGetValue(&hadc1, ADC_INJECTED_RANK_3); + uint16_t adc3 = HAL_ADCEx_InjectedGetValue(&hadc1, ADC_INJECTED_RANK_4); + printf("ADC: %4d %4d %4d %4d\r\n", adc0, adc1, adc2, adc3); + } } /* USER CODE END 3 */ } diff --git a/STM32F103C8T6/Drivers/BSP/LCD/lcd.c b/STM32F103C8T6/Drivers/BSP/LCD/lcd.c index 96c1a93..6a5b3d4 100644 --- a/STM32F103C8T6/Drivers/BSP/LCD/lcd.c +++ b/STM32F103C8T6/Drivers/BSP/LCD/lcd.c @@ -125,6 +125,81 @@ void lcd_draw_string(uint16_t x, uint16_t y, const char *str, uint16_t color, ui } } +/* + * 函数功能:显示一个6x8 ASCII字符 + * 入口参数:x - 列坐标 + * y - 行坐标 + * ch - 字符 (ASCII 32-126) + * color - 字符颜色 (RGB565) + * bg_color - 背景颜色 (RGB565) + * 返回值:无 + * 函数说明:LCD_F6x8为列式存储(每字节一列,bit0=顶行,bit7=底行) + * 框选6x8区域→逐行逐列取bit→发送color或bg_color + */ +void lcd_draw_char_6x8(uint16_t x, uint16_t y, char ch, uint16_t color, uint16_t bg_color) +{ + uint8_t row; + uint8_t col; + uint8_t col_data; + + if (ch < 32 || ch > 126) { + ch = ' '; + } + + st7735s_set_window(x, y, x + 5, y + 7); + + HAL_GPIO_WritePin(LCD_CS_PORT, LCD_CS_PIN, GPIO_PIN_RESET); + HAL_GPIO_WritePin(LCD_DC_PORT, LCD_DC_PIN, GPIO_PIN_SET); + + for (row = 0; row < 8; row++) { + for (col = 0; col < 6; col++) { + col_data = LCD_F6x8[ch - 32][col]; + if (col_data & (1 << row)) { + st7735s_spi_write_byte((uint8_t)(color >> 8)); + st7735s_spi_write_byte((uint8_t)(color & 0xFF)); + } else { + st7735s_spi_write_byte((uint8_t)(bg_color >> 8)); + st7735s_spi_write_byte((uint8_t)(bg_color & 0xFF)); + } + } + } + HAL_GPIO_WritePin(LCD_CS_PORT, LCD_CS_PIN, GPIO_PIN_SET); +} + +/* + * 函数功能:显示字符串(6x8字体) + * 入口参数:x - 列坐标 + * y - 行坐标 + * str - 字符串指针 + * color - 字符颜色 (RGB565) + * bg_color - 背景颜色 (RGB565) + * 返回值:无 + * 函数说明:连续显示6x8字符,自动换行 + */ +void lcd_draw_string_6x8(uint16_t x, uint16_t y, const char *str, uint16_t color, uint16_t bg_color) +{ + uint16_t start_x = x; + + while (*str != '\0') { + if (*str == '\n') { + y += FONT_HEIGHT_8; + x = start_x; + str++; + continue; + } + if (x + FONT_WIDTH_6 > s_lcd_width) { + y += FONT_HEIGHT_8; + x = start_x; + } + if (y + FONT_HEIGHT_8 > s_lcd_height) { + break; + } + lcd_draw_char_6x8(x, y, *str, color, bg_color); + x += FONT_WIDTH_6; + str++; + } +} + /* * 函数功能:显示一个16x16 CJK汉字 * 入口参数:x - 列坐标 diff --git a/STM32F103C8T6/Drivers/BSP/LCD/lcd.h b/STM32F103C8T6/Drivers/BSP/LCD/lcd.h index c0df2b6..ae21be1 100644 --- a/STM32F103C8T6/Drivers/BSP/LCD/lcd.h +++ b/STM32F103C8T6/Drivers/BSP/LCD/lcd.h @@ -21,6 +21,8 @@ extern "C" { /* 字体定义 */ #define FONT_WIDTH_8 8 /* 8x16字体宽度(含间距) */ #define FONT_HEIGHT_16 16 /* 8x16字体高度 */ +#define FONT_WIDTH_6 6 /* 6x8字体宽度 */ +#define FONT_HEIGHT_8 8 /* 6x8字体高度 */ /* === 字符/字符串绘制 === */ @@ -46,6 +48,28 @@ void lcd_draw_char(uint16_t x, uint16_t y, char ch, uint16_t color, uint16_t bg_ */ void lcd_draw_string(uint16_t x, uint16_t y, const char *str, uint16_t color, uint16_t bg_color); +/* + * 函数功能:显示一个6x8 ASCII字符 + * 入口参数:x - 列坐标 + * y - 行坐标 + * ch - 字符 (ASCII 32-126) + * color - 字符颜色 (RGB565) + * bg_color - 背景颜色 (RGB565) + * 返回值:无 + */ +void lcd_draw_char_6x8(uint16_t x, uint16_t y, char ch, uint16_t color, uint16_t bg_color); + +/* + * 函数功能:显示字符串(6x8字体) + * 入口参数:x - 列坐标 + * y - 行坐标 + * str - 字符串指针 + * color - 字符颜色 (RGB565) + * bg_color - 背景颜色 (RGB565) + * 返回值:无 + */ +void lcd_draw_string_6x8(uint16_t x, uint16_t y, const char *str, uint16_t color, uint16_t bg_color); + /* * 函数功能:显示一个16x16 CJK汉字 * 入口参数:x - 列坐标 diff --git a/STM32F103C8T6/Drivers/BSP/LCD/lcd_data.c b/STM32F103C8T6/Drivers/BSP/LCD/lcd_data.c index b76962e..5ff2c66 100644 --- a/STM32F103C8T6/Drivers/BSP/LCD/lcd_data.c +++ b/STM32F103C8T6/Drivers/BSP/LCD/lcd_data.c @@ -1,298 +1,300 @@ #include "lcd_data.h" -/*ASCII字模数据*********************/ +/* ASCII 字模数据 8x16 */ +/* 来源: font8x16 (hubenchang0515) — MIT 许可 */ +/* 人工逐像素设计的专业位图字体,非算法缩放生成 */ -/*宽8像素,高16像素*/ -/* 字体: simsun.ttc, 字号: 64, 阈值: 50 */ const uint8_t LCD_F8x16[][16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0 - 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, // ! 1 - 0x00, 0x16, 0x36, 0x3C, 0x68, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x3C, 0x18, 0x18, + 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, // ! 1 + 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // " 2 - 0x00, 0x00, 0x20, 0x26, 0x26, 0xFF, 0x7E, 0x24, - 0x64, 0xFF, 0xFE, 0x64, 0x64, 0x00, 0x00, 0x00, // # 3 - 0x00, 0x18, 0x3C, 0x7E, 0x7E, 0x78, 0x38, 0x18, - 0x1C, 0x1E, 0x7E, 0x56, 0x7C, 0x18, 0x18, 0x00, // $ 4 - 0x00, 0x00, 0x60, 0xF4, 0x94, 0x9C, 0x98, 0xFC, - 0x1E, 0x1B, 0x3B, 0x2B, 0x6E, 0x04, 0x00, 0x00, // % 5 - 0x00, 0x00, 0x30, 0x78, 0x68, 0x78, 0x78, 0x76, - 0xF4, 0xD4, 0xDC, 0xCC, 0x7F, 0x22, 0x00, 0x00, // & 6 - 0x00, 0x60, 0x70, 0x30, 0x60, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x6C, 0x6C, 0xFE, 0x6C, 0x6C, + 0x6C, 0xFE, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, // # 3 + 0x18, 0x18, 0x7C, 0xC6, 0xC2, 0xC0, 0x7C, 0x06, + 0x06, 0x86, 0xC6, 0x7C, 0x18, 0x18, 0x00, 0x00, // $ 4 + 0x00, 0x00, 0x00, 0x00, 0xC2, 0xC6, 0x0C, 0x18, + 0x30, 0x60, 0xC6, 0x86, 0x00, 0x00, 0x00, 0x00, // % 5 + 0x00, 0x00, 0x38, 0x6C, 0x6C, 0x38, 0x76, 0xDC, + 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, // & 6 + 0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ' 7 - 0x00, 0x02, 0x06, 0x0C, 0x0C, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x0C, 0x0C, 0x06, 0x02, 0x00, // ( 8 - 0x00, 0x40, 0x60, 0x30, 0x30, 0x10, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x30, 0x30, 0x60, 0x40, 0x00, // ) 9 - 0x00, 0x00, 0x00, 0x18, 0x18, 0xFF, 0x7E, 0x3C, - 0xFF, 0xDB, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, // * 10 - 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0xFF, 0x18, + 0x00, 0x00, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x18, 0x0C, 0x00, 0x00, 0x00, 0x00, // ( 8 + 0x00, 0x00, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x0C, + 0x0C, 0x0C, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, // ) 9 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3C, 0xFF, + 0x3C, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // * 10 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // + 11 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x70, - 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // , 12 - 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, // , 12 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // - 13 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, - 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // . 14 - 0x00, 0x02, 0x02, 0x06, 0x04, 0x0C, 0x08, 0x18, - 0x10, 0x30, 0x20, 0x60, 0x40, 0xC0, 0x80, 0x00, // / 15 - 0x00, 0x00, 0x3C, 0x66, 0x66, 0x42, 0xC3, 0xC3, - 0xC3, 0xC3, 0x42, 0x66, 0x3C, 0x18, 0x00, 0x00, // 0 16 - 0x00, 0x00, 0x18, 0x38, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x3C, 0x3C, 0x00, 0x00, // 1 17 - 0x00, 0x00, 0x3C, 0x66, 0x62, 0x62, 0x06, 0x04, - 0x08, 0x10, 0x20, 0x42, 0xFE, 0x7C, 0x00, 0x00, // 2 18 - 0x00, 0x00, 0x3C, 0x64, 0x66, 0x06, 0x0C, 0x1C, - 0x06, 0x02, 0x62, 0x66, 0x7C, 0x18, 0x00, 0x00, // 3 19 - 0x00, 0x00, 0x04, 0x0C, 0x1C, 0x1C, 0x2C, 0x6C, - 0x4C, 0xFE, 0x0C, 0x0C, 0x0E, 0x1E, 0x00, 0x00, // 4 20 - 0x00, 0x00, 0x3E, 0x7E, 0x60, 0x40, 0x7C, 0x66, - 0x06, 0x02, 0x62, 0x66, 0x7C, 0x18, 0x00, 0x00, // 5 21 - 0x00, 0x00, 0x1C, 0x26, 0x62, 0x40, 0xDC, 0xF6, - 0xC2, 0xC3, 0x43, 0x62, 0x3E, 0x18, 0x00, 0x00, // 6 22 - 0x00, 0x00, 0x7E, 0x7E, 0x44, 0x04, 0x0C, 0x08, - 0x18, 0x18, 0x18, 0x38, 0x38, 0x10, 0x00, 0x00, // 7 23 - 0x00, 0x00, 0x3C, 0x66, 0x42, 0x62, 0x76, 0x3C, - 0x6E, 0x46, 0xC2, 0x46, 0x7C, 0x18, 0x00, 0x00, // 8 24 - 0x00, 0x00, 0x3C, 0x66, 0x46, 0xC2, 0xC2, 0x66, - 0x7E, 0x16, 0x06, 0x64, 0x7C, 0x10, 0x00, 0x00, // 9 25 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, // . 14 + 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0C, 0x18, + 0x30, 0x60, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, // / 15 + 0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xD6, 0xD6, + 0xC6, 0xC6, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00, // 0 16 + 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x7E, 0x00, 0x00, 0x00, 0x00, // 1 17 + 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x0C, 0x18, 0x30, + 0x60, 0xC0, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00, // 2 18 + 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x06, 0x3C, 0x06, + 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, // 3 19 + 0x00, 0x00, 0x0C, 0x1C, 0x3C, 0x6C, 0xCC, 0xFE, + 0x0C, 0x0C, 0x0C, 0x1E, 0x00, 0x00, 0x00, 0x00, // 4 20 + 0x00, 0x00, 0xFE, 0xC0, 0xC0, 0xC0, 0xFC, 0x06, + 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, // 5 21 + 0x00, 0x00, 0x38, 0x60, 0xC0, 0xC0, 0xFC, 0xC6, + 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, // 6 22 + 0x00, 0x00, 0xFE, 0xC6, 0x06, 0x06, 0x0C, 0x18, + 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, // 7 23 + 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7C, 0xC6, + 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, // 8 24 + 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, + 0x06, 0x06, 0x0C, 0x78, 0x00, 0x00, 0x00, 0x00, // 9 25 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, // : 26 - 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, - 0x00, 0x18, 0x18, 0x18, 0x10, 0x00, 0x00, 0x00, // ; 27 - 0x00, 0x00, 0x02, 0x06, 0x0C, 0x18, 0x30, 0x60, - 0x60, 0x30, 0x18, 0x0C, 0x06, 0x00, 0x00, 0x00, // < 28 - 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // = 29 - 0x00, 0x00, 0x40, 0x60, 0x30, 0x18, 0x0C, 0x06, - 0x06, 0x0C, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, // > 30 - 0x00, 0x00, 0x3C, 0x66, 0xC3, 0xC3, 0x46, 0x0C, - 0x18, 0x10, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, // ? 31 - 0x00, 0x00, 0x1C, 0x36, 0x6F, 0x5F, 0xD7, 0xF5, - 0xF5, 0xFE, 0x7E, 0x63, 0x3E, 0x18, 0x00, 0x00, // @ 32 - 0x00, 0x00, 0x18, 0x18, 0x18, 0x3C, 0x2C, 0x2C, - 0x3C, 0x7E, 0x46, 0x46, 0xC7, 0xC7, 0x00, 0x00, // A 33 - 0x00, 0x00, 0xFC, 0x66, 0x62, 0x62, 0x66, 0x7C, - 0x66, 0x63, 0x63, 0x63, 0x7E, 0xF8, 0x00, 0x00, // B 34 - 0x00, 0x00, 0x1E, 0x63, 0x41, 0xC0, 0xC0, 0xC0, - 0xC0, 0xC0, 0xC1, 0x62, 0x3E, 0x18, 0x00, 0x00, // C 35 - 0x00, 0x00, 0xF8, 0x6C, 0x66, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x62, 0x66, 0x7C, 0xF0, 0x00, 0x00, // D 36 - 0x00, 0x00, 0x7E, 0x66, 0x62, 0x60, 0x64, 0x7C, - 0x64, 0x60, 0x60, 0x63, 0x7E, 0x7E, 0x00, 0x00, // E 37 - 0x00, 0x00, 0x7E, 0x63, 0x61, 0x60, 0x64, 0x7C, - 0x64, 0x64, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, // F 38 - 0x00, 0x00, 0x3C, 0x66, 0x42, 0xC0, 0xC0, 0xC0, - 0xC7, 0xC6, 0x46, 0x66, 0x3E, 0x18, 0x00, 0x00, // G 39 - 0x00, 0x00, 0xE7, 0x66, 0x66, 0x66, 0x66, 0x7E, - 0x66, 0x66, 0x66, 0x66, 0x66, 0xE7, 0x00, 0x00, // H 40 + 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, // : 26 + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, // ; 27 + 0x00, 0x00, 0x00, 0x06, 0x0C, 0x18, 0x30, 0x60, + 0x30, 0x18, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00, // < 28 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, + 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // = 29 + 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0C, 0x06, + 0x0C, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, // > 30 + 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0x0C, 0x18, 0x18, + 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, // ? 31 + 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xDE, 0xDE, + 0xDE, 0xDC, 0xC0, 0x7C, 0x00, 0x00, 0x00, 0x00, // @ 32 + 0x00, 0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, + 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, // A 33 + 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x66, + 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00, // B 34 + 0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xC0, + 0xC0, 0xC2, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00, // C 35 + 0x00, 0x00, 0xF8, 0x6C, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x6C, 0xF8, 0x00, 0x00, 0x00, 0x00, // D 36 + 0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, + 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00, // E 37 + 0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, + 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, // F 38 + 0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xDE, + 0xC6, 0xC6, 0x66, 0x3A, 0x00, 0x00, 0x00, 0x00, // G 39 + 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, + 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, // H 40 0x00, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x3C, 0x3C, 0x00, 0x00, // I 41 - 0x00, 0x3F, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, - 0x0C, 0x0C, 0x0C, 0x0C, 0xCC, 0xF8, 0x20, 0x00, // J 42 - 0x00, 0x00, 0xE6, 0x66, 0x6C, 0x68, 0x70, 0x78, - 0x68, 0x6C, 0x6C, 0x66, 0x67, 0x67, 0x00, 0x00, // K 43 - 0x00, 0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, - 0x60, 0x60, 0x60, 0x63, 0x7E, 0x7E, 0x00, 0x00, // L 44 - 0x00, 0x00, 0xC3, 0x66, 0x66, 0x66, 0x66, 0x6E, - 0x7E, 0x7A, 0x5A, 0x5A, 0xD7, 0xC7, 0x00, 0x00, // M 45 - 0x00, 0x00, 0xC7, 0x62, 0x72, 0x72, 0x52, 0x5A, - 0x4A, 0x4E, 0x46, 0x46, 0xE2, 0xE0, 0x00, 0x00, // N 46 - 0x00, 0x00, 0x3C, 0x66, 0x42, 0xC3, 0xC3, 0xC3, - 0xC3, 0xC3, 0x43, 0x66, 0x3C, 0x18, 0x00, 0x00, // O 47 - 0x00, 0x00, 0x7C, 0x66, 0x63, 0x63, 0x62, 0x7E, - 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, // P 48 - 0x00, 0x18, 0x3C, 0x66, 0xC3, 0xC3, 0xC3, 0xC3, - 0xC3, 0xFB, 0x7A, 0x6E, 0x3C, 0x06, 0x00, 0x00, // Q 49 - 0x00, 0x00, 0x7C, 0x66, 0x62, 0x62, 0x66, 0x7C, - 0x68, 0x6C, 0x64, 0x66, 0x67, 0x63, 0x00, 0x00, // R 50 - 0x00, 0x00, 0x3C, 0x66, 0x42, 0x60, 0x70, 0x3C, - 0x0E, 0x06, 0xC2, 0x46, 0x7E, 0x18, 0x00, 0x00, // S 51 - 0x00, 0x00, 0x7E, 0xDB, 0x99, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, // T 52 - 0x00, 0x00, 0xE7, 0x62, 0x62, 0x62, 0x62, 0x62, - 0x62, 0x62, 0x62, 0x62, 0x3C, 0x18, 0x00, 0x00, // U 53 - 0x00, 0x00, 0xE7, 0x66, 0x66, 0x64, 0x24, 0x24, - 0x3C, 0x38, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, // V 54 - 0x00, 0x00, 0xDB, 0xDB, 0x5A, 0x5A, 0x5A, 0x7E, - 0x7C, 0x7C, 0x2C, 0x2C, 0x24, 0x00, 0x00, 0x00, // W 55 - 0x00, 0x00, 0x66, 0x66, 0x24, 0x3C, 0x18, 0x18, - 0x18, 0x3C, 0x2C, 0x24, 0x66, 0x66, 0x00, 0x00, // X 56 - 0x00, 0x00, 0xE7, 0x62, 0x66, 0x34, 0x34, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, // Y 57 - 0x00, 0x00, 0x7E, 0x66, 0x46, 0x0C, 0x08, 0x18, - 0x10, 0x30, 0x20, 0x62, 0xFE, 0x7C, 0x00, 0x00, // Z 58 - 0x00, 0x1E, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1E, 0x00, // [ 59 - 0x00, 0x40, 0x60, 0x20, 0x30, 0x30, 0x10, 0x18, - 0x08, 0x0C, 0x0C, 0x04, 0x06, 0x02, 0x02, 0x00, // \ 60 - 0x00, 0x78, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x78, 0x00, // ] 61 - 0x00, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, // I 41 + 0x00, 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, + 0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0x00, // J 42 + 0x00, 0x00, 0xE6, 0x66, 0x66, 0x6C, 0x78, 0x78, + 0x6C, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00, // K 43 + 0x00, 0x00, 0xF0, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00, // L 44 + 0x00, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, + 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, // M 45 + 0x00, 0x00, 0xC6, 0xE6, 0xF6, 0xFE, 0xDE, 0xCE, + 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, // N 46 + 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, // O 47 + 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x60, + 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, // P 48 + 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, + 0xC6, 0xD6, 0xDE, 0x7C, 0x0C, 0x0E, 0x00, 0x00, // Q 49 + 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x6C, + 0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00, // R 50 + 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0x60, 0x38, 0x0C, + 0x06, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, // S 51 + 0x00, 0x00, 0x7E, 0x7E, 0x5A, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, // T 52 + 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, // U 53 + 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, + 0xC6, 0x6C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, // V 54 + 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xD6, 0xD6, + 0xD6, 0xFE, 0xEE, 0x6C, 0x00, 0x00, 0x00, 0x00, // W 55 + 0x00, 0x00, 0xC6, 0xC6, 0x6C, 0x7C, 0x38, 0x38, + 0x7C, 0x6C, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, // X 56 + 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, + 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, // Y 57 + 0x00, 0x00, 0xFE, 0xC6, 0x86, 0x0C, 0x18, 0x30, + 0x60, 0xC2, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00, // Z 58 + 0x00, 0x00, 0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x3C, 0x00, 0x00, 0x00, 0x00, // [ 59 + 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0x70, 0x38, + 0x1C, 0x0E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, // \ 60 + 0x00, 0x00, 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, + 0x0C, 0x0C, 0x0C, 0x3C, 0x00, 0x00, 0x00, 0x00, // ] 61 + 0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ^ 62 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, // _ 63 - 0x00, 0x70, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, // _ 63 + 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ` 64 - 0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x46, 0x3E, - 0x66, 0xC6, 0x6F, 0x36, 0x00, 0x00, 0x00, 0x00, // a 65 - 0x00, 0x00, 0xC0, 0x60, 0x60, 0x60, 0x7C, 0x76, - 0x66, 0x62, 0x62, 0x66, 0x66, 0x5C, 0x00, 0x00, // b 66 - 0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x66, 0x40, - 0x40, 0x62, 0x76, 0x1C, 0x00, 0x00, 0x00, 0x00, // c 67 - 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x1E, 0x76, - 0x66, 0x46, 0x46, 0x66, 0x6E, 0x3E, 0x00, 0x00, // d 68 - 0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x42, 0x7E, - 0x40, 0x62, 0x76, 0x1C, 0x00, 0x00, 0x00, 0x00, // e 69 - 0x00, 0x00, 0x0E, 0x1B, 0x31, 0x30, 0x7C, 0x30, - 0x30, 0x30, 0x30, 0x30, 0x38, 0x7C, 0x00, 0x00, // f 70 - 0x00, 0x00, 0x00, 0x1B, 0x2F, 0x66, 0x66, 0x3C, - 0x78, 0x7E, 0x46, 0x66, 0x3C, 0x00, 0x00, 0x00, // g 71 - 0x00, 0x00, 0x60, 0x60, 0x60, 0x60, 0x7C, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, // h 72 - 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x38, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x3C, 0x3C, 0x00, 0x00, // i 73 - 0x00, 0x04, 0x06, 0x00, 0x00, 0x1E, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x04, 0x6C, 0x38, 0x00, // j 74 - 0x00, 0x00, 0x60, 0x60, 0x60, 0x60, 0x66, 0x6C, - 0x68, 0x78, 0x6C, 0x6C, 0x66, 0x67, 0x00, 0x00, // k 75 - 0x00, 0x00, 0x38, 0x38, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, // l 76 - 0x00, 0x00, 0x00, 0x00, 0xFE, 0xDB, 0xDB, 0xDB, - 0xDB, 0xDB, 0xDB, 0xDB, 0x00, 0x00, 0x00, 0x00, // m 77 - 0x00, 0x00, 0x00, 0x00, 0xFC, 0x76, 0x66, 0x66, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0C, 0x7C, + 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, // a 65 + 0x00, 0x00, 0xE0, 0x60, 0x60, 0x78, 0x6C, 0x66, + 0x66, 0x66, 0x66, 0x7C, 0x00, 0x00, 0x00, 0x00, // b 66 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0, + 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, // c 67 + 0x00, 0x00, 0x1C, 0x0C, 0x0C, 0x3C, 0x6C, 0xCC, + 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, // d 68 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xFE, + 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, // e 69 + 0x00, 0x00, 0x38, 0x6C, 0x64, 0x60, 0xF0, 0x60, + 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, // f 70 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0xCC, 0x78, 0x00, // g 71 + 0x00, 0x00, 0xE0, 0x60, 0x60, 0x6C, 0x76, 0x66, + 0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00, // h 72 + 0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, // i 73 + 0x00, 0x00, 0x06, 0x06, 0x00, 0x0E, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3C, 0x00, // j 74 + 0x00, 0x00, 0xE0, 0x60, 0x60, 0x66, 0x6C, 0x78, + 0x78, 0x6C, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00, // k 75 + 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, // l 76 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0xFE, 0xD6, + 0xD6, 0xD6, 0xD6, 0xC6, 0x00, 0x00, 0x00, 0x00, // m 77 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, // n 78 - 0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x42, 0xC3, - 0xC3, 0x42, 0x66, 0x38, 0x00, 0x00, 0x00, 0x00, // o 79 - 0x00, 0x00, 0x00, 0x7C, 0x76, 0x62, 0x63, 0x63, - 0x62, 0x66, 0x7C, 0x60, 0x70, 0x00, 0x00, 0x00, // p 80 - 0x00, 0x00, 0x00, 0x3E, 0x66, 0x46, 0xC6, 0xC6, - 0x46, 0x7E, 0x16, 0x06, 0x0E, 0x00, 0x00, 0x00, // q 81 - 0x00, 0x00, 0x00, 0x00, 0xFE, 0x3B, 0x30, 0x30, - 0x30, 0x30, 0x30, 0xF8, 0x00, 0x00, 0x00, 0x00, // r 82 - 0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x60, 0x38, - 0x0E, 0x46, 0x66, 0x7C, 0x00, 0x00, 0x00, 0x00, // s 83 - 0x00, 0x00, 0x00, 0x10, 0x10, 0x7C, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x1E, 0x0C, 0x00, 0x00, 0x00, // t 84 - 0x00, 0x00, 0x00, 0x00, 0xE6, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x6E, 0x3E, 0x00, 0x00, 0x00, 0x00, // u 85 - 0x00, 0x00, 0x00, 0x00, 0xE6, 0x66, 0x24, 0x34, - 0x38, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, // v 86 - 0x00, 0x00, 0x00, 0x00, 0xDB, 0xDA, 0x5A, 0x7E, - 0x7C, 0x2C, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, // w 87 - 0x00, 0x00, 0x00, 0x00, 0x76, 0x34, 0x38, 0x18, - 0x18, 0x2C, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, // x 88 - 0x00, 0x00, 0x00, 0x67, 0x66, 0x34, 0x34, 0x1C, - 0x18, 0x18, 0x18, 0x70, 0x60, 0x00, 0x00, 0x00, // y 89 - 0x00, 0x00, 0x00, 0x00, 0x7E, 0x4C, 0x08, 0x18, - 0x30, 0x22, 0x7E, 0x7C, 0x00, 0x00, 0x00, 0x00, // z 90 - 0x00, 0x06, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x18, - 0x18, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x06, 0x00, // { 91 - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, // | 92 - 0x00, 0x60, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, - 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x60, 0x00, // } 93 - 0x00, 0x70, 0x59, 0x0E, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, // o 79 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00, // p 80 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0x0C, 0x1E, 0x00, // q 81 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x76, 0x66, + 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, // r 82 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x60, + 0x38, 0x0C, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, // s 83 + 0x00, 0x00, 0x10, 0x30, 0x30, 0xFC, 0x30, 0x30, + 0x30, 0x30, 0x36, 0x1C, 0x00, 0x00, 0x00, 0x00, // t 84 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, // u 85 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, // v 86 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xD6, + 0xD6, 0xD6, 0xFE, 0x6C, 0x00, 0x00, 0x00, 0x00, // w 87 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x6C, 0x38, + 0x38, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00, // x 88 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x0C, 0xF8, 0x00, // y 89 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xCC, 0x18, + 0x30, 0x60, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00, // z 90 + 0x00, 0x00, 0x0E, 0x18, 0x18, 0x18, 0x70, 0x18, + 0x18, 0x18, 0x18, 0x0E, 0x00, 0x00, 0x00, 0x00, // { 91 + 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, // | 92 + 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0E, 0x18, + 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, // } 93 + 0x00, 0x00, 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // ~ 94 }; -/*宽6像素,高8像素(未使用)*/ +/* 宽6像素,高8像素 */ +/* 来源: font6x8 (fantasticmao/font6x8), GPL-3.0 */ +/* 列式存储:每字节一列,bit0=顶行,bit7=底行 */ const uint8_t LCD_F6x8[][6] = { - 0x00,0x00,0x00,0x00,0x00,0x00, // 0 - 0x00,0x00,0x00,0x00,0x00,0x00, // ! 1 - 0x00,0x00,0x00,0x00,0x00,0x00, // " 2 - 0x00,0x00,0x00,0x00,0x00,0x00, // # 3 - 0x00,0x00,0x00,0x00,0x00,0x00, // $ 4 - 0x00,0x00,0x00,0x00,0x00,0x00, // % 5 - 0x00,0x00,0x00,0x00,0x00,0x00, // & 6 - 0x00,0x00,0x00,0x00,0x00,0x00, // ' 7 - 0x00,0x00,0x00,0x00,0x00,0x00, // ( 8 - 0x00,0x00,0x00,0x00,0x00,0x00, // ) 9 - 0x00,0x00,0x00,0x00,0x00,0x00, // * 10 - 0x00,0x00,0x00,0x00,0x00,0x00, // + 11 - 0x00,0x00,0x00,0x00,0x00,0x00, // , 12 - 0x00,0x00,0x00,0x00,0x00,0x00, // - 13 - 0x00,0x00,0x00,0x00,0x00,0x00, // . 14 - 0x00,0x00,0x00,0x00,0x00,0x00, // / 15 - 0x00,0x00,0x00,0x00,0x00,0x00, // 0 16 - 0x00,0x00,0x00,0x00,0x00,0x00, // 1 17 - 0x00,0x00,0x00,0x00,0x00,0x00, // 2 18 - 0x00,0x00,0x00,0x00,0x00,0x00, // 3 19 - 0x00,0x00,0x00,0x00,0x00,0x00, // 4 20 - 0x00,0x00,0x00,0x00,0x00,0x00, // 5 21 - 0x00,0x00,0x00,0x00,0x00,0x00, // 6 22 - 0x00,0x00,0x00,0x00,0x00,0x00, // 7 23 - 0x00,0x00,0x00,0x00,0x00,0x00, // 8 24 - 0x00,0x00,0x00,0x00,0x00,0x00, // 9 25 - 0x00,0x00,0x00,0x00,0x00,0x00, // : 26 - 0x00,0x00,0x00,0x00,0x00,0x00, // ; 27 - 0x00,0x00,0x00,0x00,0x00,0x00, // < 28 - 0x00,0x00,0x00,0x00,0x00,0x00, // = 29 - 0x00,0x00,0x00,0x00,0x00,0x00, // > 30 - 0x00,0x00,0x00,0x00,0x00,0x00, // ? 31 - 0x00,0x00,0x00,0x00,0x00,0x00, // @ 32 - 0x00,0x00,0x00,0x00,0x00,0x00, // A 33 - 0x00,0x00,0x00,0x00,0x00,0x00, // B 34 - 0x00,0x00,0x00,0x00,0x00,0x00, // C 35 - 0x00,0x00,0x00,0x00,0x00,0x00, // D 36 - 0x00,0x00,0x00,0x00,0x00,0x00, // E 37 - 0x00,0x00,0x00,0x00,0x00,0x00, // F 38 - 0x00,0x00,0x00,0x00,0x00,0x00, // G 39 - 0x00,0x00,0x00,0x00,0x00,0x00, // H 40 - 0x00,0x00,0x00,0x00,0x00,0x00, // I 41 - 0x00,0x00,0x00,0x00,0x00,0x00, // J 42 - 0x00,0x00,0x00,0x00,0x00,0x00, // K 43 - 0x00,0x00,0x00,0x00,0x00,0x00, // L 44 - 0x00,0x00,0x00,0x00,0x00,0x00, // M 45 - 0x00,0x00,0x00,0x00,0x00,0x00, // N 46 - 0x00,0x00,0x00,0x00,0x00,0x00, // O 47 - 0x00,0x00,0x00,0x00,0x00,0x00, // P 48 - 0x00,0x00,0x00,0x00,0x00,0x00, // Q 49 - 0x00,0x00,0x00,0x00,0x00,0x00, // R 50 - 0x00,0x00,0x00,0x00,0x00,0x00, // S 51 - 0x00,0x00,0x00,0x00,0x00,0x00, // T 52 - 0x00,0x00,0x00,0x00,0x00,0x00, // U 53 - 0x00,0x00,0x00,0x00,0x00,0x00, // V 54 - 0x00,0x00,0x00,0x00,0x00,0x00, // W 55 - 0x00,0x00,0x00,0x00,0x00,0x00, // X 56 - 0x00,0x00,0x00,0x00,0x00,0x00, // Y 57 - 0x00,0x00,0x00,0x00,0x00,0x00, // Z 58 - 0x00,0x00,0x00,0x00,0x00,0x00, // [ 59 - 0x00,0x00,0x00,0x00,0x00,0x00, // \ 60 - 0x00,0x00,0x00,0x00,0x00,0x00, // ] 61 - 0x00,0x00,0x00,0x00,0x00,0x00, // ^ 62 - 0x00,0x00,0x00,0x00,0x00,0x00, // _ 63 - 0x00,0x00,0x00,0x00,0x00,0x00, // ` 64 - 0x00,0x00,0x00,0x00,0x00,0x00, // a 65 - 0x00,0x00,0x00,0x00,0x00,0x00, // b 66 - 0x00,0x00,0x00,0x00,0x00,0x00, // c 67 - 0x00,0x00,0x00,0x00,0x00,0x00, // d 68 - 0x00,0x00,0x00,0x00,0x00,0x00, // e 69 - 0x00,0x00,0x00,0x00,0x00,0x00, // f 70 - 0x00,0x00,0x00,0x00,0x00,0x00, // g 71 - 0x00,0x00,0x00,0x00,0x00,0x00, // h 72 - 0x00,0x00,0x00,0x00,0x00,0x00, // i 73 - 0x00,0x00,0x00,0x00,0x00,0x00, // j 74 - 0x00,0x00,0x00,0x00,0x00,0x00, // k 75 - 0x00,0x00,0x00,0x00,0x00,0x00, // l 76 - 0x00,0x00,0x00,0x00,0x00,0x00, // m 77 - 0x00,0x00,0x00,0x00,0x00,0x00, // n 78 - 0x00,0x00,0x00,0x00,0x00,0x00, // o 79 - 0x00,0x00,0x00,0x00,0x00,0x00, // p 80 - 0x00,0x00,0x00,0x00,0x00,0x00, // q 81 - 0x00,0x00,0x00,0x00,0x00,0x00, // r 82 - 0x00,0x00,0x00,0x00,0x00,0x00, // s 83 - 0x00,0x00,0x00,0x00,0x00,0x00, // t 84 - 0x00,0x00,0x00,0x00,0x00,0x00, // u 85 - 0x00,0x00,0x00,0x00,0x00,0x00, // v 86 - 0x00,0x00,0x00,0x00,0x00,0x00, // w 87 - 0x00,0x00,0x00,0x00,0x00,0x00, // x 88 - 0x00,0x00,0x00,0x00,0x00,0x00, // y 89 - 0x00,0x00,0x00,0x00,0x00,0x00, // z 90 - 0x00,0x00,0x00,0x00,0x00,0x00, // { 91 - 0x00,0x00,0x00,0x00,0x00,0x00, // | 92 - 0x00,0x00,0x00,0x00,0x00,0x00, // } 93 - 0x00,0x00,0x00,0x00,0x00,0x00 // ~ 94 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0 + 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, // ! 1 + 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, // " 2 + 0x00, 0x14, 0x3E, 0x14, 0x3E, 0x14, // # 3 + 0x00, 0x04, 0x2A, 0x7F, 0x2A, 0x10, // $ 4 + 0x00, 0x26, 0x10, 0x08, 0x04, 0x32, // % 5 + 0x00, 0x1A, 0x25, 0x29, 0x10, 0x28, // & 6 + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, // ' 7 + 0x00, 0x00, 0x3E, 0x41, 0x41, 0x00, // ( 8 + 0x00, 0x00, 0x41, 0x41, 0x3E, 0x00, // ) 9 + 0x00, 0x28, 0x18, 0x0E, 0x18, 0x28, // * 10 + 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, // + 11 + 0x00, 0x00, 0x20, 0x10, 0x00, 0x00, // , 12 + 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, // - 13 + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, // . 14 + 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, // / 15 + 0x00, 0x00, 0x1E, 0x21, 0x21, 0x1E, // 0 16 + 0x00, 0x00, 0x00, 0x22, 0x3F, 0x20, // 1 17 + 0x00, 0x00, 0x22, 0x31, 0x29, 0x26, // 2 18 + 0x00, 0x00, 0x12, 0x21, 0x25, 0x1A, // 3 19 + 0x00, 0x00, 0x0C, 0x0A, 0x3F, 0x08, // 4 20 + 0x00, 0x00, 0x17, 0x25, 0x25, 0x19, // 5 21 + 0x00, 0x00, 0x1C, 0x26, 0x25, 0x18, // 6 22 + 0x00, 0x00, 0x01, 0x39, 0x05, 0x03, // 7 23 + 0x00, 0x00, 0x1A, 0x25, 0x25, 0x1A, // 8 24 + 0x00, 0x00, 0x06, 0x09, 0x29, 0x1E, // 9 25 + 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, // : 26 + 0x00, 0x00, 0x20, 0x14, 0x00, 0x00, // ; 27 + 0x00, 0x00, 0x08, 0x14, 0x22, 0x00, // < 28 + 0x00, 0x00, 0x14, 0x14, 0x14, 0x00, // = 29 + 0x00, 0x00, 0x22, 0x14, 0x08, 0x00, // > 30 + 0x00, 0x02, 0x01, 0x29, 0x06, 0x00, // ? 31 + 0x00, 0x1E, 0x21, 0x2D, 0x2E, 0x00, // @ 32 + 0x00, 0x30, 0x0C, 0x0B, 0x0C, 0x30, // A 33 + 0x00, 0x00, 0x3F, 0x25, 0x25, 0x1A, // B 34 + 0x00, 0x00, 0x1E, 0x21, 0x21, 0x12, // C 35 + 0x00, 0x00, 0x3F, 0x21, 0x21, 0x1E, // D 36 + 0x00, 0x00, 0x3F, 0x25, 0x25, 0x25, // E 37 + 0x00, 0x00, 0x3F, 0x05, 0x05, 0x05, // F 38 + 0x00, 0x00, 0x1E, 0x21, 0x29, 0x1A, // G 39 + 0x00, 0x00, 0x3F, 0x04, 0x04, 0x3F, // H 40 + 0x00, 0x00, 0x21, 0x3F, 0x21, 0x00, // I 41 + 0x00, 0x18, 0x20, 0x21, 0x1F, 0x00, // J 42 + 0x00, 0x00, 0x3F, 0x0C, 0x12, 0x21, // K 43 + 0x00, 0x00, 0x3F, 0x20, 0x20, 0x20, // L 44 + 0x00, 0x3F, 0x06, 0x08, 0x06, 0x3F, // M 45 + 0x00, 0x00, 0x3F, 0x06, 0x18, 0x3F, // N 46 + 0x00, 0x00, 0x1E, 0x21, 0x21, 0x1E, // O 47 + 0x00, 0x00, 0x3F, 0x09, 0x09, 0x06, // P 48 + 0x00, 0x1E, 0x21, 0x21, 0x5E, 0x00, // Q 49 + 0x00, 0x00, 0x3F, 0x09, 0x19, 0x26, // R 50 + 0x00, 0x00, 0x12, 0x25, 0x29, 0x12, // S 51 + 0x00, 0x01, 0x01, 0x3F, 0x01, 0x01, // T 52 + 0x00, 0x1F, 0x20, 0x20, 0x20, 0x1F, // U 53 + 0x00, 0x0F, 0x10, 0x20, 0x10, 0x0F, // V 54 + 0x00, 0x1F, 0x20, 0x1C, 0x20, 0x1F, // W 55 + 0x00, 0x21, 0x12, 0x0C, 0x12, 0x21, // X 56 + 0x00, 0x03, 0x04, 0x38, 0x04, 0x03, // Y 57 + 0x00, 0x00, 0x31, 0x29, 0x25, 0x23, // Z 58 + 0x00, 0x00, 0x3F, 0x21, 0x21, 0x00, // [ 59 + 0x00, 0x02, 0x04, 0x08, 0x10, 0x20, // \ 60 + 0x00, 0x00, 0x21, 0x21, 0x3F, 0x00, // ] 61 + 0x00, 0x04, 0x02, 0x01, 0x02, 0x04, // ^ 62 + 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, // _ 63 + 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, // ` 64 + 0x00, 0x18, 0x24, 0x24, 0x18, 0x20, // a 65 + 0x00, 0x00, 0x3F, 0x24, 0x24, 0x18, // b 66 + 0x00, 0x00, 0x18, 0x24, 0x24, 0x00, // c 67 + 0x00, 0x00, 0x18, 0x24, 0x24, 0x3F, // d 68 + 0x00, 0x00, 0x1C, 0x2A, 0x2A, 0x0C, // e 69 + 0x00, 0x04, 0x04, 0x3E, 0x05, 0x05, // f 70 + 0x00, 0x00, 0x0C, 0x52, 0x52, 0x3E, // g 71 + 0x00, 0x00, 0x3F, 0x04, 0x04, 0x38, // h 72 + 0x00, 0x00, 0x24, 0x3D, 0x20, 0x00, // i 73 + 0x00, 0x20, 0x40, 0x44, 0x3D, 0x00, // j 74 + 0x00, 0x00, 0x3F, 0x08, 0x14, 0x22, // k 75 + 0x00, 0x00, 0x1F, 0x20, 0x20, 0x10, // l 76 + 0x00, 0x3E, 0x04, 0x18, 0x04, 0x3E, // m 77 + 0x00, 0x00, 0x3C, 0x02, 0x02, 0x3C, // n 78 + 0x00, 0x00, 0x1C, 0x22, 0x22, 0x1C, // o 79 + 0x00, 0x00, 0x7E, 0x12, 0x12, 0x0C, // p 80 + 0x00, 0x00, 0x0C, 0x12, 0x12, 0x7E, // q 81 + 0x00, 0x00, 0x04, 0x38, 0x04, 0x04, // r 82 + 0x00, 0x00, 0x04, 0x2A, 0x2A, 0x10, // s 83 + 0x00, 0x00, 0x04, 0x1E, 0x24, 0x10, // t 84 + 0x00, 0x1C, 0x20, 0x20, 0x20, 0x1C, // u 85 + 0x00, 0x0C, 0x10, 0x20, 0x10, 0x0C, // v 86 + 0x00, 0x1C, 0x20, 0x18, 0x20, 0x1C, // w 87 + 0x00, 0x22, 0x14, 0x08, 0x14, 0x22, // x 88 + 0x00, 0x04, 0x48, 0x30, 0x08, 0x04, // y 89 + 0x00, 0x00, 0x24, 0x34, 0x2C, 0x24, // z 90 + 0x00, 0x08, 0x08, 0x36, 0x41, 0x41, // { 91 + 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, // | 92 + 0x00, 0x41, 0x41, 0x36, 0x08, 0x08, // } 93 + 0x00, 0x08, 0x04, 0x08, 0x10, 0x08 // ~ 94 }; diff --git a/STM32F103C8T6/Drivers/BSP/LCD/st7735s.c b/STM32F103C8T6/Drivers/BSP/LCD/st7735s.c index eea007c..576e697 100644 --- a/STM32F103C8T6/Drivers/BSP/LCD/st7735s.c +++ b/STM32F103C8T6/Drivers/BSP/LCD/st7735s.c @@ -15,13 +15,8 @@ #include "spi.h" #include -/* - * 部分屏幕厂家虽然标称128x160,但实际使用132x162驱动晶片, - * 左右各偏移2列,上下偏移1行才能正确显示。 - * 根据自己的屏幕实测调整这两个值。 - */ -#define X_OFFSET 2 -#define Y_OFFSET 1 +#define X_OFFSET 0 +#define Y_OFFSET 0 uint16_t s_lcd_width = LCD_WIDTH; uint16_t s_lcd_height = LCD_HEIGHT; diff --git a/STM32F103C8T6/MDK-ARM/STM32F103C8T6.uvprojx b/STM32F103C8T6/MDK-ARM/STM32F103C8T6.uvprojx index 3561400..4475bf4 100644 --- a/STM32F103C8T6/MDK-ARM/STM32F103C8T6.uvprojx +++ b/STM32F103C8T6/MDK-ARM/STM32F103C8T6.uvprojx @@ -340,7 +340,7 @@ USE_HAL_DRIVER,STM32F103xB - ../Core/Inc;../Drivers/STM32F1xx_HAL_Driver/Inc;../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32F1xx/Include;../Drivers/CMSIS/Include;../Drivers/BSP/MultiButton;../Drivers/BSP/LCD;..\Drivers\BSP\AT24C02 + ../Core/Inc;../Drivers/STM32F1xx_HAL_Driver/Inc;../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32F1xx/Include;../Drivers/CMSIS/Include;../Drivers/BSP/MultiButton;../Drivers/BSP/LCD;..\Drivers\BSP\AT24C02;..\User @@ -1152,6 +1152,16 @@ + + Application/User + + + menu.c + 1 + ..\User\menu.c + + + ::CMSIS diff --git a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/STM32F103C8T6.lnp b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/STM32F103C8T6.lnp index 82be112..44b1562 100644 --- a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/STM32F103C8T6.lnp +++ b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/STM32F103C8T6.lnp @@ -36,6 +36,7 @@ "stm32f103c8t6\button_driver_1.o" "stm32f103c8t6\multi_button_1.o" "stm32f103c8t6\at24c02.o" +"stm32f103c8t6\menu.o" --strict --scatter "STM32F103C8T6\STM32F103C8T6.sct" --summary_stderr --info summarysizes --map --load_addr_map_info --xref --callgraph --symbols --info sizes --info totals --info unused --info veneers diff --git a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/lcd.crf b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/lcd.crf index b09b9ed..51e3b53 100644 Binary files a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/lcd.crf and b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/lcd.crf differ diff --git a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/lcd_data.crf b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/lcd_data.crf index 24b2158..44f8667 100644 Binary files a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/lcd_data.crf and b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/lcd_data.crf differ diff --git a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/main.crf b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/main.crf index 65225f6..44c2075 100644 Binary files a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/main.crf and b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/main.crf differ diff --git a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/menu.crf b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/menu.crf new file mode 100644 index 0000000..25cd69f Binary files /dev/null and b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/menu.crf differ diff --git a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/st7735s_1.crf b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/st7735s_1.crf index 18fa0f8..cd0c82b 100644 Binary files a/STM32F103C8T6/MDK-ARM/STM32F103C8T6/st7735s_1.crf and b/STM32F103C8T6/MDK-ARM/STM32F103C8T6/st7735s_1.crf differ diff --git a/STM32F103C8T6/User/menu.c b/STM32F103C8T6/User/menu.c new file mode 100644 index 0000000..91f08ef --- /dev/null +++ b/STM32F103C8T6/User/menu.c @@ -0,0 +1,356 @@ +/* + * 模块名称:菜单系统 + * 模块功能:通过LCD显示参数,按键导航/调整,AT24C02存储 + * 适用平台:STM32F103C8T6 + * 作者:王建锋 + * 创建日期:2026-07-14 + * 修改记录: + * 2026-07-14 王建锋 创建初始版本 + */ + +#include "menu.h" +#include "button_driver.h" +#include "at24c02.h" +#include "lcd.h" +#include "tim.h" +#include + +#define COLOR_GRAY 0x8410 /* RGB565 灰 */ + +/* ======================== EEPROM 存储布局 ======================== */ +#define EEPROM_DATA_ADDR 0x10 /* 参数存储起始地址 */ +#define EEPROM_MAGIC 0xA55A /* 有效数据标识 */ +#define EEPROM_MAGIC_ADDR 0x0E /* Magic 存储地址(2字节) */ + +/* ======================== 参数定义 ======================== */ +typedef struct { + const char *name; /* 显示名称 */ + const char *unit; /* 单位 */ + int32_t default_val; /* 默认值 */ + int32_t min; /* 最小值 */ + int32_t max; /* 最大值 */ + int32_t step; /* 步进 */ +} ParamDef_t; + +static const ParamDef_t s_param_def[PARAM_COUNT] = { + {"PWM1", "", 500, 0, 999, 50 }, + {"PWM2", "", 500, 0, 999, 50 }, + {"PWM3", "", 500, 0, 999, 50 }, + {"PWM4", "", 500, 0, 999, 50 }, +}; + +/* ======================== 运行时状态 ======================== */ +static int32_t s_param_val[PARAM_COUNT]; /* 当前参数值 */ +static uint8_t s_sel = 0; /* 选中的参数索引 */ +static uint8_t s_editing = 0; /* 0=导航, 1=编辑 */ +static uint8_t s_redraw = 1; /* 需要重绘标志 */ + +/* ======================== 静态函数声明 ======================== */ +static void draw_menu(void); +static void load_params(void); +static int save_params(void); +static void apply_param(uint8_t idx); + +/* ======================== 公开函数 ======================== */ + +/* + * 函数功能:菜单系统初始化 + * 入口参数:无 + * 返回值:无 + * 函数说明:从EEPROM加载参数,清屏,绘制初始界面 + */ +void menu_init(void) +{ + lcd_draw_string(0, 0, "Menu Loading...", COLOR_WHITE, COLOR_BLACK); + load_params(); + s_sel = 0; + s_editing = 0; + s_redraw = 1; + apply_param(PARAM_PWM1); + apply_param(PARAM_PWM2); + apply_param(PARAM_PWM3); + apply_param(PARAM_PWM4); + st7735s_fill_screen(COLOR_BLACK); + draw_menu(); +} + +/* + * 函数功能:菜单系统循环处理 + * 入口参数:无 + * 返回值:无 + * 函数说明:轮询按键事件,更新参数/界面。需在主循环中频繁调用 + */ +void menu_process(void) +{ + ButtonEvent evt; + uint8_t i; + int32_t *p_val; + + /* 依次检查5个按键的事件 */ + for (i = 0; i < 5; i++) { + evt = button_driver_get_event(i); + if (evt == BTN_NONE_PRESS) { + continue; + } + + if (evt == BTN_SINGLE_CLICK) { + switch (i) { + case 0: /* KEY1: 上移 */ + if (!s_editing) { + if (s_sel > 0) { + s_sel--; + } else { + s_sel = PARAM_COUNT - 1; + } + s_redraw = 1; + } + break; + + case 1: /* KEY2: 减小 */ + p_val = &s_param_val[s_sel]; + *p_val -= s_param_def[s_sel].step; + if (*p_val < s_param_def[s_sel].min) { + *p_val = s_param_def[s_sel].min; + } + s_editing = 1; + s_redraw = 1; + apply_param(s_sel); + break; + + case 2: /* KEY3: 下移 */ + if (!s_editing) { + s_sel++; + if (s_sel >= PARAM_COUNT) { + s_sel = 0; + } + s_redraw = 1; + } + break; + + case 3: /* KEY4: 增大 */ + p_val = &s_param_val[s_sel]; + *p_val += s_param_def[s_sel].step; + if (*p_val > s_param_def[s_sel].max) { + *p_val = s_param_def[s_sel].max; + } + s_editing = 1; + s_redraw = 1; + apply_param(s_sel); + break; + + case 4: /* KEY5: 确认保存 */ + if (save_params() == AT24C02_OK) { + lcd_draw_string(0, 80, "SAVED! ", COLOR_GREEN, COLOR_BLACK); + printf("Menu: params saved\r\n"); + } else { + lcd_draw_string(0, 80, "SAVE FAIL! ", COLOR_RED, COLOR_BLACK); + printf("Menu: params save FAIL\r\n"); + } + s_editing = 0; + s_redraw = 1; + break; + + default: + break; + } + } + + /* 只处理一个按键事件每帧 */ + break; + } + + if (s_redraw) { + draw_menu(); + s_redraw = 0; + } +} + +/* + * 函数功能:获取指定参数的当前值 + * 入口参数:id - 参数ID + * 返回值:参数值 + */ +int32_t menu_get_param(ParamId_t id) +{ + if (id >= PARAM_COUNT) { + return 0; + } + return s_param_val[id]; +} + +/* + * 函数功能:强制保存参数到EEPROM + * 入口参数:无 + * 返回值:0=成功,负值=失败 + */ +int menu_save_params(void) +{ + return save_params(); +} + +/* ======================== 内部函数 ======================== */ + +/* + * 函数功能:从EEPROM加载参数 + * 入口参数:无 + * 返回值:无 + * 函数说明:读取EEPROM中存储的参数值,若Magic不对则使用默认值 + */ +static void load_params(void) +{ + uint8_t magic_buf[2]; + uint8_t data_buf[PARAM_COUNT * 4]; + int ret; + uint8_t i; + + /* 先读取Magic */ + ret = at24c02_read_buf(EEPROM_MAGIC_ADDR, magic_buf, 2); + if ((ret != AT24C02_OK) || + (magic_buf[0] != ((EEPROM_MAGIC >> 8) & 0xFF)) || + (magic_buf[1] != (EEPROM_MAGIC & 0xFF))) { + /* Magic不匹配:使用默认值 */ + for (i = 0; i < PARAM_COUNT; i++) { + s_param_val[i] = s_param_def[i].default_val; + } + printf("Menu: using defaults (no saved data)\r\n"); + return; + } + + /* 读取参数数据 */ + ret = at24c02_read_buf(EEPROM_DATA_ADDR, data_buf, PARAM_COUNT * 4); + if (ret != AT24C02_OK) { + for (i = 0; i < PARAM_COUNT; i++) { + s_param_val[i] = s_param_def[i].default_val; + } + printf("Menu: EEPROM read fail, using defaults\r\n"); + return; + } + + /* 解析数据(小端:低字节在前) */ + for (i = 0; i < PARAM_COUNT; i++) { + s_param_val[i] = (int32_t)( + (uint32_t)data_buf[i * 4 + 0] | + ((uint32_t)data_buf[i * 4 + 1] << 8) | + ((uint32_t)data_buf[i * 4 + 2] << 16) | + ((uint32_t)data_buf[i * 4 + 3] << 24)); + /* 钳位到有效范围 */ + if (s_param_val[i] < s_param_def[i].min) { + s_param_val[i] = s_param_def[i].min; + } + if (s_param_val[i] > s_param_def[i].max) { + s_param_val[i] = s_param_def[i].max; + } + } + + printf("Menu: params loaded from EEPROM\r\n"); +} + +/* + * 函数功能:保存参数到EEPROM + * 入口参数:无 + * 返回值:0=成功,负值=失败 + * 函数说明:先写Magic标识,再写参数数据 + */ +static int save_params(void) +{ + uint8_t magic_buf[2]; + uint8_t data_buf[PARAM_COUNT * 4]; + uint8_t i; + int ret; + + /* 打包Magic */ + magic_buf[0] = (EEPROM_MAGIC >> 8) & 0xFF; + magic_buf[1] = EEPROM_MAGIC & 0xFF; + + /* 打包参数(小端) */ + for (i = 0; i < PARAM_COUNT; i++) { + data_buf[i * 4 + 0] = (uint8_t)(s_param_val[i] & 0xFF); + data_buf[i * 4 + 1] = (uint8_t)((s_param_val[i] >> 8) & 0xFF); + data_buf[i * 4 + 2] = (uint8_t)((s_param_val[i] >> 16) & 0xFF); + data_buf[i * 4 + 3] = (uint8_t)((s_param_val[i] >> 24) & 0xFF); + } + + /* 写入EEPROM */ + ret = at24c02_write_buf(EEPROM_MAGIC_ADDR, magic_buf, 2); + if (ret != AT24C02_OK) { + return ret; + } + ret = at24c02_write_buf(EEPROM_DATA_ADDR, data_buf, PARAM_COUNT * 4); + if (ret != AT24C02_OK) { + return ret; + } + + return AT24C02_OK; +} + +/* + * 函数功能:将指定参数立即应用到对应PWM通道 + * 入口参数:idx - 参数索引 (0=PWM1, 1=PWM2, 2=PWM3, 3=PWM4) + * 返回值:无 + */ +static void apply_param(uint8_t idx) +{ + uint32_t duty = (uint32_t)s_param_val[idx]; + static const uint16_t ch_map[4] = { + TIM_CHANNEL_1, TIM_CHANNEL_2, TIM_CHANNEL_3, TIM_CHANNEL_4 + }; + + if (idx < PARAM_COUNT) { + __HAL_TIM_SET_COMPARE(&htim3, ch_map[idx], duty); + printf("PWM%d duty=%lu\r\n", idx + 1, (unsigned long)duty); + } +} + +/* + * 函数功能:绘制菜单界面 + * 入口参数:无 + * 返回值:无 + * 函数说明:清空参数区域,重新绘制所有参数行 + */ +static void draw_menu(void) +{ + char buf[24]; + uint8_t i; + uint16_t color; + + /* 绘制标题行 */ + + lcd_draw_string(0, 0, "-- PARAM MENU --", COLOR_CYAN, COLOR_BLACK); + + /* 绘制各参数(每行16像素,从y=16开始) */ + for (i = 0; i < PARAM_COUNT; i++) { + if (i == s_sel) { + if (s_editing) { + /* 编辑态:高亮 + 左右尖括号 */ + snprintf(buf, sizeof(buf), ">%s:%ld %s< ", + s_param_def[i].name, + (long)s_param_val[i], + s_param_def[i].unit); + color = COLOR_YELLOW; + } else { + /* 选中态:箭头 + 高亮 */ + snprintf(buf, sizeof(buf), ">%s:%ld %s ", + s_param_def[i].name, + (long)s_param_val[i], + s_param_def[i].unit); + color = COLOR_WHITE; + } + } else { + /* 未选中:普通显示 */ + snprintf(buf, sizeof(buf), " %s:%ld %s ", + s_param_def[i].name, + (long)s_param_val[i], + s_param_def[i].unit); + color = COLOR_GRAY; + } + /* 填充整行背景以覆盖之前内容 */ + lcd_draw_string(0, 16 + i * 16, buf, color, COLOR_BLACK); + } + + /* 底部提示 */ + if (s_editing) { + lcd_draw_string_6x8(0, 140, "KEY5:SAVE ", COLOR_GREEN, COLOR_BLACK); + } else { + lcd_draw_string_6x8(0, 140, "K1/K3:Sel K2/K4:Adj", COLOR_GRAY, COLOR_BLACK); + } +} diff --git a/STM32F103C8T6/User/menu.h b/STM32F103C8T6/User/menu.h new file mode 100644 index 0000000..a00c7c6 --- /dev/null +++ b/STM32F103C8T6/User/menu.h @@ -0,0 +1,55 @@ +#ifndef __MENU_H +#define __MENU_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "main.h" + +/* 参数数量 */ +#define PARAM_COUNT 4 + +/* 参数ID枚举 */ +typedef enum { + PARAM_PWM1 = 0, /* PA6 TIM3_CH1 */ + PARAM_PWM2, /* PA7 TIM3_CH2 */ + PARAM_PWM3, /* PB0 TIM3_CH3 */ + PARAM_PWM4, /* PB1 TIM3_CH4 */ +} ParamId_t; + +/* + * 函数功能:菜单系统初始化 + * 入口参数:无 + * 返回值:无 + * 函数说明:从EEPROM加载参数,清屏,绘制初始界面 + */ +void menu_init(void); + +/* + * 函数功能:菜单系统循环处理 + * 入口参数:无 + * 返回值:无 + * 函数说明:轮询按键事件,更新参数/界面。需在主循环中频繁调用 + */ +void menu_process(void); + +/* + * 函数功能:获取指定参数的当前值 + * 入口参数:id - 参数ID + * 返回值:参数值 + */ +int32_t menu_get_param(ParamId_t id); + +/* + * 函数功能:强制保存参数到EEPROM + * 入口参数:无 + * 返回值:0=成功,负值=失败 + */ +int menu_save_params(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __MENU_H */ diff --git a/tools/font_gen.py b/tools/font_gen.py index ede0ffb..f43c7f3 100644 --- a/tools/font_gen.py +++ b/tools/font_gen.py @@ -1,14 +1,10 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ -STM32 ST7735S LCD 字模生成工具(Pillow 版) -- ASCII 8×16:生成 lcd_data.c -- CJK 16×16:生成 hz16_data.c + hz16_data.h(含二分查找函数) +STM32 ST7735S LCD CJK 字模生成工具(Pillow 版) +生成 hz16_data.c + hz16_data.h(含二分查找函数) 用法: - # ASCII - python font_gen.py --font simsun --size 56 --threshold 64 - # CJK 常用汉字(GB2312 一级,约 3755 字) python font_gen.py --cjk --font simsun --size 32 --threshold 64 @@ -19,7 +15,6 @@ STM32 ST7735S LCD 字模生成工具(Pillow 版) import os import sys import argparse -import struct try: from PIL import Image, ImageFont, ImageDraw @@ -27,12 +22,44 @@ except ImportError: print("请安装 Pillow: pip install Pillow", file=sys.stderr) sys.exit(1) +# ── Otsu 自适应阈值 ── + +def otsu_threshold(pixels: list) -> int: + """Otsu 算法自动计算最佳二值化阈值""" + hist = [0] * 256 + for v in pixels: + hist[v] += 1 + total = len(pixels) + sum_all = sum(i * hist[i] for i in range(256)) + sum_bg = 0 + w_bg = 0 + w_fg = 0 + max_var = 0 + best = 128 + for t in range(256): + w_bg += hist[t] + if w_bg == 0: + continue + w_fg = total - w_bg + if w_fg == 0: + break + sum_bg += t * hist[t] + mean_bg = sum_bg / w_bg + mean_fg = (sum_all - sum_bg) / w_fg + between_var = w_bg * w_fg * (mean_bg - mean_fg) * (mean_bg - mean_fg) + if between_var > max_var: + max_var = between_var + best = t + return best + + # ── 通用渲染 ── def render_char(font, char: str, w: int, h: int, scale: int = 1, - threshold: int = 64) -> list: + threshold: int = None) -> list: """ 在 w*scale × h*scale 画布上渲染字符,缩放到 w×h + threshold=None 时自动使用 Otsu 算法 返回逐行字节列表(MSB 优先) """ bw, bh = w * scale, h * scale @@ -42,13 +69,20 @@ def render_char(font, char: str, w: int, h: int, scale: int = 1, bbox = draw.textbbox((0, 0), char, font=font) tw = bbox[2] - bbox[0] th = bbox[3] - bbox[1] - cx = (bw - tw) // 2 - bbox[0] - cy = (bh - th) // 2 - bbox[1] + + # 防止 bbox[0]/bbox[1] 为负导致偏移错误 + left = bbox[0] if bbox[0] > 0 else 0 + top = bbox[1] if bbox[1] > 0 else 0 + cx = (bw - tw) // 2 - left + cy = (bh - th) // 2 - top draw.text((cx, cy), char, font=font, fill=255) small = img.resize((w, h), Image.LANCZOS) pixels = list(small.getdata()) + if threshold is None: + threshold = otsu_threshold(pixels) + bytes_per_row = (w + 7) // 8 result = [] for r in range(h): @@ -62,57 +96,6 @@ def render_char(font, char: str, w: int, h: int, scale: int = 1, return result -# ── ASCII 8×16 ── - -def generate_ascii(output_path: str, font_path: str, size: int, - threshold: int, scale: int = 4): - font = ImageFont.truetype(font_path, size) - chars = list(range(32, 127)) - N = len(chars) - - lines = [ - '#include "lcd_data.h"', - '/*ASCII字模数据*********************/', - '', - '/*宽8像素,高16像素*/', - f'/* 字体: {os.path.basename(font_path)}, 字号: {size}, 阈值: {threshold} */', - 'const uint8_t LCD_F8x16[][16] =', - '{', - ] - - for idx, ch in enumerate(chars): - if ch == ord('_'): - bitmap = [0x00] * 15 + [0x7F] - else: - bitmap = render_char(font, chr(ch), 8, 16, scale, threshold) - - show = chr(ch) if 32 <= ch <= 126 else '?' - comma = ',' if idx < N - 1 else '' - line1 = ', '.join(f'0x{b:02X}' for b in bitmap[:8]) - line2 = ', '.join(f'0x{b:02X}' for b in bitmap[8:]) - lines.append(f' {line1},') - lines.append(f' {line2}{comma} // {show} {idx}') - if (idx + 1) % 10 == 0: - print(f" ASCII 进度: {idx+1}/{N}") - - lines.append('};') - lines.append('') - lines.append('/*宽6像素,高8像素(未使用)*/') - lines.append('const uint8_t LCD_F6x8[][6] =') - lines.append('{') - for idx, ch in enumerate(chars): - show = chr(ch) if 32 <= ch <= 126 else '?' - comma = ',' if idx < N - 1 else '' - lines.append(f' 0x00,0x00,0x00,0x00,0x00,0x00{comma} // {show} {idx}') - lines.append('};') - lines.append('') - - content = '\n'.join(lines) - with open(output_path, 'w', encoding='utf-8', newline='\n') as f: - f.write(content) - print(f"已生成 ASCII 字模: {output_path}") - - # ── CJK 16×16 ── CJK_W, CJK_H = 16, 16 @@ -344,50 +327,42 @@ def _resolve_font(name_or_path: str) -> str: def main(): - p = argparse.ArgumentParser(description='字模生成工具') + p = argparse.ArgumentParser(description='CJK 字模生成工具') p.add_argument('--font', default='simsun', help='字体名称或路径') - p.add_argument('--size', type=int, default=64, help='渲染字号') - p.add_argument('--threshold', type=int, default=50, help='二值化阈值(默认50)') - p.add_argument('--scale', type=int, default=4, help='缩放倍率') - - g = p.add_argument_group('ASCII 8×16') - g.add_argument('--ascii', action='store_true', help='生成 ASCII 字模(默认)') - - g = p.add_argument_group('CJK 16×16') - g.add_argument('--cjk', action='store_true', help='生成 CJK 汉字字模') - g.add_argument('--common', action='store_true', help='CJK:仅常用汉字(GB2312 一级)') - g.add_argument('--gb2312', action='store_true', help='CJK:GB2312 全部汉字') - g.add_argument('--punct', action='store_true', help='CJK:加入中文标点/全角字符') - g.add_argument('--string', type=str, default=None, help='CJK:仅生成指定字符串中的字符(节省空间)') - g.add_argument('--output', '-o', default=None, help='CJK 输出基名(不含扩展名)') + p.add_argument('--size', type=int, default=None, help='渲染字号') + p.add_argument('--threshold', type=int, default=None, help='二值化阈值(默认 Otsu 自适应)') + p.add_argument('--scale', type=int, default=None, help='缩放倍率(越大边缘越平滑)') + p.add_argument('--cjk', action='store_true', help='生成 CJK 汉字字模(必须指定)') + p.add_argument('--common', action='store_true', help='CJK:仅常用汉字(GB2312 一级)') + p.add_argument('--gb2312', action='store_true', help='CJK:GB2312 全部汉字') + p.add_argument('--punct', action='store_true', help='CJK:加入中文标点/全角字符') + p.add_argument('--string', type=str, default=None, help='CJK:仅生成指定字符串中的字符(节省空间)') + p.add_argument('--output', '-o', default=None, help='CJK 输出基名(不含扩展名)') args = p.parse_args() font_path = _resolve_font(args.font) print(f"字体: {font_path}") + if not args.cjk: + print("请指定 --cjk 来生成 CJK 字库,ASCII 字库已不再由此工具生成") + return + proj_dir = os.path.abspath(os.path.join( os.path.dirname(__file__), '..', 'STM32F103C8T6', 'Drivers', 'BSP', 'LCD')) - if args.cjk: - size = args.size or 48 - scale = args.scale or 3 - out_base = args.output or os.path.join(proj_dir, 'hz16_data') + size = args.size if args.size is not None else 48 + scale = args.scale if args.scale is not None else 3 + out_base = args.output or os.path.join(proj_dir, 'hz16_data') - if args.string is not None: - unicodes = sorted(set(ord(c) for c in args.string)) - generate_cjk_direct(out_base, font_path, size, args.threshold, scale, unicodes) - else: - generate_cjk(out_base, font_path, size, args.threshold, scale, - mode='common' if args.common else ('gb2312' if args.gb2312 else 'common'), - punct=args.punct) + if args.string is not None: + unicodes = sorted(set(ord(c) for c in args.string)) + generate_cjk_direct(out_base, font_path, size, args.threshold, scale, unicodes) else: - # 默认 ASCII - size = args.size or 56 - scale = args.scale or 4 - out = os.path.join(proj_dir, 'lcd_data.c') - generate_ascii(out, font_path, size, args.threshold, scale) + generate_cjk(out_base, font_path, size, args.threshold, scale, + mode='common' if args.common else ('gb2312' if args.gb2312 else 'common'), + punct=args.punct) if __name__ == '__main__':