为什么这些嵌入式C代码的排列方式表现如此不同?

3

背景

我正在使用基于8052的微控制器。我连接了LCD和编码器轮。用户可以通过旋转和按下编码器轮来浏览在LCD上显示的菜单。

编码器轮的旋转是基于中断的。

编码器轮的旋转方向 (encoder_turn) 是在编码器中断中设置的。

我在一个循环中调用update_lcd()

新的响应式代码

void update_lcd()                           
{

        //ENCODER TURN      
        switch(encoder_turn)
        {
            case RIGHT:
                 lcd_clear();
                 next_screen();
                 break;
            case LEFT:
                lcd_clear();
                previous_screen();
                break;
            default:
                break;
        }
 }

void next_screen()
{
    if(current_test_screen < screen5)
    {
        current_test_screen++;
    }

    draw_current_test_screen(); 
}

void draw_current_test_screen()
{
    switch(current_test_screen)
    {
        case screen1:
            draw_screen1();
            break;
        case screen2:
            draw_screen2();
            break;
        case screen3:
            draw_screen3();
            break;
        case screen4:
            draw_screen4();
            break;
        case screen5:
            draw_screen5();
            break;      
        default:
        break;
    }
}

老旧无响应代码

void update_lcd()                           
{

        //ENCODER TURN      
        switch(encoder_turn)
        {
            case RIGHT:
                 lcd_clear();
                 next_screen();
                 break;
            case LEFT:
                lcd_clear();
                previous_screen();
                break;
            default:
                break;
        }

        switch(current_test_screen)
        {
            case screen1:
                draw_screen1();
                break;
            case screen2:
                draw_screen2();
                break;
            case screen3:
                draw_screen3();
                break;
            case screen4:
                draw_screen4();
                break;
            case screen5:
               draw_screen5();
               break;       
            default:
               break;
       }


 }

void next_screen()
{
    if(current_test_screen < screen5)
    {
        current_test_screen++;
    }
}

问题

为什么一个是响应灵敏的,而另一个则完全无用?

当我说响应灵敏时,我是指旋转编码器时屏幕变化的响应速度。这两种方法都“可行”,但其中一种从使用的角度来看是不能接受的。


1
请展示 encoder_turn 的定义。此外,它是从哪里调用的? - Dark Falcon
@EdS. 可以将主循环看作 while(true){update_lcd();},因为本质上就是这样。 - hfitzwater
@DarkFalcon encoder_turn 是一个在另一个文件中定义的 volatile int。它在这里被声明为 extern int,表示它在使用的地方被引用。 - hfitzwater
@appleskin:好的,但这可能与问题无关。既然你不知道问题的根本原因,你怎么能假设它不在你的主循环中(更具体地说,是如何从主循环中调用函数)?也许你认为无关紧要的细节之一实际上是相关的。 - Ed S.
2个回答

9

这两段代码几乎是等价的,除了一个非常微小的区别。

如果您尝试重构旧代码,使其看起来更像新代码,您会发现旧代码多调用了一个函数。仔细观察差异:

void update_lcd()                           
{
        //ENCODER TURN      
        switch(encoder_turn)
        {
            case RIGHT:
                 lcd_clear();
                 next_screen();
                 break;
            case LEFT:
                lcd_clear();
                previous_screen();
                break;
            default:
                draw_current_test_screen();   // <--- your new code omits this call
                break;
        }
 }

尝试将您的新代码添加该行,看是否会导致无响应问题。


哇...没错。我以为这会是比那更重要的事情。 - hfitzwater
当编码器不转动时,它会输出该函数调用。 - hfitzwater

0
只是猜测,但我怀疑:由于您改变的唯一事物是函数嵌套,因此优化器可能会缓存“encoder_turn”。您需要将“encoder_turn”标记为易失性,因为中断可能会发生并随时更改其值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接