注意大小寫,wsl(也就是linux環境)嚴格區分大小寫。有幫助記得訂閱專欄+點贊,當前不定期持續更新。
一、文件夾格式:
project/ # 項目根目錄
├─ main/ # 主程序文件夾
│ ├─ main.c # 主函數文件(包含 app_main)
│ └─ CMakeLists.txt # main 組件的編譯配置
├─ components/ # 自定義組件目錄(與 main 同級)
│ └─OLED/ # OLED 組件
│ ├─ OLED.c # OLED 功能實現
│ ├─ OLED.h # OLED 頭文件(聲明函數、宏等)
│ └─ CMakeLists.txt # OLED 組件的編譯配置
├─ CMakeLists.txt # 項目根目錄編譯配置(指定項目名稱、依賴等)
├─ sdkconfig # ESP-IDF 配置文件(由 menuconfig 生成)
└─ partitions.csv # 分區表配置文件(可選,默認使用 ESP-IDF 自帶)
二、OLED.c
#include "OLED.h"
#include "font.h"
#include "driver/i2c.h"
#include "esp_log.h"static const char *TAG = "OLED";// I2C初始化
void OLED_I2C_Init(void)
{i2c_config_t conf = {.mode = I2C_MODE_MASTER,.sda_io_num = OLED_SDA_PIN,.scl_io_num = OLED_SCL_PIN,.sda_pullup_en = GPIO_PULLUP_ENABLE,.scl_pullup_en = GPIO_PULLUP_ENABLE,.master.clk_speed = OLED_FREQ_HZ,};ESP_ERROR_CHECK(i2c_param_config(OLED_I2C_PORT, &conf));ESP_ERROR_CHECK(i2c_driver_install(OLED_I2C_PORT, conf.mode, 0, 0, 0));ESP_LOGI(TAG, "I2C initialized successfully");
}// I2C寫數據
static esp_err_t i2c_master_write_slave(uint8_t *data_wr, size_t size)
{i2c_cmd_handle_t cmd = i2c_cmd_link_create();i2c_master_start(cmd);i2c_master_write_byte(cmd, (OLED_I2C_ADDRESS << 1) | I2C_MASTER_WRITE, true);i2c_master_write(cmd, data_wr, size, true);i2c_master_stop(cmd);esp_err_t ret = i2c_master_cmd_begin(OLED_I2C_PORT, cmd, pdMS_TO_TICKS(1000));i2c_cmd_link_delete(cmd);return ret;
}// 寫命令
void OLED_WriteCommand(uint8_t Command)
{uint8_t buf[2] = {0x00, Command}; // 0x00表示命令ESP_ERROR_CHECK(i2c_master_write_slave(buf, 2));
}// 寫數據
void OLED_WriteData(uint8_t Data)
{uint8_t buf[2] = {0x40, Data}; // 0x40表示數據ESP_ERROR_CHECK(i2c_master_write_slave(buf, 2));
}// 以下函數保持不變,與原始代碼相同
void OLED_SetCursor(uint8_t Y, uint8_t X)
{OLED_WriteCommand(0xB0 | Y);OLED_WriteCommand(0x10 | ((X & 0xF0) >> 4));OLED_WriteCommand(0x00 | (X & 0x0F));
}void OLED_Clear(void)
{ uint8_t i, j;for (j = 0; j < 8; j++){OLED_SetCursor(j, 0);for(i = 0; i < 128; i++){OLED_WriteData(0x00);}}
}void OLED_ShowChar(uint8_t Line, uint8_t Column, char Char)
{ uint8_t i;OLED_SetCursor((Line - 1) * 2, (Column - 1) * 8);for (i = 0; i < 8; i++){OLED_WriteData(OLED_F8x16[Char - ' '][i]);}OLED_SetCursor((Line - 1) * 2 + 1, (Column - 1) * 8);for (i = 0; i < 8; i++){OLED_WriteData(OLED_F8x16[Char - ' '][i + 8]);}
}void OLED_ShowString(uint8_t Line, uint8_t Column, char *String)
{uint8_t i;for (i = 0; String[i] != '\0'; i++){OLED_ShowChar(Line, Column + i, String[i]);}
}uint32_t OLED_Pow(uint32_t X, uint32_t Y)
{uint32_t Result = 1;while (Y--){Result *= X;}return Result;
}void OLED_ShowNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{uint8_t i;for (i = 0; i < Length; i++) {OLED_ShowChar(Line, Column + i, Number / OLED_Pow(10, Length - i - 1) % 10 + '0');}
}void OLED_ShowSignedNum(uint8_t Line, uint8_t Column, int32_t Number, uint8_t Length)
{uint8_t i;uint32_t Number1;if (Number >= 0){OLED_ShowChar(Line, Column, '+');Number1 = Number;}else{OLED_ShowChar(Line, Column, '-');Number1 = -Number;}for (i = 0; i < Length; i++) {OLED_ShowChar(Line, Column + i + 1, Number1 / OLED_Pow(10, Length - i - 1) % 10 + '0');}
}void OLED_ShowHexNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{uint8_t i, SingleNumber;for (i = 0; i < Length; i++) {SingleNumber = Number / OLED_Pow(16, Length - i - 1) % 16;if (SingleNumber < 10){OLED_ShowChar(Line, Column + i, SingleNumber + '0');}else{OLED_ShowChar(Line, Column + i, SingleNumber - 10 + 'A');}}
}void OLED_ShowBinNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{uint8_t i;for (i = 0; i < Length; i++) {OLED_ShowChar(Line, Column + i, Number / OLED_Pow(2, Length - i - 1) % 2 + '0');}
}void OLED_Init(void)
{uint32_t i, j;for (i = 0; i < 1000; i++) //上電延時{for (j = 0; j < 1000; j++);}OLED_I2C_Init(); //端口初始化OLED_WriteCommand(0xAE); //關閉顯示OLED_WriteCommand(0xD5); //設置顯示時鐘分頻比/振蕩器頻率OLED_WriteCommand(0x80);OLED_WriteCommand(0xA8); //設置多路復用率OLED_WriteCommand(0x3F);OLED_WriteCommand(0xD3); //設置顯示偏移OLED_WriteCommand(0x00);OLED_WriteCommand(0x40); //設置顯示開始行OLED_WriteCommand(0xA1); //設置左右方向,0xA1正常 0xA0左右反置OLED_WriteCommand(0xC8); //設置上下方向,0xC8正常 0xC0上下反置OLED_WriteCommand(0xDA); //設置COM引腳硬件配置OLED_WriteCommand(0x12);OLED_WriteCommand(0x81); //設置對比度控制OLED_WriteCommand(0xCF);OLED_WriteCommand(0xD9); //設置預充電周期OLED_WriteCommand(0xF1);OLED_WriteCommand(0xDB); //設置VCOMH取消選擇級別OLED_WriteCommand(0x30);OLED_WriteCommand(0xA4); //設置整個顯示打開/關閉OLED_WriteCommand(0xA6); //設置正常/倒轉顯示OLED_WriteCommand(0x8D); //設置充電泵OLED_WriteCommand(0x14);OLED_WriteCommand(0xAF); //開啟顯示OLED_Clear(); //OLED清屏
}
三、OLED.h
#ifndef __OLED_H
#define __OLED_H#include "driver/i2c.h"
#include "font.h"// I2C 配置參數
#define OLED_I2C_PORT I2C_NUM_0
#define OLED_I2C_ADDRESS 0x3C // 通常為0x3C或0x3D
#define OLED_SCL_PIN 5 // 根據實際連接修改
#define OLED_SDA_PIN 4 // 根據實際連接修改
#define OLED_FREQ_HZ 100000 // I2C頻率// 函數聲明
void OLED_I2C_Init(void);
void OLED_WriteCommand(uint8_t Command);
void OLED_WriteData(uint8_t Data);
void OLED_SetCursor(uint8_t Y, uint8_t X);
void OLED_Clear(void);
void OLED_ShowChar(uint8_t Line, uint8_t Column, char Char);
void OLED_ShowString(uint8_t Line, uint8_t Column, char *String);
void OLED_ShowNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length);
void OLED_ShowSignedNum(uint8_t Line, uint8_t Column, int32_t Number, uint8_t Length);
void OLED_ShowHexNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length);
void OLED_ShowBinNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length);
void OLED_Init(void);#endif
四、CMakeLists.txt
idf_component_register(SRCS "OLED.c"INCLUDE_DIRS "."REQUIRES driver
)
五、說明
OLED使用到了espidf官方提供的iic庫,所以REQUIRES (依賴)需要包含 driver(設備)
六、參考
[4-2] OLED顯示屏_嗶哩嗶哩_bilibili