注意大小写,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(设备)