数码之家

 找回密码
 立即注册
搜索
查看: 74|回复: 2

[Arduino] 《ESP32S3 Arduino开发指南》第十六章 IIC_OLED实验

[复制链接]
发表于 昨天 09:28 | 显示全部楼层 |阅读模式
第十六章 IIC_OLED实验

本章,我们将继续使用ESP32-S3的硬件IIC接口去驱动正点原子的OLED模块,实现ASCII字符的显示。
本章分为如下几个小节:
16.1 OLED介绍
16.2 硬件设计
16.3 软件设计
16.4 下载验证


16.1 OLED介绍
16.1.1 OLED简介
OLED,即有机发光二极管(Organic Light-Emitting Diode),又称为有机电激光显示(Organic Electroluminesence DisplayOLED)。OLED可按发光材料分为两种:小分子OLED和高分子OLED(也可称为PLED)。OLED是一种利用多层有机薄膜结构产生电致发光的器件,它很容易制作,而且只需要低的驱动电压,OLED由于同时具备自发光不需背光源、对比度高、厚度薄、视角广、反应速度快、功耗低、柔性好等优异特性,目前主要用于显示领域OLED在节能照明领域开发也成为全球趋势
本章我们将介绍正点原子的OLED显示模块及其使用方法,该模块有以下特点:
1) 模块有单色和双色两种可选,单色为纯蓝色,而双色则为黄蓝双色(分区域的双色,前16行为黄色,后48行为蓝色,且黄蓝色之间有一行不显示的间隔区)。
2) 尺寸小,显示尺寸为0.96寸,而模块的尺寸仅为27mm*26mm大小。
3) 高分辨率,该模块的分辨率为128*64
4) 多种接口方式,该模块提供了总共4种接口包括:68008080两种并行接口方式、4线SPI接口方式以及IIC接口方式(只需要2根线就可以控制OLED了!)。
5) 不需要高压,直接接3.3V就可以工作了。
这里要提醒大家的是,该模块不和5.0V接口兼容,所以请大家在使用的时候一定要小心,别直接接到5V的系统上去,否则可能烧坏模块。以下4种模式通过模块的BS1BS2设置,BS1BS2的设置与模块接口模式的关系如表16.1.1所示:
接口方式
4线SPI
IIC
86800
88080
BS1
0
1
0
1
BS2
0
0
1
1
表16.1.1 OLED模块接口方式设置表
表15.1.1中:“1”代表接VCC,而“0”代表接GND。该模块的外观图如图15.1.1所示:
图16.1.1 正点原子OLED模块外观图

正点原子OLED模块默认设置是:BS1BS2VCC,即使用8080并口方式,如果你想要设置为其他模式,则需要在OLED的背面,用烙铁修改BS1BS2的设置。
对于本实验而言,是需要将OLED模块的接口方式修改为IIC,所以就需要把BS2接到GND,并把D1D2连接起来。最终使用IIC接口的OLED模块图如下图所示。
图16.1.2 IIC接口的OLED模块


模块的原理图如图16.1.3所示:
图16.1.3 正点原子OLED模块原理图

该模块采用8*22.54排针与外部连接,总共有16个管脚,在16条线中,我们只用了15条,有一个是悬空的。15条线中,电源和地线占了2条,还剩下13条信号线。在不同模式下,我们需要的信号线数量是不同的,在8080模式下,需要全部13条,而在该模块的IIC模式下,需要4条线,分别为OLED_D0(SCL)OLED_D1D2(SDA)OLED_DCOLED_RST。在IIC模式下,OLED_D0是作为IICSCL线,OLED_D1D2连接一起作为IICSDA线,而OLED_DC是作为SA0,用于设置IIC器件地址,OLED_RST是复位线,RST上的低电平,将导致OLED复位,在每次初始化之前,都应该复位一下OLED模块。

要进行IIC通信,首先得知道器件地址,OLED器件地址是7位的,具体格式如下表所示。
Bit
7
6
5
4
3
2
1
0
Symbol
0
1
1
1
1
0
SA0
R/W


固定部分
可变部分
读写位
器件地址


表16.1.2 OLED地址格式

OLED模块的主控芯片为SSD1306,从上表可以知道,SSD1306器件地址由两部分组成,一部分就是“固定部分”即“011110”;另一部分就是“可变部分”即SA0引脚,在程序上会让该引脚输出低电平,所以该位为0”。最终可得到,SSD1306器件地址为0111100”即0x3C。读操作地址就为0x79,即0111 1001;写操作地址就为0x78,即0111 1000。
16.1.2 SSD1306库介绍
OLED模块驱动,可以参考器件手册中对时序图的描述,基于Wire库函数自行实现。但是在本章中,我们并没有讲解OLED时序,是因为这里我们要用到别人写好的库,站在别人的肩膀上进行开发。Arduino开发有一大优点,就是有很多参考库,基于这些参考库,就可以快速开发项目,并不需要重复造轮子。
接下来,我们就来看一下如何下载OLED库包。
对于OLED模块来说,它的主控芯片是SSD1306,所以我们要下载SSD1306的库包。这个库包的名字为ESP8266 and ESP32 OLED driver for SSD1306 displays”库,可以在Arduino IDE中库管理搜索到,具体下载操作如下图所示。
16.1.2.1 安装SSD1306库包步骤

在线下载过程可能会失败,不用担心,我们采用第二种方式:手动安装。在“资料盘à6,软件资料à2Arduino软件包”下,有“esp8266-oled-ssd1306-master.zip”压缩包,我们就是要安装这个软件包,操作如下:
图16.1.2.2 手动添加软件库

通过操作“项目à导入库à添加.ZIP”,后面会跳出一个页面,我们找到并选中“esp8266-oled-ssd1306-master.zip”压缩包,这时候IDE就会安装这个库。安装成功如下图所示。
16.1.2.3 SSD1306库安装成功

当我们下载好ESP8266 and ESP32 OLED driver for SSD1306 displays”库后,可以从“C:\Users\用户名\ Documents\Arduino\libraries\”路径下找到该文件,该文件夹内容如下图所示。
16.1.2.4 SSD1306库包文件夹

该文件夹下,examples文件夹下存放的是示例工程,可以快速了解库的使用。打开方式有两种:从文件夹中打开,从IDE进行打开。从IDE打开成功安装的库包示例工程操作如下图所示。
16.1.2.5 SSD1306库示例工程

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);
参数_addressSSD13067位器件地址,_sdaIIC通信的数据线,_sclIIC通信的时钟线,g为屏幕的大小,_i2cBusIIC总线,_frequencyIIC通信速率。
有了display对象就可以调用前面函数,使用以下格式:
display.init();
16.2 硬件设计
1.例程功能
使用IIC模式驱动OLED模块,不停的显示ASCII码和码值。
2. 硬件资源
1USART0
U0TXD-IO43
U0RXD-IO44
2XL9555
IIC_SDA-IO41
IIC_SCL-IO42
3OLED
IIC_SCL-IO4
IIC_SDA-IO5
D2-IO6
DC-IO38
RST-IO_05(XL9555)
3. 原理图
OLED相关原理图,如下图所示。
16.2.1 OLED模块原理图

从上图可以看到,OV2640座子即CAMERA是可以接OLED模块进行使用的,由于这部分原理图本就是为摄像头设计的,所以那些名称看起来跟OLED模块没有关系,实际上可以利用现有硬件条件对IIC接口的OLED模块进行驱动。
16.1.1小节也有对IIC接口的OLED模块连线情况进行说明,这里罗列一个IO对应关系表,方便大家更清楚去理解。
IIC接口OLED模块
OV2640端子
ESP32S3
IIC_SCL
OV_D0
IO4
IIC_SDA
OV_D1OV_D2
IO5IO6设为输入)
SA0DC
OV_SCL
IO38
RST
OV_RESET
XL9555_IO05
16.2.1 OLED模块IO

在图16.2.1中,红框里面的引脚是IIC接口OLED模块用到的,而紫框里面的内容则是IIC接口OLED模块真正连接到ESP32-S3的引脚或连接到XL9555器件的引脚。
特别注意:OLED模块与ESP32-S3开发板的连接,要靠左插!,如下图所示。
16.2.2 OLED模块与开发板连接示意图

16.3 软件设计
16.3.1 程序流程图
下面看看本实验的程序流程图:
图16.3.1 程序流程图

16.3.2 程序解析
1. OLED驱动代码
这里我们只讲解核心代码,详细的源码请大家参考光盘本实验对应源码。OLED驱动源码包括两个文件:oled.cppoled.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的数据线,IO6OLED_D2_PINIO38OLED_DC_PINOLED的器件地址为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为器件地址0x3COLED_SDA_PINIIC通信数据线,OLED_SCL_PINIIC通信时钟线,GEOMETRY_128_64为显示器尺寸,I2C_TWO为硬件IIC1800000IIC通信频率。
我们继续看一下OLED模块的初始化函数oled_init,代码如下:
/**
* @brief    OLED模块初始化
* @param   
* @retval
*/
void oled_init(void)
{
    /* 初始化OLED需要用到的引脚 */
pinMode(OLED_D2_PIN, INPUT_PULLUP);           
/* OLED模块的D2D1引脚需要连接在一起,所以为了不干扰D1,设置D2为输入模式 */
    pinMode(OLED_DC_PIN, OUTPUT); /* DC引脚跟地址有关 */
    digitalWrite(OLED_DC_PIN, 0); /* DC引脚接GND8位地址为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屏上。
2. 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字符更新显示。
16.4 下载验证
下载代码后,OLED模块显示ASCII字符集等信息,如下图所示。
图16.4.1 OLED显示效果

OLED显示了三种尺寸的字符:24*12ALIENTEK)、16*80.96OLED TEST)和10*5(剩下的内容)。说明我们的实验是成功的,实现了三种不同尺寸ASCII字符的显示,在最后一行不停的显示ASCII字符以及其码值。


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
发表于 昨天 11:08 | 显示全部楼层
谢谢分享,没看懂。
回复 支持 反对

使用道具 举报

发表于 昨天 11:14 | 显示全部楼层
谢谢分享,好好学习。
回复 支持 反对

使用道具 举报

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

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2025-5-17 21:27 , Processed in 0.156000 second(s), 11 queries , Redis On.

Powered by Discuz!

© 2006-2025 MyDigit.Net

快速回复 返回顶部 返回列表