本文介绍如何使用STM32F103C8T6(蓝板)通过软件模拟IIC协议驱动0.96英寸OLED(驱动芯片SSD1306),这个小屏幕相信每一个朋友在大学生活里都不会错过,也是很多课设毕设显示需求的首选,我一向喜欢直接干,咱们也不说那些原理啥的,直接站在前人的肩膀优化,进而形成自己的框架。


1. 硬件连接

OLED引脚STM32引脚
VCC3.3V
GNDGND
SCLPB6
SDAPB7

可根据实际修改引脚,只需在代码中对应修改即可。


2. 驱动架构

代码分为三个文件:

  • oled.h:引脚定义、函数声明

  • oled_font.h:存放所有字库数据(6x8 ASCII、8x16 ASCII、16x16汉字)

  • oled.c:IIC模拟、OLED初始化、显示函数实现

这种结构将字库与驱动分离,便于维护和扩充汉字。


3. 关键代码实现

3.1 引脚定义与IIC宏

// oled.h
#define OLED_SCL_PORT      GPIOB
#define OLED_SCL_PIN       GPIO_PIN_6
#define OLED_SDA_PORT      GPIOB
#define OLED_SDA_PIN       GPIO_PIN_7

#define OLED_SCL_H         HAL_GPIO_WritePin(OLED_SCL_PORT, OLED_SCL_PIN, GPIO_PIN_SET)
#define OLED_SCL_L         HAL_GPIO_WritePin(OLED_SCL_PORT, OLED_SCL_PIN, GPIO_PIN_RESET)
#define OLED_SDA_H         HAL_GPIO_WritePin(OLED_SDA_PORT, OLED_SDA_PIN, GPIO_PIN_SET)
#define OLED_SDA_L         HAL_GPIO_WritePin(OLED_SDA_PORT, OLED_SDA_PIN, GPIO_PIN_RESET)

3.2 软件IIC核心函数

// oled.c
static void IIC_Start(void)
{
    OLED_SDA_H; OLED_SCL_H;
    delay_us(5);
    OLED_SDA_L;
    delay_us(5);
    OLED_SCL_L;
}

static void IIC_Stop(void)
{
    OLED_SCL_L; OLED_SDA_L;
    delay_us(5);
    OLED_SCL_H;
    delay_us(5);
    OLED_SDA_H;
}

static void IIC_SendByte(uint8_t byte)
{
    for(uint8_t i=0; i<8; i++) {
        if(byte & 0x80) OLED_SDA_H; else OLED_SDA_L;
        byte <<= 1;
        delay_us(2);
        OLED_SCL_H; delay_us(2);
        OLED_SCL_L; delay_us(2);
    }
}

static void OLED_WriteCmd(uint8_t cmd)
{
    IIC_Start();
    IIC_SendByte(0x78);      // 写地址
    IIC_WaitAck();
    IIC_SendByte(0x00);      // 命令模式
    IIC_WaitAck();
    IIC_SendByte(cmd);
    IIC_WaitAck();
    IIC_Stop();
}

3.3 SSD1306初始化序列

void OLED_Init(void)
{
    // 初始化GPIO(使能时钟,开漏输出)
    OLED_WriteCmd(0xAE);     // 关闭显示
    OLED_WriteCmd(0x81);     // 对比度设置
    OLED_WriteCmd(0xFF);
    OLED_WriteCmd(0xA4);     // 正常显示
    OLED_WriteCmd(0xA6);     // 正显(0亮1灭)
    OLED_WriteCmd(0x20);     // 寻址模式
    OLED_WriteCmd(0x10);     // 页寻址模式
    OLED_WriteCmd(0xB0);     // 起始页0
    OLED_WriteCmd(0x00);     // 起始列低4位
    OLED_WriteCmd(0x10);     // 起始列高4位
    OLED_WriteCmd(0x40);     // 起始行
    OLED_WriteCmd(0xA1);     // 列重映射(SEG0->列127)
    OLED_WriteCmd(0xA8);     // 多路复用比
    OLED_WriteCmd(0x3F);
    OLED_WriteCmd(0xC8);     // COM扫描方向(反向)
    OLED_WriteCmd(0xD3);     // 显示偏移
    OLED_WriteCmd(0x00);
    OLED_WriteCmd(0xDA);     // COM引脚配置
    OLED_WriteCmd(0x12);
    OLED_WriteCmd(0xD9);     // 预充电周期
    OLED_WriteCmd(0x22);
    OLED_WriteCmd(0xDB);     // VCOMH电压
    OLED_WriteCmd(0x20);
    OLED_WriteCmd(0x8D);     // 电荷泵
    OLED_WriteCmd(0x14);
    OLED_WriteCmd(0xAF);     // 开启显示
}

3.4 显示字符

// 6x8 ASCII显示
void OLED_ShowChar_6x8(uint8_t x, uint8_t y, uint8_t ch)
{
    uint8_t c = ch - 32;
    OLED_SetPos(x, y);
    for(uint8_t i=0; i<6; i++)
        OLED_WriteData(F6x8[c][i]);
}

// 8x16 ASCII显示
void OLED_ShowChar_8x16(uint8_t x, uint8_t y, uint8_t ch)
{
    uint8_t c = ch - 32;
    OLED_SetPos(x, y);
    for(uint8_t i=0; i<8; i++)
        OLED_WriteData(F8X16[c*16 + i]);
    OLED_SetPos(x, y+1);
    for(uint8_t i=0; i<8; i++)
        OLED_WriteData(F8X16[c*16 + i + 8]);
}

3.5 显示汉字(16x16)

void OLED_ShowChinese(uint8_t x, uint8_t y, uint8_t index)
{
    uint16_t addr = index * 32;   // 每个汉字32字节
    OLED_SetPos(x, y);
    for(uint8_t i=0; i<16; i++)
        OLED_WriteData(F16x16[addr + i]);
    OLED_SetPos(x, y+1);
    for(uint8_t i=0; i<16; i++)
        OLED_WriteData(F16x16[addr + 16 + i]);
}

5. 字库说明

  • 6x8 ASCII:共95个字符,每个6字节,适合显示简单英文。

  • 8x16 ASCII:共95个字符,每个16字节,高度为16,可显示更清晰的英文。

  • 16x16汉字:用户可自行添加汉字,每个汉字32字节(列行式逆向输出)。示例中内置了“野火电子”四个汉字,可根据需要扩充。

字库数据存放在独立的头文件 oled_font.h 中,便于维护和替换。


6. 效果展示

通过网盘分享的文件:STM32_OLED_SoftIIC.zip
链接: https://pan.baidu.com/s/1CdxPxJS3hajggX4NcLUoxQ?pwd=rxnz 提取码: rxnz 
--来自百度网盘超级会员v8的分享

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐