OLED 显示屏详解(IIC 协议 0.96 寸 STM32)

✅作者简介:热爱科研的嵌入式开发者,修心和技术同步精进

❤欢迎关注我的知乎:对error视而不见

代码获取、问题探讨及文章转载可私信。

☁ 愿你的生命中有够多的云翳,来造就一个美丽的黄昏。

🍎获取更多嵌入式资料可点击链接进群领取,谢谢支持!👇

点击领取更多详细资料

一、OLED 显示屏概述

OLED(Organic Light - Emitting Diode)即有机发光二极管,0.96 寸的 OLED 显示屏具有体积小、功耗低、视角广、响应速度快等优点,在很多嵌入式系统中被广泛应用。当它与 STM32 微控制器通过 IIC(Inter - Integrated Circuit)协议进行通信时,能够实现简洁高效的显示功能。

二、IIC 协议基础

2.1 IIC 协议简介

IIC 是一种串行通信协议,由飞利浦公司开发。它使用两根线进行通信:SCL(时钟线)和 SDA(数据线)。IIC 总线上可以挂载多个设备,每个设备都有唯一的地址。在 STM32 与 0.96 寸 OLED 显示屏通信时,STM32 作为主设备,OLED 显示屏作为从设备。

2.2 IIC 通信流程

  1. 起始信号:主设备在 SCL 为高电平时,将 SDA 从高电平拉低,表示开始一次通信。
  2. 设备地址:主设备发送从设备的 7 位地址和 1 位读写位(0 表示写,1 表示读)。
  3. 应答信号:从设备在接收到地址后,如果地址匹配,会在第 9 个时钟周期将 SDA 拉低,表示应答。
  4. 数据传输:主设备和从设备之间进行数据传输,每个字节传输后都需要一个应答信号。
  5. 停止信号:主设备在 SCL 为高电平时,将 SDA 从低电平拉高,表示通信结束。

三、0.96 寸 OLED 显示屏硬件连接

3.1 引脚说明

0.96 寸 IIC 接口的 OLED 显示屏通常有 4 个引脚:

  • VCC:电源正极,一般接 3.3V 或 5V。
  • GND:电源负极,接地。
  • SCL:IIC 时钟线,连接到 STM32 的 IIC 时钟引脚。
  • SDA:IIC 数据线,连接到 STM32 的 IIC 数据引脚。

3.2 硬件连接示例

以 STM32F103C8T6 为例,假设使用 I2C1 接口,将 OLED 的 SCL 连接到 PB6,SDA 连接到 PB7,VCC 接 3.3V,GND 接地。

四、STM32 配置 IIC 接口

4.1 初始化 IIC 接口

以下是使用 STM32 HAL 库初始化 I2C1 接口的代码示例:

#include "stm32f1xx_hal.h"

I2C_HandleTypeDef hi2c1;

void MX_I2C1_Init(void)
{
    hi2c1.Instance = I2C1;
    hi2c1.Init.ClockSpeed = 400000;
    hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
    hi2c1.Init.OwnAddress1 = 0;
    hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
    hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
    hi2c1.Init.OwnAddress2 = 0;
    hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
    hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
    if (HAL_I2C_Init(&hi2c1) != HAL_OK)
    {
        Error_Handler();
    }
}

void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    if(i2cHandle->Instance==I2C1)
    {
        __HAL_RCC_GPIOB_CLK_ENABLE();
        __HAL_RCC_I2C1_CLK_ENABLE();

        GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    }
}

4.2 向 OLED 发送数据

以下是向 OLED 发送一个字节数据的函数:

#define OLED_ADDR 0x78  // OLED 设备地址

void OLED_Write_Byte(uint8_t dat, uint8_t cmd)
{
    uint8_t send_data[2];
    send_data[0] = (cmd == 0)? 0x00 : 0x40;
    send_data[1] = dat;
    HAL_I2C_Master_Transmit(&hi2c1, OLED_ADDR, send_data, 2, 100);
}

4.3 OLED 初始化

void OLED_Init(void)
{
    HAL_Delay(100);

    OLED_Write_Byte(0xAE, OLED_CMD); // 关闭显示
    OLED_Write_Byte(0xD5, OLED_CMD); // 设置时钟分频因子
    OLED_Write_Byte(0x80, OLED_CMD);
    OLED_Write_Byte(0xA8, OLED_CMD); // 设置驱动路数
    OLED_Write_Byte(0x3F, OLED_CMD);
    OLED_Write_Byte(0xD3, OLED_CMD); // 设置显示偏移
    OLED_Write_Byte(0x00, OLED_CMD);
    OLED_Write_Byte(0x40, OLED_CMD); // 设置显示开始行
    OLED_Write_Byte(0x8D, OLED_CMD); // 电荷泵设置
    OLED_Write_Byte(0x14, OLED_CMD);
    OLED_Write_Byte(0x20, OLED_CMD); // 设置内存地址模式
    OLED_Write_Byte(0x02, OLED_CMD);
    OLED_Write_Byte(0xA1, OLED_CMD); // 设置段重定义
    OLED_Write_Byte(0xC8, OLED_CMD); // 设置 COM 扫描方向
    OLED_Write_Byte(0xDA, OLED_CMD); // 设置 COM 硬件引脚配置
    OLED_Write_Byte(0x12, OLED_CMD);
    OLED_Write_Byte(0x81, OLED_CMD); // 对比度设置
    OLED_Write_Byte(0xCF, OLED_CMD);
    OLED_Write_Byte(0xD9, OLED_CMD); // 设置预充电周期
    OLED_Write_Byte(0xF1, OLED_CMD);
    OLED_Write_Byte(0xDB, OLED_CMD); // 设置 VCOMH 电压倍率
    OLED_Write_Byte(0x40, OLED_CMD);
    OLED_Write_Byte(0xA4, OLED_CMD); // 全局显示开启
    OLED_Write_Byte(0xA6, OLED_CMD); // 正常显示
    OLED_Write_Byte(0xAF, OLED_CMD); // 开启显示
}

五、在 OLED 上显示字符和图形

5.1 显示字符

以下是在 OLED 上显示一个字符的函数:

void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t chr, uint8_t size)
{
    uint8_t c = 0, i = 0;
    c = chr - ' ';
    if (x > 128 - size / 2)
    {
        x = 0;
        y = y + 2;
    }
    if (size == 16)
    {
        for (i = 0; i < 8; i++)
        {
            OLED_Set_Pos(x, y);
            OLED_Write_Byte(F8X16[c * 16 + i], OLED_DATA);
            OLED_Set_Pos(x, y + 1);
            OLED_Write_Byte(F8X16[c * 16 + i + 8], OLED_DATA);
            x++;
        }
    }
}

5.2 显示字符串

void OLED_ShowString(uint8_t x, uint8_t y, uint8_t *chr, uint8_t size)
{
    unsigned char j = 0;
    while (chr[j] != '\0')
    {
        OLED_ShowChar(x, y, chr[j], size);
        x += size / 2;
        if (x > 128 - size / 2)
        {
            x = 0;
            y += 2;
        }
        j++;
    }
}

5.3 显示图形

要显示图形,需要将图形数据存储在数组中,然后逐字节写入 OLED。以下是一个简单的示例:

const uint8_t gImage_logo[] = {
    // 图形数据
};

void OLED_ShowPicture(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, const uint8_t BMP[])
{
    unsigned int j = 0;
    uint8_t x, y;

    if (y1 % 8 == 0)
        y = y1 / 8;
    else
        y = y1 / 8 + 1;
    for (y = y0; y < y1; y++)
    {
        OLED_Set_Pos(x0, y);
        for (x = x0; x < x1; x++)
        {
            OLED_Write_Byte(BMP[j++], OLED_DATA);
        }
    }
}

六、主函数调用示例

int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_I2C1_Init();

    OLED_Init();
    OLED_ShowString(0, 0, "Hello, World!", 16);
    while (1)
    {
        // 主循环
    }
}

七、总结

通过以上步骤,我们可以实现 STM32 与 0.96 寸 IIC 接口 OLED 显示屏的通信,并在上面显示字符和图形。在实际应用中,可以根据需求进一步扩展功能,如显示动态图形、实现菜单界面等。同时,要注意 IIC 通信的稳定性和数据传输的准确性,确保显示效果的质量。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值