OpenHarmony鸿蒙硬件-OLED显示屏开发-显示箭头

开发步骤

  1. 创建 oled_demo.c,加上头文件
  2. 封装向I2C写数据函数
  3. 创建初始化oled函数
  4. 清空屏幕
  5. 完成显示数据功能

步骤1

创建 oled_demo.c

头文件如下:

#include <stdio.h>
#include <unistd.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "wifiiot_gpio.h"
#include "wifiiot_gpio_ex.h"
#include "wifiiot_i2c.h"

#define ARRAY_SIZE(a) sizeof(a)/sizeof(a[0])

步骤2

通过程序控制 oled 屏幕,就要调用 I2cWrite() 函数向 oled 屏幕发送指令,显示图像,为了简化代码,封装成函数 Write(),如下:

/*

cmdType:指令类型:0x00表示写指令,0x40表示写数据
data:数据。
      当cmdType是0x00时,data表示指令内容
      当cmdType是0x40时,data表示显示的内容
*/
static uint32_t Write(uint8_t cmdType, uint8_t data)
{
    uint8_t buffer[] = {cmdType, data};
    WifiIotI2cData i2cData = {0};

    i2cData.sendBuf = buffer;
    i2cData.sendLen = sizeof(buffer)/sizeof(buffer[0]);

    return I2cWrite(WIFI_IOT_I2C_IDX_0, 0x78, &i2cData);
}

代码解释:

  • WifiIotI2cData结构体详见 链接

  • I2cWrite()函数详见 链接

步骤3

创建 OledInit() 函数对GPIO管脚及oled进行初始化

/**
 * @brief ssd1306 OLED 初始化操作.
 */
uint32_t OledInit(void)
{
    // 初始化命令
    static const uint8_t initCmds[] = {
        0xAE, // --display off
        0x00, // ---set low column address
        0x10, // ---set high column address
        0x40, // --set start line address  
        0xB0, // --set page address
        0x81, // contract control
        0xFF, // --128   
        0xA1, // set segment remap 
        0xA6, // --normal / reverse
        0xA8, // --set multiplex ratio(1 to 64)
        0x3F, // --1/32 duty
        0xC8, // Com scan direction
        0xD3, // -set display offset
        0x00, // 
        0xD5, // set osc division
        0x80, // 
        0xD8, // set area color mode off
        0x05, // 
        0xD9, // Set Pre-Charge Period
        0xF1, // 
        0xDA, // set com pin configuartion
        0x12, // 
        0xDB, // set Vcomh
        0x30, // 
        0x8D, // set charge pump enable
        0x14, // 
        0xAF, // --turn on oled panel
    };

    // 设置 13 引脚为 SDA 总线
    IoSetFunc(WIFI_IOT_IO_NAME_GPIO_13, WIFI_IOT_IO_FUNC_GPIO_13_I2C0_SDA);
    // 设置 14 引脚为 SCL 时钟线
    IoSetFunc(WIFI_IOT_IO_NAME_GPIO_14, WIFI_IOT_IO_FUNC_GPIO_14_I2C0_SCL);

    // 设置 I2C 波特率,能够与外部 I2C 设备(如 OLED 屏幕、传感器等)正常通信。
    I2cInit(WIFI_IOT_I2C_IDX_0, (400*1000)); // 400k
    // I2cSetBaudrate(WIFI_IOT_I2C_IDX_0, OLED_I2C_BAUDRATE);

    for (size_t i = 0; i < ARRAY_SIZE(initCmds); i++) {
        uint32_t status = Write(0x00,initCmds[i]);
        if (status != 0) {
            return status;
        }
    }
    return 0;
}

步骤4

定义全屏填充函数,用于清空屏幕

/*全屏填充*/
void OledFillScreen(uint8_t fillData)
{
    uint8_t m = 0;
    uint8_t n = 0;

    for (m=0; m < 8; m++) {
        Write(0x00,0xb0 + m); // 设置起始行
        // Write(0x00,0x00);
        // Write(0x00,0x10);

        for (n=0; n < 128; n++) {
            Write(0x40, fillData); // 显示到屏幕上
        }
    }
}

代码解释:

  • Write(0x00,0xb0 + m):向 I2C 设备写指令

    • 0x00:表示写命令
    • 0xb0:表示设置起始行为0,0xb0 + 1 表示设置起始行为1,共有8行
  • Write(0x40, fillData):

    • 0x40:向 I2C 设备写数据,即:显示到oled显示屏上。
    • fillData 是 8位 二进制数,0 表示像素点灭,0 表示像素点亮

主函数

// 小箭头,从左向右逐渐显示
static void OledDemo(void)
{
    GpioInit();
    OledInit();

    OledFillScreen(0x00);

    Write(0x00,0xb0 + 1); // 移动到第二页
    // 显示箭头尾部
    for(uint8_t i = 0 ;i<20;i++){
        // 一列8位,1表示亮灯、0表示灭灯
        Write(0x40,0b00111100);
        usleep(500);
    }
    // 显示指向右侧的箭头
    Write(0x40,0b1111111);
    Write(0x40,0b1111111);
    usleep(500);
    Write(0x40,0b0111110);
    Write(0x40,0b0111110);
    usleep(500);
    Write(0x40,0b0011100);
    Write(0x40,0b0011100);
    usleep(500);
    Write(0x40,0b0001000);
    Write(0x40,0b0001000);

}
APP_FEATURE_INIT(OledDemo);

完整代码

#include <stdio.h>
#include <unistd.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "wifiiot_gpio.h"
#include "wifiiot_gpio_ex.h"
#include "wifiiot_i2c.h"

#define ARRAY_SIZE(a) sizeof(a)/sizeof(a[0])


/*

cmdType:指令类型:0x00表示写指令,0x40表示写数据
data:数据。
      当cmdType是0x00时,data表示指令内容
      当cmdType是0x40时,data表示显示的内容
*/
static uint32_t Write(uint8_t cmdType, uint8_t data)
{
    uint8_t buffer[] = {cmdType, data};
    WifiIotI2cData i2cData = {0};

    i2cData.sendBuf = buffer;
    i2cData.sendLen = sizeof(buffer)/sizeof(buffer[0]);

    return I2cWrite(WIFI_IOT_I2C_IDX_0, 0x78, &i2cData);
}

/**
 * @brief ssd1306 OLED 初始化操作.
 */
uint32_t OledInit(void)
{
    // 初始化命令
    static const uint8_t initCmds[] = {
        0xAE, // --display off
        0x00, // ---set low column address
        0x10, // ---set high column address
        0x40, // --set start line address  
        0xB0, // --set page address
        0x81, // contract control
        0xFF, // --128   
        0xA1, // set segment remap 
        0xA6, // --normal / reverse
        0xA8, // --set multiplex ratio(1 to 64)
        0x3F, // --1/32 duty
        0xC8, // Com scan direction
        0xD3, // -set display offset
        0x00, // 
        0xD5, // set osc division
        0x80, // 
        0xD8, // set area color mode off
        0x05, // 
        0xD9, // Set Pre-Charge Period
        0xF1, // 
        0xDA, // set com pin configuartion
        0x12, // 
        0xDB, // set Vcomh
        0x30, // 
        0x8D, // set charge pump enable
        0x14, // 
        0xAF, // --turn on oled panel
    };

    // 设置 13 引脚为 SDA 总线
    IoSetFunc(WIFI_IOT_IO_NAME_GPIO_13, WIFI_IOT_IO_FUNC_GPIO_13_I2C0_SDA);
    // 设置 14 引脚为 SCL 时钟线
    IoSetFunc(WIFI_IOT_IO_NAME_GPIO_14, WIFI_IOT_IO_FUNC_GPIO_14_I2C0_SCL);

    // 设置 I2C 波特率,能够与外部 I2C 设备(如 OLED 屏幕、传感器等)正常通信。
    I2cInit(WIFI_IOT_I2C_IDX_0, 400*1000); // 400k
    // I2cSetBaudrate(WIFI_IOT_I2C_IDX_0, OLED_I2C_BAUDRATE);

    for (size_t i = 0; i < ARRAY_SIZE(initCmds); i++) {
        uint32_t status = Write(0x00,initCmds[i]);
        if (status != 0) {
            return status;
        }
    }
    return 0;
}



/*全屏填充*/
void OledFillScreen(uint8_t fillData)
{
    uint8_t m = 0;
    uint8_t n = 0;

    for (m=0; m < 8; m++) {
        Write(0x00,0xb0 + m); // 设置起始行
        // Write(0x00,0x00);
        // Write(0x00,0x10);

        for (n=0; n < 128; n++) {
            Write(0x40, fillData); // 显示到屏幕上
        }
    }
}

// 小箭头,从左向右逐渐显示
static void OledDemo(void)
{
    GpioInit();
    OledInit();

    OledFillScreen(0x00);

    Write(0x00,0xb0 + 1);
    // 显示箭头尾部
    for(uint8_t i = 0 ;i<20;i++){
        // 一列8位,1表示亮灯、0表示灭灯
        Write(0x40,0b00111100);
        usleep(500);
    }
    // 显示指向右侧的箭头
    Write(0x40,0b1111111);
    Write(0x40,0b1111111);
    usleep(500);
    Write(0x40,0b0111110);
    Write(0x40,0b0111110);
    usleep(500);
    Write(0x40,0b0011100);
    Write(0x40,0b0011100);
    usleep(500);
    Write(0x40,0b0001000);
    Write(0x40,0b0001000);

}
APP_FEATURE_INIT(OledDemo);

编辑BUILD.gn文件

编辑1

在代码同级目录创建下面文件:

BUILD.gn

内容:

static_library("oled_demo") {
    sources = [
        "oled_demo.c", 
    ]
    include_dirs = [
        "//utils/native/lite/include",
        "//kernel/liteos_m/components/cmsis/2.0",
        "//base/iot_hardware/interfaces/kits/wifiiot_lite",
    ]
}

编辑2

编辑下面文件:

\\applications\sample\wifi-iot\app\BUILD.gn

内容:

import("//build/lite/config/component/lite_component.gni")

lite_component("app") {
    features = [
        # "code_v2.0/std_03:hello_demo",
        # "code_v2.0/std_04:traffic_demo"
        # "code_v2.0/std_07/ssd1306:oled_ssd1306",
        # "code_v2.0/std_07/examples:oled_test",
        # "code_v2.0/std_07/libm_port:libm_port",
        "code_v2.0/std_06:oled_demo", 
    ]
}

启用I2C功能

OpenHarmony鸿蒙硬件-启用I2C功能(关键)

编译代码

详见链接:
https://www.malaoshi.top/show_1GW1wTyUOMPk.html

烧写固件到芯片

详见链接:
https://www.malaoshi.top/show_1GW1wWWflGbq.html


原文出处:/show_1GW203b8MFu3.html