Peter
Peter

Reputation: 183

predefined condition calculates at first time only

I've implemented a function which must perform the action then button was pressed and released.

void debouncedAction(bool condition, void (* action)()) {
    if(condition) {
        HAL_Delay(DEBOUNCE_TIME);
        if(condition) {
            while(condition) {
            }
            action();
        }
    }
}

Predefined condition is

#define BTN_PUSHED              (HAL_GPIO_ReadPin(BTN_PORT, BTN_PIN) == GPIO_PIN_SET)

While debugging I was found that condition does not calculated each time (as I thought) but only at the first call. Therefore while cycle becomes infinite. Where is the error?

Upvotes: 0

Views: 66

Answers (3)

Peter
Peter

Reputation: 183

Working version is

void debouncedAction(bool (* condition)(), void (* action)()) {
    if(condition()) {
        HAL_Delay(DEBOUNCE_TIME);
        if(condition()) {
            while(condition()) {
            }
            action();
        }
    }
}

or

void debouncedAction(bool (* condition)(), void (* action)()) {
    if(!condition()) {
        return;
    }
    HAL_Delay(DEBOUNCE_TIME);
    if(!condition()) {
        return;
    }
    while(condition()) {
    }
    action();
}

Upvotes: 0

Evil Dog Pie
Evil Dog Pie

Reputation: 2320

While the answer provided by Joachim is correct, this may provide a little more light. When you make the call to the debounce routine it will probably look like this (I have assumed that you have a function called onButtonAction to handle the 'action'):

debouncedAction(BTN_PUSHED, onButtonAction);

The pre-compiler will substitue the body of the BTN_PUSHED macro in this line:

debouncedAction((HAL_GPIO_ReadPin(BTN_PORT, BTN_PIN) == GPIO_PIN_SET),
    onButtonAction);

So the (HAL_GPIO_ReadPin(BTN_PORT, BTN_PIN) == GPIO_PIN_SET) condition is evaluated and passed to the function 'by value'.

If the 'debouncedAction' function needs to be generic, consider passing a function pointer as the condition argument, in the same way as the action argument.

void debouncedAction(bool (* condition)(), void (* action)())

And then define a function to test the GPIO state:

bool buttonPushed(void){ return BTN_PUSHED; }

The call to the debouncedAction function now looks like this:

debouncedAction(buttonPushed, onButtonAction);

Upvotes: 1

Some programmer dude
Some programmer dude

Reputation: 409404

The "error" is that the expressions used when calling a function are evaluated only once, and the result of that expression is passed as the value of the argument. That's how pass by value works, it passes a single value.

If you want an expression to be called multiple times within a function, you should probably make the condition a pointer to a function that can be called, like your action argument.

Upvotes: 3

Related Questions