[低端局][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.rhkb.cn/news/84449.html

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

相关文章

【多维定向滤波器组和表面波】表面变换:用于高效表示多维 s 的多分辨率变换(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

mysql基础之触发器的简单使用

1.建立学生信息表 -- 触发器 -- 建立学生信息表 create table s1(id int unsigned auto_increment,name varchar(30),score tinyint unsigned,dept varchar(50),primary key(id) );2.建立学生补考信息表 -- 建立学生补考信息表 create table s2 like s1;3.建立触发器&#xf…

linux文件I/O之 close()、lseek()、read()、write() 函数用法

1. close() 函数 头文件和函数声明 #include <unistd.h> int close(int fd); 函数功能 关闭一个文件描述符 返回值 成功时返回 0。失败则返回 -1&#xff0c;并设置 errno 为相应的错误标志。 参数 fd&#xff1a;文件描述符 说明 像其它所有系统调用一样&…

二级python和二级c哪个简单,二级c语言和二级python

大家好&#xff0c;小编为大家解答二级c语言和二级office一起报可以吗的问题。很多人还不知道计算机二级c语言和python哪个好考&#xff0c;现在让我们一起来看看吧&#xff01; 介绍Python有很多库和使用Qt编写的接口,这自然创建c调用Python的需求。一路摸索,充满艰辛的添加头…

创建型模式-原型模式

文章目录 一、原型模式1. 概述2. 结构3. 实现4. 案例1.5 使用场景1.6 扩展&#xff08;深克隆&#xff09; 一、原型模式 1. 概述 用一个已经创建的实例作为原型&#xff0c;通过复制该原型对象来创建一个和原型对象相同的新对象。 2. 结构 原型模式包含如下角色&#xff1a; …

8月10日上课内容 Tomacat部署及优化

tomcat 开放源代码的web应用服务器。基于java代码开发的。 Tomcat介绍 tomcat就是处理动态请求和基于java代码的页面开发 可以在html当中写入java代码&#xff0c;tomcat可以解析html页面当中的java,执行动态请求&#xff0c;动态页面。缺点是机制有问题:不对tomcat进行优化&…

Hello,SpringBoot!

一、回顾什么是Spring Spring是一个开源框架&#xff0c;2003 年兴起的一个轻量级的Java 开发框架&#xff0c;作者&#xff1a;Rod Johnson Spring是为了解决企业级应用开发的复杂性而创建的&#xff0c;简化开发。 Spring是如何简化Java开发的 为了降低Java开发的复杂性…

mac安装nvm管理工具遇到的问题和解决方法

nvm 是一款可以管理多版本node的工具&#xff0c;因为是刚买没多久的电脑之前用的都是windows&#xff0c;昨天折腾了一下午终于倒腾好了 第一步&#xff1a; 卸载电脑已有的node&#xff1b;访问nvm脚本网址&#xff0c;另存为到电脑上任何目录&#xff0c;我是放在桌面上的…

【pinia】Pinia入门和基本使用:

文章目录 一、 什么是pinia二、 创建空Vue项目并安装Pinia1. 创建空Vue项目2. 安装Pinia并注册 三、 实现counter四、 实现getters五、 异步action六、 storeToRefs保持响应式解构七、基本使用&#xff1a;【1】main.js【2】store》index.js【3】member.ts 一、 什么是pinia P…

使用一个python脚本抓取大量网站【2/3】

一、说明 我如何使用一个 Python 脚本抓取大量网站&#xff0c;在第 2 部分使用 Docker &#xff0c;“我如何使用一个python脚本抓取大量网站”统计数据。在本文中&#xff0c;我将与您分享&#xff1a; Github存储库&#xff0c;您可以从中克隆它;链接到 docker 容器&#xf…

【Docker】Windows下docker环境搭建及解决使用非官方终端时的连接问题

目录 背景 Windows Docker 安装 安装docker toolbox cmder 解决cmder 连接失败问题 资料获取方法 背景 时常有容器方面的需求&#xff0c;经常构建调试导致测试环境有些混乱&#xff0c;所以想在本地构建一套环境&#xff0c;镜像调试稳定后再放到测试环境中。 Windows …

缓存平均的两种算法

引言 线边库存物料的合理性问题是物流仿真中研究的重要问题之一,如果线边库存量过多,则会对生产现场的布局产生负面影响,增加成本,降低效益。 写在前面 仿真分析后对线边Buffer的使用情况进行合理的评估就是一个非常重要的事情。比较关心的参数包括:缓存位最大值…

k8s-----集群调度

目录 一&#xff1a;调度约束 二&#xff1a;Pod 启动创建过程 三&#xff1a;k8s调度过程 1、Predicate 有一系列的常见的算法 2、常见优先级选项 3、指定调度节点 &#xff08;1&#xff09;nodeName指定 &#xff08;2&#xff09;nodeSelector指定 四&#xff1a;亲和…

基于金融行业的软件测试分析

随着银行业务不断增加&#xff0c;业务模式不断复杂化&#xff0c;对我们的银行软件也要求越来越高&#xff0c;产出高质量的产品也非常重要&#xff0c;下面对银行软件测试进行分析总结。 银行软件集中度高&#xff0c;规模庞大&#xff0c;往往是以系统群的方式存在&#xff…

【算法篇C++实现】五大常规算法

文章目录 &#x1f680;一、分治法⛳&#xff08;一&#xff09;算法思想⛳&#xff08;二&#xff09;相关代码 &#x1f680;二、动态规划算法⛳&#xff08;一&#xff09;算法思想⛳&#xff08;二&#xff09;相关代码 &#x1f680;三、回溯算法⛳&#xff08;一&#xf…

ELK 将数据流转换回常规索引

ELK 将数据流转换回常规索引 现象&#xff1a;创建索引模板是打开了数据流&#xff0c;导致不能创建常规索引&#xff0c;并且手动修改、删除索引模板失败 "reason" : "composable template [logs_template] with index patterns [new-pattern*], priority [2…

微服务Ribbon-负载均衡策略和饥饿加载

目录 一、负载均衡策略 1.1 负载均衡策略介绍 1.2 自定义负载均衡策略 二、饥饿加载 &#xff08;笔记整理自bilibili黑马程序员课程&#xff09; 一、负载均衡策略 1.1 负载均衡策略介绍 负载均衡的规则都定义在IRule接口中&#xff0c;而IRule有很多不同的实现类&…

uniapp 格式化时间刚刚,几分钟前,几小时前,几天前…

效果如图&#xff1a; 根目录下新建utils文件夹&#xff0c;文件夹下新增js文件&#xff0c;文件内容&#xff1a; export const filters {dateTimeSub(data) {if (data undefined) {return;}// 传进来的data必须是日期格式&#xff0c;不能是时间戳//将字符串转换成时间格式…

Vue3使用wangEditor

那么这一节我们在编辑公司信息的弹窗中使用富文本插件wangEditor官网 Vue3使用wangEditor 安装wangEditor在弹窗中引入wangEditor结构api接口部分editor组件script部分怎么去修改富文本的编辑器&#xff1f; 案例内效果&#xff1a; 安装wangEditor npm install wangeditor/…

RabbitMQ学习——发布订阅/fanout模式 topic模式 rabbitmq回调确认 延迟队列(死信)设计

目录 引出点对点(simple)Work queues 一对多发布订阅/fanout模式以登陆验证码为例pom文件导包application.yml文件rabbitmq的配置生产者生成验证码&#xff0c;发送给交换机消费者消费验证码 topic模式配置类增加配置生产者发送信息进行发送控制台查看 rabbitmq回调确认配置类验…