Arduino 入门学习笔记(十三):IIC_OLED实验

Arduino IIC_OLED实验入门学习

Arduino 入门学习笔记(十三):IIC_OLED实验

开发板:正点原子ESP32S3
外设: 正点原子OLED
例程源码在文章顶部可免费下载

1. OLED 介绍

1.1 OLED 简介

OLED,即有机发光二极管(Organic Light-Emitting Diode),又称为有机电激光显示(OrganicElectroluminesence Display,OLED)。 OLED 可按发光材料分为两种:小分子 OLED 和高分子OLED(也可称为 PLED)。 OLED 是一种利用多层有机薄膜结构产生电致发光的器件,它很容易制作,而且只需要低的驱动电压, OLED 由于同时具备自发光(不需背光源)、对比度高、厚度薄、视角广、反应速度快、 功耗低、柔性好等优异特性, 目前主要用于显示领域, OLED 在节能照明领域的开发也成为全球趋势。
本实验我们将介绍正点原子的 OLED 显示模块及其使用方法,该模块有以下特点:

  • 模块有单色和双色两种可选,单色为纯蓝色,而双色则为黄蓝双色(分区域的双色,前 16 行为黄色,后 48 行为蓝色,且黄蓝色之间有一行不显示的间隔区)。
  • 尺寸小,显示尺寸为 0.96 寸,而模块的尺寸仅为 27mm*26mm 大小。
  • 高分辨率,该模块的分辨率为 128*64。
  • 多种接口方式,该模块提供了总共 4 种接口包括: 6800、 8080 两种并行接口方式、 4线 SPI 接口方式以及 IIC 接口方式(只需要 2 根线就可以控制 OLED 了!)。
  • 不需要高压,直接接 3.3V 就可以工作了。

这里要提醒大家的是,该模块不和 5.0V 接口兼容,所以请大家在使用的时候一定要小心,别直接接到 5V 的系统上去,否则可能烧坏模块。以下 4 种模式通过模块的 BS1 和 BS2 设置,B S1 和 BS2 的设置与模块接口模式的关系如表 16.1.1 所示:
在这里插入图片描述
表中:“1”代表接 VCC,“0”代表接 GND。该模块的外观图如图所示:
在这里插入图片描述
正点原子 OLED 模块默认设置是: BS1 和 BS2 接 VCC,即使用 8080 并口方式,如果你想要设置为其他模式,则需要在 OLED 的背面,用烙铁修改 BS1 和 BS2 的设置。对于本实验而言,是需要将 OLED 模块的接口方式修改为 IIC,所以就需要把 BS2 接到GND,并把 D1 和 D2 连接起来。最终使用 IIC 接口的 OLED 模块图如下图所示。
在这里插入图片描述
模块的原理图如图所示:
在这里插入图片描述
该模块采用 8*2 的 2.54 排针与外部连接,总共有 16 个管脚,在 16 条线中,我们只用了 15条,有一个是悬空的。 15 条线中,电源和地线占了 2 条,还剩下 13 条信号线。在不同模式下,我们需要的信号线数量是不同的,在 8080 模式下,需要全部 13 条,而在该模块的 IIC 模式下,需要 4 条线,分别为 OLED_D0(SCL)、 OLED_D1 和 D2(SDA)、 OLED_DC、 OLED_RST。在 IIC模式下, OLED_D0 是作为 IIC 的 SCL 线, OLED_D1 和 D2 连接一起作为 IIC 的 SDA 线,而OLED_DC 是作为 SA0,用于设置 IIC 器件地址, OLED_RST 是复位线, RST 上的低电平,将导致 OLED 复位,在每次初始化之前,都应该复位一下 OLED 模块。
要进行 IIC 通信,首先得知道器件地址, OLED 器件地址是 7 位的,具体格式如下表所示:
在这里插入图片描述
OLED 模块的主控芯片为 SSD1306, 从上表可以知道, SSD1306 器件地址由两部分组成,一部分就是“固定部分”即“011110”;另一部分就是“可变部分”即 SA0 引脚,在程序上会让该引脚输出低电平,所以该位为“0”。最终可得到, SSD1306 器件地址为“0111100”即 0x3C。读操作地址就为 0x79,即 0111 1001;写操作地址就为 0x78,即 0111 1000。

1.2 SSD1306 库介绍

OLED 模块驱动,可以参考器件手册中对时序图的描述,基于 Wire 库函数自行实现。但是在本章中,我们并没有讲解 OLED 时序,是因为这里我们要用到别人写好的库,站在别人的肩膀上进行开发。 Arduino 开发有一大优点,就是有很多参考库,基于这些参考库,就可以快速开发项目,并不需要重复造轮子。
接下来,我们就来看一下如何下载 OLED 库包。对于 OLED 模块来说,它的主控芯片是 SSD1306,所以我们要下载 SSD1306 的库包。这个库包的名字为“ESP8266 and ESP32 OLED driver for SSD1306 displays” 库, 可以在 Arduino IDE中库管理搜索到,具体下载操作如下图所示:
在这里插入图片描述
当我们下载好“ ESP8266 and ESP32 OLED driver for SSD1306 displays”库后,可以从“C:\Users\用户名\ Documents\Arduino\libraries\”路径下找到该文件,该文件夹内容如下图所示:
在这里插入图片描述
该文件夹下, examples 文件夹下存放的是示例工程, 可以快速了解库的使用。打开方式有两种: 从文件夹中打开, 从 IDE 进行打开。从 IDE 打开成功安装的库包示例工程操作如下图所示:
在这里插入图片描述
resources 文件夹存放的是该库实现的效果照片,而 src 文件夹存放的是实现代码,大家有兴趣去研究的可以自行查看。
在 SSD1306 库中,主要分为显示控制、绘制、文本等功能函数,这里就简单介绍一下本例程用到的,其余函数可以自行去看源文件。本例程用到显示控制功能函数如下:

void init(); /* 初始化显示器 */
void clear(void); /* 清屏 */
void display(void); /* 显示 */
void flipScreenVertically(); /* 倒转显示 */

绘制功能函数如下:

void setColor(OLEDDISPLAY_COLOR color); /* 设置当前画笔颜色 */
void fillRect(int16_t x, int16_t y, int16_t width, int16_t height);/* 填充矩阵 */

文本功能函数如下:

void drawString(int16_t x, int16_t y, String text); /* 显示字符串 */
void setFont(const uint8_t* fontData); /* 设置字体大小 */

在使用前面罗列的函数前, 首先实例化一个 display 对象, 因为前面的函数都是 display 类中的成员函数, 操作如下:

SSD1306Wire display(OLED_ADDR, OLED_SDA_PIN, OLED_SCL_PIN, GEOMETRY_128_64,
I2C_TWO, 800000);

上面函数的原型如下所示:

SSD1306Wire(uint8_t _address, int _sda, int _scl, OLEDDISPLAY_GEOMETRY g,
HW_I2C _i2cBus, int _frequency)

参数_address 为 SSD1306 的 7 位器件地址, _sda 为 IIC 通信的数据线, _scl 为 IIC 通信的时钟线, g 为屏幕的大小, _i2cBus 为 IIC 总线, _frequency 为 IIC 通信速率。
有了 display 对象就可以调用前面函数,使用以下格式:

display.init();

2. 硬件设计

2.1 例程功能

使用 IIC 模式驱动 OLED 模块,不停的显示 ASCII 码和码值。

2.2 硬件资源

  • USART0
    U0TXD-IO43
    U0RXD-IO44
  • XL9555
    IIC_SDA-IO41
    IIC_SCL-IO42
  • OLED
    IIC_SCL-IO4
    IIC_SDA-IO5
    D2-IO6
    DC-IO38
    RST-IO_05(XL9555)

2.3 原理图

OLED 相关原理图,如下图所示:
在这里插入图片描述
从上图可以看到, OV2640 座子即 CAMERA 是可以接 OLED 模块进行使用的,由于这部分原理图本就是为摄像头设计的,所以那些名称看起来跟 OLED 模块没有关系,实际上可以利用现有硬件条件对 IIC 接口的 OLED 模块进行驱动。
在之前小节也有对 IIC 接口的 OLED 模块连线情况进行说明,这里罗列一个 IO 对应关系表,方便大家更清楚去理解。
在这里插入图片描述
在图中,红框里面的引脚是 IIC 接口 OLED 模块用到的,而紫框里面的内容则是 IIC接口 OLED 模块真正连接到 ESP32-S3 的引脚或连接到 XL9555 器件的引脚。
特别注意: OLED 模块与 ESP32-S3 开发板的连接,要靠左插!,如下图所示:
在这里插入图片描述

3. 软件设计

3.1 程序流程图

下面看看本实验的程序流程图:
在这里插入图片描述

3.2 程序解析

OLED 驱动代码
这里我们只讲解核心代码,详细的源码请大家参考光盘本实验对应源码。 OLED 驱动源码包括两个文件: oled.cpp 和 oled.h。
下面我们先解析 oled.h 的程序。 对 OLED 模块 IIC 引脚和 OLED 器件地址做了相关定义。

#define OLED_SCL_PIN 4
#define OLED_SDA_PIN 5
#define OLED_D2_PIN 6
#define OLED_DC_PIN 38
#define OLED_ADDR 0X3C /* 7 位器件地址 */

我们选择使用 IO4 作为 IIC 的时钟线, IO5 作为 IIC 的数据线, IO6 为 OLED_D2_PIN,IO38 为 OLED_DC_PIN。 OLED 的器件地址为 0x3C。
由于会使用到 RST 引脚, 而 RST 引脚是 XL9555 器件上的 IO,这里便有 OLED_RST 宏用来控制 RST 引脚输出高低电平,实现 OLED 的硬件复位。

#define OLED_RST(x) xl9555_pin_set(OV_RESET, x ? IO_SET_HIGH : IO_SET_LOW)

接下来,我们来解析一下 oled.cpp 的程序,首先先来看一下实例化一个 display 对象操作,在前面也有提及到了,代码如下:

SSD1306Wire display(OLED_ADDR, OLED_SDA_PIN, OLED_SCL_PIN, GEOMETRY_128_64,
I2C_TWO, 800000); /* 定义 OLED 对象(显示异常,把 800000 降低) */

上面涉及到的参数简单做一个说明, OLED_ADDR 为器件地址 0x3C, OLED_SDA_PIN 为IIC 通信数据线, OLED_SCL_PIN 为 IIC 通信时钟线, GEOMETRY_128_64 为显示器尺寸,I2C_TWO 为硬件 IIC1, 800000 为 IIC 通信频率。
我们继续看一下 OLED 模块的初始化函数 oled_init,代码如下:

/**
* @brief OLED 模块初始化
* @param 无
* @retval 无
*/
void oled_init(void)
{
	/* 初始化 OLED 需要用到的引脚 */
	pinMode(OLED_D2_PIN, INPUT_PULLUP);
	/* OLED 模块的 D2 和 D1 引脚需要连接在一起,所以为了不干扰 D1,设置 D2 为输入模式 */
	pinMode(OLED_DC_PIN, OUTPUT); /* DC 引脚跟地址有关 */
	digitalWrite(OLED_DC_PIN, 0); /* DC 引脚接 GND, 8 位地址为 0x78 */
	xl9555_io_config(OV_RESET, IO_SET_OUTPUT);
	/* OLED 模块的复位引脚连接到 XL9555 器件的 P05 引脚 */
	xl9555_pin_set(OV_RESET, IO_SET_HIGH); /* 默认拉高复位引脚 */
	/* 硬件复位 OLED 模块 */
	OLED_RST(0);
	delay(100);
	OLED_RST(1);
	delay(100);
	display.init(); /* 初始化 OLED 模块 */
	display.flipScreenVertically(); /* 垂直翻转屏幕设置 */
	display.setFont(ArialMT_Plain_24); /* 设置 24 号字体 */
	display.drawString(0, 0, "ALIENTEK"); /* 24 号字体 ALIENTEK */
	display.setFont(ArialMT_Plain_16); /* 设置 16 号字体 */
	display.drawString(0, 24, "0.96' OLED TEST"); /* 16 号字体 0.96' OLED TEST */
	display.setFont(ArialMT_Plain_10); /* 设置 10 号字体 */
	display.drawString(0, 40, "ATOM 2023/12/1"); /* 10 号字体 ATOM 2023/12/1 */
	display.drawString(0, 50, "ASCII:"); /* 10 号字体 ASCII: */
	display.drawString(64, 50, "CODE:"); /* 10 号字体 CODE: */
	display.display(); /* 将缓存数据写入到显示器 */
}
/**
* @brief OLED 模块展示效果
* @param 无
* @retval 无
*/
void oled_show_demo(void)
{
	char t = ' ';
	while(1)
	{
		display.setColor(BLACK); /* 颜色设置黑色 */
		display.fillRect(35, 50, 10, 15); /* 清除 ASCII 显示区域 */
		display.fillRect(104, 50, 20, 15); /* 清除 CODE 显示区域 */
		display.setColor(WHITE); /* 颜色设置白色 */
		display.drawString(35, 50, String(t)); /* 显示 ASCII 字符 */
		display.drawString(104, 50, String(t - 0)); /* 显示 ASCII 字符的码值 */
		display.display(); /* 更新显示到 OLED */
		t++;
		if (t > '~')
		{
		t = ' ';
		}
		delay(500);
	}
}

oled_init 函数主要做了四件事情:

  1. 对涉及的 IO 口进行配置,比如 OLED_D2_PIN, 在硬件上人为将其 OLED_SDA 焊接上了,所以为了避免影响 SDA 线,所以要设置为上拉输入模式。 OLED 模块初始化时,通常需要硬件复位,这里也提供有 RST 引脚,只不过是连接在 XL9555 器件上。在这里就需要首先通过xl9555_io_config 接口对 RST 引脚配置成输出模式,然后通过 xl9555_pin_set 函数接口设置默认输出高电平。随后,就可以通过调用在 oled.h 文件编写的 OLED_RST 宏产生复位信号,硬件复
    位 OLED 模块。
  2. 调用 ssd1306 库的 init 函数初始化 OLED 模块,主要就是发送 OLED 初始化序列完成其寄存器的配置并开启显示。
  3. 调用 ssd1306 库的功能函数去显示实验信息, setFont 函数设置当前字体大小, drawString函数设置显示内容。注意: 这些数据内容都会被存放到一个缓冲区,还未能显示在 OLED 上。
  4. 调用 ssd1306 库的 display 函数去更新显示。 该函数的功能就是要把缓冲区的数据发送到 OLED 模块,这样才能更新数据的显示。oled_show_demo 函数主要就是调用 drawString 函数对 ASCII 码“ ”到“~”的字符以及码值进行显示,最后一定要调用 display 函数才能更新到 OLED 屏上。
    10_iic_oled.ino 代码
    在 10_iic_oled.ino 里面编写如下代码:
#include "oled.h"
#include "uart.h"
#include "xl9555.h"
/**
* @brief 当程序开始执行时,将调用 setup()函数,通常用来初始化变量、函数等
* @param 无
* @retval 无
*/
void setup()
{
	uart_init(0, 115200); /* 串口 0 初始化 */
	xl9555_init(); /* IO 扩展芯片初始化 */
	oled_init(); /* OLED 模块初始化 */
}
/**
* @brief 循环函数,通常放程序的主体或者需要不断刷新的语句
* @param 无
* @retval 无
*/
void loop()
{
	oled_show_demo();
}

在 setup 函数中,调用 uart_init 函数完成串口初始化,调用 xl9555_init 函数完成 XL9555 初始化,然后调用 oled_init 函数完成 OLED 模块初始化。
在 loop 函数中,调用 oled_show_demo 函数实现 ASCII 字符更新显示。

4. 下载验证

下载代码后, OLED 模块显示 ASCII 字符集等信息, 如下图所示:
在这里插入图片描述
OLED 显示了三种尺寸的字符: 2412(ALIENTEK)、 168(0.96’ OLED TEST)和 10*5(剩下的内容)。说明我们的实验是成功的,实现了三种不同尺寸 ASCII 字符的显示,在最后一行不停的显示 ASCII 字符以及其码值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

常将有日思无日-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值