[STM32F1] STM32F103 OLED显示

[复制链接]
103|0
Haizangwang 发表于 2025-11-5 21:55 | 显示全部楼层 |阅读模式
一、实验目的
掌握STM32F103通过I2C接口驱动OLED显示屏的方法
学习U8g2图形库的移植和使用
实现多种显示效果:学号姓名显示、滑动动画、图形绘制
了解I2C通信协议及调试方法
U8g2库开源网址:https://github.com/olikraus/u8g2
二、实验环境
2.1 硬件环境
主控芯片:STM32F103C8T6
OLED显示屏:0.96寸SSD1306,I2C接口
接口连接:
SCL → PB10
SDA → PB11
VCC → 3.3V
GND → GND
2.2 软件环境
开发环境:STM32CubeMX + Keil MDK
图形库:U8g2
调试工具:逻辑分析仪
三、实验原理
3.1 OLED显示原理
OLED(Organic Light-Emitting Diode)是有机发光二极管,具有自发光特性,不需要背光。SSD1306控制器支持128×64分辨率,通过I2C协议进行通信。

3.2 I2C通信协议
I2C(Inter-Integrated Circuit)是一种同步、多主从的串行总线,包含:

SCL:时钟线
SDA:数据线
7位设备地址:0x78(OLED地址)
3.3 U8g2图形库
U8g2是嵌入式设备的单色图形库,支持多种显示器控制器,提供丰富的绘图API。

四、实验步骤
4.1 CubeMX配置
时钟配置

HSE:8MHz
PLL倍频:9倍
系统时钟:72MHz

72159690b10b1ea013.png

I2C配置

使用I2C2
标准模式(100kHz)
SCL:PB10
SDA:PB11

40967690b10aacaf2a.png

生成代码

生成HAL库基础框架

28812690b10a4f06cf.png

4.2 U8g2库移植
4.2.1准备U8g2库文件
    移植U8g2图像库需要准备好,U8g2的源码是在GitHub上开源的。

    U8g2下载地址: https://github.com/olikraus/u8g2
    进入源码地址后下载整个U8g2图形库的压缩包。


————————————————

原文链接:https://blog.csdn.net/black_sneak/article/details/126312657

68787690b108b151db.png

4.2.2将精简后的U8g2库添加至Keil

73353690b10710fee5.png

56982690b1079f2b0d.png


// stm32_u8g2.c
uint8_t u8x8_byte_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
    static uint8_t buffer[32];
    static uint8_t buf_idx;
    uint8_t *data;

    switch(msg)
    {
        case U8X8_MSG_BYTE_SEND:
            data = (uint8_t *)arg_ptr;
            while(arg_int > 0)
            {
                buffer[buf_idx++] = *data;
                data++;
                arg_int--;
            }
            break;

        case U8X8_MSG_BYTE_START_TRANSFER:
            buf_idx = 0;
            break;

        case U8X8_MSG_BYTE_END_TRANSFER:
            HAL_I2C_Master_Transmit(&hi2c2, 0x78, buffer, buf_idx, 1000);
            break;

        default:
            return 0;
    }
    return 1;
}

uint8_t u8x8_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
    switch(msg)
    {
        case U8X8_MSG_DELAY_MILLI:
            HAL_Delay(arg_int);
            break;
        default:
            return 0;
    }
    return 1;
}

void u8g2Init(u8g2_t *u8g2)
{
    u8g2_Setup_ssd1306_i2c_128x64_noname_f(u8g2, U8G2_R0, u8x8_byte_hw_i2c, u8x8_gpio_and_delay);
    u8g2_InitDisplay(u8g2);
    u8g2_SetPowerSave(u8g2, 0);
}



4.3 显示功能实现
主程序框架:

// main.c
int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_I2C2_Init();

    u8g2_t u8g2;
    u8g2Init(&u8g2);

    while(1)
    {
        u8g2_FirstPage(&u8g2);
        do {
            u8g2DrawTest(&u8g2);  // 主要显示函数
        } while(u8g2_NextPage(&u8g2));
    }
}



五、功能实现与代码分析
5.1 三模式切换显示
void testMyDisplay(u8g2_t *u8g2)
{
    static uint8_t mode = 0;
    static uint32_t last_change = 0;

    // 3秒自动切换模式
    if(HAL_GetTick() - last_change > 3000) {
        mode = (mode + 1) % 3;
        last_change = HAL_GetTick();
    }

    u8g2_ClearBuffer(u8g2);

    switch(mode) {
        case 0:
            // 模式0:大字体显示学号
            u8g2_SetFont(u8g2, u8g2_font_ncenB18_tr);
            u8g2_DrawStr(u8g2, 5, 35, "632307030613");
            break;

        case 1:
            // 模式1:显示中文名字
            u8g2_SetFont(u8g2, u8g2_font_ncenB14_tr);
            u8g2_DrawStr(u8g2, 30, 35, "扎西坚才");
            break;

        case 2:
            // 模式2:同时显示学号和名字
            u8g2_SetFont(u8g2, u8g2_font_ncenB12_tr);
            u8g2_DrawStr(u8g2, 15, 25, "632307030613");
            u8g2_SetFont(u8g2, u8g2_font_ncenB10_tr);
            u8g2_DrawStr(u8g2, 40, 45, "扎西坚才");
            break;
    }
}



5.2 滑动动画效果
void slideAnimation(u8g2_t *u8g2)
{
    // 文字从右侧滑入
    for(int x = 128; x >= 0; x -= 2) {
        u8g2_ClearBuffer(u8g2);
        u8g2_SetFont(u8g2, u8g2_font_ncenB12_tr);
        u8g2_DrawStr(u8g2, x, 32, "滑动显示效果");
        u8g2_SendBuffer(u8g2);
        HAL_Delay(30);
    }

    // 文字向上滑动消失
    for(int y = 32; y >= -20; y -= 2) {
        u8g2_ClearBuffer(u8g2);
        u8g2_SetFont(u8g2, u8g2_font_ncenB12_tr);
        u8g2_DrawStr(u8g2, 0, y, "向上滑动");
        u8g2_SendBuffer(u8g2);
        HAL_Delay(30);
    }
}


5.3 图形绘制与动态效果
void drawGraphics(u8g2_t *u8g2)
{
    // 绘制基本图形
    u8g2_ClearBuffer(u8g2);

    // 绘制矩形框
    u8g2_DrawFrame(u8g2, 10, 10, 50, 30);

    // 绘制填充圆
    u8g2_DrawDisc(u8g2, 90, 25, 15, U8G2_DRAW_ALL);

    // 绘制三角形
    u8g2_DrawTriangle(u8g2, 30, 50, 50, 30, 70, 50);

    // 绘制线条
    u8g2_DrawLine(u8g2, 5, 5, 120, 60);

    u8g2_SendBuffer(u8g2);
    HAL_Delay(2000);
}

void dynamicSmile(u8g2_t *u8g2)
{
    // 动态笑脸动画
    for(int i = 0; i < 5; i++) {
        u8g2_ClearBuffer(u8g2);

        // 绘制脸型
        u8g2_DrawCircle(u8g2, 64, 32, 25, U8G2_DRAW_ALL);

        // 眼睛
        u8g2_DrawDisc(u8g2, 50, 25, 4, U8G2_DRAW_ALL);
        u8g2_DrawDisc(u8g2, 78, 25, 4, U8G2_DRAW_ALL);

        // 动态嘴巴
        if(i % 2 == 0) {
            // 直线嘴巴
            u8g2_DrawLine(u8g2, 50, 40, 78, 40);
        } else {
            // 微笑嘴巴
            u8g2_DrawCircle(u8g2, 64, 40, 12, U8G2_DRAW_UPPER_LEFT | U8G2_DRAW_UPPER_RIGHT);
        }

        u8g2_SendBuffer(u8g2);
        HAL_Delay(500);
    }
}


5.4 进度条显示
void progressBar(u8g2_t *u8g2)
{
    for(int i = 0; i <= 100; i += 5) {
        u8g2_ClearBuffer(u8g2);

        // 显示标题
        u8g2_SetFont(u8g2, u8g2_font_ncenB10_tr);
        u8g2_DrawStr(u8g2, 10, 15, "Loading...");

        // 绘制进度条边框
        u8g2_DrawRFrame(u8g2, 10, 25, 100, 15, 3);

        // 绘制进度条填充
        u8g2_DrawRBox(u8g2, 10, 25, i, 15, 3);

        // 显示百分比
        char percent[10];
        sprintf(percent, "%d%%", i);
        u8g2_DrawStr(u8g2, 115, 38, percent);

        u8g2_SendBuffer(u8g2);
        HAL_Delay(100);
    }
}


六、I2C通信分析
6.1 波形特征分析
使用逻辑分析仪捕获的I2C波形显示:

起始条件:SCL为高电平时,SDA出现下降沿
设备地址:0x78(写模式)
数据传送:每个字节后跟随ACK位
停止条件:SCL为高电平时,SDA出现上升沿
6.2 通信数据格式
开始 → 设备地址(0x78) → 控制字节(0x00) → 显示数据 → 停止


6.3 调试方法
逻辑分析仪:直接捕获硬件I2C波形
软件模拟:使用GPIO模拟I2C便于调试
串口打印:输出调试信息验证通信状态
七、实验结果
7.1 显示效果




嵌入式2

7.2 性能指标
显示刷新率:约30fps
模式切换间隔:3秒
动画流畅度:良好
内存占用:优化合理
八、实验总结
8.1 技术要点
U8g2库移植:成功将U8g2库移植到STM32F103平台
I2C驱动:实现了稳定的硬件I2C通信
显示优化:通过页面刷新机制提高显示效率
动画实现:掌握了嵌入式系统中的动画编程技巧
8.2 遇到的问题及解决方案
问题:初始显示乱码
解决:检查I2C地址配置,确认使用0x78

问题:显示刷新闪烁
解决:使用u8g2的页面刷新机制,减少闪烁

问题:中文字符显示异常
解决:使用合适的字体或点阵显示中文

8.3 创新点
实现了多种显示模式的自动切换
结合了静态显示和动态动画效果
优化了显示性能,提高了用户体验
九、附录
9.1 源代码结构
Project/
├── Core/
│   ├── main.c
│   ├── stm32_u8g2.c
│   └── test.c
├── Drivers/
└── U8g2/
    └── u8g2库文件


9.2 参考资料
STM32F103 Reference Manual
U8g2 Library Documentation
SSD1306 Datasheet
I2C Protocol Specification
感谢友情链接https://blog.csdn.net/black_sneak/article/details/126312657
————————————————
版权声明:本文为CSDN博主「བཀྲིས་」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/2301_79825245/article/details/154251730

您需要登录后才可以回帖 登录 | 注册

本版积分规则

95

主题

300

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部