U8G2自定义 新增屏幕适配
本质上是构造函数的适配
u8g2_d_setup.c //仅保留使用 驱动函数
u8g2_d_memory.c //仅保留使用 驱动函数
u8g2-master\csrc //仅保留使用 驱动文件 u8x8_d_xxxxxxxx.c
实现byte_cd() 和 delay_cd()

然后把其他函数给删除或者注释掉。
u8g2_d_memory
我们需要找到下面这个函数
uint8_t *u8g2_m_16_8_f(uint8_t *page_cnt)
{
#ifdef U8G2_USE_DYNAMIC_ALLOC
*page_cnt = 8;
return 0;
#else
static uint8_t buf[1024];
*page_cnt = 8;
return buf;
#endif
}
把其他函数删除或注释掉.
修改屏幕分辨率
1.修改构造函数

2.修改内存映射;大小
u8g2_t u8g2;
void Disp_Init(void) {
u8g2Init(&u8g2); // 初始化U8g2库,为OLED显示做准备
OLED_SetFont(MENU_FONT); // 设置默认使用的字体为MENU_FONT
//u8g2_Setup_ssd1306_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_4wire_sw_spi, u8x8_stm32_gpio_and_delay);
u8g2_InitDisplay(&u8g2);
u8g2_SetPowerSave(&u8g2,0);
}
一键获取完整项目代码
bash
1
使用方法
清除缓存内容:u8g2.clearBuffer()。
使用绘图指令绘制图形。
发送缓存数据给显示器以显示:u8g2.sendBuffer()。
void setup(void) {
u8g2.begin();
}
void loop(void) {
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_ncenB14_tr);
u8g2.drawStr(0,20,"Hello World!");
u8g2.sendBuffer();
}
一键获取完整项目代码
一键获取完整项目代码
bash
1
使用方法
调用 u8g2.firstPage()
运行一个 do-while 循环
在循环体内绘制一些图形
循环到U8g2.nextPage()返回真结束
void setup(void) {
u8g2.begin();
}
void loop(void) {
u8g2.firstPage();
do {
u8g2.setFont(u8g2_font_ncenB14_tr);
u8g2.drawStr(0,24,"Hello World!");
} while ( u8g2.nextPage() );
}
U8g2 支持3中不同的绘图模式
| 全屏缓存模式 | 全屏缓存模式(full buffer) 快速 可使用所有的图形程序 需要大量的内存(RAM) 从上面支持的类型中选择一个 U8g2 的构造器,全屏缓存模式的构造器包含了“F”,比如: U8G2_ST7920_128X64_ F _SW_SPI(rotation, clock, data, cs [, reset]) |
使用方法 void loop(void) { |
| 页面模式(U8glib 图片轮询) | 页面模式(U8glib 图片轮询) 所有的图形程序可用 要求少量的内存(RAM) 速度慢 从上面支持的类型中,选择一个 U8g2 的构造器,全屏缓存模式的构造器包含了“1”,或者“2,”比如: U8G2_ST7920_128X64_ 1 _SW_SPI(rotation, clock, data, cs [, reset]) |
使用方法 void loop(void) { |
| U8c8,纯字符模式 |
U8x8 字符模式 U8G2_ST7920_128X64_ 1 _SW_SPI(rotation, clock, data, cs [, reset]) |
使用方法 void loop(void) { |
//x:0~127; //y:1~63;//8 void setAddrPt(uint8_t x ,uint8_t y){ lcdBuff[y/8][x] |= 1<<(y%8); } uint8_t getAddrPt(uint8_t x ,uint8_t y){ if(lcdBuff[y/8][x] & 1<<(y%8)){ return 1; } return 0; } extern void setGrayPot(uint16_t x,uint16_t y,uint8_t v); void lcdMainLoop(void){ uint16_t i,j; for(i=0; i<(240-1); i++){ for(j=0; (j<80-1); j++){ if(getAddrPt(i,j)){ //TFT_Point(i,j); lcd_set_cursor(i, j); /* 设置光标位置 */ lcd_write_ram_prepare(); /* 开始写入GRAM */ LCD->LCD_RAM = RED; setGrayPot(i,j,3); }else{ lcd_set_cursor(i, j); /* 设置光标位置 */ lcd_write_ram_prepare(); /* 开始写入GRAM */ LCD->LCD_RAM = YELLOW; setGrayPot(i,j,1); } } } }
3. 初始化u8g2结构体 在用户代码中初始化u8g2结构体,并分配足够大的缓冲区: u8g2_t u8g2; // u8g2对象 static uint8_t u8g2_buffer[12800];// 缓冲区大小:320x320单色屏幕需要320*320/8 = 12800字节 void init_u8g2(void) { // 设置屏幕尺寸、回调函数和旋转方向 u8g2_SetupCustom(&u8g2, 320, 320, display_cb, hardware_cb); // 设置缓冲区 u8g2_SetupBuffer(&u8g2, u8g2_buffer, sizeof(u8g2_buffer), U8G2_FLAG_1_BIT); // 初始化屏幕 u8g2_InitDisplay(&u8g2); u8g2_SetPowerSave(&u8g2, 0); // 开启屏幕 //u8g2_SetDisplayRotation(&u8g2, U8G2_R0); // U8G2_R0 ~ U8G2_R3 屏幕旋转设置(可选) //void test_draw(void) //测试代码示例 { u8g2_ClearBuffer(&u8g2); u8g2_SetFont(&u8g2, u8g2_font_ncenB08_tr); // 设置字体 u8g2_DrawStr(&u8g2, 0, 10, "Hello 320x320"); // 绘制字符串 u8g2_SendBuffer(&u8g2); // 发送缓冲区到屏幕 } }
void Disp_Init(void) { // 初始化U8g2库,为OLED显示做准备 u8g2Init(&u8g2); // 设置默认使用的字体为MENU_FONT OLED_SetFont(MENU_FONT); //u8g2_Setup_ssd1306_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_4wire_sw_spi, u8x8_stm32_gpio_and_delay); u8g2_InitDisplay(&u8g2); u8g2_SetPowerSave(&u8g2,0); } void u8g2Init(u8g2_t *u8g2) { // #ifdef SOFTWARE_I2C // MyI2C_Init(); // u8g2_Setup_ssd1306_i2c_128x64_noname_f(u8g2, U8G2_R0, u8x8_byte_sw_i2c, u8x8_gpio_and_delay); // #endif // #ifdef HARDWARE_I2C // HardWare_I2C2_GPIOInit(); // u8g2_Setup_ssd1306_i2c_128x64_noname_f(u8g2, U8G2_R0, u8x8_byte_hw_i2c, u8x8_gpio_and_delay_hw); // #endif //TODO HardWare_I2C2_GPIOInit(); // u8x8_byte_4wire_sw_spi //u8g2_gpio_and_delay_stm32 u8g2_Setup_st7567_jlx12864_f(u8g2, U8G2_R0, u8x8_byte_4wire_sw_spi, u8g2_gpio_and_delay_stm32); u8g2_InitDisplay(u8g2); u8g2_SetPowerSave(u8g2, 0); u8g2_ClearBuffer(u8g2); }
https://zhuanlan.zhihu.com/p/489251923
https://www.codeleading.com/article/94655971569/ //构造函数适配
移植U8G2单色图形库 - 韦东山嵌入式开发者社区 //百问移植示例
- u8g2_Setup_ssd1306_128x64_noname_1
- u8g2_Setup_ssd1306_128x64_noname_2
- u8g2_Setup_ssd1306_128x64_noname_f
- u8g2_Setup_ssd1306_i2c_128x64_noname_1
- u8g2_Setup_ssd1306_i2c_128x64_noname_2
- u8g2_Setup_ssd1306_i2c_128x64_noname_f
其中,前面3个,是给SPI接口的OLED用的,函数最后的数字或字母,代表显示时的buf大小:
- 1:128字节
- 2:256字节
- f:1024字节
在u8g2中新增一个320x320屏幕适配,需要结合你的底层绘图函数lcd_draw_point,并遵循u8g2的回调机制。以下是分步骤的实现方案,确保兼容性和性能。
1. 定义回调函数处理显示消息
u8g2通过回调函数处理底层显示操作。我们需要实现以下关键消息:
- U8X8_MSG_DISPLAY_INIT:屏幕初始化
- U8X8_MSG_DISPLAY_DRAW_TILE:将缓冲区的图块数据绘制到屏幕
#include "u8g2.h" // 假设颜色定义(单色) #define BLACK 0 #define WHITE 1 // 用户提供的底层点绘制函数 extern void lcd_draw_point(unsigned int x, unsigned int y, unsigned int color); // 回调函数处理显示消息 uint8_t display_cb(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) { switch (msg) { case U8X8_MSG_DISPLAY_INIT: // 调用用户提供的初始化函数 init_my_screen(); break; case U8X8_MSG_DISPLAY_DRAW_TILE: { // 获取当前行起始像素Y坐标 uint16_t curr_row = u8x8->tile_current_row * 8; // 遍历每个tile for (uint8_t tile_col = 0; tile_col < arg_int; tile_col++) { // 遍历每个tile中的8行 for (uint8_t y = 0; y < 8; y++) { uint8_t byte = *(uint8_t *)arg_ptr++; // 遍历每个bit(即像素) for (uint8_t x = 0; x < 8; x++) { // 提取bit值(高位在前) uint8_t bit = (byte >> (7 - x)) & 0x01; // 计算实际屏幕坐标 unsigned int draw_x = tile_col * 8 + x; unsigned int draw_y = curr_row + y; // 调用用户提供的点绘制函数 lcd_draw_point(draw_x, draw_y, bit ? WHITE : BLACK); } } } } break; default: return 0; } return 1; }
2. 定义硬件接口回调(可选)
如果你的lcd_draw_point函数已经处理了通信接口(如SPI或I2C),可以将硬件回调设为NULL。否则,需实现以下回调:
uint8_t hardware_cb(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) { switch (msg) { case U8X8_MSG_BYTE_SendByte: // 发送一个字节到屏幕 send_byte_to_lcd(*(uint8_t *)arg_ptr); break; case U8X8_MSG_BYTE_StartTransfer: case U8X8_MSG_BYTE_EndTransfer: // 启动或结束传输(如片选控制) break; case U8X8_MSG_GPIO_and_Delay: // 延时或控制GPIO(如复位、DC) if (arg_int == U8X8_MSG_GPIO_RESET) { if (*(uint8_t *)arg_ptr == 0) set_reset_low(); else set_reset_high(); } break; default: return 0; } return 1; }
3. 初始化u8g2结构体
在用户代码中初始化u8g2结构体,并分配足够大的缓冲区:
u8g2_t u8g2; // u8g2对象 // 缓冲区大小:320x320单色屏幕需要320*320/8 = 12800字节 static uint8_t u8g2_buffer[12800]; void init_u8g2(void) { // 设置屏幕尺寸、回调函数和旋转方向 u8g2_SetupCustom(&u8g2, 320, 320, display_cb, hardware_cb); // 设置缓冲区 u8g2_SetupBuffer(&u8g2, u8g2_buffer, sizeof(u8g2_buffer), U8G2_FLAG_1_BIT); // 初始化屏幕 u8g2_InitDisplay(&u8g2); u8g2_SetPowerSave(&u8g2, 0); // 开启屏幕 }
4. 屏幕旋转设置(可选)
如果屏幕方向不正确,可以通过以下函数调整:
u8g2_SetDisplayRotation(&u8g2, U8G2_R0); // U8G2_R0 ~ U8G2_R3
5. 测试代码示例
void test_draw(void) { u8g2_ClearBuffer(&u8g2); u8g2_SetFont(&u8g2, u8g2_font_ncenB08_tr); // 设置字体 u8g2_DrawStr(&u8g2, 0, 10, "Hello 320x320"); // 绘制字符串 u8g2_SendBuffer(&u8g2); // 发送缓冲区到屏幕 }
- 性能问题:
lcd_draw_point逐像素绘制可能导致性能低下。对于大屏幕,建议使用DMA或批量传输优化。 - 颜色深度:示例中使用单色(1bit),若需彩色,需调整缓冲区大小和颜色处理逻辑。
- 坐标映射:确保
lcd_draw_point的坐标原点与u8g2一致(通常为左上角)。 - 缓冲区大小:320x320单色屏幕需要12800字节缓冲区,确保MCU内存充足。
通过以上步骤,你可以在u8g2中成功适配320x320屏幕,并利用lcd_draw_point作为底层绘图函数。
移植U8G2指南
U8G2库简介
U8G2是嵌入式设备的单色图形库,主要应用于嵌入式设备,包括我们常见的单片机。
移植
打开项目链接 看到项目的 README 介绍如下:
U8g2是一个用于嵌入式设备的单色图形库。
U8g2支持单色OLED和LCD,其中包括以下控制器:SSD1305、SSD1306、SSD1309、SSD1312、SSD1316、SSD1318、SSD1320、SSD1322、SSD1325、SSD1327、SSD1329、SSD1606、SSD1607、SH1106、SH1107、SH1108、 SH1122、T6963、RA8835、LC7981、PCD8544、PCF8812、HX1230、UC1601、UC1604、UC1608、UC1610、UC1611、UC1617、UC1638、UC1701、ST7511、ST7528、 ST7565、ST7567、ST7571、ST7586、ST7588、ST75160、ST75256、ST75320、NT7534、ST7920、IST3020、IST3088、IST7920、LD7032、KS0108、KS0713、HD44102、T7932、 SED1520、SBN1661、IL3820、MAX7219、GP1287、GP1247、GU800(完整列表请参见此处)。
U8g2还包括U8x8库:
U8g2
包括所有图形程序(线/框/圆绘制)。
支持多种字体。 (几乎)对字体高度没有限制。
微控制器中需要一些内存来渲染显示。
U8x8
仅文本输出(字符)设备。
仅允许适合 8x8 像素网格的字体。
直接写入显示器。微控制器中不需要缓冲器。
点击 Setup Guide and Reference Manual
在此之前,可以先将项目源码下载到本地。将项目移动到我们的工程目录下,打开我们下载的u8g2源码,可以看到里面有许多文件夹。其他的文件夹里面都是一些说明文档,可以不用关注,注意红框标注的 csrc 文件夹,这里面存放的都是我们所需要的源码。

将 csrc 文件夹复制到新的目录下,我这里复制到了 ./U8g2 打开复制的 csrc 文件夹,可以看到里面有许多.c文件。注意到有许多U8x8_d_*****类型的c文件,这是针对不同的驱动芯片所写的驱动程序,我们只选择我们需要的就行,其他的在移植到自己的工程的时候,可以把删除。我们此次使用的是ssd1306,因此在移植的时候,只保留ssd1306相关的驱动程序就可以了(图中画红线的部分)。
删除掉不需要的文件,最终需要的文件列表如下图所示:

到这一步距离成功仅有一步之遥了,接下来我们需要实现接口即可。
驱动程序
driver_u8g2_interface.h
driver_u8g2_interface.c