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
  • Can be made simpler too.

    One alternative (inside your infinite loop):

    switch (state) {
        case STATE_IDLE:
            if (s2_pressed) state = STATE_BLINK0;
            break;
        case STATE_BLINK0:
        case STATE_BLINK2:
        case STATE_BLINK4:
            if (s3_pressed) {
                led_off();
                state = STATE_IDLE;
            } else {
                led_on();
                state++;
            }
            break;
        case STATE_BLINK1:
        case STATE_BLINK3:
        case STATE_BLINK5:
            led_off();
            if (s3_pressed || state == STATE_BLINK5) {
                state = STATE_IDLE;
            } else {
                state++;
            }
            break;
        default:
            // bummer - invalid state encountered.
            led_off();
            state = STATE_IDLE;
    }
    

    or you could do:

    for (;;) {
        if (s3_pressed) {
            led_off();
            state = STATE_IDLE;
        }
        switch (state) {
            case STATE_IDLE:
                if (s2_pressed) state = STATE_BLINK0;
                break;
            ...
        }
    }
    

    Of course, you don't need to waste 6 states for generating 3 blinks. You could use a counter as sub-state information, to keep track of number of blinks performed.

    One thing I glossed over in above code is the delay during LED on and LED off.

    This is easy to handle by have the states check if there are time remaining before they may either perform their action, or before they may change state to the next state in the blink sequence. This delay code should be bypassed in regards to detection of the s3 button since you want s3 to instantly reset the sequence.

Reply
  • Can be made simpler too.

    One alternative (inside your infinite loop):

    switch (state) {
        case STATE_IDLE:
            if (s2_pressed) state = STATE_BLINK0;
            break;
        case STATE_BLINK0:
        case STATE_BLINK2:
        case STATE_BLINK4:
            if (s3_pressed) {
                led_off();
                state = STATE_IDLE;
            } else {
                led_on();
                state++;
            }
            break;
        case STATE_BLINK1:
        case STATE_BLINK3:
        case STATE_BLINK5:
            led_off();
            if (s3_pressed || state == STATE_BLINK5) {
                state = STATE_IDLE;
            } else {
                state++;
            }
            break;
        default:
            // bummer - invalid state encountered.
            led_off();
            state = STATE_IDLE;
    }
    

    or you could do:

    for (;;) {
        if (s3_pressed) {
            led_off();
            state = STATE_IDLE;
        }
        switch (state) {
            case STATE_IDLE:
                if (s2_pressed) state = STATE_BLINK0;
                break;
            ...
        }
    }
    

    Of course, you don't need to waste 6 states for generating 3 blinks. You could use a counter as sub-state information, to keep track of number of blinks performed.

    One thing I glossed over in above code is the delay during LED on and LED off.

    This is easy to handle by have the states check if there are time remaining before they may either perform their action, or before they may change state to the next state in the blink sequence. This delay code should be bypassed in regards to detection of the s3 button since you want s3 to instantly reset the sequence.

Children
  • sorry Westermark. I could not follow your codes.
    First of all , i think you have mistaken about the LED blinking.
    The code below makes one light to move through the LEDs with a specified time gap in between. i.e 7.0 glows- goes out, 7.2 glows- goes out... 7.7 glows-goes out. This whole one length takes aprrox 1 -2 sec. This length to lenght LED glow takes place 3 times.

    for ( k = 0; k <= 2;k++)
    {
      for (n = 0x01; n <= 0xFF; n <<= 1) /*One LED moving from 7.0 to 7.7*/
      {
         wait_LED();
         GPIO7->DR[0x3FC] = n;            /* Turn on LED */
      }
    }
    

    And what i am tying to do is this:

    If S2 is pressed ,this( the above code) process starts. In between the LED run, if i press S3, LED blinking should stop. i.e it should also interrupt the running LED and all LEDs off.

    Your first option ( in ur previous reply), i could not follow it.
    I tried the Second option,but it just gives the same output. i.e
    if S2 is pressed--> LEDs run,
    if S3 is pressed in between S2 function --> Nothing happens
    If S3 is pressed alone -->all LEDs OFF

  • 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;
    ...
    

  • 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