当MM32F5330化身按键监工:用4个GPIO和OLED上演数字版《1984》

分享作者:wechat_15135690968
作者昵称:禹黎151
评测品牌:灵动微电子
评测型号:Mini-F5333
发布时间:2025-12-29 11:06:14
2
概要
显示程序是江科大0.96OLED驱动程序移植,纯gpio模拟iic,按键驱动程序使用官方例程
开源口碑分享内容

开发板上的按键不能只是摆设

各位看官,今天咱们玩点阴间的。当你们还在用按键触发中断、搞事件标志组、玩消息队列的时候,我选择了一条邪路——把4个卑微的物理按键变成24小时不间断被监视的"数字劳工",并且把它们的"心理活动"实时投影在OLED上,上演一出裸机轮询的极权主义美学。

硬件?简单到 insulting:MM32F5330(这芯片跑分能吊打当年登月计算机),4个弹片按键(寿命10万次,今天让你1秒尝尽10万次的心跳),一块0.96寸OLED(128×64像素,每个像素都在尖叫"我看见了!")

轮询即正义,延时即和平

在main.c这个微型社会架构里,我植入了赤裸裸的暴力循环。上电那一刻,MCU就成了无情的监工:

int main(void)
{
    PLATFORM_Init();  // 平台初始化,准备搭建数字监狱
    OLED_Init();      // 显示器亮起,老大哥在看着你
    
    OLED_ShowString(1,1,"MM32F5333"); // 宣告主权:这片屏幕姓MM
    
    while(1)  // 永恒的循环,比《盗梦空间》还狠
    {
        PLATFORM_LED_Toggle(LED1);  // 心跳灯,证明MCU还没过劳死
        PLATFORM_DelayMS(200);      // 每200ms喘息一下,资本家的仁慈
        
        // 四个按键的状态数组,它们的人生被量化成0和1
        static uint8_t KeyState[4] = {0, 0, 0, 0};  
        static uint8_t KeyCount[4] = {0, 0, 0, 0};  // 计数器,记录按键被"审讯"的次数
        
        GPIO_Configure();  // 配置GPIO,给按键戴上电子镣铐
        
        printf("\r\nPress K1-K4...");  // 虚伪的提示,其实不按也得按
        
        while (1)  // 嵌套循环,恶魔的低语
        {
            // 下面四行,是核心暴政:每10ms审讯一次所有按键
            KEY_FSM_Handler(&KeyState[0], &KeyCount[0], 
                           GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_4), Bit_SET, "K1");
            // ↑ 对PC4号按键实施"SET电平有效"政策,不按的时候是高电平,按下去反而是低电平?
            // 官方例程就是这么叛逆,反人类设计但We'll Make It Work
            
            KEY_FSM_Handler(&KeyState[1], &KeyCount[1], 
                           GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_5), Bit_RESET, "K2");
            // ↑ PC5这位更惨,Bit_RESET才有效,天生贱命必须常按才能被看见
            
            KEY_FSM_Handler(&KeyState[2], &KeyCount[2], 
                           GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1), Bit_RESET, "K3");
            // ↑ PB1:别问,问就是RESET党
            
            KEY_FSM_Handler(&KeyState[3], &KeyCount[3], 
                           GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_2), Bit_RESET, "K4");
            // ↑ PB2:四个按键三种待遇,MCU界的种姓制度
            
            // LED同步指示:按键状态直接映射到LED,物理层面的公开处刑
            PLATFORM_LED_Enable(LED1, (FunctionalState)GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_4));
            PLATFORM_LED_Enable(LED2, (FunctionalState)GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_5));
            PLATFORM_LED_Enable(LED3, (FunctionalState)GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1));
            PLATFORM_LED_Enable(LED4, (FunctionalState)GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_2));
            
            PLATFORM_DelayMS(10);  // 10ms轮询一次,按键的瞳孔地震
            
            // OLED实时直播:把按键的屈辱状态打在公屏上
            OLED_ShowNum(3, 1, KeyState[0], 1);  // 第3行第1列:K1的精神状态
            OLED_ShowNum(3, 3, KeyState[1], 1);  // 第3行第3列:K2的灵魂编号
            OLED_ShowNum(3, 5, KeyState[2], 1);  // 第3行第5列:K3的忏悔值
            OLED_ShowNum(3, 7, KeyState[3], 1);  // 第3行第7列:K4的忠诚度
            
            // 这画面,四个数字在OLED上跳动,像四个囚徒在牢房里数数
        }
    }
}

按键的心理医生,也是精神折磨大师

那KEY_FSM_Handler到底是何方神圣?它是官方例程塞进来的"按键心理医生",用状态机给按键做精神分析:


void KEY_FSM_Handler(uint8_t *state, uint8_t *count, uint8_t raw, uint8_t valid_logic, char* name)
{
    switch(*state)
    {
        case 0: // 按键 IDLE 状态,岁月静好
            if(raw == valid_logic)  // 突然检测到有效电平!
            {
                (*count)++;         // 可能误触,先计数观察
                if(*count > DEBOUNCE_TIME)  // 计数达标,确认不是抖动
                {
                    *state = 1;     // 状态转移:按键确认被按下
                    printf("\r\n%s is pressed!", name);  // 昭告天下
                    *count = 0;     // 计数器清零,准备下次折磨
                }
            }
            else
            {
                *count = 0;  // 误触?计数器归零,重新做人
            }
            break;
            
        case 1: // 按键已按下状态
            if(raw != valid_logic)  // 电平恢复正常
            {
                (*count)++;
                if(*count > DEBOUNCE_TIME)
                {
                    *state = 0;     // 返回IDLE,等待下次压迫
                    printf("\r\n%s is released!", name);
                    *count = 0;
                }
            }
            else
            {
                *count = 0;
            }
            break;
    }
}

这代码,每个按键配一个state和count,用轮询代替中断,用延时代替事件,把异步世界硬生生干成同步奴隶制。按键按下那一刻,CPU不是在服务中断,而是在10ms轮询里"恰好"抓住了你,然后像班主任点名一样把你记录在案。

CPU的996福报

  • 轮询频率:100Hz(10ms一次),四个按键无一幸免
  • CPU占用:主循环里全是GPIO_Read、LED控制、OLED刷新,实际算力浪费在99%的空转等待
  • 实时性:按键响应延迟最坏情况20ms(刚好错过上轮轮询),但谁在乎呢?又不是导弹发射
  • 功耗:MM32F5330在48MHz下疯狂空转,功耗堪比小型暖手宝
  • 代码美学:官方例程的Bit_SET和Bit_RESET混用,是对称美学的终极亵渎,但"能跑就行"

轮询党的末日狂欢

你可能要问:为什么不用中断?为什么不上RTOS?为什么要这样虐待自己?

答案很简单:因为可以

在这个RTOS教程满天飞、中断驱动被奉为圣经的时代,裸机轮询就像朋克摇滚——粗糙、原始、直接,带着一种"老子就爱这么干"的叛逆。GPIO_ReadInputDataBit这个函数被调用了8次(4次状态机+4次LED映射),每一次都是对"效率"二字的公开处刑,但当你看到OLED上那四个数字忠实地跟随按键跳动时,你会明白:

有些代码,跑的不是逻辑,是态度。

四个按键,四个LED,一块OLED,一个48MHz的主循环,构建了一个微型极权社会。按键没有自由,CPU没有喘息,LED没有隐私,OLED没有灵魂。但它们都在工作,在裸机的铁拳下,以一种原始而有效的方式共存。

别在生产环境这么干

如果你敢把这段代码用在量产产品上:

  • 硬件工程师会把你绑在示波器上电疗
  • 软件架构师会用状态图把你凌迟
  • 产品经理会让你去产线按10万次按键测试寿命
  • 测试工程师会把你和按键关在一起,不按够100万次不许出来
  • 但,在这块开发板上,在这间实验室里,在这段被10ms延时撕裂的时间里,你就是那个掌控一切的暴君。轮询是你的鞭子,OLED是你的审判庭,而MM32F5330,是那个默默执行你所有暴政的沉默机器。
  • 按下K1,看着LED1亮起,OLED上的数字从0变1,那一刻,你触摸到了裸机编程最原始的快感——我是CPU,我即轮回

-------------------------------------------------------------我是分割线-----------------------------------------------------------------

冷知识:把PLATFORM_DelayMS(10)改成1ms,按键会被轮询到怀疑鼠生。建议试试,烧了别找我。

全部评论
暂无评论
0/144