(esp-idf)一文看懂u8g2库点亮OLED

github仓库地址:HawkJ02/esp32_oled (github.com)

首先丢一个u8g2库的地址:olikraus/u8g2: U8glib library for monochrome displays, version 2 (github.com)

u8g2库中常用的函数有

u8g2_InitDisplay(u8g2):调用 u8x8_InitDisplay() 函数初始化 OLED 屏幕。

u8g2_SetPowerSave(u8g2, is_enable):调用 u8x8_SetPowerSave() 函数将 OLED 屏幕设置为可用或不可用状态。

u8g2_SetFlipMode(u8g2, mode):调用 u8x8_SetFlipMode() 函数设置 OLED 屏幕的翻转模式。

u8g2_SetContrast(u8g2, value):调用 u8x8_SetContrast() 函数设置 OLED 屏幕的对比度。

u8g2_ClearDisplay(u8g2):调用 u8x8_ClearDisplay() 函数清空 OLED 屏幕的显示内容。

u8g2_GetDisplayHeight(u8g2):获取 OLED 屏幕的高度属性。

u8g2_GetDisplayWidth(u8g2):获取 OLED 屏幕的宽度属性。

u8g2_GetDrawColor(u8g2):获取 OLED 屏幕的当前绘制颜色属性。

u8g2_SetI2CAddress(u8g2, address):设置 OLED 屏幕的 I2C 地址。

u8g2_GetI2CAddress(u8g2):获取 OLED 屏幕的 I2C 地址属性。

我们首先在u8g2_hal(我们自己的驱动函数)中定义了一个I2C的结构体:

static u8g2_hal_i2c_cfg_t i2c_cfg = U8G2_HAL_I2C_CFG_DEFAULT(); // I2C 引脚配置信息

定义如下:

typedef struct
{
  gpio_num_t sda;
  gpio_num_t scl;
} u8g2_hal_i2c_cfg_t;

这个结构体包含了sda与scl接口的定义,默认是

#define U8G2_HAL_I2C_CFG_DEFAULT()         \
  {                                        \
    GPIO_NUM_UNDEFINED, GPIO_NUM_UNDEFINED \
  }

接着我们需要写一个回调函数,U8G2库使用这个回调函数将待发送的字节发送到I2C总线上,并且在接收到来自I2C总线的响应时读取字节数据。

static uint8_t u8g2_i2c_byte_cb(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
  ESP_LOGD(TAG, "i2c_byte_cb: Received a msg: %d, arg_int: %d, arg_ptr: %p", msg, arg_int, arg_ptr);

  switch (msg)
  {
  case U8X8_MSG_BYTE_SET_DC:
    break;

  case U8X8_MSG_BYTE_INIT:
  {
    if (i2c_cfg.sda == GPIO_NUM_UNDEFINED ||
        i2c_cfg.scl == GPIO_NUM_UNDEFINED)
    {
      /**
       * 没有提供 i2c 参数
       * 需要先调用 u8g2_hal_i2c_init(i2c_cfg) 以配置 i2c 参数
       */
      ESP_LOGE(TAG, "No i2c configuration provided.");
      break;
    }

    i2c_config_t conf = {0};
    conf.mode = I2C_MODE_MASTER;
    conf.sda_io_num = i2c_cfg.sda;
    conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
    conf.scl_io_num = i2c_cfg.scl;
    conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
    conf.master.clk_speed = I2C_FREQ_HZ;
    ESP_LOGI(TAG, "sda_io_num %d", conf.sda_io_num);
    ESP_LOGI(TAG, "scl_io_num %d", conf.scl_io_num);
    ESP_LOGI(TAG, "clk_speed %d", conf.master.clk_speed);
    ESP_ERROR_CHECK(i2c_param_config(I2C_NUM, &conf));
    ESP_LOGI(TAG, "i2c_driver_install %d", I2C_NUM);
    ESP_ERROR_CHECK(i2c_driver_install(I2C_NUM, conf.mode, 0, 0, 0));
    break;
  }

  case U8X8_MSG_BYTE_SEND:
  {
    // arg_ptr 是要发送的数据(uint8_t[])
    // arg_int 是数据的长度
    uint8_t *data_ptr = (uint8_t *)arg_ptr;
    while (arg_int > 0)
    {
      ESP_ERROR_CHECK(i2c_master_write_byte(handle_i2c, *data_ptr, 1));
      data_ptr++;
      arg_int--;
    }
    break;
  }

  case U8X8_MSG_BYTE_START_TRANSFER:
  {
    uint8_t i2c_address = u8x8_GetI2CAddress(u8x8);
    handle_i2c = i2c_cmd_link_create();
    ESP_LOGD(TAG, "Start I2C transfer to %02X.", i2c_address >> 1);
    ESP_ERROR_CHECK(i2c_master_start(handle_i2c));
    ESP_ERROR_CHECK(i2c_master_write_byte(handle_i2c, i2c_address | I2C_MASTER_WRITE, 1));
    break;
  }

  case U8X8_MSG_BYTE_END_TRANSFER:
  {
    ESP_LOGD(TAG, "End I2C transfer.");
    ESP_ERROR_CHECK(i2c_master_stop(handle_i2c));
    ESP_ERROR_CHECK(i2c_master_cmd_begin(I2C_NUM, handle_i2c, I2C_TIMEOUT_MS / portTICK_RATE_MS));
    i2c_cmd_link_delete(handle_i2c);
    break;
  }
  }
  return 0;
}

        最后我们初始化屏幕:

u8g2_t *u8g2_hal_i2c_init(u8g2_hal_i2c_cfg_t cfg)
{
  i2c_cfg = cfg;

  u8g2_Setup_ssd1306_i2c_128x64_noname_f(&u8g2,            //这是U8G2库的实例,用于控制显示屏。在这里,代码使用&符号获取该实例的地址,并将其传递给函数。
                                         U8G2_R0,          //这是显示屏旋转设置的参数。这里的U8G2_R0表示旋转设置为0度。
                                         u8g2_i2c_byte_cb, //回调函数
                                         u8x8_dummy_cb     //空参数
  );

  u8g2_SetI2CAddress(&u8g2, 0x78); // 设置屏幕 I2C 地址
  u8g2_InitDisplay(&u8g2);         // 发送初始化命令序列给屏幕,执行完毕后屏幕会进入睡眠模式
  u8g2_SetPowerSave(&u8g2, 0);     // 唤醒屏幕
  u8g2_ClearDisplay(&u8g2);        // 清屏

  return &u8g2;
}

        在主函数main.c中我们调用驱动函数:

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_spi_flash.h"

#include "u8g2.h"
#include "u8g2_hal.h"

void app_main(void)
{
    // 根据自身情况修改 I2C 引脚
    u8g2_hal_i2c_cfg_t i2c_cfg = {
        .scl = 21,
        .sda = 20,
    };

    u8g2_t *u8g2 = u8g2_hal_i2c_init(i2c_cfg);

    // ==== 下面开始编写你的代码 ====
    u8g2_ClearBuffer(u8g2);
    u8g2_SetFont(u8g2, u8g2_font_ncenB14_tr);
    u8g2_DrawStr(u8g2, 0, 20, "Hello World!");
    u8g2_SendBuffer(u8g2);

    printf("All done!\n");
}

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值