丨budboool · 2023年10月17日 · 广东

全志R128驱动OLED屏幕步骤教程

驱动 OLED 屏

本文案例代码

下载地址

OLED驱动案例代码

https://www.aw-ol.com/downloads?cat=24

OLED,即有机发光二极管( Organic Light Emitting Diode)。 OLED 由于同时具备自发光,不需背 光源、对比度高、厚度薄、视角广、反应速度快、可用于挠曲性面板、使用温度范围广、构造及 制程较简单等优异之特性,被认为是下一代的平面显示器新兴应用技术。

LCD 都需要背光,而 OLED 不需要,因为它是自发光的。这样同样的显示 OLED 效果要来得好一 些。以目前的技术,OLED 的尺寸还难以大型化,但是分辨率确可以做到很高。

在此我们使用的 是0.96寸OLED显示屏,该屏有以下特点:

  1. 0.96 寸 OLED 有黄蓝,白,蓝三种颜色可选;其中黄蓝是屏上 1/4 部分为黄光,下 3/4 为蓝; 而且是固定区域显示固定颜色,颜色和显示区域均不能修改;白光则为纯白,也就是黑底白字; 蓝色则为纯蓝,也就是黑底蓝字。
  2. 分辨率为 128*64
  3. 多种接口方式;OLED 裸屏总共种接口包括:6800、8080 两种并行接口方式、3 线或 4 线的 串行 SPI 接口方式、 IIC 接口方式(只需要 2 根线就可以控制 OLED 了!),这五种接口是通过屏上的 BS0~BS2 来配置的。

本次使用的是四针的IIC 模块,如下图:

image-20230824100826958.png

引脚配置如下

R128 Devkit

OLED

PA23

SCL

PA24

SDA

GND

GND

3V3

VCC

载入方案

我们使用的开发板是 R128-Devkit,需要开发 C906 核心的应用程序,所以载入方案选择 r128s2_module_c906

$ source envsetup.sh 
$ lunch_rtos 1

image-20230802110150203 (1).png

设置 TWI 驱动

运行 mrtos_menuconfig 进入配置页面。前往下列地址找到 TWI Devices

Drivers Options  --->
    soc related device drivers  --->
            TWI Devices --->
            -*- enable twi driver

image-20230824101004267.png

配置 TWI 引脚

打开你喜欢的编辑器,修改文件:board/r128s2/module/configs/sys_config.fex

增加 TWI0 的配置,参考手册可知 PA23,PA24 的 TWI0 复用为 6

[twi0]
twi0_sck        = port:PA23<6><1><default><default>
twi0_sda        = port:PA24<6><1><default><default>

image-20230824101853370.png

编写程序

打开你喜欢的编辑器,新增文件:lichee/rtos/projects/r128s2/module_c906/src/oled.c 用于编写 OLED 的驱动。

image-20230824102937839.png

编写 OLED 驱动

使用一个宏储存 TWI 的地址和使用的 TWI 端口,并定义显存。

#define OLED_IIC_ADDR 0x3c
#define OLED_IIC_PORT 0

uint8_t OLED_GRAM[144][8]; /* 显存 */

编写 OLED 的基础操作驱动 TWI 通讯函数。

#define OLED_CMD 0 /*写命令 */
#define OLED_DATA 1 /* 写数据 */

void OLED_WR_Byte(uint8_t dat, uint8_t mode)
{
    twi_msg_t msg;
    twi_port_t port = OLED_IIC_PORT;

    uint8_t buf[2];

    if (mode)
        buf[0] = 0x40;
    else
        buf[0] = 0x00;
    buf[1] = dat;

    msg.flags = 0;
    msg.addr = OLED_IIC_ADDR;
    msg.len = 2;
    msg.buf = buf;
    hal_twi_control(port, I2C_RDWR, &msg);
}

编写 OLED 的驱动函数:显示开关

void OLED_ColorTurn(uint8_t i)
{
    if (i == 0) {
        OLED_WR_Byte(0xA6, OLED_CMD); /* 正常显示 */
    }
    if (i == 1) {
        OLED_WR_Byte(0xA7, OLED_CMD); /* 反色显示 */
    }
}


编写 OLED 的驱动函数:反显设置


void OLED_DisplayTurn(uint8_t i)
{
    if (i == 0) {
        OLED_WR_Byte(0xC8, OLED_CMD); /* 正常显示 */
        OLED_WR_Byte(0xA1, OLED_CMD);
    }
    if (i == 1) {
        OLED_WR_Byte(0xC0, OLED_CMD); /* 反转显示 */
        OLED_WR_Byte(0xA0, OLED_CMD);
    }
}

编写 OLED 的驱动函数:刷新屏幕

void OLED_Refresh(void)
{
    for (int i = 0; i < 8; i++) {
        OLED_WR_Byte(0xb0 + i, OLED_CMD); //设置行起始地址
        OLED_WR_Byte(0x00, OLED_CMD); //设置低列起始地址
        OLED_WR_Byte(0x10, OLED_CMD); //设置高列起始地址
        OLED_WR_Byte(0x78, OLED_DATA);
        OLED_WR_Byte(0x40, OLED_DATA);
        for (int n = 0; n < 128; n++) {
            OLED_WR_Byte(OLED_GRAM[n][i], OLED_DATA);
        }
    }
}

编写 OLED 的驱动函数:清屏

void OLED_Clear(void)
{
    for (int i = 0; i < 8; i++) {
        OLED_WR_Byte(0xb0 + i, OLED_CMD); //设置页地址(0~7)
        OLED_WR_Byte(0x00, OLED_CMD); //设置显示位置—列低地址
        OLED_WR_Byte(0x10, OLED_CMD); //设置显示位置—列高地址
        for (int n = 0; n < 128; n++)
            OLED_GRAM[n][i] = 0;
        OLED_Refresh(); //刷新GRAM内容
    }
}


编写 OLED 的驱动函数:画点

void OLED_DrawPoint(uint8_t x, uint8_t y, uint8_t t)
{
    uint8_t i, m, n;
    i = y / 8;
    m = y % 8;
    n = 1 << m;
    if (t) {
        OLED_GRAM[x][i] |= n;
    }
    else {
        OLED_GRAM[x][i] = ~OLED_GRAM[x][i];
        OLED_GRAM[x][i] |= n;
        OLED_GRAM[x][i] = ~OLED_GRAM[x][i];
    }
}

编写 OLED 的驱动函数:画线

void OLED_DrawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t mode)
{
    int xerr = 0, yerr = 0, delta_x, delta_y, distance;
    int incx, incy, uRow, uCol;
    delta_x = x2 - x1; //计算坐标增量
    delta_y = y2 - y1;
    uRow = x1; //画线起点坐标
    uCol = y1;
    if (delta_x > 0)
        incx = 1; //设置单步方向
    else if (delta_x == 0)
        incx = 0; //垂直线
    else {
        incx = -1;
        delta_x = -delta_x;
    }
    if (delta_y > 0)
        incy = 1;
    else if (delta_y == 0)
        incy = 0; //水平线
    else {
        incy = -1;
        delta_y = -delta_x;
    }
    if (delta_x > delta_y)
        distance = delta_x; //选取基本增量坐标轴
    else
        distance = delta_y;
    for (uint16_t t = 0; t < distance + 1; t++) {
        OLED_DrawPoint(uRow, uCol, mode); //画点
        xerr += delta_x;
        yerr += delta_y;
        if (xerr > distance) {
            xerr -= distance;
            uRow += incx;
        }
        if (yerr > distance) {
            yerr -= distance;
            uCol += incy;
        }
    }
}

编写 OLED 的驱动函数:画园

void OLED_DrawCircle(uint8_t x, uint8_t y, uint8_t r)
{
    int a, b, num;
    a = 0;
    b = r;
    while (2 * b * b >= r * r) {
        OLED_DrawPoint(x + a, y - b, 1);
        OLED_DrawPoint(x - a, y - b, 1);
        OLED_DrawPoint(x - a, y + b, 1);
        OLED_DrawPoint(x + a, y + b, 1);

        OLED_DrawPoint(x + b, y + a, 1);
        OLED_DrawPoint(x + b, y - a, 1);
        OLED_DrawPoint(x - b, y - a, 1);
        OLED_DrawPoint(x - b, y + a, 1);

        a++;
        num = (a * a + b * b) - r * r; //计算画的点离圆心的距离
        if (num > 0) {
            b--;
            a--;
        }
    }
}

编写 OLED 的驱动函数:显示字符

void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t chr, uint8_t size1, uint8_t mode)
{
    uint8_t temp, size2, chr1;
    uint8_t x0 = x, y0 = y;
    if (size1 == 8)
        size2 = 6;
    else
        size2 = (size1 / 8 + ((size1 % 8) ? 1 : 0)) * (size1 / 2); //得到字体一个字符对应点阵集所占的字节数
    chr1 = chr - ' '; //计算偏移后的值
    for (uint8_t i = 0; i < size2; i++) {
        if (size1 == 8) {
            temp = asc2_0806[chr1][i];
        } //调用0806字体
        else if (size1 == 12) {
            temp = asc2_1206[chr1][i];
        } //调用1206字体
        else if (size1 == 16) {
            temp = asc2_1608[chr1][i];
        } //调用1608字体
        else if (size1 == 24) {
            temp = asc2_2412[chr1][i];
        } //调用2412字体
        else
            return;
        for (uint8_t m = 0; m < 8; m++) {
            if (temp & 0x01)
                OLED_DrawPoint(x, y, mode);
            else
                OLED_DrawPoint(x, y, !mode);
            temp >>= 1;
            y++;
        }
        x++;
        if ((size1 != 8) && ((x - x0) == size1 / 2)) {
            x = x0;
            y0 = y0 + 8;
        }
        y = y0;
    }
}

编写 OLED 的驱动函数:显示字符串

void OLED_ShowString(uint8_t x, uint8_t y, uint8_t* chr, uint8_t size1, uint8_t mode)
{
    while ((*chr >= ' ') && (*chr <= '~')) //判断是不是非法字符!
    {
        OLED_ShowChar(x, y, *chr, size1, mode);
        if (size1 == 8)
            x += 6;
        else
            x += size1 / 2;
        chr++;
    }
}

编写 OLED 的驱动函数:显示数字

void OLED_ShowNum(uint8_t x, uint8_t y, uint32_t num, uint8_t len, uint8_t size1, uint8_t mode)
{
    uint8_t temp, m = 0;
    if (size1 == 8)
        m = 2;
    for (uint8_t t = 0; t < len; t++) {
        temp = (num / OLED_Pow(10, len - t - 1)) % 10;
        if (temp == 0) {
            OLED_ShowChar(x + (size1 / 2 + m) * t, y, '0', size1, mode);
        }
        else {
            OLED_ShowChar(x + (size1 / 2 + m) * t, y, temp + '0', size1, mode);
        }
    }
}

编写 OLED 的驱动函数:配置位置

void OLED_Set_Pos(uint8_t x, uint8_t y)
{
    OLED_WR_Byte(0xb0 + y, OLED_CMD);
    OLED_WR_Byte(((x & 0xf0) >> 4) | 0x10, OLED_CMD);
    OLED_WR_Byte((x & 0x0f), OLED_CMD);
}

编写 OLED 的驱动函数:初始化屏幕


void OLED_Init(void)
{
    hal_twi_init(OLED_IIC_PORT); //-- init TWI

    OLED_WR_Byte(0xAE, OLED_CMD);//--turn off oled panel
    OLED_WR_Byte(0x00, OLED_CMD);//---set low column address
    OLED_WR_Byte(0x10, OLED_CMD);//---set high column address
    OLED_WR_Byte(0x40, OLED_CMD);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
    OLED_WR_Byte(0x81, OLED_CMD);//--set contrast control register
    OLED_WR_Byte(0xCF, OLED_CMD); // Set SEG Output Current Brightness
    OLED_WR_Byte(0xA1, OLED_CMD);//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常
    OLED_WR_Byte(0xC8, OLED_CMD);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
    OLED_WR_Byte(0xA6, OLED_CMD);//--set normal display
    OLED_WR_Byte(0xA8, OLED_CMD);//--set multiplex ratio(1 to 64)
    OLED_WR_Byte(0x3f, OLED_CMD);//--1/64 duty
    OLED_WR_Byte(0xD3, OLED_CMD);//-set display offset Shift Mapping RAM Counter (0x00~0x3F)
    OLED_WR_Byte(0x00, OLED_CMD);//-not offset
    OLED_WR_Byte(0xd5, OLED_CMD);//--set display clock divide ratio/oscillator frequency
    OLED_WR_Byte(0x80, OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
    OLED_WR_Byte(0xD9, OLED_CMD);//--set pre-charge period
    OLED_WR_Byte(0xF1, OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
    OLED_WR_Byte(0xDA, OLED_CMD);//--set com pins hardware configuration
    OLED_WR_Byte(0x12, OLED_CMD);
    OLED_WR_Byte(0xDB, OLED_CMD);//--set vcomh
    OLED_WR_Byte(0x40, OLED_CMD);//Set VCOM Deselect Level
    OLED_WR_Byte(0x20, OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)
    OLED_WR_Byte(0x02, OLED_CMD);//
    OLED_WR_Byte(0x8D, OLED_CMD);//--set Charge Pump enable/disable
    OLED_WR_Byte(0x14, OLED_CMD);//--set(0x10) disable
    OLED_WR_Byte(0xA4, OLED_CMD);// Disable Entire Display On (0xa4/0xa5)
    OLED_WR_Byte(0xA6, OLED_CMD);// Disable Inverse Display On (0xa6/a7)
    OLED_Clear();
    OLED_WR_Byte(0xAF, OLED_CMD); /*display ON*/  
}

我们把这些驱动放到一个单独的文件里,命名为 oled.c,完整内容如下:

#include <sunxi_hal_twi.h>

#include "oledfont.h"

#define OLED_IIC_ADDR 0x3c
#define OLED_IIC_PORT 0

#define OLED_CMD 0 /*写命令 */
#define OLED_DATA 1 /* 写数据 */

uint8_t OLED_GRAM[144][8]; /* 显存 */

void OLED_WR_Byte(uint8_t dat, uint8_t mode)
{
    twi_msg_t msg;
    twi_port_t port = OLED_IIC_PORT;

    uint8_t buf[2];

    if (mode)
        buf[0] = 0x40;
    else
        buf[0] = 0x00;
    buf[1] = dat;

    msg.flags = 0;
    msg.addr = OLED_IIC_ADDR;
    msg.len = 2;
    msg.buf = buf;
    hal_twi_control(port, I2C_RDWR, &msg);
}

uint32_t OLED_Pow(uint8_t m, uint8_t n)
{
    uint32_t result = 1;
    while (n--)
        result *= m;
    return result;
}

void OLED_ColorTurn(uint8_t i)
{
    if (i == 0) {
        OLED_WR_Byte(0xA6, OLED_CMD); /* 正常显示 */
    }
    if (i == 1) {
        OLED_WR_Byte(0xA7, OLED_CMD); /* 反色显示 */
    }
}

void OLED_DisplayTurn(uint8_t i)
{
    if (i == 0) {
        OLED_WR_Byte(0xC8, OLED_CMD); /* 正常显示 */
        OLED_WR_Byte(0xA1, OLED_CMD);
    }
    if (i == 1) {
        OLED_WR_Byte(0xC0, OLED_CMD); /* 反转显示 */
        OLED_WR_Byte(0xA0, OLED_CMD);
    }
}

void OLED_Refresh(void)
{
    for (int i = 0; i < 8; i++) {
        OLED_WR_Byte(0xb0 + i, OLED_CMD); //设置行起始地址
        OLED_WR_Byte(0x00, OLED_CMD); //设置低列起始地址
        OLED_WR_Byte(0x10, OLED_CMD); //设置高列起始地址
        OLED_WR_Byte(0x78, OLED_DATA);
        OLED_WR_Byte(0x40, OLED_DATA);
        for (int n = 0; n < 128; n++) {
            OLED_WR_Byte(OLED_GRAM[n][i], OLED_DATA);
        }
    }
}

void OLED_Clear(void)
{
    for (int i = 0; i < 8; i++) {
        OLED_WR_Byte(0xb0 + i, OLED_CMD); //设置页地址(0~7)
        OLED_WR_Byte(0x00, OLED_CMD); //设置显示位置—列低地址
        OLED_WR_Byte(0x10, OLED_CMD); //设置显示位置—列高地址
        for (int n = 0; n < 128; n++)
            OLED_GRAM[n][i] = 0;
        OLED_Refresh(); //刷新GRAM内容
    }
}

void OLED_DrawPoint(uint8_t x, uint8_t y, uint8_t t)
{
    uint8_t i, m, n;
    i = y / 8;
    m = y % 8;
    n = 1 << m;
    if (t) {
        OLED_GRAM[x][i] |= n;
    }
    else {
        OLED_GRAM[x][i] = ~OLED_GRAM[x][i];
        OLED_GRAM[x][i] |= n;
        OLED_GRAM[x][i] = ~OLED_GRAM[x][i];
    }
}

void OLED_DrawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t mode)
{
    int xerr = 0, yerr = 0, delta_x, delta_y, distance;
    int incx, incy, uRow, uCol;
    delta_x = x2 - x1; //计算坐标增量
    delta_y = y2 - y1;
    uRow = x1; //画线起点坐标
    uCol = y1;
    if (delta_x > 0)
        incx = 1; //设置单步方向
    else if (delta_x == 0)
        incx = 0; //垂直线
    else {
        incx = -1;
        delta_x = -delta_x;
    }
    if (delta_y > 0)
        incy = 1;
    else if (delta_y == 0)
        incy = 0; //水平线
    else {
        incy = -1;
        delta_y = -delta_x;
    }
    if (delta_x > delta_y)
        distance = delta_x; //选取基本增量坐标轴
    else
        distance = delta_y;
    for (uint16_t t = 0; t < distance + 1; t++) {
        OLED_DrawPoint(uRow, uCol, mode); //画点
        xerr += delta_x;
        yerr += delta_y;
        if (xerr > distance) {
            xerr -= distance;
            uRow += incx;
        }
        if (yerr > distance) {
            yerr -= distance;
            uCol += incy;
        }
    }
}

void OLED_DrawCircle(uint8_t x, uint8_t y, uint8_t r)
{
    int a, b, num;
    a = 0;
    b = r;
    while (2 * b * b >= r * r) {
        OLED_DrawPoint(x + a, y - b, 1);
        OLED_DrawPoint(x - a, y - b, 1);
        OLED_DrawPoint(x - a, y + b, 1);
        OLED_DrawPoint(x + a, y + b, 1);

        OLED_DrawPoint(x + b, y + a, 1);
        OLED_DrawPoint(x + b, y - a, 1);
        OLED_DrawPoint(x - b, y - a, 1);
        OLED_DrawPoint(x - b, y + a, 1);

        a++;
        num = (a * a + b * b) - r * r; //计算画的点离圆心的距离
        if (num > 0) {
            b--;
            a--;
        }
    }
}

void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t chr, uint8_t size1, uint8_t mode)
{
    uint8_t temp, size2, chr1;
    uint8_t x0 = x, y0 = y;
    if (size1 == 8)
        size2 = 6;
    else
        size2 = (size1 / 8 + ((size1 % 8) ? 1 : 0)) * (size1 / 2); //得到字体一个字符对应点阵集所占的字节数
    chr1 = chr - ' '; //计算偏移后的值
    for (uint8_t i = 0; i < size2; i++) {
        if (size1 == 8) {
            temp = asc2_0806[chr1][i];
        } //调用0806字体
        else if (size1 == 12) {
            temp = asc2_1206[chr1][i];
        } //调用1206字体
        else if (size1 == 16) {
            temp = asc2_1608[chr1][i];
        } //调用1608字体
        else if (size1 == 24) {
            temp = asc2_2412[chr1][i];
        } //调用2412字体
        else
            return;
        for (uint8_t m = 0; m < 8; m++) {
            if (temp & 0x01)
                OLED_DrawPoint(x, y, mode);
            else
                OLED_DrawPoint(x, y, !mode);
            temp >>= 1;
            y++;
        }
        x++;
        if ((size1 != 8) && ((x - x0) == size1 / 2)) {
            x = x0;
            y0 = y0 + 8;
        }
        y = y0;
    }
}

void OLED_ShowString(uint8_t x, uint8_t y, uint8_t* chr, uint8_t size1, uint8_t mode)
{
    while ((*chr >= ' ') && (*chr <= '~')) //判断是不是非法字符!
    {
        OLED_ShowChar(x, y, *chr, size1, mode);
        if (size1 == 8)
            x += 6;
        else
            x += size1 / 2;
        chr++;
    }
}

void OLED_ShowNum(uint8_t x, uint8_t y, uint32_t num, uint8_t len, uint8_t size1, uint8_t mode)
{
    uint8_t temp, m = 0;
    if (size1 == 8)
        m = 2;
    for (uint8_t t = 0; t < len; t++) {
        temp = (num / OLED_Pow(10, len - t - 1)) % 10;
        if (temp == 0) {
            OLED_ShowChar(x + (size1 / 2 + m) * t, y, '0', size1, mode);
        }
        else {
            OLED_ShowChar(x + (size1 / 2 + m) * t, y, temp + '0', size1, mode);
        }
    }
}

void OLED_Set_Pos(uint8_t x, uint8_t y)
{
    OLED_WR_Byte(0xb0 + y, OLED_CMD);
    OLED_WR_Byte(((x & 0xf0) >> 4) | 0x10, OLED_CMD);
    OLED_WR_Byte((x & 0x0f), OLED_CMD);
}

void OLED_Init(void)
{
    hal_twi_init(OLED_IIC_PORT); //-- init TWI

    OLED_WR_Byte(0xAE, OLED_CMD);//--turn off oled panel
    OLED_WR_Byte(0x00, OLED_CMD);//---set low column address
    OLED_WR_Byte(0x10, OLED_CMD);//---set high column address
    OLED_WR_Byte(0x40, OLED_CMD);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
    OLED_WR_Byte(0x81, OLED_CMD);//--set contrast control register
    OLED_WR_Byte(0xCF, OLED_CMD); // Set SEG Output Current Brightness
    OLED_WR_Byte(0xA1, OLED_CMD);//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常
    OLED_WR_Byte(0xC8, OLED_CMD);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
    OLED_WR_Byte(0xA6, OLED_CMD);//--set normal display
    OLED_WR_Byte(0xA8, OLED_CMD);//--set multiplex ratio(1 to 64)
    OLED_WR_Byte(0x3f, OLED_CMD);//--1/64 duty
    OLED_WR_Byte(0xD3, OLED_CMD);//-set display offset Shift Mapping RAM Counter (0x00~0x3F)
    OLED_WR_Byte(0x00, OLED_CMD);//-not offset
    OLED_WR_Byte(0xd5, OLED_CMD);//--set display clock divide ratio/oscillator frequency
    OLED_WR_Byte(0x80, OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
    OLED_WR_Byte(0xD9, OLED_CMD);//--set pre-charge period
    OLED_WR_Byte(0xF1, OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
    OLED_WR_Byte(0xDA, OLED_CMD);//--set com pins hardware configuration
    OLED_WR_Byte(0x12, OLED_CMD);
    OLED_WR_Byte(0xDB, OLED_CMD);//--set vcomh
    OLED_WR_Byte(0x40, OLED_CMD);//Set VCOM Deselect Level
    OLED_WR_Byte(0x20, OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)
    OLED_WR_Byte(0x02, OLED_CMD);//
    OLED_WR_Byte(0x8D, OLED_CMD);//--set Charge Pump enable/disable
    OLED_WR_Byte(0x14, OLED_CMD);//--set(0x10) disable
    OLED_WR_Byte(0xA4, OLED_CMD);// Disable Entire Display On (0xa4/0xa5)
    OLED_WR_Byte(0xA6, OLED_CMD);// Disable Inverse Display On (0xa6/a7)
    OLED_Clear();
    OLED_WR_Byte(0xAF, OLED_CMD); /*display ON*/  
}

同时提供对应的头文件 oled.holedfont.h 由于较大,见文章末尾。

#ifndef __OLED_H
#define __OLED_H

/* 发送一个字节 
 * mode:数据/命令标志 0,表示命令;1,表示数据;
 */
void OLED_WR_Byte(uint8_t dat, uint8_t mode);

/* Pow 函数 */
uint32_t OLED_Pow(uint8_t m, uint8_t n);

/* 反显函数 */
void OLED_ColorTurn(uint8_t i);

/* 屏幕旋转180度 */
void OLED_DisplayTurn(uint8_t i);

/* 更新显存到OLED */
void OLED_Refresh(void);

/* OLED 清屏 */
void OLED_Clear(void);

/* 画点 
 * x: 0~127
 * y: 0~63
 * t: 1 填充 0,清空    
 */
void OLED_DrawPoint(uint8_t x, uint8_t y, uint8_t t);

/* 画线
 * x1, y1: 起点坐标
 * x2, y2: 结束坐标
 */
void OLED_DrawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t mode);

/* 画圆
 * x, y: 圆心坐标
 * r: 圆的半径
 */

void OLED_DrawCircle(uint8_t x, uint8_t y, uint8_t r);

/* 在指定位置显示一个字符,包括部分字符
 * x: 0 ~ 127
 * y: 0 ~ 63
 * size1: 选择字体 6x8/6x12/8x16/12x24
 * mode: 0,反色显示; 1,正常显示
 */
void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t chr, uint8_t size1, uint8_t mode);

/* 显示字符串
 * x: 0 ~ 127
 * y: 0 ~ 63
 * *chr: 字符串起始地址 
 * size1: 选择字体 6x8/6x12/8x16/12x24
 * mode: 0,反色显示; 1,正常显示
 */
void OLED_ShowString(uint8_t x, uint8_t y, uint8_t* chr, uint8_t size1, uint8_t mode);

/* 显示数字
 * x: 0 ~ 127
 * y: 0 ~ 63
 * num: 要显示的数字 
 * len: 数字的位数
 * size1: 选择字体 6x8/6x12/8x16/12x24
 * mode: 0,反色显示; 1,正常显示
 */
void OLED_ShowNum(uint8_t x, uint8_t y, uint32_t num, uint8_t len, uint8_t size1, uint8_t mode);

/* 初始化 OLED */
void OLED_Init(void);

#endif

然后把 oled.c 加入编译,修改 lichee/rtos/projects/r128s2/module_c906/Makefile加入

obj-y += src/oled.o

image-20230824103308320.png

编写主程序

打开你喜欢的编辑器,修改文件:lichee/rtos/projects/r128s2/module_c906/src/main.c

image-20230803112142315 (1).png

OLED_Init();

OLED_ShowString(12, 16, "====AWOL====", 16, 1);
OLED_ShowString(20, 32, "2023/08/24", 16, 1);

OLED_Refresh();

初始化 OLED,然后显示字符串。

image-20230824103012542.png

结果

驱动了 OLED 屏

image-20230824103128313.png

推荐阅读
关注数
16
文章数
79
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息