当前位置: 首页 > 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字体 基础组件实现 我们现在离手…...

负荷预测算法模型

1. 时间序列分析方法 时间序列分析方法是最早被用来进行电力负荷预测的方法之一&#xff0c;它基于历史数据来构建数学模型&#xff0c;以描述时间与负荷值之间的关系。这种方法通常只考虑时间变量&#xff0c;不需要大量的输入数据&#xff0c;因此计算速度快。然而&#xff…...

Flutter Candies 一桶天下

| | | | | | | | 入魔的冬瓜 最近刚入桶的兄弟&#xff0c;有责任心的开发者&#xff0c;对自己的项目会不断进行优化&#xff0c;达到最完美的状态 自定义日历组件 主要功能 支持公历&#xff0c;农历&#xff0c;节气&#xff0c;传统节日&#xff0c;常用节假日 …...

android Camera 的进化

引言 Android 的camera 发展经历了3个阶段 &#xff1a; camera1 -》camera2 -》cameraX。 正文 Camera1 Camera1 的开发中&#xff0c;打开相机&#xff0c;设置参数的过程是同步的&#xff0c;就跟用户实际使用camera的操作步骤一样。但是如果有耗时情况发生时&#xff0c;会…...

HarmonyOS简介:应用开发的机遇、挑战和趋势

问题 更多的智能设备并没有带来更好的全场景体验 连接步骤复杂数据难以互通生态无法共享能力难以协同 主要挑战 针对不同设备上的不同操作系统&#xff0c;重复开发&#xff0c;维护多套版本 多种语言栈&#xff0c;对人员技能要求高 多种开发框架&#xff0c;不同的编程…...

反向代理模块b

1 概念 1.1 反向代理概念 反向代理是指以代理服务器来接收客户端的请求&#xff0c;然后将请求转发给内部网络上的服务器&#xff0c;将从服务器上得到的结果返回给客户端&#xff0c;此时代理服务器对外表现为一个反向代理服务器。 对于客户端来说&#xff0c;反向代理就相当于…...

C++并发:设计基于锁的并发数据结构

&#xff08;上一篇主要讲了底层逻辑&#xff0c;比较晦涩难懂&#xff0c;这一章讲解数据结构设计&#xff09; 对于并发场景&#xff0c;数据保护的形式主要如下&#xff1a; 1 采用独立互斥和外部锁 2 专门为并发访问自行设计的数据结构 1 并发设计的内涵 互斥保护数据结…...

数据分析系列--⑥RapidMiner构建决策树(泰坦尼克号案例含数据)

一、资源下载 二、数据处理 1.导入数据 2.数据预处理 三、构建模型 1.构建决策树 2.划分训练集和测试集 3.应用模型 4.结果分析 一、资源下载 点击下载数据集 二、数据处理 1.导入数据 2.数据预处理 三、构建模型 1.构建决策树 虽然决策树已经构建,但对于大多数初学者或…...

leetcode 844 比较含退格的字符串

leetcode 844 比较含退格的字符串 题目描述 给定 s 和 t 两个字符串&#xff0c;当它们分别被输入到空白的文本编辑器后&#xff0c;如果两者相等&#xff0c;返回 true 。# 代表退格字符。 注意&#xff1a;如果对空文本输入退格字符&#xff0c;文本继续为空。 示例 1&#…...

【ArcGIS遇上Python】批量提取多波段影像至单个波段

本案例基于ArcGIS python,将landsat影像的7个波段影像数据,批量提取至单个波段。 相关阅读:【ArcGIS微课1000例】0141:提取多波段影像中的单个波段 文章目录 一、数据准备二、效果比对二、python批处理1. 编写python代码2. 运行代码一、数据准备 实验数据及完整的python位…...

10.6 LangChain提示工程终极指南:从基础模板到动态生成的工业级实践

LangChain提示工程终极指南:从基础模板到动态生成的工业级实践 关键词: LangChain提示模板、动态Prompt生成、少样本学习、结构化输出、Prompt工程 一、Prompt Engineering 的本质:用设计模式重构大模型交互 传统Prompt的局限性: 硬编码文本:修改需求需重构代码缺乏结构…...

DeepSeek-R1 论文解读 —— 强化学习大语言模型新时代来临?

近年来&#xff0c;人工智能&#xff08;AI&#xff09;领域发展迅猛&#xff0c;大语言模型&#xff08;LLMs&#xff09;为通用人工智能&#xff08;AGI&#xff09;的发展开辟了道路。OpenAI 的 o1 模型表现非凡&#xff0c;它引入的创新性推理时缩放技术显著提升了推理能力…...

联想拯救者R720笔记本外接显示屏方法,显示屏是2K屏27英寸

晚上23点10分前下单&#xff0c;第二天上午显示屏送到&#xff0c;检查外包装没拆封过。这个屏幕左下方有几个按键&#xff0c;按一按就开屏幕、按一按就关闭屏幕&#xff0c;按一按方便节省时间&#xff0c;也支持阅读等模式。 显示屏是 &#xff1a;AOC 27英寸 2K高清 100Hz…...

编译安装PaddleClas@openKylin(失败,安装好后报错缺scikit-learn)

编译安装 前置需求&#xff1a; 手工安装swig和faiss-cpu pip install swig pip install faiss-cpu 小技巧&#xff0c;pip编译安装的时候&#xff0c;可以加上--jobs64来多核编译。 注意先升级pip版本&#xff1a;pip install pip -U pip3 install faiss-cpu --config-s…...

传输层协议TCP与UDP:深入解析与对比

传输层协议TCP与UDP&#xff1a;深入解析与对比 目录 传输层协议TCP与UDP&#xff1a;深入解析与对比引言1. 传输层协议概述2. TCP协议详解2.1 TCP的特点2.2 TCP的三次握手与四次挥手三次握手四次挥手 2.3 TCP的流量控制与拥塞控制2.4 TCP的可靠性机制 3. UDP协议详解3.1 UDP的…...

《解码AI大模型涌现能力:从量变到质变的智能跃迁》

在当今科技飞速发展的时代&#xff0c;人工智能大模型的涌现能力成为了众人瞩目的焦点。从ChatGPT与用户的流畅对话&#xff0c;到GPT-4在复杂任务中的出色表现&#xff0c;这些大模型仿佛一夜之间解锁了超乎想象的技能&#xff0c;那么&#xff0c;这种神奇的涌现能力究竟是如…...

【数据结构】_C语言实现带头双向循环链表

目录 1. 单链表与双链表 1.1 单链表的结构及结点属性 1.2 双链表的结构及结点属性 2. 单链表与双链表的区别 3. 双链表的实现 3.1 List.h 3.2 List.c 3.3 Test_List.c 注&#xff1a;部分方法的实现细节注释 1. 双链表结点前驱、后继指针域的初始化 2. 各种增、删结…...

优盘恢复原始容量工具

买到一个优盘&#xff0c;显示32mb&#xff0c;我见过扩容盘&#xff0c;但是这次见到的是缩容盘&#xff0c;把2g的容量缩成32MB了&#xff0c;首次见到。。用芯片查询工具显示如下 ChipsBank(芯邦) CBM2199E 使用以下工具&#xff0c;恢复原始容量。。 其他CMB工具可能不行…...

JVM的GC详解

获取GC日志方式大抵有两种 第一种就是设定JVM参数在程序启动时查看&#xff0c;具体的命令参数为: -XX:PrintGCDetails # 打印GC日志 -XX:PrintGCTimeStamps # 打印每一次触发GC时发生的时间第二种则是在服务器上监控:使用jstat查看,如下所示&#xff0c;命令格式为jstat -gc…...

反转单向链表以及单链表添加节点、遍历单链表

反转1个单向链表 /*** 节点类*/ class ListNode {public int val;public ListNode next;public ListNode(int val) {this.val val;}Overridepublic String toString() {return "ListNode{" "val" val ", next" next };} }借助一个pre来存储每…...

ZZNUOJ(C/C++)基础练习1021——1030(详解版)

目录 1021 : 三数求大值 C语言版 C版 代码逻辑解释 1022 : 三整数排序 C语言版 C版 代码逻辑解释 补充 &#xff08;C语言版&#xff0c;三目运算&#xff09;C类似 代码逻辑解释 1023 : 大小写转换 C语言版 C版 1024 : 计算字母序号 C语言版 C版 代码逻辑总结…...

Linux学习笔记——系统维护命令

一、进程管理 1、ps命令&#xff08;查&#xff09; 来自process缩写&#xff0c;显示当前的进程状态。包括&#xff1a;进程的号码&#xff0c;发起者&#xff0c;系统资源&#xff0c;使用占比&#xff0c;运行状态等等。 语法格式&#xff1a;ps 参数 实例&#x…...

Harbor 部署

harbor镜像仓库搭建 版本v2.10.3 文章目录 一. docker 安装 harbor1. harbor 配置http访问1.1 下载harbor二进制包1.2 修改配置文件1.3 运行1.4 访问 2.【可选】harbor 配置https访问2.1 自签证书2.1 修改配置文件2.3 修改hosts文件2.4 运行2.5 访问 二. k8s 安装harbor1 .安装…...

three.js+WebGL踩坑经验合集(6.1):负缩放,负定矩阵和行列式的关系(2D版本)

春节忙完一轮&#xff0c;总算可以继续来写博客了。希望在春节假期结束之前能多更新几篇。 这一篇会偏理论多一点。笔者本没打算在这一系列里面重点讲理论&#xff0c;所以像相机矩阵推导这种网上已经很多优质文章的内容&#xff0c;笔者就一笔带过。 然而关于负缩放&#xf…...

开源的瓷砖式图像板系统Pinry

简介 什么是 Pinry &#xff1f; Pinry 是一个开源的瓷砖式图像板系统&#xff0c;旨在帮助用户轻松保存、标记和分享图像、视频和网页。它提供了一种便于快速浏览的格式&#xff0c;适合喜欢整理和分享多种媒体内容的人。 主要特点 图像抓取和在线预览&#xff1a;支持从网页…...

LabVIEW透镜多参数自动检测系统

在现代制造业中&#xff0c;提升产品质量检测的自动化水平是提高生产效率和准确性的关键。本文介绍了一个基于LabVIEW的透镜多参数自动检测系统&#xff0c;该系统能够在单一工位上完成透镜的多项质量参数检测&#xff0c;并实现透镜的自动搬运与分选&#xff0c;极大地提升了检…...

socket实现HTTP请求,参考HttpURLConnection源码解析

背景 有台服务器&#xff0c;网卡绑定有2个ip地址&#xff0c;分别为&#xff1a; A&#xff1a;192.168.111.201 B&#xff1a;192.168.111.202 在这台服务器请求目标地址 C&#xff1a;192.168.111.203 时必须使用B作为源地址才能访问目标地址C&#xff0c;在这台服务器默认…...

反向代理模块jmh

1 概念 1.1 反向代理概念 反向代理是指以代理服务器来接收客户端的请求&#xff0c;然后将请求转发给内部网络上的服务器&#xff0c;将从服务器上得到的结果返回给客户端&#xff0c;此时代理服务器对外表现为一个反向代理服务器。 对于客户端来说&#xff0c;反向代理就相当…...

安卓(android)实现注册界面【Android移动开发基础案例教程(第2版)黑马程序员】

一、实验目的&#xff08;如果代码有错漏&#xff0c;可查看源码&#xff09; 1.掌握LinearLayout、RelativeLayout、FrameLayout等布局的综合使用。 2.掌握ImageView、TextView、EditText、CheckBox、Button、RadioGroup、RadioButton、ListView、RecyclerView等控件在项目中的…...

RubyFPV开源代码之系统简介

RubyFPV开源代码之系统简介 1. 源由2. 工程架构3. 特性介绍&#xff08;软件&#xff09;3.1 特性亮点3.2 数字优势3.3 使用功能 4. DEMO推荐&#xff08;硬件&#xff09;4.1 天空端4.2 地面端4.3 按键硬件Raspberry PiRadxa 3W/E/C 5. 软件设计6. 参考资料 1. 源由 RubyFPV以…...

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

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

Unity游戏(Assault空对地打击)开发(2) 基础场景布置

目录 导入插件 文件夹整理 场景布置 山地场景 导入插件 打开【My Assets】&#xff08;如果你刚进行上篇的操作&#xff0c;该窗口默认已经打开了&#xff09;。 找到添加的几个插件&#xff0c;点击Download并Import x.x to...。 文件夹整理 我们的目录下多了两个文件夹&a…...

Office / WPS 公式、Mathtype 公式输入花体字、空心字

注&#xff1a;引文主要看注意事项。 1、Office / WPS 公式中字体转换 花体字 字体选择 “Eulid Math One” 空心字 字体选择 “Eulid Math Two” 使用空心字时&#xff0c;一般不用斜体&#xff0c;取消勾选 “斜体”。 2、Mathtype 公式输入花体字、空心字 2.1 直接输…...

代码随想录算法训练营第三十九天-动态规划-213. 打家劫舍 II

与上一题基本一样&#xff0c;只不过房间形成一个环&#xff0c;就需要在首尾考虑状况多一些这不是多一些状况的问题&#xff0c;是完全不知道如何选择的问题这种状况详细分析一下就是要分成三种情况 第一种&#xff1a;不考虑首元素&#xff0c;也不考虑尾元素&#xff0c;只考…...

自然语言处理-词嵌入 (Word Embeddings)

词嵌入&#xff08;Word Embedding&#xff09;是一种将单词或短语映射到高维向量空间的技术&#xff0c;使其能够以数学方式表示单词之间的关系。词嵌入能够捕捉语义信息&#xff0c;使得相似的词在向量空间中具有相近的表示。 &#x1f4cc; 常见词嵌入方法 基于矩阵分解的方…...

Redis 数据备份与恢复

Redis 数据备份与恢复 引言 Redis 是一款高性能的键值对存储系统,广泛应用于缓存、消息队列、分布式锁等领域。为了保证数据的安全性和可靠性,定期对 Redis 数据进行备份与恢复是至关重要的。本文将详细介绍 Redis 数据备份与恢复的方法,帮助您更好地管理和维护 Redis 数据…...

【leetcode】T541 (两点反思)

解题反思 闷着头往&#xff0c;往往会写成一团浆糊&#xff0c;还推倒重来&#xff0c;谋划好全局思路再开始很重要。 熟悉C的工具库很重要&#xff0c;一开始看到反转就还想着用stack来着&#xff0c;后面突然想起来用reverse函数刚好可以用哇&#xff0c;这题也就迎刃而解了…...

《STL基础之vector、list、deque》

【vector、list、deque导读】vector、list、deque这三种序列式的容器&#xff0c;算是比较的基础容器&#xff0c;也是大家在日常开发中常用到的容器&#xff0c;因为底层用到的数据结构比较简单&#xff0c;笔者就将他们三者放到一起做下对比分析&#xff0c;介绍下基本用法&a…...

嵌入式系统|DMA和SPI

文章目录 DMA&#xff08;直接内存访问&#xff09;DMA底层原理1. 关键组件2. 工作机制3. DMA传输模式 SPI&#xff08;串行外设接口&#xff09;SPI的基本原理SPI连接示例 DMA与SPI的共同作用 DMA&#xff08;直接内存访问&#xff09; 类型&#xff1a;DMA是一种数据传输接口…...

LevelDB 源码阅读:写入键值的工程实现和优化细节

读、写键值是 KV 数据库中最重要的两个操作&#xff0c;LevelDB 中提供了一个 Put 接口&#xff0c;用于写入键值对。使用方法很简单&#xff1a; leveldb::Status status leveldb::DB::Open(options, "./db", &db); status db->Put(leveldb::WriteOptions…...

寒假刷题Day18

一、16. 最接近的三数之和 这一题有负数&#xff0c;没有单调性&#xff0c;不能“大了右指针左移&#xff0c;小了左指针右移&#xff0c;最后存值域求差绝对值”。 class Solution { public:int threeSumClosest(vector<int>& nums, int target) {ranges::sort(n…...

力扣219.存在重复元素每日一题(大年初一)

以一道简单题开启全新的一年 哈希表&#xff1a;我们可以使用 哈希表 来存储数组元素及其对应的索引。通过遍历数组&#xff0c;我们可以检查当前元素是否已经存在于哈希表中&#xff0c;并判断索引差是否满足条件。 具体步骤如下&#xff1a; 创建一个哈希表 map&#xff0c…...

Midjourney中的强变化、弱变化、局部重绘的本质区别以及其有多逆天的功能

开篇 Midjourney中有3个图片“微调”&#xff0c;它们分别为&#xff1a; 强变化&#xff1b;弱变化&#xff1b;局部重绘&#xff1b; 在Discord里分别都是用命令唤出的&#xff0c;但如今随着AI技术的发达在类似AI可人一类的纯图形化界面中&#xff0c;我们发觉这样的逆天…...

Blazor-选择循环语句

今天我们来说说Blazor选择语句和循环语句。 下面我们以一个简单的例子来讲解相关的语法&#xff0c;我已经创建好了一个Student类&#xff0c;以此类来进行语法的运用 因为我们需要交互性所以我们将类创建在*.client目录下 if 我们做一个学生信息的显示&#xff0c;Gender为…...

根据每月流量和市场份额排名前20 的AI工具列表

ChatGPT&#xff1a;由Open AI研发&#xff0c;是一款对话式大型语言模型。它能够理解自然语言输入&#xff0c;生成连贯且符合逻辑的回复。可用于文本创作&#xff0c;如撰写文章、故事、诗歌&#xff1b;还能解答各种领域的知识问题&#xff0c;提供翻译、代码解释等服务&…...

关于安卓greendao打包时报错问题修复

背景 项目在使用greendao的时候&#xff0c;debug安装没有问题&#xff0c;一到打包签名就报了。 环境 win10 jdk17 gradle8 项目依赖情况 博主的greendao是一个独立的module项目&#xff0c;项目目前只适配了java&#xff0c;不支持Kotlin。然后被外部集成。greendao版本…...

前端面试笔试题目(一)

以下模拟了大厂前端面试流程&#xff0c;并给出了涵盖HTML、CSS、JavaScript等基础和进阶知识的前端笔试题目&#xff0c;以帮助你更好地准备面试。 面试流程模拟 1. 自我介绍&#xff08;5 - 10分钟&#xff09;&#xff1a;面试官会请你进行简单的自我介绍&#xff0c;包括…...

网络工程师 (10)设备管理

前言 设备管理中的数据传输控制方式是确保设备与内存&#xff08;或CPU&#xff09;之间高效、准确地进行数据传送的关键。 一、程序直接控制方式 1.工作原理&#xff1a; 由CPU发出I/O指令&#xff0c;直接控制数据的传输过程。CPU需要不断查询外设的状态&#xff0c;以确定数…...

如何让一个用户具备创建审批流程的权限

最近碰到一个问题&#xff0c;两个sandbox&#xff0c;照理用户的权限应该是一样的&#xff0c;结果开发环境里面我可以左右的做各种管理工作&#xff0c;但是使用change set上传后&#xff0c;另一个环境的同一个用户&#xff0c;没有相对于的权限&#xff0c;权限不足。 当时…...

unity学习23:场景scene相关,场景信息,场景跳转

目录 1 默认场景和Assets里的场景 1.1 scene的作用 1.2 scene作为project的入口 1.3 默认场景 2 场景scene相关 2.1 创建scene 2.2 切换场景 2.3 build中的场景&#xff0c;在构建中包含的场景 &#xff08;否则会认为是失效的Scene&#xff09; 2.4 Scenes in Bui…...