1
\$\begingroup\$

I am trying to detect a switch input so that, if the switch is pressed, a number is incremented on the seven segment display. For example if the seven segment display shows 0, and the switch is pressed, the SSD will now show 1. If pressed again, it will show 2 and so on.

  • My seven segment display is connected on P0.0 to P0.6
  • MY switch is on P0.9

How can I detect each time the switch is pressed? I am trying to increment a variable k in my program so that each time the switch is pressed, k is incremented, and thus I will be able to perform different functions each time the switch is pressed. However this part is not working properly.

I am thinking something similar to the following program. However, I must be overlooking something as only the first button click is working. When the switch is pressed, 1 appears on the display. Nothing happens when it is pressed again.

#include <LPC21xx.h>
#define a 0x00000001 
#define b 0x00000002
#define c 0x00000004
#define d 0x00000008
#define e 0x00000010
#define f 0x00000020
#define g 0x00000040


void small_delay (void);

void infinite (void);
int main (void)
{
int k = 0;
unsigned int SW1;

PINSEL0 = 0;                                //Set P0.0 - P0.15 as GPIOS
PINSEL1 = 0;                                //Set P0.16 - P0.31 as GPIOS
IO0DIR  = 0xFFFFFDFF;               //Setting  P0.9 as input for SW1     

while (1)
{

    SW1 = IO0PIN & 0x00000200; //switch connected on P0.9

    if ( SW1 == 0x00000200 )        //when not pressed
    {   

    }

  if ( SW1 != 0x00000200 )  //when pressed      
    {
        k++;

        if (k == 1){
        IO0SET = b;                     
        IO0SET = c;                         //displaying number 1 

        }       

        else if (k == 2){

        IO0CLR = c; 
        IO0SET = a;
        IO0SET = b;
        IO0SET = g;                         //displaying number 2
        IO0SET = d;
        IO0SET = e;
        //small_delay();
            }
        }
    }
}

 void small_delay (void) 
 {
 unsigned int i, j;

 for (i=0; i<1000; i++)
 {  
    for (j=0; j<1000; j++)
     {
     }
 }
 }

Any suggestions or pointers on what I could improve, would be appreciated.

\$\endgroup\$
3
\$\begingroup\$

Two issues I can see. Firstly when setting the display to show a 2 you don't first clear the display so all of the segments that were lit remain lit.

Secondly my guess is that you are seeing switch contact bouncing issues. When a switch or button closes the contacts touch, bounce apart, touch again, bounce apart etc... this can go on for several milliseconds and will look like lots of very fast button presses to the software.

The techniques to avoid this are known as debouncing, you can either implement them in hardware (a low pass filter on the input pin) or software (wait for the value on the input to remain stable for a fixed length of time) or a mixture of both.

For details on how to implement this sort of thing see google or search here for debouncing.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Hi Andrew, thanks for your input on this matter. I have decided to implement a delay. Is this considered good practice? Edited question accordingly with regards to your first issue. \$\endgroup\$ – Rizzo Feb 20 '17 at 13:11
  • 1
    \$\begingroup\$ Generally sitting in a delay loop isn't good practice. If this is all you are doing then it works fine but it's not very portable since the delay time is compiler (make sure it doesn't get optimized out), processor and clock speed dependent. It is better practice to use timer interrupts, this gives a more controlled time and leaves the CPU free to do other tasks while waiting. That said, if all you are doing is looking for button presses then unless you are very power critical a loop works fine in this case. \$\endgroup\$ – Andrew Feb 20 '17 at 13:15
0
\$\begingroup\$

How can I detect each time the switch is pressed?

polling frequently or interrupt will do.

However this part is not working properly.

because the code is wrong. it can handle just 1 and 2. anything else, the display is unchanged. your code runs so fast you are likely out of range.

the right way to do this is to put the display routine in a timer interrupt.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.