TB作品】51单片机 Proteus仿真 51单片机SPI显示OLED字符驱动

// GND 电源地

// VCC 接5V或3.3v电源

// D0 P1^4(SCL)

// D1 P1^3(SDA)

// RES 接P12

// DC 接P11

// CS 接P10

OLED显示接口与控制实验报告

背景

OLED(有机发光二极管)显示器由于其高对比度、低功耗和快速响应时间,被广泛应用于各种电子设备。本实验旨在使用单片机接口和控制OLED显示器。所用的显示驱动器是SSD1306,这是小型OLED屏幕常用的控制器。

硬件组件

  1. OLED显示器:使用由SSD1306控制器驱动的显示模块。
  2. 单片机:使用基于8051的单片机来控制OLED显示器。
  3. 电源:需要3.3V或5V电源为OLED模块供电。
  4. 连接线:用于将OLED与单片机连接。

电路连接

  • GND:连接到电源地。
  • VCC:连接到3.3V或5V电源。
  • D0 (SCL):连接到P1^4(SCL)。
  • D1 (SDA):连接到P1^3(SDA)。
  • RES:连接到P12。
  • DC:连接到P11。
  • CS:连接到P10。

设计原理

显存结构

OLED的显存存放格式如下:

复制代码
[0]0 1 2 3 ... 127
[1]0 1 2 3 ... 127
[2]0 1 2 3 ... 127
...
[7]0 1 2 3 ... 127

延时函数

c 复制代码
void delay_ms1(unsigned int ms) {
    unsigned int a;
    while (ms) {
        a = 80;
        while (a--);
        ms--;
    }
    return;
}

该延时函数通过简单的循环实现毫秒级延时,用于在OLED初始化和控制过程中确保操作稳定。

写入字节

根据不同的OLED模式,通过并行或串行接口向SSD1306写入字节。以下代码展示了并行和串行模式下的写入操作:

c 复制代码
#if OLED_MODE == 1
// 并行模式
void OLED_WR_Byte(u8 dat, u8 cmd) {
    DATAOUT(dat);
    if (cmd) OLED_DC_Set();
    else OLED_DC_Clr();
    OLED_CS_Clr();
    OLED_WR_Clr();
    OLED_WR_Set();
    OLED_CS_Set();
    OLED_DC_Set();
}
#else
// 串行模式
void OLED_WR_Byte(u8 dat, u8 cmd) {
    u8 i;
    if (cmd) OLED_DC_Set();
    else OLED_DC_Clr();
    OLED_CS_Clr();
    for (i = 0; i < 8; i++) {
        OLED_SCLK_Clr();
        if (dat & 0x80) OLED_SDIN_Set();
        else OLED_SDIN_Clr();
        OLED_SCLK_Set();
        dat <<= 1;
    }
    OLED_CS_Set();
    OLED_DC_Set();
}
#endif

主要功能实现

设置光标位置
c 复制代码
void OLED_Set_Pos(unsigned char x, unsigned char y) {
    OLED_WR_Byte(0xb0 + y, OLED_CMD);
    OLED_WR_Byte(((x & 0xf0) >> 4) | 0x10, OLED_CMD);
    OLED_WR_Byte((x & 0x0f) | 0x01, OLED_CMD);
}
显示控制

开启和关闭OLED显示:

c 复制代码
void OLED_Display_On(void) {
    OLED_WR_Byte(0X8D, OLED_CMD); // SET DCDC命令
    OLED_WR_Byte(0X14, OLED_CMD); // DCDC ON
    OLED_WR_Byte(0XAF, OLED_CMD); // DISPLAY ON
}

void OLED_Display_Off(void) {
    OLED_WR_Byte(0X8D, OLED_CMD); // SET DCDC命令
    OLED_WR_Byte(0X10, OLED_CMD); // DCDC OFF
    OLED_WR_Byte(0XAE, OLED_CMD); // DISPLAY OFF
}
清屏
c 复制代码
void OLED_Clear(void) {
    u8 i, n;
    for (i = 0; i < 8; i++) {
        OLED_WR_Byte(0xb0 + i, OLED_CMD); // 设置页地址(0~7)
        OLED_WR_Byte(0x00, OLED_CMD);     // 设置显示位置---列低地址
        OLED_WR_Byte(0x10, OLED_CMD);     // 设置显示位置---列高地址
        for (n = 0; n < 128; n++) OLED_WR_Byte(0, OLED_DATA);
    }
}
显示字符

在指定位置显示一个字符:

c 复制代码
void OLED_ShowChar(u8 x, u8 y, u8 chr) {
    unsigned char c = 0, i = 0;
    c = chr - ' ';
    if (x > Max_Column - 1) {
        x = 0; y = y + 2;
    }
    if (SIZE == 16) {
        OLED_Set_Pos(x, y);
        for (i = 0; i < 8; i++) OLED_WR_Byte(F8X16[c * 16 + i], OLED_DATA);
        OLED_Set_Pos(x, y + 1);
        for (i = 0; i < 8; i++) OLED_WR_Byte(F8X16[c * 16 + i + 8], OLED_DATA);
    } else {
        OLED_Set_Pos(x, y + 1);
        for (i = 0; i < 6; i++) OLED_WR_Byte(F6x8[c][i], OLED_DATA);
    }
}
显示字符串
c 复制代码
void OLED_ShowString(u8 x, u8 y, u8 *chr) {
    unsigned char j = 0;
    while (chr[j] != '\0') {
        OLED_ShowChar(x, y, chr[j]);
        x += 8;
        if (x > 120) {
            x = 0; y += 2;
        }
        j++;
    }
}

初始化

OLED的初始化过程涉及一系列的配置命令,以确保显示器正确工作:

c 复制代码
void OLED_Init(void) {
    OLED_RST_Set();
    delay_ms1(100);
    OLED_RST_Clr();
    delay_ms1(100);
    OLED_RST_Set();

    OLED_WR_Byte(0xAE, OLED_CMD); // 关闭OLED面板
    OLED_WR_Byte(0x00, OLED_CMD); // 设置低列地址
    OLED_WR_Byte(0x10, OLED_CMD); // 设置高列地址
    OLED_WR_Byte(0x40, OLED_CMD); // 设置起始行地址
    OLED_WR_Byte(0x81, OLED_CMD); // 设置对比度控制寄存器
    OLED_WR_Byte(0xCF, OLED_CMD); // 设置SEG输出电流亮度
    OLED_WR_Byte(0xA1, OLED_CMD); // 设置段/列映射
    OLED_WR_Byte(0xC8, OLED_CMD); // 设置COM/行扫描方向
    OLED_WR_Byte(0xA6, OLED_CMD); // 设置正常显示
    OLED_WR_Byte(0xA8, OLED_CMD); // 设置多路复用比率
    OLED_WR_Byte(0x3f, OLED_CMD); // 1/64 duty
    OLED_WR_Byte(0xD3, OLED_CMD); // 设置显示偏移
    OLED_WR_Byte(0x00, OLED_CMD); // 不偏移
    OLED_WR_Byte(0xd5, OLED_CMD); // 设置显示时钟分频比/振荡频率
    OLED_WR_Byte(0x80, OLED_CMD); // 设置时钟为100帧/秒
    OLED_WR_Byte(0xD9, OLED_CMD); // 设置预充电周期
    OLED_WR_Byte(0xF1, OLED_CMD); // 设置预充电为15时钟和放电为1时钟
    OLED_WR_Byte(0xDA, OLED_CMD); // 设置COM引脚硬件配置
    OLED_WR_Byte(0x12, OLED_CMD);
    OLED_WR_Byte(0xDB, OLED_CMD); // 设置VCOMH
    OLED_WR_Byte(0x40, OLED_CMD); // 设置VCOM解除电平
    OLED_WR_Byte(0x20, OLED_CMD); // 设置页地址模式
    OLED_WR_Byte(0x02, OLED_CMD);
    OLED_WR_Byte(0x8D, OLED_CMD); // 设置电荷泵使能/禁用
    OLED_WR_Byte(0x14, OLED_CMD); // 设置(0x10)禁用
    OLED_WR_Byte(0xA4, OLED_CMD); // 禁用整个显示
    OLED_WR_Byte(0xA6, OLED_CMD); // 禁用反向显示
    OLED_WR_Byte(0xAF, OLED_CMD); // 打开OLED面板
    OLED_Clear();
    OLED_Set_Pos(0, 0);
}

资料

复制代码
https://docs.qq.com/sheet/DUEdqZ2lmbmR6UVdU?tab=BB08J2
相关推荐
LXY_BUAA1 天前
《嵌入式操作系统》_GPIOLIB前置知识_20260328
驱动开发·嵌入式硬件
17(无规则自律)1 天前
深度剖析Linux Input子系统(2):驱动开发流程与现代 Multi-touch 协议
linux·驱动开发·嵌入式硬件
BackCatK Chen1 天前
STM32保姆级入门教程|第5章:GPIO内部结构 + 8种模式 + 功能详解
stm32·嵌入式硬件·gpio·推挽输出·开漏输出·gpio内部结构·上拉输入
Heartache boy1 天前
野火STM32_HAL库版课程笔记-TIM触发ADC采集
笔记·stm32·单片机·嵌入式硬件
你疯了抱抱我1 天前
【Altium Designer】网络线(颜色、旋转、粗细);网络标签 && 端口的差别(重点!)
嵌入式硬件·嵌入式·pcb·电路
蓝凌y1 天前
51单片机之按键控制RGB灯
单片机·嵌入式硬件
156082072191 天前
关于XILINX的fir compiler小数倍内插设计
单片机·嵌入式硬件
ivy159868377151 天前
芯锦科技 HP9116 QC3+多协议USB快充接口芯片
网络·单片机·嵌入式硬件·5g·p2p
LXY_BUAA1 天前
《嵌入式操作系统》_使用GPIOLIB编写驱动_添加驱动到内核中_20260328
驱动开发·嵌入式硬件
liwulin05062 天前
【ESP32-S3】通过ROS2使用YDLIDAR X2进行SLAM、自主导航方案选择
单片机·嵌入式硬件