968|3

445

帖子

0

TA的资源

纯净的硅(初级)

楼主
 

【全能小网关|CH32V208】--8.图形库u8g2的oled显示 [复制链接]

 
本帖最后由 dirty 于 2024-7-19 22:34 编辑

      本篇讲述使用u8g2图形库驱动oled显示,使用改图形库优势功能强大,具有字体库,包含中文GB2312,显示汉字非常方便全面,不用取模工具去取汉字点阵,此外也有很多可界面设计的API函数,非常推荐实际工程项目中使用。

 

一.准备工作

      本次使用ssd1306驱动OLED屏,像素分辨率128*32,I2C接口。u8g2是单色显示库的第二个版本,其是开源的。u8g2支持lcd和oled,支持众多驱动芯片,包含了SSD1306,具体支持驱动情况可以资源库查看到。

硬件连接如下:

开发板     OLED

PB9      SDA

PB8      SCL   

3V3       VCC

GND     GND

 

二.代码准备

      本工程移植支持ssd1306 128*64/128*32分辨率,通过如下宏选择使用。移植中注意根据需要裁剪,不需要的尽量删掉,避免占用资源。

#define SSD1306_128x64  1
#define SSD1306_128x32  2

#define SSD1306_DEVICE  SSD1306_128x32//SSD1306_128x64//

1.u8g2资源克隆下来后,使用scrc文件里资源

2.删除u8x8_d_xxx.c非相关驱动源文件.这里选择 ssd1306 128x64/128x32(选其中一个)

3.u8g2_d_setup.c源文件选择使用的驱动芯片初始化函数,删除其他。这里保留选择u8g2_Setup_ssd1306_i2c_128x64_noname_f/u8g2_Setup_ssd1306_i2c_128x32_univision_f

4.修改“u8g2_d_memory.c”文件,这个文件里面其实就是“u8g2_d_setup.c”文件对应的缓冲区,同上面一样,屏蔽掉没用到的,留下用到的

5.关于字库.u8g2_fonts.c”文件中定义了各种字库,这些字库比较占用空间,根据使用情况屏蔽掉没有使用的。使用到GB2312字体库,需要使能宏U8G2_USE_LARGE_FONTS。具体做法如下:

图1:使能GB2312字体库

6.两个回调函数
void u8g2_Setup_ssd1306_i2c_128x64_noname_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);参数byte_cb和gpio_and_delay_cb是需要编写的两个回调函数。byte_cb:是通信相关的函数,比如i2c写数据,gpio_and_delay_cb:是延时相关的函数。通信函数分为硬件接口和软件模拟方式,软件模拟方式官方基本写好了,只需要简单的指定io口即可。这里使用硬件方式。实现如下:

uint8_t u8x8_byte_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
      static uint8_t buffer[32]; /* u8g2/u8x8 will never send more than 32 bytes between START_TRANSFER and END_TRANSFER */
      static uint8_t buf_idx;
      uint8_t *data;

      switch (msg)
      {
      case U8X8_MSG_BYTE_SEND:
            data = (uint8_t *)arg_ptr;
            while (arg_int > 0)
            {
                  buffer[buf_idx++] = *data;
                  data++;
                  arg_int--;
            }
            break;

      case U8X8_MSG_BYTE_INIT:
            /* add your custom code to init i2c subsystem */
            break;

      case U8X8_MSG_BYTE_START_TRANSFER:
            buf_idx = 0;
            break;

      case U8X8_MSG_BYTE_END_TRANSFER:
            HW_I2cWrite(buffer, buf_idx);   //硬件I2C写字节
            break;

      default:
            return 0;
      }
      return 1;
}

uint8_t u8g2_gpio_and_delay(U8X8_UNUSED u8x8_t *u8x8, U8X8_UNUSED uint8_t msg, U8X8_UNUSED uint8_t arg_int, U8X8_UNUSED void *arg_ptr)
{
      switch (msg)
      {
      case U8X8_MSG_GPIO_AND_DELAY_INIT:
            OLED_I2C_Init();    //初始化
            break;

      case U8X8_MSG_DELAY_MILLI:
            Delay_Ms(arg_int);  //延时
            break;

      case U8X8_MSG_GPIO_I2C_CLOCK:
            break;

      case U8X8_MSG_GPIO_I2C_DATA:
            break;

      default:
            return 0;
      }
      return 1; // command processed successfully.
}

7.u8g2初始化

void u8g2_Init(u8g2_t *u8g2)
{
     #if(SSD1306_DEVICE==SSD1306_128x64)
	  u8g2_Setup_ssd1306_i2c_128x64_noname_f(u8g2, U8G2_R0, u8x8_byte_hw_i2c, u8g2_gpio_and_delay); // 初始化 u8g2,硬件I2C
      #elif(SSD1306_DEVICE==SSD1306_128x32)
	  u8g2_Setup_ssd1306_i2c_128x32_univision_f(u8g2, U8G2_R0, u8x8_byte_hw_i2c, u8g2_gpio_and_delay);
	  #endif
	  u8g2_InitDisplay(u8g2); 		//根据所选芯片初始化,完成后显示器处于关闭状态                                                                      // 根据所选的芯片进行初始化工作,初始化完成后,显示器处于关闭状态
      u8g2_SetPowerSave(u8g2, 0); 	//唤醒显示器                                                                 
      u8g2_SetContrast(u8g2, 88);  	//设置对比度                                                                
      u8g2_ClearBuffer(u8g2);    	//清除显示缓存                                                                
}

8.设计界面

(1)画对角线

   #if(SSD1306_DEVICE==SSD1306_128x64)
	u8g2_DrawLine(&u8g2, 0, 0, 127, 63); // 画一条线,起始坐标(0,0),终点坐标(127,63)
	u8g2_SendBuffer(&u8g2);              // 发送缓冲区数据
	u8g2_DrawLine(&u8g2, 127, 0, 0, 63);
	u8g2_SendBuffer(&u8g2);
    #elif(SSD1306_DEVICE==SSD1306_128x32)
	u8g2_DrawLine(&u8g2, 0, 0, 127, 31); // 画一条线,起始坐标(0,0),终点坐标(127,63)
    u8g2_SendBuffer(&u8g2);              // 发送缓冲区数据
    u8g2_DrawLine(&u8g2, 127, 0, 0, 31);
    u8g2_SendBuffer(&u8g2);
    #endif

(2)画U8g2的Logo大体的,横着放,竖着放等。

void draw(u8g2_t *u8g2)
{
	#if(SSD1306_DEVICE==SSD1306_128x64)
	u8g2_SetFontMode(u8g2, 1);              /*字体模式选择*/
	u8g2_SetFontDirection(u8g2, 0);         /*字体方向选择*/
	u8g2_SetFont(u8g2, u8g2_font_inb24_mf); /*字库选择*/
	u8g2_DrawStr(u8g2, 0, 20, "U");

	u8g2_SetFontDirection(u8g2, 1);
	u8g2_SetFont(u8g2, u8g2_font_inb30_mn);
	u8g2_DrawStr(u8g2, 21, 8, "8");

	u8g2_SetFontDirection(u8g2, 0);
	u8g2_SetFont(u8g2, u8g2_font_inb24_mf);
	u8g2_DrawStr(u8g2, 51, 30, "g");
	u8g2_DrawStr(u8g2, 67, 30, "\xb2");

	u8g2_DrawHLine(u8g2, 2, 35, 47);
	u8g2_DrawHLine(u8g2, 3, 36, 47);
	u8g2_DrawVLine(u8g2, 45, 32, 12);
	u8g2_DrawVLine(u8g2, 46, 33, 12);

	u8g2_SetFont(u8g2, u8g2_font_4x6_tr);
	u8g2_DrawStr(u8g2, 1, 54, "github.com/olikraus/u8g2");

	#elif(SSD1306_DEVICE==SSD1306_128x32)

	u8g2_SetFontMode(u8g2, 1);              /*字体模式选择*/
	u8g2_SetFontDirection(u8g2, 0);         /*字体方向选择*/
	u8g2_SetFont(u8g2, u8g2_font_inb24_mf); /*字库选择*/
	u8g2_DrawStr(u8g2, 0, 24, "U");

	u8g2_SetFontDirection(u8g2, 1);
	u8g2_SetFont(u8g2, u8g2_font_inb30_mn);
	u8g2_DrawStr(u8g2, 24, 8, "8");

	u8g2_SetFontDirection(u8g2, 0);
	u8g2_SetFont(u8g2, u8g2_font_inb24_mf);
	u8g2_DrawStr(u8g2, 64, 24, "g");
	u8g2_DrawStr(u8g2, 96, 32, "\xb2");

	#endif

}

(3)显示中英文。这里显示我们EEWorld和沁恒相关的。

	#if(SSD1306_DEVICE==SSD1306_128x64)
	u8g2_ClearBuffer(&u8g2);
	u8g2_SetFont(&u8g2, u8g2_font_ncenB14_tr);    //选择字库
	u8g2_DrawStr(&u8g2, 0, 15, "Hello World!");

	u8g2_SetFont(&u8g2, u8g2_font_wqy16_t_chinese2);
	u8g2_DrawUTF8(&u8g2, 0, 30, "H你好世界");

	u8g2_SetFont(&u8g2, u8g2_font_wqy12_t_chinese2);
	u8g2_DrawUTF8(&u8g2, 0, 43, "H你好世界");
	
	u8g2_SetFont(&u8g2, u8g2_font_fur11_tr);
	u8g2_DrawUTF8(&u8g2, 0, 59, "blog.zeruns.tech");
	#elif(SSD1306_DEVICE==SSD1306_128x32)
	u8g2_ClearBuffer(&u8g2);
	u8g2_SetFont(&u8g2, u8g2_font_ncenB14_tr);    //选择字库
	u8g2_DrawStr(&u8g2, 0, 14, "EEWorld");

	u8g2_SetFont(&u8g2, u8g2_font_wqy13_t_gb2312);
	u8g2_DrawUTF8(&u8g2, 0, 30, "沁恒");

	u8g2_SetFont(&u8g2, u8g2_font_ncenB08_tr);    //选择字库
	u8g2_DrawStr(&u8g2, 26, 30, "CH32V208");

	u8g2_SetFont(&u8g2, u8g2_font_wqy13_t_gb2312);
	u8g2_DrawUTF8(&u8g2, 80, 30, "开发板");

	#endif

(4)循环显示渐变同心圆。

	while(1)
	{
	    Delay_Ms(100);
		u8g2_ClearBuffer(&u8g2);//清除缓冲区数据
		#if(SSD1306_DEVICE==SSD1306_128x64)
		if (++t >= 32)
			t = 1;
		u8g2_DrawCircle(&u8g2, 64, 32, t, U8G2_DRAW_ALL);   //画圆
		u8g2_DrawCircle(&u8g2, 32, 32, t, U8G2_DRAW_ALL);
		u8g2_DrawCircle(&u8g2, 96, 32, t, U8G2_DRAW_ALL);
		u8g2_SendBuffer(&u8g2); // 发送缓冲区数据
		#elif(SSD1306_DEVICE==SSD1306_128x32)
		if (++t >= 16)
			t = 1;
		u8g2_DrawCircle(&u8g2, 64, 16, t, U8G2_DRAW_ALL);   //画圆
		u8g2_DrawCircle(&u8g2, 32, 16, t, U8G2_DRAW_ALL);
		u8g2_DrawCircle(&u8g2, 96, 16, t, U8G2_DRAW_ALL);
		u8g2_SendBuffer(&u8g2); // 发送缓冲区数据

		#endif

	}

9.主函数如下。这里工程u8g2源文件添加等就不具体讲了。

int main(void)
{
	uint8_t t = 0;

    SystemCoreClockUpdate();
    Delay_Init();
    USART_Printf_Init(115200);
    printf( "SystemClk:%d\r\n", SystemCoreClock );
    printf( "ChipID:%08x\r\n", DBGMCU_GetCHIPID() );

	OLED_I2C_Init();

    u8g2_Init(&u8g2);     //初始化U8g2
	Delay_Ms(100);

    #if(SSD1306_DEVICE==SSD1306_128x64)
	u8g2_DrawLine(&u8g2, 0, 0, 127, 63); // 画一条线,起始坐标(0,0),终点坐标(127,63)
	u8g2_SendBuffer(&u8g2);              // 发送缓冲区数据
	u8g2_DrawLine(&u8g2, 127, 0, 0, 63);
	u8g2_SendBuffer(&u8g2);
    #elif(SSD1306_DEVICE==SSD1306_128x32)
	u8g2_DrawLine(&u8g2, 0, 0, 127, 31); // 画一条线,起始坐标(0,0),终点坐标(127,63)
    u8g2_SendBuffer(&u8g2);              // 发送缓冲区数据
    u8g2_DrawLine(&u8g2, 127, 0, 0, 31);
    u8g2_SendBuffer(&u8g2);
    #endif

	Delay_Ms(300);

	u8g2_ClearBuffer(&u8g2);  //清除缓冲区数据
	draw(&u8g2);
	u8g2_SendBuffer(&u8g2);
	Delay_Ms(1000);
	
	#if(SSD1306_DEVICE==SSD1306_128x64)
	u8g2_ClearBuffer(&u8g2);
	u8g2_SetFont(&u8g2, u8g2_font_ncenB14_tr);    //选择字库
	u8g2_DrawStr(&u8g2, 0, 15, "Hello World!");

	u8g2_SetFont(&u8g2, u8g2_font_wqy16_t_chinese2);
	u8g2_DrawUTF8(&u8g2, 0, 30, "H你好世界");

	u8g2_SetFont(&u8g2, u8g2_font_wqy12_t_chinese2);
	u8g2_DrawUTF8(&u8g2, 0, 43, "H你好世界");
	
	
	#elif(SSD1306_DEVICE==SSD1306_128x32)
	u8g2_ClearBuffer(&u8g2);
	u8g2_SetFont(&u8g2, u8g2_font_ncenB14_tr);    //选择字库
	u8g2_DrawStr(&u8g2, 0, 14, "EEWorld");

	u8g2_SetFont(&u8g2, u8g2_font_wqy13_t_gb2312);
	u8g2_DrawUTF8(&u8g2, 0, 30, "沁恒");

	u8g2_SetFont(&u8g2, u8g2_font_ncenB08_tr);    //选择字库
	u8g2_DrawStr(&u8g2, 26, 30, "CH32V208");

	u8g2_SetFont(&u8g2, u8g2_font_wqy13_t_gb2312);
	u8g2_DrawUTF8(&u8g2, 80, 30, "开发板");

	#endif

	u8g2_SendBuffer(&u8g2);

	Delay_Ms(1300);

	while(1)
	{
	    Delay_Ms(100);
		u8g2_ClearBuffer(&u8g2);//清除缓冲区数据
		#if(SSD1306_DEVICE==SSD1306_128x64)
		if (++t >= 32)
			t = 1;
		u8g2_DrawCircle(&u8g2, 64, 32, t, U8G2_DRAW_ALL);   //画圆
		u8g2_DrawCircle(&u8g2, 32, 32, t, U8G2_DRAW_ALL);
		u8g2_DrawCircle(&u8g2, 96, 32, t, U8G2_DRAW_ALL);
		u8g2_SendBuffer(&u8g2); // 发送缓冲区数据
		#elif(SSD1306_DEVICE==SSD1306_128x32)
		if (++t >= 16)
			t = 1;
		u8g2_DrawCircle(&u8g2, 64, 16, t, U8G2_DRAW_ALL);   //画圆
		u8g2_DrawCircle(&u8g2, 32, 16, t, U8G2_DRAW_ALL);
		u8g2_DrawCircle(&u8g2, 96, 16, t, U8G2_DRAW_ALL);
		u8g2_SendBuffer(&u8g2); // 发送缓冲区数据

		#endif

	}
}

 

三.测验

      编译烧录后,可以看到惊艳的显示效果如下,使用u8g2做关于oled的显示设计,真的很丰富灵活。

 

 

      效果视频如下:

u8g2_oled_show

 

      源代码该文下置顶帖,敬请关注。

 

最新回复

 本篇讲述使用u8g2图形库驱动oled显示,使用改图形库优势功能强大,具有字体库,包含中文GB2312,显示汉字非常方便全面,不用取模工具去取汉字点阵,此外也有很多可界面设计的API函数,非常推荐实际工程项目中使用。 flash够用吗?   详情 回复 发表于 2024-7-20 11:50
点赞 关注
 
 

回复
举报

445

帖子

0

TA的资源

纯净的硅(初级)

来自 2楼
 

图形库u8g2的oled工程

 

CH32V20x_OLED.rar

14.47 MB, 下载次数: 6

CH32V20x_U8g2_OLED 工程

 
 
 

回复

6841

帖子

11

TA的资源

版主

板凳
 

 本篇讲述使用u8g2图形库驱动oled显示,使用改图形库优势功能强大,具有字体库,包含中文GB2312,显示汉字非常方便全面,不用取模工具去取汉字点阵,此外也有很多可界面设计的API函数,非常推荐实际工程项目中使用。

flash够用吗?

点评

够用,注意芯片用法,配置可到480K. U8g2使用中文库GB2312,资源消耗在300K左右。  详情 回复 发表于 2024-7-20 16:55
 
 
 

回复

445

帖子

0

TA的资源

纯净的硅(初级)

4
 
lugl4313820 发表于 2024-7-20 11:50  本篇讲述使用u8g2图形库驱动oled显示,使用改图形库优势功能强大,具有字体库,包含中文GB2312,显示 ...

够用,注意芯片用法,配置可到480K. U8g2使用中文库GB2312,资源消耗在300K左右。

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表