ITPub博客

首页 > 嵌入式/内核开发 > 嵌入式/内核开发 > 《ESP32S3 Arduino开发指南 V1.0 》第十六章 IIC_OLED实验

《ESP32S3 Arduino开发指南 V1.0 》第十六章 IIC_OLED实验

原创 嵌入式/内核开发 作者:正点原子 时间:2024-12-06 09:31:05 0 删除 编辑

第十六章 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 Display,OLED)。OLED可按发光材料分为两种:小分子OLED和高分子OLED(也可称为PLED)。OLED是一种利用多层有机薄膜结构产生电致发光的器件,它很容易制作,而且只需要低的驱动电压,OLED由于同时具备自发光(不需背光源)、对比度高、厚度薄、视角广、反应速度快、功耗低、柔性好等优异特性,目前主要用于显示领域,OLED在节能照明领域的开发也成为全球趋势。

       本章我们将介绍正点原子的OLED显示模块及其使用方法,该模块有以下特点:

       1) 模块有单色和双色两种可选,单色为纯蓝色,而双色则为黄蓝双色(分区域的双色,前16行为黄色,后48行为蓝色,且黄蓝色之间有一行不显示的间隔区)。

       2) 尺寸小,显示尺寸为0.96寸,而模块的尺寸仅为27mm*26mm大小。

       3) 高分辨率,该模块的分辨率为128*64。

       4) 多种接口方式,该模块提供了总共4种接口包括:6800、8080两种并行接口方式、4线SPI接口方式以及IIC接口方式(只需要2根线就可以控制OLED了!)。

       5) 不需要高压,直接接3.3V就可以工作了。

       这里要提醒大家的是,该模块不和5.0V接口兼容,所以请大家在使用的时候一定要小心,别直接接到5V的系统上去,否则可能烧坏模块。以下4种模式通过模块的BS1和BS2设置,BS1和BS2的设置与模块接口模式的关系如表16.1.1所示:


表16.1.1 OLED模块接口方式设置表


       表15.1.1中:“1”代表接VCC,而“0”代表接GND。该模块的外观图如图15.1.1所示:


图16.1.1 正点原子OLED模块外观图


       正点原子OLED模块默认设置是:BS1和BS2接VCC,即使用8080并口方式,如果你想要设置为其他模式,则需要在OLED的背面,用烙铁修改BS1和BS2的设置。

       对于本实验而言,是需要将OLED模块的接口方式修改为IIC,所以就需要把BS2接到GND,并把D1和D2连接起来。最终使用IIC接口的OLED模块图如下图所示。


图16.1.2 IIC接口的OLED模块


       模块的原理图如图16.1.3所示:


图16.1.3 正点原子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位的,具体格式如下表所示。


表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,软件资料→2,Arduino软件包”下,有“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);

       参数_address为SSD1306的7位器件地址,_sda为IIC通信的数据线,_scl为IIC通信的时钟线,g为屏幕的大小,_i2cBus为IIC总线,_frequency为IIC通信速率。

       有了display对象就可以调用前面函数,使用以下格式:

display.init();


        16.2 硬件设计


       1. 例程功能

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


       2. 硬件资源


       1)USART0

              U0TXD-IO43

              U0RXD-IO44


       2)XL9555

              IIC_SDA-IO41

              IIC_SCL-IO42


       3)OLED

              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对应关系表,方便大家更清楚去理解。


表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.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屏上。


       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*12(ALIENTEK)、16*8(0.96’ OLED TEST)和10*5(剩下的内容)。说明我们的实验是成功的,实现了三种不同尺寸ASCII字符的显示,在最后一行不停的显示ASCII字符以及其码值。


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70040860/viewspace-3054868/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2024-08-30

  • 博文量
    588
  • 访问量
    764165