This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Push button S2 & S3 in ARM9

Hello

I am trying to assign a function to each S2 and S3 push buttons. ( port 3.5 & 3.6 ) I want to get a display that the button S2 is pressed when it is pressed.
But i always get the message " S2 not Pressed". any ideas??

I did the following ( just the important things). These come inside the void main (void).


unsigned short Read_value2;

//*******************************
// Buttons 5 and 6 on Port 3
//*******************************

  SCU_APBPeriphClockConfig(__GPIO3,ENABLE);
  SCU_APBPeriphReset(__GPIO3,DISABLE);

  GPIO_StructInit(&GPIO_InitStruct);
  GPIO_InitStruct.GPIO_Pin= GPIO_Pin_5 | GPIO_Pin_6;
  GPIO_InitStruct.GPIO_Direction=GPIO_PinInput;
  GPIO_InitStruct.GPIO_Type=GPIO_Type_PushPull;
  GPIO_InitStruct.GPIO_IPInputConnected = GPIO_IPInputConnected_Enable;
  GPIO_Init(GPIO3,&GPIO_InitStruct);

Read_value2= GPIO_Read(GPIO3);
if ((Read_value2 && 0x20) == 0x00)// checking whether the push button is pressed
{
    lcd_clear();
    lcd_print (" S2 Pressed ");
}
else
{
lcd_clear();
lcd_print (" S2 Not pressed ");
}

Parents
  • You should implemenent a state machine that evaluates the state information and optionally performs any action quickly, and then returns to reevaluate the state information again. And again. And again.

    You should not implement a huge loop in the middle, with a huge delay. If you create a single close block that takes 1 second to run, then it obviously will not look at the key presses during that second, unless you sprinkle your code with new key tests.

    So you may have any numbers of LEDs. Then it would be state information what LED to light. And you have a delay. Then you shouldn't lock the state machine while the delay executes. You should have your state machine start a software or hardware timer. Then your state machine should - in a specific state - constantly check if that timer has run the full time or if there are any other stimuli that motivates the state machine to jump out of that state.

    With your code, wait_LED() will wait whatever long time without caring about any button presses. And when you return, your for loop will continue with next LED pattern to output, without caring about any state information or button presses.

    My code did show an example where the state machine did flash a single LED three times. It should be too hard to figure out a state machine that did count 0 to 255 on 8 LED using an 8-bit counter as sub-state information. So

    ...
    case STATE_IDLE:
        if (button_s3_pressed()) {
            // Ignore looking at s2 for starting a new sequence as long as
            // the S3 - reset - button is detected. Would be meaningless
            // to try to jump for first display state just to instantly
            // see S3 pressed and return back to the idle state...
        } else if (button_s2_pressed()) {
            // S2 button requests us to start displaying our LED pattern
            // sequence.
            led_pattern = 0;
            state = STATE_SHOW_LED_PATTERN;
        }
        break;
    case STATE_SHOW_LED_PATTERN:
        // The state machine spends too little time in this state - it directly jumps
        // to a delay state - so let's ignore checking for any buttons or other
        // stimuli that might request state-machine changes.
        // Only safe to do if button presses are cached, or if the buttons are
        // processed by an interrupt handler, or if the state machine loop runs
        // fast enough that it has time to perform all work in this state and
        // return back for next iteration of the state machine loop and scan
        // buttons in less time than the button press detection code requires
        // to catch the shortest allowed button press.
        set_led_pattern(led_pattern);
        delay_t0 = timer_now();
        state = STATE_WAIT_LED_PAUSE:
        break;
    case STATE_WAIT_LED_PAUSE:
        if (button_s3_pressed()) {
            // Button S3 pressed - exit from our pattern output and reset state
            // machine to idle again.
            set_led_pattern(0);
            state = STATE_IDLE;
        } else if ((timer_now() - delay_t0) >= LED_DELAY_TICKS) {
            // OK - current LED pattern have shown for long enough time. Now
            // check if all 256 patterns have been shown, or if we should
            // step to next pattern.
            if (led_pattern == 255) {
                // Full 256-step sequence shown - back to idle until s2 pressed again.
                set_led_pattern(0);
                state = STATE_IDLE;
            } else {
                // Should show next LED pattern.
                led_pattern++;
                state = STATE_SHOW_LED_PATTERN;
            }
        }
        break;
    ...
    

Reply
  • You should implemenent a state machine that evaluates the state information and optionally performs any action quickly, and then returns to reevaluate the state information again. And again. And again.

    You should not implement a huge loop in the middle, with a huge delay. If you create a single close block that takes 1 second to run, then it obviously will not look at the key presses during that second, unless you sprinkle your code with new key tests.

    So you may have any numbers of LEDs. Then it would be state information what LED to light. And you have a delay. Then you shouldn't lock the state machine while the delay executes. You should have your state machine start a software or hardware timer. Then your state machine should - in a specific state - constantly check if that timer has run the full time or if there are any other stimuli that motivates the state machine to jump out of that state.

    With your code, wait_LED() will wait whatever long time without caring about any button presses. And when you return, your for loop will continue with next LED pattern to output, without caring about any state information or button presses.

    My code did show an example where the state machine did flash a single LED three times. It should be too hard to figure out a state machine that did count 0 to 255 on 8 LED using an 8-bit counter as sub-state information. So

    ...
    case STATE_IDLE:
        if (button_s3_pressed()) {
            // Ignore looking at s2 for starting a new sequence as long as
            // the S3 - reset - button is detected. Would be meaningless
            // to try to jump for first display state just to instantly
            // see S3 pressed and return back to the idle state...
        } else if (button_s2_pressed()) {
            // S2 button requests us to start displaying our LED pattern
            // sequence.
            led_pattern = 0;
            state = STATE_SHOW_LED_PATTERN;
        }
        break;
    case STATE_SHOW_LED_PATTERN:
        // The state machine spends too little time in this state - it directly jumps
        // to a delay state - so let's ignore checking for any buttons or other
        // stimuli that might request state-machine changes.
        // Only safe to do if button presses are cached, or if the buttons are
        // processed by an interrupt handler, or if the state machine loop runs
        // fast enough that it has time to perform all work in this state and
        // return back for next iteration of the state machine loop and scan
        // buttons in less time than the button press detection code requires
        // to catch the shortest allowed button press.
        set_led_pattern(led_pattern);
        delay_t0 = timer_now();
        state = STATE_WAIT_LED_PAUSE:
        break;
    case STATE_WAIT_LED_PAUSE:
        if (button_s3_pressed()) {
            // Button S3 pressed - exit from our pattern output and reset state
            // machine to idle again.
            set_led_pattern(0);
            state = STATE_IDLE;
        } else if ((timer_now() - delay_t0) >= LED_DELAY_TICKS) {
            // OK - current LED pattern have shown for long enough time. Now
            // check if all 256 patterns have been shown, or if we should
            // step to next pattern.
            if (led_pattern == 255) {
                // Full 256-step sequence shown - back to idle until s2 pressed again.
                set_led_pattern(0);
                state = STATE_IDLE;
            } else {
                // Should show next LED pattern.
                led_pattern++;
                state = STATE_SHOW_LED_PATTERN;
            }
        }
        break;
    ...
    

Children
  • ufff.. thnx Per Westermark!! i hv been fighting with your explanation for a while. But at last it worked. I had to make it simpler by breaking down into simpler pieces.

    Also i changed a bit from what u mentioned. I used seperate IF loops like you said but without any case structures(state machines).

    Anyway now it is working.. both buttons work and i can interrupt each other

    thnx again