当前位置: 首页 > news >正文

从0开始使用面对对象C语言搭建一个基于OLED的图形显示框架(基础组件实现)

目录

基础组件实现

如何将图像和文字显示到OLED上

如何绘制图像

如何绘制文字

如何获取字体?

如何正确的访问字体

如何抽象字体

如何绘制字符串

绘制方案

文本绘制

更加方便的绘制

字体附录

ascii 6x8字体

ascii 8 x 16字体


基础组件实现

我们现在离手搓一个动态的多级菜单越来越近了。终于!我们来到了最基础的组件实现,我们现在搓的东西的代码库放到了:MCU_Libs/OLED/library/Graphic/widgets/base at main · Charliechen114514/MCU_Libs (github.com)当中,也就是手搓图像显示和文字显示。如果你对这篇博客所属的集合有任何疑问,可以到从0开始使用面对对象C语言搭建一个基于OLED的图形显示框架-CSDN博客阅读。

如何将图像和文字显示到OLED上

三个字:画出来!带上一个KeysKing大跌手搓的取码地址:波特律动LED字模生成器 (baud-dance.com),实际上,你的悟性足够高,已经可以离开这篇博客自己继续手搓了。

好吧,你继续往下看了,那我就详细的好好说明。

如何绘制图像

绘制图像之前,我们还要遵循老步骤,思考一下如何设计我们的抽象。

我们如何描述一个给定的图像呢?我们可能着急于描述这个图像表达了什么,也就是图像的资源,在OLED中,我们习惯于阐述为一个字节的数组,这个数组描述了我们的图像,只要把它传递上去,一个图像就显示出来我们可以看了。

但是还是有问题:你这个图像放到哪里呢?画的要多大呢?这就是我们需要设计一个结构体抽象的原因了。请看VCR:

typedef struct __CCGraphic_Image{CCGraphic_Point point;CCGraphic_Size  image_size;uint8_t*        sources_register;
}CCGraphic_Image;

关于CCGraphic_Size,并不复杂,可以到MCU_Libs/OLED/library/Graphic/widgets/common/CCGraphic_Size at main · Charliechen114514/MCU_Libs (github.com)中看到源码,实际上就是宽和高的一个封装,没什么大不了的。

此外,我们对图像的操作就是绘制了

void CCGraphicWidget_init_image(CCGraphic_Image*    image,CCGraphic_Point     tl_point,CCGraphic_Size      image_size,uint8_t*      sources_register
);
​
void CCGraphicWidget_draw_image(CCDeviceHandler*    handler,CCGraphic_Image*    image
);

出乎你意料的是。绘制图像远远比你想象的简单的多

#include "Graphic/widgets/base/CCGraphic_Image/CCGraphic_Image.h"
#include "Graphic/CCGraphic_device_adapter.h"
void CCGraphicWidget_init_image(CCGraphic_Image*    image,CCGraphic_Point     tl_point,CCGraphic_Size      image_size,uint8_t*      sources_register
)
{image->image_size = image_size;image->point = tl_point;image->sources_register = sources_register;
}
​
void CCGraphicWidget_draw_image(CCDeviceHandler*    handler,CCGraphic_Image*    image
)
{if(!image->sources_register) return;handler->operations.draw_area_device_function(handler, image->point.x, image->point.y,image->image_size.width, image->image_size.height, image->sources_register);
}

我们直接使用设备draw_area的方法,将图像资源传递上去了。

CCGraphicWidget_draw_image -> draw_area_device_function(draw_area_device_oled) -> oled_helper_draw_area

你看,干净利落!完事。

如何绘制文字

现在这个事情就需要深思熟虑了,设计到文字,就必然需要考虑字体大小,以及解析字符串的问题。笔者这里没有实现UTF-8字符的打印实现,但是笔者提示你,仍然是画出来字符。让我们看看该咋做。

typedef struct __CCGraphic_TextHandle{char*               sources_borrowed;       // 这个就是所持有的字体资源指针CCGraphic_Point     tl_point;               // 这个是所占有的左上角的绘制起点CCGraphic_Point     indexed_point;          // 这个是现在的绘制指针,表明现在我们绘制到了那个地方CCGraphic_Size      TexthandleSize;         // 整个Text所在的BoundingRect大小Ascii_Font_Size     font_size;              // 字体多大?
}CCGraphic_AsciiTextItem;
如何获取字体?

关于ASCII字体的获取,笔者放到了附录里,值得一提的是,江科大的OLED_Data.h中对字体数组的初始化时不严谨的,不规范的,正确的初始化方案已经放到了附录,不再赘述。

如何正确的访问字体

C语言中,有一个著名的关键字叫extern,他随了汇编语言的关键字extern,在所属权层面上表达的同static完全相反,即这个资源的定义需要到其他文件中寻找。所以,当我们想要引用字体(这个字体被存放到了其他的C源文件中)的时候,只需要手动的extern一下,而且确保资源被正确的编译进来就OK了。

extern const uint8_t ascii6x8_sources[][6];
如何抽象字体

很简单,虽然说正常而言只需要抽象一个TextFont结构体即可,但是笔者认为这里更多看重的是方法,而且,没有必要对用户暴露一个Font结构体,选择结构体更加不如暴露的是一个枚举和公开的方法。

#ifndef CCGraphic_TextConfig_H
#define CCGraphic_TextConfig_H
#include "Graphic/config/CCGraphic_config.h"
#include "Graphic/CCGraphic_common.h"
#include "Graphic/widgets/common/CCGraphic_Size/CCGraphic_Size.h"
/*current version we only support6x8 and 8x16. to register more, u shouldprovide the source and implement the functions
*/
typedef enum {
#if ENABLE_ASCII_6x8_SOURCESASCII_6x8,
#endif
​
#if ENABLE_ASCII_8x16_SOURCESASCII_8x16,
#endifNO_ASCII_SIZE 
}Ascii_Font_Size;
​
typedef enum {Unicode_16x16
}Unicode_Font_Size;
​
#define UNSUPPORTIVE_FONT_SOURCE    ((void*)0)
​
/*** @brief Selects the font data array based on the specified font size.** This function receives an `Ascii_Font_Size` value * and returns a pointer to the corresponding font data array. * The function helps in selecting* the appropriate font data for display purposes, allowing for different* font sizes (e.g., 8x16, 6x8, etc.).** @param s The font size to be selected *          (from the `Ascii_Font_Size` enum).* @param ch the character wanna display* @return  A pointer to the font data array corresponding to the selected font size.*          If an invalid font size is passed, *          the function returns UNSUPPORTIVE_FONT_SOURCE.*/
uint8_t*        __select_from_ascii_font_size(const Ascii_Font_Size s, const char ch);
​
​
CCGraphic_Size  __fetch_font_size(const Ascii_Font_Size s);
​
#endif
#include "Graphic/widgets/base/CCGraphic_TextItem/CCGraphic_TextConfig.h"
​
extern const uint8_t ascii8x16_sources[][16];
extern const uint8_t ascii6x8_sources[][6];
​
uint8_t* __select_from_ascii_font_size(const Ascii_Font_Size s, const char ch)
{switch(s){
#if ENABLE_ASCII_6x8_SOURCEScase ASCII_6x8:return (uint8_t*)(ascii6x8_sources[ch - ' ']);
#endif
#if ENABLE_ASCII_8x16_SOURCES       case ASCII_8x16:return (uint8_t*)(ascii8x16_sources[ch - ' ']);
#endif/* To programmers, if new ascii like sources isregistered, please implement follows*/default:return UNSUPPORTIVE_FONT_SOURCE;}
}
​
CCGraphic_Size  __fetch_font_size(const Ascii_Font_Size s)
{CCGraphic_Size size = {0, 0};switch(s){
#if ENABLE_ASCII_6x8_SOURCEScase ASCII_6x8:size.height     =   8;size.width      =   6;break;
#endif
​
#if ENABLE_ASCII_8x16_SOURCES  case ASCII_8x16:size.height     =   16;size.width      =   8;break;
#endifdefault:break;}return size;
}

题外话:使用编译宏控制资源编译:GCC是一个智能的编译器,对于任何没有使用到的资源,概不参与编译,所以,对于使用GCC的编译器,只需要确保自己不额外使用其他资源,就不会将冗余的C符号纳入编译。

但还是那句话,为了确保语义更加清晰,仍然使用控制宏对资源进行编译控制和符号控制,让自己的代码语义更加的明确,是一件事半功倍的举措

如何绘制字符串

绘制字符串是一个复杂的活。但是在那之前,把杂活做了。

#include "Graphic/widgets/base/CCGraphic_TextItem/CCGraphic_TextItem.h"
#include "Graphic/widgets/base/CCGraphic_TextItem/CCGraphic_TextConfig.h"
#include "Graphic/widgets/base/CCGraphic_Image/CCGraphic_Image.h"
#include "Graphic/CCGraphic_device_adapter.h"
#include <string.h>
​
/*** 初始化一个ASCII文本项。* @param item 指向CCGraphic_AsciiTextItem的指针。* @param tl_point 文本项的左上角起始坐标。* @param textHandleSize 文本项的尺寸信息(宽度和高度)。* @param text_size 字体大小枚举类型。*/
void CCGraphicWidget_init_AsciiTextItem(CCGraphic_AsciiTextItem* item,CCGraphic_Point tl_point,CCGraphic_Size textHandleSize,Ascii_Font_Size text_size
)
{item->font_size = text_size;item->sources_borrowed = "";  // 初始化为空字符串,表示未设置内容。item->tl_point = tl_point;item->indexed_point = tl_point;item->TexthandleSize = textHandleSize;
}
​
/*** 设置ASCII文本项的内容。* @param item 指向CCGraphic_AsciiTextItem的指针。* @param text 待设置的文本内容字符串。*/
void CCGraphicWidget_AsciiTextItem_setAsciiText(CCGraphic_AsciiTextItem* item,char* text
)
{item->sources_borrowed = text;
}
​
/*** 设置ASCII文本项的索引点。* @param item 指向CCGraphic_AsciiTextItem的指针。* @param p 索引点的指针。*/
void CCGraphicWidget_AsciiTextItem_setIndexedPoint(CCGraphic_AsciiTextItem* item,CCGraphic_Point* p
)
{item->indexed_point = *p;
}
​
/*** 重新定位ASCII文本项。* @param item 指向CCGraphic_AsciiTextItem的指针。* @param tl_point 新的左上角起始坐标。* @param textHandleSize 新的尺寸信息(宽度和高度)。*/
void CCGraphicWidget_AsciiTextItem_relocate(CCGraphic_AsciiTextItem* item,CCGraphic_Point tl_point,CCGraphic_Size textHandleSize
)
{// 这个函数的一个重要的目的就是重定位文本框,为之后的文本显示做铺垫。item->tl_point = tl_point;item->TexthandleSize = textHandleSize;
}

绘制一个字符串本身就是绘制一串字符,掌握整个原理,事情就会变得非常简单,我们线讨论如何绘制字符本身

/*** 绘制ASCII字符到设备。* @param device_handle 设备句柄。* @param borrowing_image 临时用于绘制的图像对象。* @param ch 要绘制的字符。* @param size 字体大小枚举类型。*/
static void __pvt_draw_char_each(CCDeviceHandler* device_handle, CCGraphic_Image* borrowing_image, const char ch, Ascii_Font_Size size
)
{borrowing_image->image_size = __fetch_font_size(size);uint8_t* ascii = __select_from_ascii_font_size(size, ch);borrowing_image->sources_register = ascii;CCGraphicWidget_draw_image(device_handle, borrowing_image);
#if CCGraphic_TextDebugdevice_handle->operations.update_device_function(device_handle);
#endif
}

我们将一个字符的字体绘制文件放置到Image中,所以我强调:字符是画出来的

设计缺陷:注意到,我这里并没有设置绘制的位置,这是因为这件事情在上层做好了,所以我也在参变量中警示自己:整个变量是部分初始化的。

绘制方案

我们绘制的时候,更多会去在乎:是在之前的文本基础上继续绘制呢?还是换一行继续绘制,还是直接清空文本重新绘制?为了防止反复的刷新,笔者设计了三个函数完成整个工作。

首先,设置游标点:

CCGraphic_Point     indexed_point;          // 这个是现在的绘制指针,表明现在我们绘制到了那个地方

整个在Text的结构体中,不由用户直接设置。

下面,就是依赖设置:

/*** 判断当前字符是否需要换行。* @param device_handle 设备句柄。* @param brpoint 右下角边界点。* @param cur_draw_p 当前绘制点的指针。* @param s 字体大小枚举类型。* @return 如果需要换行,返回非零值;否则返回零。*/
static uint8_t inline __pvt_should_be_next_line(CCDeviceHandler* device_handle,CCGraphic_Point* brpoint,CCGraphic_Point* cur_draw_p, Ascii_Font_Size s 
)
{return cur_draw_p->x + (int16_t)(1.5 * __fetch_font_size(s).width) >= brpoint->x;
}
/*** 计算有效的右下角点。* @param device_handle 设备句柄。* @param size 文本项的尺寸信息。* @param tl 文本项的左上角起始点。* @return 计算后的右下角点。*/
static CCGraphic_Point inline __pvt_fetch_valid_final_point(CCDeviceHandler* device_handle,CCGraphic_Size* size, CCGraphic_Point* tl
) 
{CCGraphic_Point br;int16_t device_width = 0;device_handle->operations.property_function(device_handle, &device_width, CommonProperty_WIDTH);int16_t device_height = 0;device_handle->operations.property_function(device_handle, &device_height, CommonProperty_HEIGHT);// 上面我们获取了设备的宽高,现在我们开获取最大的合法右下角的点br.x = tl->x + size->width;br.y = tl->y + size->height;if(device_width < br.x) { br.x = device_width; }if(device_height < br.y) { br.y = device_height; }return br;
}
文本绘制

绘制文本的本质是绘图。这一点务必注意。下面的整个函数实现了自动的文本换行!

/*** 绘制ASCII文本项。* @param device_handle 设备句柄,用于控制绘制设备。* @param item 要绘制的ASCII文本项,包含文本内容、位置及尺寸信息。*/
void CCGraphicWidget_drawAsciiTextItem(CCDeviceHandler* device_handle,CCGraphic_AsciiTextItem* item)
{// 如果文本内容为空,直接返回,不进行绘制。if(strcmp(item->sources_borrowed, "") == 0) {return;}
​// 定义用于绘制的图像结构体。CCGraphic_Image handle_draw_image;
​// 初始化绘制的起始点为当前索引位置。CCGraphic_Point draw_tl_point = item->indexed_point;
​// 获取当前文本字体的尺寸(宽度和高度)。const Ascii_Font_Size font_size = item->font_size;const CCGraphic_Size size = __fetch_font_size(font_size);const SizeBaseType font_width = size.width;const SizeBaseType font_height = size.height;
​// 计算文本绘制区域的有效右下角点(即绘制边界)。CCGraphic_Point br = __pvt_fetch_valid_final_point(device_handle, &(item->TexthandleSize), &(item->tl_point) );
​// 定义x方向和y方向的字符偏移量,用于逐字符定位绘制。uint8_t offseterx = 0;uint8_t offsetery = 0;
​// 遍历文本中的每个字符并绘制。for(uint8_t i = 0; item->sources_borrowed[i] != '\0'; i++) {// 计算当前字符的绘制位置。draw_tl_point.x = item->indexed_point.x + offseterx * font_width;draw_tl_point.y = item->indexed_point.y + offsetery * font_height;
​// 设置图像绘制的左上角点。handle_draw_image.point = draw_tl_point;
​// 绘制当前字符到目标设备上。__pvt_draw_char_each(device_handle, &handle_draw_image, item->sources_borrowed[i], item->font_size);
​// 判断是否需要换行绘制。if(__pvt_should_be_next_line(device_handle, &br, &draw_tl_point, font_size)) {// 如果需要换行,将x偏移量归零,并增加y方向的行数。offseterx = 0;offsetery++;// 重置x方向的起点位置为文本的左上角点。item->indexed_point.x = item->tl_point.x;} else {// 否则继续绘制当前行的下一个字符。offseterx++;}}
​// 更新文本项的索引点位置为最后一个字符的右侧位置。item->indexed_point = draw_tl_point;item->indexed_point.x += font_width;
}
更加方便的绘制

当然,还可以为了之后的组件方便生成一个返回绘制点的方便函数:

/*** 绘制ASCII文本项,并返回绘制后的点。* @param device_handle 设备句柄,用于控制绘制设备。* @param item 要绘制的ASCII文本项,包含文本内容、位置及尺寸信息。* @param method 文本追加方式,指示绘制后是否换行或连续追加。* @return 绘制后的坐标点,表示下一个绘制位置。*/
CCGraphic_Point CCGraphicWidget_drawAsciiTextItem_with_finPoint(CCDeviceHandler* device_handle,CCGraphic_AsciiTextItem* item,AppendMethod method
)
{// 如果文本内容为空,直接返回文本的初始左上角点。if(strcmp(item->sources_borrowed, "") == 0) {return item->tl_point;}
​// 定义绘制图像和绘制位置。CCGraphic_Image handle_draw_image;CCGraphic_Point draw_tl_point = item->indexed_point;
​// 获取字体尺寸。const Ascii_Font_Size font_size = item->font_size;const CCGraphic_Size size = __fetch_font_size(font_size);const SizeBaseType font_width = size.width;const SizeBaseType font_height = size.height;
​// 获取有效绘制区域的右下角点。CCGraphic_Point br = __pvt_fetch_valid_final_point(device_handle, &(item->TexthandleSize), &(item->tl_point) );
​// x方向和y方向的偏移量,用于字符定位。uint8_t offseterx = 0;uint8_t offsetery = 0;
​// 遍历文本中的每个字符。for(uint8_t i = 0; item->sources_borrowed[i] != '\0'; i++) {// 计算当前字符的绘制位置。draw_tl_point.x = item->indexed_point.x + offseterx * font_width;draw_tl_point.y = item->indexed_point.y + offsetery * font_height;
​// 设置图像的绘制点。handle_draw_image.point = draw_tl_point;
​// 绘制当前字符。__pvt_draw_char_each(device_handle, &handle_draw_image, item->sources_borrowed[i], item->font_size);
​// 判断是否需要换行绘制。if(__pvt_should_be_next_line(device_handle, &br, &draw_tl_point, font_size)) {offseterx = 0; // x方向偏移归零offsetery++;   // y方向增加一行item->indexed_point.x = item->tl_point.x; // 重置x起点} else {offseterx++; // 继续绘制当前行的下一个字符}}
​// 更新文本项的索引点为最后一个字符位置。item->indexed_point = draw_tl_point;item->indexed_point.x += font_width;
​// 根据文本追加方式调整返回的最终坐标点。switch(method) {case CCGraphic_AsciiTextItem_AppendNextLine:// 追加到下一行开始位置。draw_tl_point.x = item->tl_point.x;draw_tl_point.y += font_height;break;case CCGraphic_AsciiTextItem_AppendContinously:// 继续追加到同一行的下一个位置。draw_tl_point.x += font_width;break;default:break;}
​// 返回绘制完成后的坐标点。return draw_tl_point;
}
​
​
/*** 获取当前文本项的附加点(追加位置)。* @param item ASCII文本项。* @return 当前索引位置坐标点。*/
CCGraphic_Point CCGraphicWidget_AsciiTextItem_on_append_point(CCGraphic_AsciiTextItem* item)
{return item->indexed_point;
}
​
/*** 获取文本项换行后的新行起点。* @param item ASCII文本项。* @return 新行的起始坐标点。*/
CCGraphic_Point CCGraphicWidget_AsciiTextItem_on_newLine_point(CCGraphic_AsciiTextItem* item)
{CCGraphic_Point draw_tl_point;draw_tl_point.x = item->tl_point.x;const CCGraphic_Size size = __fetch_font_size(item->font_size);draw_tl_point.y = item->indexed_point.y + size.height;return draw_tl_point;    
}

为什么要给函数标记为inline

对于现代的编译器,inline只是起到了一种劝说的作用,他将调用转换为直接插入函数的汇编代码,节约了流水线刷新和代码跳转,这样来看,是一个不错的关键字,但是,一个过于庞大的函数标记为inline是一个无效的举措(几乎没有节约开销,所以编译器有的时候不会理睬,对于GCC,尝试使用force_inline标记符强制内联),现代的inline更加像是一种允许重复定义的关键字(因为他直接将汇编代码插入到了调用者上,符号直接被替换消失了)

字体附录

或者,你可以访问Github地址:MCU_Libs/OLED/library/Graphic/resources/default at main · Charliechen114514/MCU_Libs (github.com)

ascii 6x8字体

#include "Graphic/CCGraphic_common.h"
#include "Graphic/config/CCGraphic_config.h"
//  This is an array of font data for a 
//  6x8 OLED display using 6x8 pixel font representation.
//  Each character in this font set is defined by an 
//  6x8 pixel matrix (8 pixels wide, 16 pixels high).
​
/* sources should be externed copy this for the usage in application level
*/
​
// ---------------------------------------------
// extern const uint8_t ascii6x8_sources[][6];
// ---------------------------------------------
#if ENABLE_ASCII_6x8_SOURCES
const uint8_t ascii6x8_sources[][6] = 
{{0x00,0x00,0x00,0x00,0x00,0x00}, // 0{0x00,0x00,0x00,0x2F,0x00,0x00}, // ! 1{0x00,0x00,0x07,0x00,0x07,0x00}, // " 2{0x00,0x14,0x7F,0x14,0x7F,0x14}, // # 3{0x00,0x24,0x2A,0x7F,0x2A,0x12}, // $ 4{0x00,0x23,0x13,0x08,0x64,0x62}, // % 5{0x00,0x36,0x49,0x55,0x22,0x50}, // & 6{0x00,0x00,0x00,0x07,0x00,0x00}, // ' 7{0x00,0x00,0x1C,0x22,0x41,0x00}, // ( 8{0x00,0x00,0x41,0x22,0x1C,0x00}, // ) 9{0x00,0x14,0x08,0x3E,0x08,0x14}, // * 10{0x00,0x08,0x08,0x3E,0x08,0x08}, // + 11{0x00,0x00,0x00,0xA0,0x60,0x00}, // , 12{0x00,0x08,0x08,0x08,0x08,0x08}, // - 13{0x00,0x00,0x60,0x60,0x00,0x00}, // . 14{0x00,0x20,0x10,0x08,0x04,0x02}, // / 15{0x00,0x3E,0x51,0x49,0x45,0x3E}, // 0 16{0x00,0x00,0x42,0x7F,0x40,0x00}, // 1 17{0x00,0x42,0x61,0x51,0x49,0x46}, // 2 18{0x00,0x21,0x41,0x45,0x4B,0x31}, // 3 19{0x00,0x18,0x14,0x12,0x7F,0x10}, // 4 20{0x00,0x27,0x45,0x45,0x45,0x39}, // 5 21{0x00,0x3C,0x4A,0x49,0x49,0x30}, // 6 22{0x00,0x01,0x71,0x09,0x05,0x03}, // 7 23{0x00,0x36,0x49,0x49,0x49,0x36}, // 8 24{0x00,0x06,0x49,0x49,0x29,0x1E}, // 9 25{0x00,0x00,0x36,0x36,0x00,0x00}, // : 26{0x00,0x00,0x56,0x36,0x00,0x00}, // ; 27{0x00,0x08,0x14,0x22,0x41,0x00}, // < 28{0x00,0x14,0x14,0x14,0x14,0x14}, // = 29{0x00,0x00,0x41,0x22,0x14,0x08}, // > 30{0x00,0x02,0x01,0x51,0x09,0x06}, // ? 31{0x00,0x3E,0x49,0x55,0x59,0x2E}, // @ 32{0x00,0x7C,0x12,0x11,0x12,0x7C}, // A 33{0x00,0x7F,0x49,0x49,0x49,0x36}, // B 34{0x00,0x3E,0x41,0x41,0x41,0x22}, // C 35{0x00,0x7F,0x41,0x41,0x22,0x1C}, // D 36{0x00,0x7F,0x49,0x49,0x49,0x41}, // E 37{0x00,0x7F,0x09,0x09,0x09,0x01}, // F 38{0x00,0x3E,0x41,0x49,0x49,0x7A}, // G 39{0x00,0x7F,0x08,0x08,0x08,0x7F}, // H 40{0x00,0x00,0x41,0x7F,0x41,0x00}, // I 41{0x00,0x20,0x40,0x41,0x3F,0x01}, // J 42{0x00,0x7F,0x08,0x14,0x22,0x41}, // K 43{0x00,0x7F,0x40,0x40,0x40,0x40}, // L 44{0x00,0x7F,0x02,0x0C,0x02,0x7F}, // M 45{0x00,0x7F,0x04,0x08,0x10,0x7F}, // N 46{0x00,0x3E,0x41,0x41,0x41,0x3E}, // O 47{0x00,0x7F,0x09,0x09,0x09,0x06}, // P 48{0x00,0x3E,0x41,0x51,0x21,0x5E}, // Q 49{0x00,0x7F,0x09,0x19,0x29,0x46}, // R 50{0x00,0x46,0x49,0x49,0x49,0x31}, // S 51{0x00,0x01,0x01,0x7F,0x01,0x01}, // T 52{0x00,0x3F,0x40,0x40,0x40,0x3F}, // U 53{0x00,0x1F,0x20,0x40,0x20,0x1F}, // V 54{0x00,0x3F,0x40,0x38,0x40,0x3F}, // W 55{0x00,0x63,0x14,0x08,0x14,0x63}, // X 56{0x00,0x07,0x08,0x70,0x08,0x07}, // Y 57{0x00,0x61,0x51,0x49,0x45,0x43}, // Z 58{0x00,0x00,0x7F,0x41,0x41,0x00}, // [ 59{0x00,0x02,0x04,0x08,0x10,0x20}, // \ 60{0x00,0x00,0x41,0x41,0x7F,0x00}, // ] 61{0x00,0x04,0x02,0x01,0x02,0x04}, // ^ 62{0x00,0x40,0x40,0x40,0x40,0x40}, // _ 63{0x00,0x00,0x01,0x02,0x04,0x00}, // ` 64{0x00,0x20,0x54,0x54,0x54,0x78}, // a 65{0x00,0x7F,0x48,0x44,0x44,0x38}, // b 66{0x00,0x38,0x44,0x44,0x44,0x20}, // c 67{0x00,0x38,0x44,0x44,0x48,0x7F}, // d 68{0x00,0x38,0x54,0x54,0x54,0x18}, // e 69{0x00,0x08,0x7E,0x09,0x01,0x02}, // f 70{0x00,0x18,0xA4,0xA4,0xA4,0x7C}, // g 71{0x00,0x7F,0x08,0x04,0x04,0x78}, // h 72{0x00,0x00,0x44,0x7D,0x40,0x00}, // i 73{0x00,0x40,0x80,0x84,0x7D,0x00}, // j 74{0x00,0x7F,0x10,0x28,0x44,0x00}, // k 75{0x00,0x00,0x41,0x7F,0x40,0x00}, // l 76{0x00,0x7C,0x04,0x18,0x04,0x78}, // m 77{0x00,0x7C,0x08,0x04,0x04,0x78}, // n 78{0x00,0x38,0x44,0x44,0x44,0x38}, // o 79{0x00,0xFC,0x24,0x24,0x24,0x18}, // p 80{0x00,0x18,0x24,0x24,0x18,0xFC}, // q 81{0x00,0x7C,0x08,0x04,0x04,0x08}, // r 82{0x00,0x48,0x54,0x54,0x54,0x20}, // s 83{0x00,0x04,0x3F,0x44,0x40,0x20}, // t 84{0x00,0x3C,0x40,0x40,0x20,0x7C}, // u 85{0x00,0x1C,0x20,0x40,0x20,0x1C}, // v 86{0x00,0x3C,0x40,0x30,0x40,0x3C}, // w 87{0x00,0x44,0x28,0x10,0x28,0x44}, // x 88{0x00,0x1C,0xA0,0xA0,0xA0,0x7C}, // y 89{0x00,0x44,0x64,0x54,0x4C,0x44}, // z 90{0x00,0x00,0x08,0x7F,0x41,0x00}, // { 91{0x00,0x00,0x00,0x7F,0x00,0x00}, // | 92{0x00,0x00,0x41,0x7F,0x08,0x00}, // } 93{0x00,0x08,0x04,0x08,0x10,0x08}, // ~ 94
};
#endif

ascii 8 x 16字体

#include "Graphic/CCGraphic_common.h"
#include "Graphic/config/CCGraphic_config.h"
//  This is an array of font data for a 
//  8x16 OLED display using 8x16 pixel font representation.
//  Each character in this font set is defined by an 
//  8x16 pixel matrix (8 pixels wide, 16 pixels high).
​
/* sources should be externed copy this for the usage in application level
*/
​
// ---------------------------------------------
// extern const uint8_t ascii8x16_sources[][16];
// ---------------------------------------------
#if ENABLE_ASCII_8x16_SOURCES
const uint8_t ascii8x16_sources[][16] =
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},//   0{0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x30,0x00,0x00,0x00},// ! 1{0x00,0x16,0x0E,0x00,0x16,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},// " 2{0x40,0xC0,0x78,0x40,0xC0,0x78,0x40,0x00,0x04,0x3F,0x04,0x04,0x3F,0x04,0x04,0x00},// # 3{0x00,0x70,0x88,0xFC,0x08,0x30,0x00,0x00,0x00,0x18,0x20,0xFF,0x21,0x1E,0x00,0x00},// $ 4{0xF0,0x08,0xF0,0x00,0xE0,0x18,0x00,0x00,0x00,0x21,0x1C,0x03,0x1E,0x21,0x1E,0x00},// % 5{0x00,0xF0,0x08,0x88,0x70,0x00,0x00,0x00,0x1E,0x21,0x23,0x24,0x19,0x27,0x21,0x10},// & 6{0x00,0x00,0x00,0x16,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},// ' 7{0x00,0x00,0x00,0xE0,0x18,0x04,0x02,0x00,0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x00},// ( 8{0x00,0x02,0x04,0x18,0xE0,0x00,0x00,0x00,0x00,0x40,0x20,0x18,0x07,0x00,0x00,0x00},// ) 9{0x40,0x40,0x80,0xF0,0x80,0x40,0x40,0x00,0x02,0x02,0x01,0x0F,0x01,0x02,0x02,0x00},// * 10{0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x1F,0x01,0x01,0x01,0x00},// + 11{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB0,0x70,0x00,0x00,0x00,0x00,0x00},// , 12{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01},// - 13{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00},// . 14{0x00,0x00,0x00,0x00,0x80,0x60,0x18,0x04,0x00,0x60,0x18,0x06,0x01,0x00,0x00,0x00},// / 15{0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00},// 0 16{0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},// 1 17{0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00},// 2 18{0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00},// 3 19{0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00},// 4 20{0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00},// 5 21{0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00},// 6 22{0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00},// 7 23{0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00},// 8 24{0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00},// 9 25{0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00},// : 26{0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x80,0xB0,0x70,0x00,0x00,0x00},// ; 27{0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x00},// < 28{0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00},// = 29{0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00,0x00,0x20,0x10,0x08,0x04,0x02,0x01,0x00},// > 30{0x00,0x70,0x48,0x08,0x08,0x08,0xF0,0x00,0x00,0x00,0x00,0x30,0x36,0x01,0x00,0x00},// ? 31{0xC0,0x30,0xC8,0x28,0xE8,0x10,0xE0,0x00,0x07,0x18,0x27,0x24,0x23,0x14,0x0B,0x00},// @ 32{0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20},// A 33{0x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00},// B 34{0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00},// C 35{0x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00,0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00},// D 36{0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00},// E 37{0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00},// F 38{0xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00,0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00},// G 39{0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20},// H 40{0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},// I 41{0x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00},// J 42{0x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00,0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00},// K 43{0x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00},// L 44{0x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00,0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00},// M 45{0x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08,0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00},// N 46{0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00},// O 47{0x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00,0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00},// P 48{0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x18,0x24,0x24,0x38,0x50,0x4F,0x00},// Q 49{0x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00,0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20},// R 50{0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00},// S 51{0x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00},// T 52{0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00},// U 53{0x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08,0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00},// V 54{0xF8,0x08,0x00,0xF8,0x00,0x08,0xF8,0x00,0x03,0x3C,0x07,0x00,0x07,0x3C,0x03,0x00},// W 55{0x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08,0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20},// X 56{0x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00},// Y 57{0x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00,0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00},// Z 58{0x00,0x00,0x00,0xFE,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x00},// [ 59{0x00,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x06,0x38,0xC0,0x00},// \ 60{0x00,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x7F,0x00,0x00,0x00},// ] 61{0x00,0x20,0x10,0x08,0x04,0x08,0x10,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},// ^ 62{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80},// _ 63{0x00,0x02,0x04,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},// ` 64{0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x19,0x24,0x22,0x22,0x22,0x3F,0x20},// a 65{0x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00},// b 66{0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00},// c 67{0x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00,0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20},// d 68{0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00},// e 69{0x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},// f 70{0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00},// g 71{0x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20},// h 72{0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},// i 73{0x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00},// j 74{0x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00,0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00},// k 75{0x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},// l 76{0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F},// m 77{0x00,0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,0x20,0x3F,0x21,0x00,0x20,0x3F,0x20},// n 78{0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00},// o 79{0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00},// p 80{0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80},// q 81{0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00},// r 82{0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00},// s 83{0x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00},// t 84{0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20},// u 85{0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00},// v 86{0x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80,0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00},// w 87{0x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00},// x 88{0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00},// y 89{0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00},// z 90{0x00,0x00,0x00,0x00,0x80,0x7C,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x3F,0x40,0x40},// { 91{0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00},// | 92{0x00,0x02,0x02,0x7C,0x80,0x00,0x00,0x00,0x00,0x40,0x40,0x3F,0x00,0x00,0x00,0x00},// } 93{0x00,0x80,0x40,0x40,0x80,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x00},// ~ 94
};
#endif

目录导览

总览

协议层封装

OLED设备封装

绘图设备抽象

基础图形库封装

基础组件实现

动态菜单组件实现

相关文章:

从0开始使用面对对象C语言搭建一个基于OLED的图形显示框架(基础组件实现)

目录 基础组件实现 如何将图像和文字显示到OLED上 如何绘制图像 如何绘制文字 如何获取字体&#xff1f; 如何正确的访问字体 如何抽象字体 如何绘制字符串 绘制方案 文本绘制 更加方便的绘制 字体附录 ascii 6x8字体 ascii 8 x 16字体 基础组件实现 我们现在离手…...

windows系统如何检查是否开启了mongodb服务

windows系统如何检查是否开启了mongodb服务&#xff01;我们有很多软件开发&#xff0c;网站开发时候需要使用到这个mongodb数据库&#xff0c;下面我们看看&#xff0c;如何在windows系统内排查&#xff0c;是否已经启动了本地服务。 在 Windows 系统上&#xff0c;您可以通过…...

VS安卓仿真器下载失败怎么办?

如果网络不稳定&#xff0c;则VS的安卓仿真器很容易下载失败&#xff0c;如下 Downloaded file <USER_HOME>\AppData\Local\Temp\xamarin-android-sdk\x86_64-35_r08.zip not found for Android SDK archive https://dl.google.com/android/repository/sys-img/google_a…...

计算机网络一点事(24)

TCP可靠传输&#xff0c;流量控制 可靠传输&#xff1a;每字节对应一个序号 累计确认&#xff1a;收到ack则正确接收 返回ack推迟确认&#xff08;不超过0.5s&#xff09; 两种ack&#xff1a;专门确认&#xff08;只有首部无数据&#xff09; 捎带确认&#xff08;带数据…...

视频拼接,拼接时长版本

目录 视频较长&#xff0c;分辨率较大&#xff0c;这个效果很好&#xff0c;不耗用内存 ffmpeg imageio&#xff0c;适合视频较短 视频较长&#xff0c;分辨率较大&#xff0c;这个效果很好&#xff0c;不耗用内存 ffmpeg import subprocess import glob import os from nats…...

制造企业的成本核算

一、生产成本与制造费用的区别 (1)生产成本,是直接用于产品生产,构成产品实体的材料成本。 包括企业在生产经营过程中实际消耗的原材料、辅助材料、备品备件、外购半成品、燃料、动力包装物以及其它直接材料,和直接参加产品生产的工人工资,以及按生产工人的工资总额和规…...

doris:高并发导入优化(Group Commit)

在高频小批量写入场景下&#xff0c;传统的导入方式存在以下问题&#xff1a; 每个导入都会创建一个独立的事务&#xff0c;都需要经过 FE 解析 SQL 和生成执行计划&#xff0c;影响整体性能每个导入都会生成一个新的版本&#xff0c;导致版本数快速增长&#xff0c;增加了后台…...

LLMs之WebRAG:STORM/Co-STORM的简介、安装和使用方法、案例应用之详细攻略

LLMs之WebRAG&#xff1a;STORM/Co-STORM的简介、安装和使用方法、案例应用之详细攻略 目录 STORM系统简介 1、Co-STORM 2、更新新闻 STORM系统安装和使用方法 1、安装 pip安装 直接克隆GitHub仓库 2、模型和数据集 两个数据集 FreshWiki数据集 WildSeek数据集 支持…...

鸿蒙HarmonyOS实战-ArkUI动画(页面转场动画)_鸿蒙arkui tab 切换动画

PageTransitionExit({type?: RouteType,duration?: number,curve?: Curve | string,delay?: number}) 在HarmonyOS中&#xff0c;PageTransitionEnter和PageTransitionExit是用于控制页面切换动画的参数。它们分别表示页面进入和退出时的动画。1. type&#xff08;动画类型…...

图漾相机-ROS2-SDK-Ubuntu版本编译(新版本)

文章目录 前言1.Camport ROS2 SDK 介绍1.1 Camport ROS2 SDK源文件介绍1.2 Camport ROS2 SDK工作流程1.2.1 包含头文件1.2.2 2 初始化 ROS 2 节点1.2.3 创建节点对象1.2.4 创建发布者对象并实现发布逻辑1.2.5 启动 ROS 2 1.3 ROS2 SDK环境配置与编译1.3.1 Ubuntu 20.04 下ROS2 …...

小程序的协同工作与发布

1.小程序API的三大分类 2.小程序管理的概念&#xff0c;以及成员管理两个方面 3.开发者权限说明以及如何维护项目成员 4.小程序版本...

解锁维特比算法:探寻复杂系统的最优解密码

引言 在复杂的技术世界中&#xff0c;维特比算法以其独特的魅力和广泛的应用&#xff0c;成为通信、自然语言处理、生物信息学等领域的关键技术。今天&#xff0c;让我们一同深入探索维特比算法的奥秘。 一、维特比算法的诞生背景 维特比算法由安德鲁・维特比在 1967 年提出…...

计算机网络一点事(20)

IEEE802.11 无线局域网 分类有无基础设施 星型拓扑&#xff0c;基本服务集BSS一基站多移动站&#xff0c;服务集标识符SSID不超过32b&#xff0c;可接入802.3 漫游&#xff1a;移动站从一个基本服务集切换到另一个&#xff08;类似换联WiFi&#xff09; 802.11帧&#xff1…...

java求职学习day23

MySQL 单表 & 约束 & 事务 1. DQL操作单表 1.1 创建数据库,复制表 1) 创建一个新的数据库 db2 CREATE DATABASE db2 CHARACTER SET utf8; 2) 将 db1 数据库中的 emp 表 复制到当前 db2 数据库 1.2 排序 通过 ORDER BY 子句 , 可以将查询出的结果进行排序 ( 排序只…...

Vue-cli 脚手架搭建

安装node.js 官网下载node.js安装包&#xff0c;地址&#xff1a;Node.js — Download Node.js 先在node.js即将要安装的路径下创建两个文件夹&#xff1a;node_cache&#xff08;缓存&#xff09;、node_global&#xff08;全局&#xff09; 点击安装包&#xf…...

认识小程序的基本组成结构

1.基本组成结构 2.页面的组成部分 3.json配置文件 4.app.json文件(全局配置文件&#xff09; 5.project.config.json文件 6.sitemap.json文件 7.页面的.json配置文件 通过window节点可以控制小程序的外观...

Spring Boot 热部署实现指南

在开发 Spring Bot 项目时&#xff0c;热部署功能能够显著提升开发效率&#xff0c;让开发者无需频繁重启服务器就能看到代码修改后的效果。下面为大家详细介绍一种实现 Spring Boot 热部署的方法&#xff0c;同时也欢迎大家补充其他实现形式。 步骤一、开启 IDEA 自动编译功能…...

深度学习编译器的演进:从计算图到跨硬件部署的自动化之路

第一章 问题的诞生——深度学习部署的硬件困境 1.1 计算图的理想化抽象 什么是计算图&#xff1f; 想象你正在组装乐高积木。每个积木块代表一个数学运算&#xff08;如加法、乘法&#xff09;&#xff0c;积木之间的连接代表数据流动。深度学习框架正是用这种"积木拼接…...

【数据结构】_顺序表经典算法OJ(力扣版)

目录 1. 移除元素 1.1 题目描述及链接 1.2 解题思路 1.3 程序 2. 合并两个有序数组 1.1 原题链接及题目描述 1.2 解题思路 1.3 程序 1. 移除元素 1.1 题目描述及链接 原题链接&#xff1a;27. 移除元素 - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a…...

数据结构:队列篇

图均为手绘,代码基于vs2022实现 系列文章目录 数据结构初探: 顺序表 数据结构初探:链表之单链表篇 数据结构初探:链表之双向链表篇 链表特别篇:链表经典算法问题 数据结构:栈篇 文章目录 系列文章目录前言一.队列的概念和结构1.1概念一、动态内存管理优势二、操作效率与安全性…...

19c补丁后oracle属主变化,导致不能识别磁盘组

补丁后服务器重启&#xff0c;数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后&#xff0c;存在与用户组权限相关的问题。具体表现为&#xff0c;Oracle 实例的运行用户&#xff08;oracle&#xff09;和集…...

使用VSCode开发Django指南

使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架&#xff0c;专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用&#xff0c;其中包含三个使用通用基本模板的页面。在此…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

第25节 Node.js 断言测试

Node.js的assert模块主要用于编写程序的单元测试时使用&#xff0c;通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试&#xff0c;通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...

2025盘古石杯决赛【手机取证】

前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来&#xff0c;实在找不到&#xff0c;希望有大佬教一下我。 还有就会议时间&#xff0c;我感觉不是图片时间&#xff0c;因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机

这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机&#xff0c;因为在使用过程中发现 Airsim 对外部监控相机的描述模糊&#xff0c;而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置&#xff0c;最后在源码示例中找到了&#xff0c;所以感…...

Webpack性能优化:构建速度与体积优化策略

一、构建速度优化 1、​​升级Webpack和Node.js​​ ​​优化效果​​&#xff1a;Webpack 4比Webpack 3构建时间降低60%-98%。​​原因​​&#xff1a; V8引擎优化&#xff08;for of替代forEach、Map/Set替代Object&#xff09;。默认使用更快的md4哈希算法。AST直接从Loa…...

【C++】纯虚函数类外可以写实现吗?

1. 答案 先说答案&#xff0c;可以。 2.代码测试 .h头文件 #include <iostream> #include <string>// 抽象基类 class AbstractBase { public:AbstractBase() default;virtual ~AbstractBase() default; // 默认析构函数public:virtual int PureVirtualFunct…...

阿里云Ubuntu 22.04 64位搭建Flask流程(亲测)

cd /home 进入home盘 安装虚拟环境&#xff1a; 1、安装virtualenv pip install virtualenv 2.创建新的虚拟环境&#xff1a; virtualenv myenv 3、激活虚拟环境&#xff08;激活环境可以在当前环境下安装包&#xff09; source myenv/bin/activate 此时&#xff0c;终端…...