ESP32移植u8g2庫,實現oled界面顯示
- 1. 簡單描述
- 2. 環境準備
- 1. 硬件準備
- 2. 軟件準備
- 3. IIC屏幕 【基于 ssd1362 + 256*64 】
- 4. SPI屏幕 【基于 ssd1306 + 128*32】
1. 簡單描述
- 開發方式為 IDF5.0
- 參考連接為
iic基于esp-idf移植使用u8g2
spi基于esp-idf移植使用u8g2
2. 環境準備
1. 硬件準備
- 首先屏幕有兩種通信方式:spi,iic
- 然后得知道你手上屏幕的型號和分辨率:
-
ssd1362 iic 淘寶連接
-
ssd1306 spi 淘寶連接
2. 軟件準備
- 使用git下載好u8g2 下載連接
3. IIC屏幕 【基于 ssd1362 + 256*64 】
- 在idf里面新建 components 取名為 【u8g2】
- 將下載的u8g2文件下csrc文件按照文件類型排序,將h文件放在include,c文件直接放u8g2目錄下。
u8g2├─include│ mui.h│ mui_u8g2.h│ u8g2.h│ u8x8.h└─根目錄mui.cmui_u8g2.cu8g2_bitmap.cu8g2_box.cu8g2_buffer.cu8g2_button.cu8g2_circle.cu8g2_cleardisplay.cu8g2_d_memory.cu8g2_d_setup.cu8g2_font.cu8g2_fonts.cu8g2_hvline.cu8g2_input_value.cu8g2_intersection.cu8g2_kerning.cu8g2_line.cu8g2_ll_hvline.cu8g2_message.cu8g2_polygon.cu8g2_selection_list.cu8g2_setup.cu8log.cu8log_u8g2.cu8log_u8x8.cu8x8_8x8.cu8x8_byte.cu8x8_cad.cu8x8_capture.c[這中間有很多文件不需要拷貝]u8x8_debounce.cu8x8_display.cu8x8_fonts.cu8x8_gpio.cu8x8_input_value.cu8x8_message.cu8x8_selection_list.cu8x8_setup.cu8x8_string.cu8x8_u16toa.cu8x8_u8toa.c
- 在下載的u8g2文件下csrc找到對應芯片的.c文件,比如我這就找到ssd1362,并放在我們的代碼u8g2下
u8x8_d_ssd1362.c
- 修改 CMakeLists.txt ,注意最后是一個自己芯片.c文件
idf_component_register(SRCS "mui.c""mui_u8g2.c""u8g2_bitmap.c""u8g2_box.c""u8g2_buffer.c""u8g2_button.c""u8g2.c""u8g2_circle.c""u8g2_cleardisplay.c""u8g2_d_memory.c""u8g2_d_setup.c""u8g2_font.c""u8g2_fonts.c""u8g2_hvline.c""u8g2_input_value.c""u8g2_intersection.c""u8g2_kerning.c""u8g2_line.c""u8g2_ll_hvline.c""u8g2_message.c""u8g2_polygon.c""u8g2_selection_list.c""u8g2_setup.c""u8log.c""u8log_u8g2.c""u8log_u8x8.c""u8x8_8x8.c""u8x8_byte.c""u8x8_cad.c""u8x8_capture.c""u8x8_debounce.c""u8x8_display.c""u8x8_fonts.c""u8x8_gpio.c""u8x8_input_value.c""u8x8_message.c""u8x8_selection_list.c""u8x8_setup.c""u8x8_string.c""u8x8_u16toa.c""u8x8_u8toa.c""u8x8_d_ssd1362.c"INCLUDE_DIRS "include"REQUIRES driverREQUIRES freertos)
-
在u8g2_d_setup.c文件找到對應函數,注釋掉所有函數只留這個,別忘了不注釋
#include "u8g2.h"
-
再通過上面函數中的函數
u8g2_m_32_8_f(&tile_buf_height);
跳轉到u8g2_d_memory.c
文件注釋其他函數
- 將u8g2/u8g2.c文件內容替換如下
#include <stdio.h>
#include "driver/spi_master.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "unistd.h"
#include "string.h"
#include "stdlib.h"
#include "esp_log.h"
#include "driver/i2c.h"
#include "u8g2.h"
#include "u8x8.h"#define I2C_SCL_IO GPIO_NUM_17
#define I2C_SDA_IO GPIO_NUM_9
#define ACK_CHECK_EN 0x1
#define WRITE_BIT I2C_MASTER_WRITE static const char *TAG = "u8g2";
static __inline void delay_clock(int ts)
{uint32_t start, curr;__asm__ __volatile__("rsr %0, ccount" : "=r"(start));do__asm__ __volatile__("rsr %0, ccount" : "=r"(curr));while (curr - start <= ts);
}
#define delay_us(val) delay_clock(240 * val)
#define delay_100ns(val) delay_clock(24 * val)i2c_config_t i2c_config = {.mode = I2C_MODE_MASTER, // 主機模式.sda_io_num = I2C_SDA_IO, // sda i引腳編號.scl_io_num = I2C_SCL_IO, // scl 引腳編號.sda_pullup_en = GPIO_PULLUP_ENABLE, // 上拉使能.scl_pullup_en = GPIO_PULLUP_ENABLE, // 上拉使能.master.clk_speed = 900000 // 100k
};static void _oled_i2c_init(void)
{ESP_LOGE(TAG, "u8g2 init start");i2c_param_config(I2C_NUM_1, &i2c_config);i2c_driver_install(I2C_NUM_1, I2C_MODE_MASTER, 0, 0, 0);ESP_LOGE(TAG, "u8g2 init end");
}void esp32_i2c_write(uint8_t addr, uint32_t idx, uint8_t *data)
{i2c_cmd_handle_t handler = i2c_cmd_link_create();i2c_master_start(handler);i2c_master_write_byte(handler, addr | WRITE_BIT, ACK_CHECK_EN);i2c_master_write(handler, data, idx, 2);i2c_master_stop(handler);i2c_master_cmd_begin(I2C_NUM_1, handler, 100 / portTICK_PERIOD_MS);i2c_cmd_link_delete(handler);
}// u8g2用到的系統資源
uint8_t u8x8_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{switch (msg){case U8X8_MSG_GPIO_AND_DELAY_INIT:_oled_i2c_init(); // 調用iic初始化break;case U8X8_MSG_DELAY_MILLI:vTaskDelay(arg_int);break;default:return 0;}return 1;
}
// u8g2用到的顯示屏控制接口
uint8_t u8x8_byte_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{static uint8_t buffer[32]; /* u8g2/u8x8 will never send more than 32 bytes between START_TRANSFER and END_TRANSFER */static uint8_t buf_idx;uint8_t *data;switch (msg){case U8X8_MSG_BYTE_SEND:data = (uint8_t *)arg_ptr;while (arg_int > 0){buffer[buf_idx++] = *data;data++;arg_int--;}break;case U8X8_MSG_BYTE_INIT:/* add your custom code to init i2c subsystem */break;case U8X8_MSG_BYTE_SET_DC:/* ignored for i2c */break;case U8X8_MSG_BYTE_START_TRANSFER:buf_idx = 0;break;case U8X8_MSG_BYTE_END_TRANSFER:esp32_i2c_write(u8x8_GetI2CAddress(u8x8), buf_idx, buffer);break;default:return 0;}return 1;
}void u8g2Init(u8g2_t *u8g2)
{u8g2_Setup_ssd1362_i2c_256x64_f(u8g2, U8G2_R2, u8x8_byte_i2c, u8x8_gpio_and_delay); // 初始化 u8g2 結構體u8g2_InitDisplay(u8g2); // 根據所選的芯片進行初始化工作,初始化完成后,顯示器處于關閉狀態u8g2_SetPowerSave(u8g2, 0); // 打開顯示器u8g2_ClearBuffer(u8g2);u8g2_SendBuffer(u8g2); // 清屏ESP_LOGI(TAG, "u8g2 init done");
}
- 在u8g2.h文件最近添加聲明
void u8g2Init(u8g2_t *u8g2);
- 將
main.c
代碼改為如下
#include "u8g2.h"
#include "u8x8.h"static u8g2_t u8g2;void oled_init()
{u8g2Init(&u8g2);
}void showmain()
{u8g2_ClearBuffer(&u8g2);u8g2_SendBuffer(&u8g2); // 清屏u8g2_SetFont(&u8g2, u8g2_font_spleen32x64_me); // 設置英文字體u8g2_DrawStr(&u8g2, 64, 64, "1000");u8g2_DrawStr(&u8g2, 192, 64, "KG");u8g2_SendBuffer(&u8g2);
}void showmain2()
{u8g2_ClearBuffer(&u8g2);u8g2_SendBuffer(&u8g2); // 清屏u8g2_SetFont(&u8g2, u8g2_font_wqy16_t_gb2312b); //u8g2_DrawUTF8(&u8g2, 32, 32, "總重量");u8g2_SendBuffer(&u8g2);
}void app_main(void)
{oled_init(); // INITshowmain();showmain2();while (1){vTaskDelay(1000 / portTICK_PERIOD_MS);}
}