一、项目概述

本教程将指导你使用STM32微控制器制作一款具有炫酷动态效果的桌面摆件,功能包括:

开机动画: OLED屏幕显示宇航员、火箭、原子花等动态效果。

按键交互: 通过按键切换不同的显示模式(如动画切换、图片轮播)。

I2C通信: 驱动OLED屏幕,实现图形和文字的灵活显示。

硬件清单:

  • STM32F103C8T6核心板

  • 0.96寸OLED屏幕(SSD1306驱动,I2C接口)

  • 2个轻触按键

  • RGB LED(可选,用于状态指示)

实现效果:

科技感桌面摆件

二、系统初始化配置

1. 时钟与定时器

在System_Init函数中初始化系统时钟和定时器,为动画提供时间基准:

void SysInit(void) {  
    Systick_Init(72);                // 系统滴答定时器,72MHz主频  
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 中断优先级分组  
    STM32_TIM2_Init(1000-1, 72-1);   // 1ms定时器中断,用于动画刷新  
}  

2. 外设初始化

初始化OLED、按键和LED:

void SysInit(void) {  
    // ...(定时器配置)  
    STM32_OLED_Init();      // OLED屏幕初始化  
    STM32_Key_Init();       // 按键初始化  
    STM32_5050RGBGPIO_Init(); // RGB LED初始化(可选)  
}  

三、OLED驱动与I2C通信

1. I2C引脚配置

在STM32_OLED_Init中配置PB3和PB4为I2C通信引脚:

void STM32_OLED_Init(void) {  
    GPIO_InitTypeDef GPIO_InitStructure;  
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);  
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4;  
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
    GPIO_Init(GPIOB, &GPIO_InitStructure);  
    // ...(OLED初始化指令)  
}  

2. OLED显示基础函数

清屏: STM32_OLED_Clear()

显示字符: OLED_ShowChar(x, y, char, size, mode)

显示图片: OLED_ShowBMP(x0, y0, x1, y1, bitmap)

四、按键交互实现

1. 按键消抖

在CModKey::GetKeyValue中检测按键状态,结合定时器实现软件消抖:

INT8U CModKey::GetKeyValue(void) {  
    static u8 b_key1_release = 1;  
    if (!KEY1_SCAN && b_key1_release) {  
        if (TmrOut()) {   // 20ms延时消抖  
            b_key1_release = 0;  
            return KEY1_V;  
        }  
    }  
    // ...(类似处理KEY2)  
}  

2. 按键切换显示模式

在COLedCtrl::Process中根据按键值切换动画:

void COLedCtrl::Process() {  
    switch (g_CModKey.GetKeyValue()) {  
        case KEY1_V:  
            g_CModOled.SetAtomStateDec(); // 上一动画  
            break;  
        case KEY2_V:  
            g_CModOled.SetAtomStateAsc(); // 下一动画  
            break;  
    }  
}  

五、动态显示效果设计

1. 开机动画

在CModOLed::RuningAtom中实现多帧动画切换:

void CModOLed::RuningAtom(void) {  
    switch (m_uchAtomState % OLED_ASTOM_CASE_NUM) {  
        case 0: // 宇航员动画  
            OLED_ShowBMP(32, 0, 96, 64, puch_BMP_ASTRONAUT0[uch_BmpIdx % 9]);  
            break;  
        case 1: // 火箭动画  
            OLED_ShowBMP(40, 16, 88, 64, puch_BMP_ROCKET[uch_BmpIdx % 4]);  
            break;  
        // ...(其他动画模式)  
    }  
}  

2. 图片切换逻辑

通过SetAtomStateAsc和SetAtomStateDec控制动画索引:

void CModOLed::SetAtomStateAsc() {  
    m_uchAtomState++;  
    OLED_DrawRectFill(0, 0, OLED_WIDTH, OLED_HEIGH, 0x00); // 清屏  
    OLED_ShowBMP(0, 0, OLED_WIDTH, 16, BMP_DeskTitle);     // 显示标题  
}  

六、系统整合与主循环

在main函数中循环调用处理逻辑:

int main(void) {  
    System_Init();  
    while (1) {  
        a_OLedCtrl.Process(); // 持续更新OLED显示  
    }  
}  

七、效果展示与优化

效果演示:开机时OLED播放火箭升空动画,按键切换至原子花或钢铁侠特效。

优化建议:

  • 使用DMA加速OLED数据传输。

  • 添加呼吸灯效果(通过PWM控制RGB LED)。

  • 将图片数据存储在外部Flash,支持更多素材。

八、代码获取

完整代码与素材:回复公众号“技术笔记闲谈”,发送OLED免费获取

九、常见问题

OLED不显示?检查I2C引脚连接和初始化顺序。

按键无响应?确认消抖时间与GPIO配置。

通过本教程,你可以掌握STM32的外设驱动、交互逻辑与动态显示设计,打造个性化的炫酷桌面摆件!

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐