From 3dcc2f8f208acbc3e86654763e09677d3a65b482 Mon Sep 17 00:00:00 2001 From: JiXieShi Date: Sun, 23 Jun 2024 18:03:57 +0800 Subject: [PATCH] =?UTF-8?q?UP=20=E5=AD=97=E5=BA=93=E7=94=9F=E6=88=90?= =?UTF-8?q?=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 +- demo/oled/test.c | 14 ++++-- lib/inc/oled/oled.h | 12 +++++ lib/inc/oled/oled_font.h | 13 ++--- lib/inc/oled/oled_font_chuc.h | 46 ++++++++++++++++++ lib/inc/utils/tool.h | 2 +- lib/src/oled/oled.cpp | 49 ++++++++++++++++--- lib/src/utils/tool.cpp | 11 +++++ tools/unicode_ch_gen.py | 90 +++++++++++++++++++++++++++++++++++ 9 files changed, 218 insertions(+), 22 deletions(-) create mode 100644 lib/inc/oled/oled_font_chuc.h create mode 100644 tools/unicode_ch_gen.py diff --git a/.gitignore b/.gitignore index ae6b19c..fcac95d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /cmake-build-debug/ -/.idea/ \ No newline at end of file +/.idea/ +/.venv/ diff --git a/demo/oled/test.c b/demo/oled/test.c index 9b37147..2288c26 100644 --- a/demo/oled/test.c +++ b/demo/oled/test.c @@ -106,19 +106,23 @@ OLED_T oled = { void Test_OLED() { SIM_OLED_INIT(128, 64, CYAN, 0x0, 5, 0); + SIM_OLED_START(); + OLED_Init(&oled); OLED_CLS(&oled); -// OLED_DrawRect(&oled, 0, 0, 127, 63); - mainpage(&oled); + OLED_DrawRect(&oled, 0, 0, 127, 63); - SIM_OLED_START(); int s = 0; - char buf[30]; + char buf[30] = {0x5B, 0x57, 0x5E, 0x93, 0x75, 0x1F, 0x62, 0x10, 0x6D, 0x4B, 0x8B, 0xD5}; + OLED_ShowCHString(&oled, 15, 16, buf, 16); + OLED_Refresh(&oled); + _beginthread(Get_Key, 0, NULL); pageinit(); + Sleep(5000); while (1) { if (pageid > 3)pageid = 0; - pagesearch(pageid).page(&oled); +// pagesearch(pageid).page(&oled); // sprintf(buf, "DATA:%d", s); // OLED_ShowString(&oled, 2, 51, buf, 12); OLED_Refresh(&oled); diff --git a/lib/inc/oled/oled.h b/lib/inc/oled/oled.h index 47f81e5..9352cba 100644 --- a/lib/inc/oled/oled.h +++ b/lib/inc/oled/oled.h @@ -213,6 +213,18 @@ void OLED_ShowChar(OLED_T *dev, uint8_t x, uint8_t y, uint8_t chr, uint8_t size1 */ void OLED_ShowString(OLED_T *dev, uint8_t x, uint8_t y, uint8_t *chr, uint8_t size1); +/** + * @brief 在OLED上显示指定大小的中文字符串 + * @param dev: [输入] OLED设备指针 + * @param x: [输入] X坐标 + * @param y: [输入] Y坐标 + * @param str: [输入] 中文字符串指针 + * @param size: [输入] 字体大小 + * @return void + * @example OLED_ShowCHString(&oled_device, 0, 0, chinese_str, 16); + **/ +void OLED_ShowCHString(OLED_T *dev, uint8_t x, uint8_t y, uint8_t *str, uint8_t size); + /** * @brief 在OLED屏幕上显示数字 * @param dev: [输入] OLED设备指针 diff --git a/lib/inc/oled/oled_font.h b/lib/inc/oled/oled_font.h index 21b170b..355652f 100644 --- a/lib/inc/oled/oled_font.h +++ b/lib/inc/oled/oled_font.h @@ -1,12 +1,7 @@ #ifndef HW_LIB_OLED_FONT_H #define HW_LIB_OLED_FONT_H -//常用ASCII表 -//偏移量32 -//ASCII字符集 -//偏移量32 -//大小:12*6 -/************************************6*8的点阵************************************/ -//12*12 ASCII字符集点阵 + +//12*6 ASCII字符集点阵 const unsigned char asc2_1206[95][12] = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},/*" ",0*/ {0x00, 0x00, 0x00, 0x00, 0x3F, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},/*"!",1*/ @@ -104,7 +99,7 @@ const unsigned char asc2_1206[95][12] = { {0x00, 0x00, 0x40, 0x20, 0x7B, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00},/*"}",93*/ {0x40, 0x00, 0x80, 0x00, 0x40, 0x00, 0x20, 0x00, 0x20, 0x00, 0x40, 0x00},/*"~",94*/ }; -//16*16 ASCII字符集点阵 +//16*8 ASCII字符集点阵 const unsigned char asc2_1608[95][16] = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},/*" ",0*/ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xCC, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},/*"!",1*/ @@ -202,7 +197,7 @@ const unsigned char asc2_1608[95][16] = { {0x00, 0x00, 0x40, 0x02, 0x40, 0x02, 0x3E, 0xFC, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},/*"}",93*/ {0x00, 0x00, 0x60, 0x00, 0x80, 0x00, 0x80, 0x00, 0x40, 0x00, 0x40, 0x00, 0x20, 0x00, 0x20, 0x00},/*"~",94*/ }; -//24*24 ASICII字符集点阵 +//24*12 ASICII字符集点阵 const unsigned char asc2_2412[95][36] = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},/*" ",0*/ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x38, 0x0F, 0xFE, 0x38, 0x0F, 0x80, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},/*"!",1*/ diff --git a/lib/inc/oled/oled_font_chuc.h b/lib/inc/oled/oled_font_chuc.h new file mode 100644 index 0000000..9d52911 --- /dev/null +++ b/lib/inc/oled/oled_font_chuc.h @@ -0,0 +1,46 @@ +#ifndef HW_LIB_OLED_FONT_CHUC_H +#define HW_LIB_OLED_FONT_CHUC_H +typedef struct { + uint8_t name[3]; + uint8_t data[32]; +} Chinese_t; + +Chinese_t Hzk[] = { + { + // Original: 字 + {0x5B, 0x57}, + {0x10, 0x0C, 0x04, 0x24, 0x24, 0x24, 0x25, 0x26, 0xA4, 0x64, 0x24, 0x04, 0x04, 0x14, 0x0C, 0x00, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x42, 0x82, 0x7F, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00 + }}, + { + // Original: 库 + {0x5E, 0x93}, + {0x00, 0x00, 0xFC, 0x24, 0x24, 0xA4, 0x64, 0x3D, 0xA6, 0x24, 0x24, 0x24, 0x24, 0x24, 0x04, 0x00, + 0x40, 0x30, 0x0F, 0x10, 0x13, 0x12, 0x12, 0x12, 0xFF, 0x12, 0x12, 0x12, 0x12, 0x10, 0x10, 0x00 + }}, + { + // Original: 生 + {0x75, 0x1F}, + {0x80, 0x40, 0x30, 0x1E, 0x10, 0x10, 0x10, 0xFF, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, + 0x40, 0x40, 0x42, 0x42, 0x42, 0x42, 0x42, 0x7F, 0x42, 0x42, 0x42, 0x42, 0x42, 0x40, 0x40, 0x00 + }}, + { + // Original: 成 + {0x62, 0x10}, + {0x00, 0x00, 0xF8, 0x88, 0x88, 0x88, 0x88, 0x08, 0x08, 0xFF, 0x08, 0x09, 0x0A, 0xC8, 0x08, 0x00, + 0x80, 0x60, 0x1F, 0x00, 0x10, 0x20, 0x1F, 0x80, 0x40, 0x21, 0x16, 0x18, 0x26, 0x41, 0xF8, 0x00 + }}, + { + // Original: 测 + {0x6D, 0x4B}, + {0x10, 0x60, 0x02, 0x8C, 0x00, 0xFE, 0x02, 0xF2, 0x02, 0xFE, 0x00, 0xF8, 0x00, 0xFF, 0x00, 0x00, + 0x04, 0x04, 0x7E, 0x01, 0x80, 0x47, 0x30, 0x0F, 0x10, 0x27, 0x00, 0x47, 0x80, 0x7F, 0x00, 0x00 + }}, + { + // Original: 试 + {0x8B, 0xD5}, + {0x40, 0x40, 0x42, 0xCC, 0x00, 0x90, 0x90, 0x90, 0x90, 0x90, 0xFF, 0x10, 0x11, 0x16, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x3F, 0x10, 0x28, 0x60, 0x3F, 0x10, 0x10, 0x01, 0x0E, 0x30, 0x40, 0xF0, 0x00 + }}, +}; +#endif //HW_LIB_OLED_FONT_CHUC_H diff --git a/lib/inc/utils/tool.h b/lib/inc/utils/tool.h index 0b3c6ac..d96778c 100644 --- a/lib/inc/utils/tool.h +++ b/lib/inc/utils/tool.h @@ -153,7 +153,7 @@ double :"[double]-> "#v"=%.2f" END, \ default: "[err]-> "#v"=%p" END) #define POUT(s) printf(TYPE_F(s) ,s) - +#define GET_BIT(x, bit) ((x & (1 << bit)) >> bit) #ifdef __cplusplus } diff --git a/lib/src/oled/oled.cpp b/lib/src/oled/oled.cpp index 88d39f4..aa39040 100644 --- a/lib/src/oled/oled.cpp +++ b/lib/src/oled/oled.cpp @@ -1,7 +1,9 @@ #include "oled.h" #include "oled_font.h" +#include "oled_font_chuc.h" #define BUFPOINT(x, y) (*(dev->buf + x + (y * dev->width))) +#define GET_BIT(x, bit) ((x & (1 << bit)) >> bit) const uint8_t initCmd[] = { 0xAE, // 关闭显示 @@ -104,6 +106,16 @@ void OLED_Set(OLED_T *dev, uint8_t x, uint8_t y) { BUFPOINT(x, i) |= n; } +void OLED_BSet(OLED_T *dev, uint8_t x, uint8_t y, uint8_t data) { + uint8_t i, ys = y; + for (i = 0; i < 8; i++) //写入数据 + { + if (GET_BIT(data, i))OLED_Set(dev, x, ys); + else OLED_RSet(dev, x, ys); + ys++; + } +} + void OLED_RSet(OLED_T *dev, uint8_t x, uint8_t y) { uint8_t i, m, n; i = y / 8; @@ -171,7 +183,7 @@ void OLED_DrawCircle(OLED_T *dev, uint8_t x, uint8_t y, uint8_t r) { void OLED_ShowChar(OLED_T *dev, uint8_t x, uint8_t y, uint8_t chr, uint8_t size1) { uint8_t i, m, temp, size2, chr1; - uint8_t y0 = y; + uint8_t ys = y; size2 = (size1 / 8 + ((size1 % 8) ? 1 : 0)) * (size1 / 2); //得到字体一个字符对应点阵集所占的字节数 chr1 = chr - ' '; //计算偏移后的值 for (i = 0; i < size2; i++) { @@ -181,12 +193,12 @@ void OLED_ShowChar(OLED_T *dev, uint8_t x, uint8_t y, uint8_t chr, uint8_t size1 else return; for (m = 0; m < 8; m++) //写入数据 { - if (temp & 0x80)OLED_Set(dev, x, y); - else OLED_RSet(dev, x, y); + if (temp & 0x80)OLED_Set(dev, x, ys); + else OLED_RSet(dev, x, ys); temp <<= 1; - y++; - if ((y - y0) == size1) { - y = y0; + ys++; + if ((ys - y) == size1) { + ys = y; x++; break; } @@ -208,6 +220,30 @@ void OLED_ShowString(OLED_T *dev, uint8_t x, uint8_t y, uint8_t *chr, uint8_t si } } +void OLED_ShowCHString(OLED_T *dev, uint8_t x, uint8_t y, uint8_t *str, uint8_t size) { + uint8_t i, temp, size2, ys = y, xs = x; + uint16_t index; + size2 = (size / 8 + ((size % 8) ? 1 : 0)) * (size); //得到字体一个字符对应点阵集所占的字节数 + while (*str) { + for (index = 0; index < sizeof(Hzk) / 35; index++) { + if (Hzk[index].name[0] == str[0] && Hzk[index].name[1] == str[1])//对比汉字区码位码 + { + for (i = 0; i < size2; i++) { + temp = Hzk[index].data[i]; + OLED_BSet(dev, xs + (i % size), ys, temp); + if (i == size2 / 2)ys += size / 2; + } + xs += size; + ys = y; + str++; + str++; + } else { + return; + } + } + } +} + uint32_t OLED_Pow(uint8_t m, uint8_t n) { uint32_t result = 1; while (n--) { @@ -237,6 +273,7 @@ void OLED_ShowPic(OLED_T *dev, uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, u dev->data(bmp + y * (x1 - x0), x1 - x0); } } + void OLED_Fill(OLED_T *dev, uint8_t data) { uint8_t x, y; for (y = 0; y < (dev->height >> 3); y++) { diff --git a/lib/src/utils/tool.cpp b/lib/src/utils/tool.cpp index 96cc927..81d3f74 100644 --- a/lib/src/utils/tool.cpp +++ b/lib/src/utils/tool.cpp @@ -3,6 +3,7 @@ // #include #include +#include #include "tool.h" float Mapping(float val, float I_Min, float I_Max, float O_Min, float O_Max) { @@ -45,6 +46,16 @@ void BufPrint(char *name, void *buf, Type_t type, unsigned int len, unsigned cha printf("\n"); } +uint8_t UTF8ToUnicode(uint8_t *dataArea, uint8_t dataAreaLength, uint8_t *uniDA) { + uint8_t len = dataAreaLength * 2 / 3; +// uint8_t uniDA[len]; + for (int i = 0; i < dataAreaLength / 3; i++) { + uniDA[i * 2] = ((dataArea[i * 3] & 0xF) << 4) + ((dataArea[i * 3 + 1] >> 2) & 0xF); + uniDA[i * 2 + 1] = ((dataArea[i * 3 + 1] & 0x3) << 6) + (dataArea[i * 3 + 2] & 0x3F); + } + return len; +} + float Str2Float(char *str) { int integer = 0; double decimal = 0; diff --git a/tools/unicode_ch_gen.py b/tools/unicode_ch_gen.py new file mode 100644 index 0000000..6447a64 --- /dev/null +++ b/tools/unicode_ch_gen.py @@ -0,0 +1,90 @@ +import numpy as np +import PIL.ImageFont as pilfont +import PIL.Image as pilimage +import PIL.ImageDraw as pildraw + + +def generate_chinese_struct(char_code, font, size): + image = pilimage.new('L', size) + draw = pildraw.Draw(image) + draw.text((0, 0), char_code, font=font, fill=255) + pixel_array = np.array(image) + result = np.zeros(size[0] * size[1] // 8, dtype=np.uint8) + for i in range(size[1]): + for j in range(size[0] // 8): + for k in range(8): + if pixel_array[j * 8 + k, i]: + result[j * size[1] + i] |= (1 << k) + return result + + +def generate_chinese_array(input_str, font_str, size): + font = pilfont.truetype(font_str, size=size[1]) + chinese_array = [] + for char_code in input_str: + char_struct = generate_chinese_struct(char_code, font, size) + chinese_array.append({'name': char_code, 'data': char_struct}) + return chinese_array + + +def format_chinese_array_as_text(chinese_array, size): + text_output = "#pragma pack(1)\n\n" + text_output += f"typedef struct {{\n" + text_output += " uint8_t unicode[2];\n" + text_output += f" uint8_t data[{size[0] * size[1] // 8}];\n" + text_output += "} Chinese_t;\n\n" + text_output += f"uint8_t Hzk_size={size[0]};\n\n" + text_output += "Chinese_t Hzk[] = {\n" + line_size = size[0] * size[1] // 8 + line_size = line_size // 2 + # line_size = 16 if line_size >= 16 else 8 + for item in chinese_array: + unicode_hex = ', '.join(f"0x{ord(char) >> 8:02X}, 0x{ord(char) & 0xFF:02X}" for char in item['name']) + text_output += f" {{\n // Original: {item['name']}\n" + text_output += f" {{ {unicode_hex} }},\n {{\n " + bytes_str = ', '.join(f"0x{byte:02X}" for byte in item['data']) + bytes_lines = [bytes_str[i:i + 6 * line_size] for i in range(0, len(bytes_str), 6 * line_size)] + # 每行显示line_size个字节 + text_output += '\n '.join(bytes_lines) + text_output += ",\n }\n },\n" + text_output += "};\n\n" + text_output += "Chinese_t* find_chinese_data(uint8_t unicode_high, uint8_t unicode_low) {\n" + text_output += " for (int i = 0; i < sizeof(Hzk) / sizeof(Chinese_t); ++i) {\n" + text_output += " if (Hzk[i].unicode[0] == unicode_high && Hzk[i].unicode[1] == unicode_low) {\n" + text_output += " return &Hzk[i];\n" + text_output += " }\n" + text_output += " }\n" + text_output += " return NULL;\n" + text_output += "}\n" + return text_output + + +def generate_and_write_chinese_array_output(): + # 生成包含汉字结构体的数组 + # simsun: 宋体 + # kaiti: 楷体 + # size = (20, 20) + # size = (20, 20) + size = (16, 16) + chinese_array = generate_chinese_array("字库生成测试", 'simsun', size) + + # 将数组格式化为文本输出并写入文件 + text_output = format_chinese_array_as_text(chinese_array, size) + with open('chinese_array_output.txt', 'w') as file: + file.write(text_output) + + +# 调用函数生成并写入汉字数组输出文件 +generate_and_write_chinese_array_output() + + +def generate_unicode_bin_file(): + font = pilfont.truetype('simsun', size=16) + with open('cao.bin', 'wb') as file: + for char_code in range(0x4e00, 0xa000): + result = generate_chinese_struct(chr(char_code), font) + file.write(result) + file.close() + +# 调用函数生成Unicode二进制文件 +# generate_unicode_bin_file()