[低端局][cx32L003] 移植U8G2

文章目录

  • 一、简介
    • (1)U8g2
    • (2)U8x8
  • 二、配置要求
  • 三、移植步骤
    • (1)文件准备和添加
    • (2)实现回调接口(I2C的读写函数)
      • ①软件I2C
      • ②硬件I2C
    • (3)功能裁剪
      • ① u8g2_d_setup.c
      • ② u8g2_d_memory.c
      • ③ 关于字库

在低端芯片上使用U8G2

一、简介

U8g2:单色显示库,版本2

U8g2是一个用于嵌入式设备的单色图形库。U8g2支持单色oled和lcd,其中包括以下控制器:Ssd1305、ssd1306、ssd1309、ssd1312、ssd1316、ssd1318、ssd1320、ssd1322、ssd1325、ssd1327、ssd1327、ssd1327、ssd1327、ssd1327、ssd1327、ssd1106、sh1107、sh1108、ssd1607、hx1230、uc1601、uc1604、uc1608、pcd8544、pcf8812、hx1230、uc1601、uc1611、uc1617、uc1638、uc1701、st7511、st7528、st7565、st7567、st7586、st7588、st75160、st75256、st75320、nt7534、st7920、ist3020、ist3088、ist7920、ld7032、ks0108、ks0713、hd44102、t7932、sed1520、sbn1661、il3820、max7219、gp1287、gp1247、GU800(查看完整列表)。

Arduino库U8g2可以从Arduino IDE的库管理器中安装。U8g2还包括U8x8库:

(1)U8g2

  1. 包括所有图形程序(线/框/圆绘制)。

  2. 支持多种字体。(几乎)对字体高度没有限制。

  3. 在微控制器中需要一些内存来呈现显示。

(2)U8x8

  1. 仅文本输出(字符)设备。

  2. 只允许适合8x8像素网格的字体。

  3. 直接写入显示。在微控制器中不需要缓冲区。

二、配置要求

最少要求:
ROM:122+354+12+56+304+723+312+72+134+280+12+28+502+412+288+101+192+10+72=3986byte
RAM:0x80+0x01=0x81=129byte

在这里插入图片描述

在这里插入图片描述

RAM范围[128,1024],越大刷新越快。

Demo工程整体大小:NOS+IIC+GPIO+U8G2

  • Total RO Size (Code + RO Data) 9472 ( 9.25kB)
  • Total RW Size (RW Data + ZI Data) 880 ( 0.86kB)
  • Total ROM Size (Code + RO Data + RW Data) 9492 ( 9.27kB)

三、移植步骤

(1)文件准备和添加

  1. 下载文件(Gitee)
  2. 解压csrc到工程根目录在这里插入图片描述
  3. keil添加目录文件
    在这里插入图片描述

注意:带_d_是用户自定义文件,可以移动到工程中修改。

  1. keil添加头文件 [csrc的目录]
    在这里插入图片描述
  2. 添加驱动文件
    u8g2里面支持多种驱动芯片,以u8x8_d_xxx.c命名的就是驱动文件,本文使用的是0.96吋oled,芯片是ssd1306,因此只需将u8x8_d_ssd1312_128x64_noname.c这个驱动文件添加到工程中:
    在这里插入图片描述

(2)实现回调接口(I2C的读写函数)

void u8g2_Setup_ssd1306_i2c_128x64_noname_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb)

byte_cb:是通信相关的函数,比如i2c写数据,
gpio_and_delay_cb:是延时相关的函数。

①软件I2C

u8g2_Setup_ssd1306_i2c_128x64_noname_1(&u8g2, U8G2_R0, u8x8_byte_sw_i2c, gpio_and_delay); // init u8g2 structure

  1. u8x8_byte_sw_i2c官方已经实现 <–u8x8_byte.c
  2. 我们需要实现gpio_and_delay函数
uint8_t gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) {//printf("%s:msg = %d,arg_int = %d\r\n",__FUNCTION__,msg,arg_int);switch(msg) {case U8X8_MSG_DELAY_100NANO:		// delay arg_int * 100 nano seconds__NOP();break;case U8X8_MSG_DELAY_10MICRO:		// delay arg_int * 10 micro secondsfor (uint16_t n = 0; n < 320; n++) {__NOP();}     break;case U8X8_MSG_DELAY_MILLI:			// delay arg_int * 1 milli secondHAL_Delay(1);break;case U8X8_MSG_DELAY_I2C:		    // arg_int is the I2C speed in 100KHz, e.g. 4 = 400 KHz//delay 5usdelay_us(5);						// arg_int=1: delay by 5us, arg_int = 4: delay by 1.25uscase U8X8_MSG_GPIO_I2C_CLOCK:		// arg_int=0: Output low at I2C clock pinif(arg_int == 1) {HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_SET);} else if(arg_int == 0) {HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET);  }          break;							// arg_int=1: Input dir with pullup high for I2C clock pincase U8X8_MSG_GPIO_I2C_DATA:		// arg_int=0: Output low at I2C data pin//  printf("U8X8_MSG_GPIO_I2C_DATA:%d\r\n",arg_int);if(arg_int == 1)  {HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_SET);} else if(arg_int == 0) {HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_RESET);  }         break;							// arg_int=1: Input dir with pullup high for I2C data pincase U8X8_MSG_GPIO_MENU_SELECT:u8x8_SetGPIOResult(u8x8, /* get menu select pin state */ 0);break;case U8X8_MSG_GPIO_MENU_NEXT:u8x8_SetGPIOResult(u8x8, /* get menu next pin state */ 0);break;case U8X8_MSG_GPIO_MENU_PREV:u8x8_SetGPIOResult(u8x8, /* get menu prev pin state */ 0);break;case U8X8_MSG_GPIO_MENU_HOME:u8x8_SetGPIOResult(u8x8, /* get menu home pin state */ 0);break;default:u8x8_SetGPIOResult(u8x8, 1);		// default return valuebreak;}return 1;
}

②硬件I2C

跟软件实现方式类似

u8g2_Setup_ssd1306_i2c_128x64_noname_1(&u8g2, U8G2_R0, u8x8_byte_hw_i2c, gpio_and_delay); // init u8g2 structure

#define I2C_SPEED_RATE	100   //uint khz
I2C_HandleTypeDef i2c_test = {0};
FlagStatus i2c_int = RESET;main:
{__HAL_RCC_I2C_CLK_ENABLE();gpioi2c.Pin    = GPIO_PIN_5;gpioi2c.Mode = GPIO_MODE_AF; // GPIO端口复用功能 gpioi2c.Alternate = GPIO_AF4_I2C_SDA;gpioi2c.OpenDrain = GPIO_OPENDRAIN; // 开漏输出gpioi2c.Debounce.Enable = GPIO_DEBOUNCE_DISABLE; // 禁止输入去抖动gpioi2c.SlewRate = GPIO_SLEW_RATE_HIGH; // 电压转换速率gpioi2c.DrvStrength = GPIO_DRV_STRENGTH_HIGH; // 驱动强度gpioi2c.Pull = GPIO_PULLUP;			// 上拉HAL_GPIO_Init(GPIOB, &gpioi2c);gpioi2c.Pin = GPIO_PIN_4;gpioi2c.Mode = GPIO_MODE_AF;gpioi2c.Alternate = GPIO_AF4_I2C_SCL;gpioi2c.OpenDrain = GPIO_OPENDRAIN; gpioi2c.Debounce.Enable = GPIO_DEBOUNCE_DISABLE;gpioi2c.SlewRate = GPIO_SLEW_RATE_HIGH;gpioi2c.DrvStrength = GPIO_DRV_STRENGTH_HIGH;gpioi2c.Pull = GPIO_PULLUP;	HAL_GPIO_Init(GPIOB, &gpioi2c);i2c_test.Instance = I2C;i2c_test.Init.master = I2C_MASTER_MODE_ENABLE; // 主机模式使能i2c_test.Init.slave = I2C_SLAVE_MODE_DISABLE; // 从机模式禁止i2c_test.Mode = HAL_I2C_MODE_MASTER; // 主机模式i2c_test.Init.broadack = I2C_BROAD_ACK_DISABLE; // 广播地址应答禁止i2c_test.Init.speedclock = I2C_SPEED_RATE; // I2C传输速率  i2c_test.State = HAL_I2C_STATE_RESET; //HAL_I2C_Init(&i2c_test);
}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:HAL_I2C_Master_Transmit(&i2c_test, buffer[0], &buffer[1], buf_idx - 1);break;default:return 0;}return 1;
}uint8_t 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:break;case U8X8_MSG_DELAY_MILLI:HAL_Delay(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.
}

到此,移植完毕,但是编译失败,空间不足!

(3)功能裁剪

① u8g2_d_setup.c

  1. 注释全部函数
  2. 找到u8g2_Setup_ssd1306_i2c_128x64_noname_1函数,解除注释。
    在这里插入图片描述
    注:用缓存128举例。有条件的可以使用256,1024.
    u8g2_Setup_ssd1306_i2c_128x64_noname_1() --缓存128byte
    u8g2_Setup_ssd1306_i2c_128x64_noname_2() --缓存256byte
    u8g2_Setup_ssd1306_i2c_128x64_noname_f() --缓存1024byte

② u8g2_d_memory.c

  1. 注释全部函数
  2. 找到u8g2_m_16_8_1函数,解除注释。
    在这里插入图片描述

注:用缓存128举例。有条件的可以使用256,1024.
u8g2_Setup_ssd1306_i2c_128x64_noname_1() --缓存128byte
u8g2_Setup_ssd1306_i2c_128x64_noname_2() --缓存256byte
u8g2_Setup_ssd1306_i2c_128x64_noname_f() --缓存1024byte

u8g2_Setup_ssd1306_128x64_noname_1、
u8g2_Setup_ssd1306_128x64_noname_2、
u8g2_Setup_ssd1306_128x64_noname_f,
这些都是spi接口的;
u8g2_Setup_ssd1306_i2c_128x64_noname_1、
u8g2_Setup_ssd1306_i2c_128x64_noname_2、
u8g2_Setup_ssd1306_i2c_128x64_noname_f,
这些都是i2c接口的;
后缀1、2、f代表缓冲区大小的不同:
1代表128字节,
2代表256字节,
f代表1024字节;
根据单片机空间的大小选择合适的接口,缓冲区小的,刷新lcd/oled的时候就比较耗时,反之。

③ 关于字库

“u8g2_fonts.c”文件中定义了各种字库,这些字库比较占用空间,根据使用情况屏蔽掉没有使用的。

demo工程gitee

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/61434.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

NLP语言模型概览

语言模型结构分类 Encoder-Decoder&#xff08;Transformer&#xff09;: Encoder 部分是 Masked Multi-Head Self-Attention&#xff0c;Decoder 部分是 Casual Multi-Head Cross-Attention 和 Casual Multi-Head Self-Attention 兼具。比如T5&#xff0c;BART&#xff0c;MA…

家电用PCM板:市场现状研究分析与发展前景预测

家电PCM板属于一种兴起不久的功能性复合材料。属于家电复合外观材料中占比较大的一种。家电复合外观材料主要分为覆膜板&#xff08;VCM&#xff09;系列和有机涂层板&#xff08;PCM&#xff09;系列两大类&#xff1a;VCM系列表面复合各类功能性薄膜&#xff0c;可根据需要实…

整理mongodb文档:集合名字有类似-等特殊字符串如何处理?

个人博客 整理mongodb文档:集合名字有类似-等特殊字符串如何处理&#xff1f; 首先&#xff0c;先创建一个collection的名字为’collection-test’&#xff0c;这个表名中&#xff0c;colletion的名字有一个特殊字符串“-”&#xff0c;但是后面插入数据的时候会有这么一个错…

springboot汽车租赁后台java出租客户管理jsp源代码mysql

本项目为前几天收费帮学妹做的一个项目&#xff0c;Java EE JSP项目&#xff0c;在工作环境中基本使用不到&#xff0c;但是很多学校把这个当作编程入门的项目来做&#xff0c;故分享出本项目供初学者参考。 一、项目描述 springboot汽车租赁后台 系统有1权限&#xff1a;管理…

使用自己的数据集预加载 Elasticsearch

作者&#xff1a;David Pilato 我最近在讨论论坛上收到一个问题&#xff0c;关于如何修改官方 Docker 镜像以提供一个现成的 Elasticsearch 集群&#xff0c;其中已经包含一些数据。 说实话&#xff0c;我不喜欢这个想法&#xff0c;因为你必须通过提 entrypoint.sh 的分叉版本…

模板的进阶

目录 1.非类型模板参数 2.模板特化 2.1概念 2.2函数模板特化 2.3类模板特化 2.3.1全特化 2.3.2偏特化 3.模板分离编译 3.1什么是分离编译 3.2 模板的分离编译 3.3解决方法 4. 模板总结 1.非类型模板参数 模板参数分类类型形参与非类型形参。 类型形参即&#xff1a…

Qt应用开发(基础篇)——工具箱 QToolBox

一、前言 QToolBox类继承于QFrame&#xff0c;QFrame继承于QWidget&#xff0c;是Qt常用的基础工具部件。 框架类QFrame介绍 QToolBox工具箱类提供了一列选项卡窗口&#xff0c;当前项显示在当前选项卡下面&#xff0c;适用于分类浏览、内容展示、操作指引这一类的使用场景。 二…

华为新版ENSP PRO模拟器测评:性能表现与功能扩展一览

一、引言 在网络领域不断涌现的新技术和复杂的网络拓扑要求&#xff0c;推动了网络设备模拟器的持续发展和创新。华为作为一家领先的通信技术解决方案提供商&#xff0c;不断致力于为网络工程师和技术从业人员提供更优秀的仿真环境。最近&#xff0c;华为推出了ensp pro模拟器的…

怎么进行流程图制作?用这个工具制作很方便

怎么进行流程图制作&#xff1f;流程图是一种非常有用的工具&#xff0c;可以帮助我们更好地理解和展示各种复杂的业务流程和工作流程。它可以将复杂的过程简化为易于理解的图形和文本&#xff0c;使得人们更容易理解和跟踪整个流程。因此&#xff0c;制作流程图是在日常工作中…

yolov5代码解读之train.py【训练模型】

哇咔咔&#xff0c;登场 代码开头都是一些导包到模块的&#xff1a; 接下来来到入口函数&#xff1a; 我们直接来到main函数的内容&#xff1a;&#xff08;分四个部分&#xff09; 前两部分&#xff1a; 关于main函数的第二部分中的resume参数&#xff08;496行&#xff09;&…

taro Swiper组件--异形滚动

效果 <SwiperindicatorDots{false}previousMargin50pxnextMargin50pxautoplay{false}interval100onChange{onChangeSwiper} >{[1,2,3].map((item, index) > {return (<SwiperItemkey{item-${index}}><View className{demo-item ${currentIndex index ? ac…