esp32 使用u8g2图形库 IIC驱动OLED

news2024/11/26 3:28:44

简介:

使用U8g2库进行OLED的显示十分简单,首先要包含两个库,U8g2lib和Wire,后者是IIC通信需要用。

对于IIC接口的OLED,需要在程序中指定一下引脚的接口定义,如果是SPI接口,可以参考U8g2库自带例程中SPI接口是使用方法。

工程创建:

    • 新建工程:

    • 导入u8g2库

3.添加头文件和引脚定义

相关API:

初始化:

在Ardunio的setup中进行u8g2的初始化。

#include <U8g2lib.h>
#include <Wire.h>
 
#define SCL 5
#define SDA 4
 
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /*clock=*/SCL, /*data=*/SDA, /*reset=*/U8X8_PIN_NONE);   
 
void setup()
{
  u8g2.begin();
  u8g2.enableUTF8Print(); // enable UTF8 support for the Arduino print() function
}

loop中的通用写法:

在Ardunio的loop中编写自己想要的代码逻辑,温馨提醒,在U8g2库在loop中的通用写法是使用do{}while()的形式:

  u8g2.firstPage();
  do
  {
    //自己的的逻辑
  } while (u8g2.nextPage());
  delay(1000);

U8g2常用API函数 :基础设置

setFont(font) 设置字体

  • font:u8g2的字体,比较常用的有u8g2_font_unifont_t_symbols(通常使用这个)和u8g2_font_wqy12_t_gb2312b(用于显示汉字)等

setFontMode(num) 设置字体背景颜色模式

  • num:启用(1)透明模式

  • num:禁用(0)透明模式

setDrawColor(color) 设置所有绘图函数的位值

  • color:0(显示RAM中的清晰像素值)

  • color:1(设置像素值)

  • color:2(异或模式)

drawPixel(x,y) 画像素点

  • x、y:像素点的坐标

例如我们可以显示所有的点:

#include <U8g2lib.h>
#include <Wire.h>
 
#define SCL 5
#define SDA 4
//定义了一个宏定义,用于延时显示每一次的画图,方便观察OLED的显示过程:
#define SEND_BUFFER_DISPLAY_MS(ms)\
  do {\
    u8g2.sendBuffer(); \
    delay(ms);\
  }while(0);
 
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /*clock=*/SCL, /*data=*/SDA, /*reset=*/U8X8_PIN_NONE);   
 
void setup()
{
  u8g2.begin();
  u8g2.enableUTF8Print(); // enable UTF8 support for the Arduino print() function
}
 
//画像素点-填充屏幕
void testDrawPixelToFillScreen()
{
  int t = 1000;
  u8g2.clearBuffer();
 
  for (int j = 0; j < 64; j++)
  {
    for (int i = 0; i < 128; i++)
    {
      u8g2.drawPixel(i, j);
    }
  }
  SEND_BUFFER_DISPLAY_MS(t);
}
void loop()
{
  testDrawPixelToFillScreen();
 
}
 
 

画直线:

1.drawLine(x0,y0,x1,y1) 画一条线:

  • x0,y0线的起点

  • x1,y1线的终点

2.drawHLine(x,y,w) 画一条水平线:

  • x,y线的起点

  • w水平线的长度(宽度)

3.drawVLine(x,y,h) 画一条竖直线:

  • x,y线的起点

  • h竖直线的长度(高度)

测试函数:

//画直线
void testDrawLine()
{
  int t = 500;
  u8g2.clearBuffer();
  u8g2.drawStr(33, 14, "drawLine");
 
  u8g2.drawLine(0, 0, 127, 63);
  SEND_BUFFER_DISPLAY_MS(t);
  u8g2.drawLine(0, 0, 127, 0);
  SEND_BUFFER_DISPLAY_MS(t);
  u8g2.drawLine(32, 15, 127, 15);
  SEND_BUFFER_DISPLAY_MS(t);
  u8g2.drawLine(33, 16, 127, 16);
  SEND_BUFFER_DISPLAY_MS(t);
  u8g2.drawLine(127, 0, 127, 15);
  SEND_BUFFER_DISPLAY_MS(t);
  u8g2.drawLine(127, 16, 127, 63);
  SEND_BUFFER_DISPLAY_MS(t);
}

画空心/实心(圆角)矩形:

1.drawFrame(x,y,w,h) 绘制一个空心框

2.drawBox(x,y,w,h) 绘制一个实心矩形

3.drawRFrame(x,y,w,h,r) 绘制一个空心框(圆角)

4.drawRBox(x,y,w,h,r) 绘制一个实心矩形 (圆角)

  • x,y起点坐标

  • w,h框的宽度和高度

  • r圆角的半径

5.测试函数:

//画空心圆角矩形
void testDrawRFrame()
{
  int t = 500;
  int x = 16;
  int y = 32;
  int w = 50;
  int h = 20;
  int r = 3;
  u8g2.clearBuffer();
  u8g2.drawStr(0, 15, "drawRFrame");
 
  u8g2.drawRFrame(x, y, w, h, r);
  SEND_BUFFER_DISPLAY_MS(t);
  u8g2.drawRFrame(x+w+5, y-10, w-20, h+20, r);
  SEND_BUFFER_DISPLAY_MS(t);
}

画空心实心圆:

    • drawCircle(x,y,rad,opt) 绘制一个空心圆

    • drawDisc(x,y,rad,opt) 绘制一个实心圆

  • x,y为圆心坐标

  • rad为圆的半径

  • opt为选择画的部分,分为:

U8G2_DRAW_UPPER_RIGHT(右上)

U8G2_DRAW_UPPER_LEFT(左上)

U8G2_DRAW_LOWER_LEFT(左下)

U8G2_DRAW_LOWER_RIGHT(右下)

U8G2_DRAW_ALL(全部)

    • 测试函数:

空心圆:

//画空心圆
void testDrawCircle()
{
  int t = 500;
  int stx = 0;  //画图起始x
  int sty = 16; //画图起始y
  int with = 16;//一个图块的间隔
  int r = 15;   //圆的半径
  u8g2.clearBuffer();
  u8g2.drawStr(0, 15, "drawCircle");
 
  u8g2.drawCircle(stx, sty - 1 + with, r, U8G2_DRAW_UPPER_RIGHT); //右上
  SEND_BUFFER_DISPLAY_MS(t);
  u8g2.drawCircle(stx + with, sty, r, U8G2_DRAW_LOWER_RIGHT); //右下
  SEND_BUFFER_DISPLAY_MS(t);
  u8g2.drawCircle(stx - 1 + with * 3, sty - 1 + with, r, U8G2_DRAW_UPPER_LEFT); //左上
  SEND_BUFFER_DISPLAY_MS(t);
  u8g2.drawCircle(stx - 1 + with * 4, sty, r, U8G2_DRAW_LOWER_LEFT); //左下
  SEND_BUFFER_DISPLAY_MS(t);
  u8g2.drawCircle(stx - 1 + with * 2, sty - 1 + with * 2, r, U8G2_DRAW_ALL);//整个圆
  SEND_BUFFER_DISPLAY_MS(t);
}

注意,U8g2库画出的圆,因像素点的显示原理,圆的直径占用的宽度不是半径的2倍,而是2倍再加一个像素点

画空心/实心椭圆

    • drawEllipse(x,y,rx,ry,opt) 绘制一个空心椭圆

    • drawFilledEllipse(x,y,rx,ry,opt) 绘制一个实心椭圆

  • x,y为圆心坐标

  • rx,ry为与椭圆x和y方向的半径

  • opt与画圆时的作用一致

椭圆的显示与圆的显示类似,只是椭圆可以分别指定x和y方向的半径

字符串、汉字和变量显示:

字符串的显示,可以使用drawStr函数,也可以使用通用风格的print函数。

drawStr(x,y,string) 绘制一个字符串

  • x,y起点坐标

  • string字符串

print(""),打印显示:

如果想要使用print显示汉子,需要先设置如下两句:

u8g2.enableUTF8Print();//enable UTF8
u8g2.setFont(u8g2_font_wqy12_t_gb2312b);//设置中文字符集

如果想要显示变量,使用print函数即可。

测试函数

//字符串/文字/变量显示测试
void testDrawStr()
{
  int t = 1000;
  u8g2.clearBuffer();
  u8g2.drawStr(0, 14, "drawStr / print");
  SEND_BUFFER_DISPLAY_MS(t);
 
  u8g2.drawStr(0, 32, "~!@#$%^&*()_+");
  SEND_BUFFER_DISPLAY_MS(t);
 
  u8g2.enableUTF8Print();//enable UTF8
  u8g2.setFont(u8g2_font_wqy12_t_gb2312b);//设置中文字符集
  u8g2.setCursor(0, 48);
  u8g2.print("码农爱学习");
  SEND_BUFFER_DISPLAY_MS(t);
 
  int a = 234;
  u8g2.setCursor(0, 64);
  u8g2.print("int a = ");
  u8g2.setCursor(40, 64);
  u8g2.print(a);//显示变量
  SEND_BUFFER_DISPLAY_MS(t);
}

画内置图标:

drawGlyph(x,y,addr) 绘制U8g2内置的图标

  • x,y起点坐标

  • addr内置图标的地址

U8g2库内置了需要预先定义的图形,通过drawGlyp函数以及指定的地址,即可看OLED上显示对应的图标:

各个图形的地址定义如下:

测试程序:

void testGlyph()
{
  int t = 1000;
  u8g2.clearBuffer();
  u8g2.drawStr(0, 14, "drawGlyph");
 
  u8g2.drawGlyph(0, 32, 0x23f0);
  SEND_BUFFER_DISPLAY_MS(t);
 
  u8g2.drawGlyph(16, 32, 0x23f3);
  SEND_BUFFER_DISPLAY_MS(t);
 
  u8g2.drawGlyph(32, 32, 0x2603);
  SEND_BUFFER_DISPLAY_MS(t);
 
  u8g2.drawGlyph(48, 32, 0x2615);
  SEND_BUFFER_DISPLAY_MS(t);
 
  u8g2.drawGlyph(64, 32, 0x2618);
  SEND_BUFFER_DISPLAY_MS(t);
}

画自定义图片

drawXBM(x,y,w,h,addr) 绘制自定义图片

  • x,y起点坐标

  • w,h图片的宽度和高度`

  • addr图片(数组)的地址

测试程序:

// width: 128, height: 48
const unsigned char bilibili[] U8X8_PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ... 省略若干行 };
 
void testDrawXBM()
{
  int t = 1000;
  u8g2.clearBuffer();
  u8g2.drawStr(0, 14, "drawXBM");
  u8g2.drawXBM(0, 16, 128, 48, bilibili);
  SEND_BUFFER_DISPLAY_MS(t);
}

总结:

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Leetcode】NC31 第一个只出现一次的字符(牛客网)、面试题 01.01. 判定字符是否唯一

作者&#xff1a;一个喜欢猫咪的的程序员 专栏&#xff1a;《Leetcode》 喜欢的话&#xff1a;世间因为少年的挺身而出&#xff0c;而更加瑰丽。 ——《人民日报》 NC31 第一个只出现一次的字符 第一个只出现一次的字符_牛客题霸_牛客网【牛…

数据结构与算法(三)——顺序查找和二分查找

什么是查找 在一些数据元素中&#xff0c;通过一定的方法找出与给定关键字相同的数据元素的过程。 什么是列表查找 也叫线性表查找&#xff0c;从列表中查找指定元素 列表查找是一种算法&#xff0c;对应的自然就有输入和输出&#xff1a; 输入&#xff1a;列表、待查找元素…

【实际开发08】- Controller 层处理入参 , 可避免进去 impl 层

目录 1. 增 / 删 / 改 - 记录日志 , 查询不记录日志 2. 第一批次 : 参数校验 ( id、id1 id2 、&#xff1f;) 3. 增 / 改 dto 判空 , 实体类层 ( entity ) 进行处理 4. 通用修改 的 impl 层可供 ( status、普通 ) 使用 5. 入参优先级 : Json > Map > Javabean 1. …

终于有人将Session和cookie讲明白了!一节课彻底搞懂

1 引出session cookie session与cookie属于一种会话控制技术。常用在身份识别&#xff0c;登录验证&#xff0c;数据传输等。举个例子&#xff0c;就像我们去超市买东西结账的时候&#xff0c;我们要拿出我们的会员卡才会获取优惠。这时候&#xff0c;我们怎么识别这个会员卡真…

软考那些事儿,看这一篇就够了!

软考7个常见问题解答一、报考条件凡遵守中华人民共和国宪法和各项法律&#xff0c;恪守职业道德&#xff0c;具有一定计算机技术应用能力的人员&#xff0c;均可根据本人情况&#xff0c;报名参加相应专业类别、级别的考试。因此&#xff0c;计算机软件资格考试报名条件不设学历…

ITIL 问题管理综合指南

什么是ITIL问题管理 问题是多个事件的原因或潜在原因。影响许多用户的重大事件或重复发生的事件可能会出现问题。此外&#xff0c;可以在基础设施诊断系统中识别问题之前 用户会受到影响。 事件会阻碍业务生产力&#xff0c;提供快速解决方案有助于确保业务运营的无缝连续性。…

第四章SpringFramework之Ioc

文章目录IoC思想认识什么叫依赖/耦合控制反转和依赖注入的理解IoC&#xff1a;Inversion of Control&#xff0c;控制反转。DI&#xff1a;Dependency Injection&#xff0c;翻译过来是依赖注入。为什么需要这样齿轮的例子来突出Ioc的重要IOC容器在Spring中的实现Spring 提供了…

剑指 Offer 36. 二叉搜索树与双向链表

剑指 Offer 36. 二叉搜索树与双向链表 难度中等619 输入一棵二叉搜索树&#xff0c;将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点&#xff0c;只能调整树中节点指针的指向。 为了让您更好地理解问题&#xff0c;以下面的二叉搜索树为例&#xff1a…

【翻车现场】初读《编程之美》就想秀一下,结果还翻车了

文章目录 一、前言 二、我的思路 三、Code 四、翻车现场 五、后续问题 一、前言 ———如何写一个短小的程序&#xff0c;让 Windows 的任务管理器显示CPU的占用率为50%? 这道有趣的面试题我是这两天从《编程之美》电子版中看到的&#xff0c;看意思就是邹老师在微软对一…

LabVIEW写入可快速加载的TDMS文件

LabVIEW写入可快速加载的TDMS文件TDMS文件格式的设计目的是在尽可能快地读写数据的同时仍保持足够的灵活性来适应采集过程中通道数量和采样率的变化。 但是数据读写速度快的文件未必可快速加载。 TDMS文件是一个完全的二进制文件&#xff0c;由多个部分数据段组成&#xff0c;在…

多线程~实现一个自己的线程池,以及基于单例模式的线程池

目录 1.线程池的概念 2.线程池的实现 3.基于单例模式的线程池 &#xff08;1&#xff09;.单例模式的概念 &#xff08;2&#xff09;.基于单例模式的线程池 1.线程池的概念 池化技术本质上都是为了提高效率。线程池也是同理&#xff0c;提前准备好一些线程&#xff0c;用…

Lesson 1. 线性回归模型的一般实现形式

文章目录一、线性回归模型建模准备1. 数据准备2. 模型准备二、线性回归模型训练1. 模型训练的本质&#xff1a;有方向的参数调整1.1 模型训练与模型参数调整1.2 模型评估指标与损失函数1.3 损失函数与参数求解2. 利用最优化方法求解损失函数2.1 损失函数的求解2.2 图形展示损失…

【DevOps实战|基于Jenkins与Gitlab构建企业级持续集成环境系统】(更新中未完成)

目录 一、DevOps简介 二、CI/CD简介 1、代码部署的最基本流程 2、软件开发生命周期 3、持续集成整体流程 三、Git简介 1、GitHub与Gitlab区别 四、基于Jenkins与Gitlab构建持续集成环境系统 1、环境说明 2、安装gitlab 1&#xff09;配置邮件报警 一、DevOps简介 De…

目标检测的新范式:Towards Open World Object Detection

论文题目&#xff1a;Towards Open World Object Detection 1 摘要 人类有一种识别其环境中未知物体实例的自然本能(natural instinct)。当这些未知的实例最终获得相应的知识时&#xff0c;对它们的内在好奇心有助于了解它们。这促使我们提出一种新的计算机视觉问题称为&…

Week 11

洛谷P1796 汤姆斯的天堂梦 题目描述 汤姆斯生活在一个等级为 000 的星球上。那里的环境极其恶劣&#xff0c;每天 121212 小时的工作和成堆的垃圾让人忍无可忍。他向往着等级为 NNN 的星球上天堂般的生活。 有一些航班将人从低等级的星球送上高一级的星球&#xff0c;有时需…

算法第十四期——动态规划(DP)初入门

目录 DP初步:状态转移与递推 最少硬币问题 DP基础 DP的两个特征 DP:记忆化 图解DP求解过程 最经典的DP问题&#xff1a;0/1背包 模板题&#xff1a;小明的背包 DP状态设计 DP状态转移方程&#xff08;重点&#xff09; 代码 空间优化:滚动数组 (1&#xff09;交替滚…

【机组组合】基于Benders分解算法解决混合整数规划问题——机组组合问题(Matlab代码实现)

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

【鸟哥杂谈】腾讯云 CentOS8 Linux环境下通过docker安装mysql

忘记过去&#xff0c;超越自己 ❤️ 博客主页 单片机菜鸟哥&#xff0c;一个野生非专业硬件IOT爱好者 ❤️❤️ 本篇创建记录 2023-01-15 ❤️❤️ 本篇更新记录 2023-01-15 ❤️&#x1f389; 欢迎关注 &#x1f50e;点赞 &#x1f44d;收藏 ⭐️留言&#x1f4dd;&#x1f64…

Vite中如何更好的使用TS

TS 是JS的一个类型检查工具&#xff0c;检查我们代码中可能会存在的一些隐形问题&#xff1b;同时可以使我们的编译器具备一些语法提示功能。 如果我们使用create-vue&#xff08;vue3官方脚手架工具&#xff09;创建了项目&#xff0c;该项目基于 Vite 且 TypeScript 已经准备…

SpringBoot+Vue使用easypol出现无法导出Excel表的问题

本篇博文目录1.异常信息2.原因3.解决办法4.详细的SpringBooteasypol前后端分离实现excel导出的步骤1.异常信息 今天在使用easypol导出Excel表的时候,发现能够从后端接口返回数据&#xff0c;但是就是无法导出Excel,控制台输出devicepolicies:1 Uncaught (in promise) error,并且…