PIC12F675 Switch I/O

Discussion in 'Programmer's Corner' started by RodneyB, Feb 4, 2014.

  1. RodneyB

    Thread Starter Active Member

    Apr 28, 2012
    633
    13
    I am VERY VERY new at writing code and am basically trying to teach myself C

    I am writing a routine to push a button and an LED will come on for a short period then switch off. What I am wanting to add now is that when the button is pushed the output is checked first. If it is high it ignores the push button if low it goes high.

    I have no idea how

    My code thus far is

    Code ( (Unknown Language)):
    1.  
    2. if(SW1==0)// switch pushed
    3. { __delay_ms(100); // debounce delay
    4. }
    5. if(SW1==0)// switch still pushed
    6. {
    7. LED=1;// turn on LED1
    8. __delay_ms(1000); //Delay
    9. LED1=0; //Turn LED1 off
    10. }
    11.  
     
  2. MrChips

    Moderator

    Oct 2, 2009
    12,421
    3,357
    Writing code is the last thing you want to do.
    Before you start writing code, lay out the flow of the code using flowcharts or pseudo-code.

    Pseudo-code is the algorithm of your solution written out it plain English. I will provide an example of what is known as Structured Programming.

    An IF-THEN-ELSE structure is written out as:

    Code ( (Unknown Language)):
    1.  
    2. IF (some condition)
    3. THEN (process A)
    4. ELSE (process B)
    5.  
    Edit: You don't need to use the braces ( ).

    Code ( (Unknown Language)):
    1.  
    2. IF some condition
    3. THEN process A
    4. ELSE process B
    5.  
    Recognize that in your example you need to test two conditions, the switch and the status of the LED. One possible solution would involve two nested IF-THEN-ELSE structures:

    Code ( (Unknown Language)):
    1.  
    2. IF (switch pushed)
    3. THEN
    4.  
    5.   IF (LED is on)
    6.   THEN (do nothing)
    7.   ELSE (turn on LED for 1 second)
    8.  
    9. ELSE (do nothing)
    10.  
    You can reverse the logic as follows:

    Code ( (Unknown Language)):
    1.  
    2. IF (switch pushed)
    3. THEN
    4.  
    5.   IF (LED is not on)
    6.   THEN (turn on LED for 1 second)
    7.   ELSE (do nothing)
    8.  
    9. ELSE (do nothing)
    10.  
    Since the ELSE (do nothing) is redundant, it can be eliminated:

    Code ( (Unknown Language)):
    1.  
    2. IF (switch pushed)
    3. THEN
    4.  
    5.   IF (LED is NOT on)
    6.   THEN (turn on LED for 1 second)
    7.  
    8.  
    Another solution would be to combine the two tests into one boolean test:

    Code ( (Unknown Language)):
    1.  
    2. IF (switch pushed AND LED is NOT on)
    3. THEN (turn on LED for 1 second)
    4.  
    5.  
    One final word:

    Since your 1-sec delay is inside your process, when your program exits from the process the LED will always be OFF. Hence all of the above code is unnecessary.

    The above example applies to any programming language, not only C or ASM.
    In C, the IF-THEN-ELSE structure is coded as

    Code ( (Unknown Language)):
    1.  
    2.   if (condition)
    3.   { process A }
    4.   else
    5.   { process B }
    6.  
    Careful analysis before beginning to write code can save you a lot of time and effort.
     
    Last edited: Feb 4, 2014
    RodneyB likes this.
  3. RodneyB

    Thread Starter Active Member

    Apr 28, 2012
    633
    13
    Thank you this is extremely helpful

    How would I code this ,

    Is output high, if high wait tell low when low check if the switch is pushed, wait for de bounce then check switch again if still pushed turn on output for a set period then switch off.

    It would be in a forever loop
    Code ( (Unknown Language)):
    1.  while(1)
    What I don't understand is how you get it to wait for that condition?
     
  4. takao21203

    Distinguished Member

    Apr 28, 2012
    3,577
    463
    jump backwards as long as it is not satisfied.

    Code ( (Unknown Language)):
    1.  
    2. reloop:;
    3.  
    4. if(condition != condition_true) goto reloop;
    5.  
    Some people use a while loop:

    Code ( (Unknown Language)):
    1.  
    2. while(!condition);
    3.  
    Sometimes you'd want to branch if the condition is fulfilled, otherwise continue. Then you can use the main() while loop.
     
  5. takao21203

    Distinguished Member

    Apr 28, 2012
    3,577
    463
    It must be said that condition testing loops just on their own are very bad programming practice.

    If the condition is not met, your program essentially hangs.

    For this reason, timeout is used with interrupts.


    You can test the IO with interrupt, and in your main code, you test a key variable. If it was pressed and released, you branch to some code, and reset the key variable.

    For the microcontrollers the timer is very important for program flow, so you should learn about it from early on.
     
    RodneyB likes this.
  6. RodneyB

    Thread Starter Active Member

    Apr 28, 2012
    633
    13
    My Sincere thanks for your help, I will take your advice 100% ! Firstly I will try the loop and then after that will go to the interrupt.

    It is extremely helpful to know that something is bad programming practice, I feel often as a beginner we tend to never find the full potential of something once something works because we never are encouraged to explore other alternatives, however your reply has opened a new door for me. THANKYOU!!
     
  7. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    This looks like an excellent task to begin learning C for micros. One button to debounce, one LED to light, simple and direct but building on concepts needed for more advanced works.

    For a one-task process such as this I would not worry about an interrupt check: if no one pressed the button for 3 days, so what? The LED doesn't light and all is well.

    When more tasks get added, a more involved button test is needed, such that if the button is not pressed other tasks may run.

    An alternate to an ISR to keep things active (in case of a crash) is the watchdog timer: active and correctly running code can reset the watchdog timer, but an error that halts the code running will not reset the watchdog, and the watchdog will then do a reset of the processor so you start as if the power was just applied.

    But again, that's not for today but a later project.

    Keep at it and good luck!
     
  8. RodneyB

    Thread Starter Active Member

    Apr 28, 2012
    633
    13
    After an extremely frustrating day of trying to get a simple push button to switch on an LED for 10 seconds I have had to give up and ask for help.

    The idea was to actually get an LED to switch on for 10 Seconds then switch off and loop forever so each time the switch is pushed the LED comes on. I also tried to check the output in all honesty I have no idea what's going on anymore.

    Code ( (Unknown Language)):
    1.  
    2.  [SIZE=3][FONT=Calibri]   if(SW1==0)[/FONT][/SIZE]
    3.  [SIZE=3][FONT=Calibri]  {__delay_ms(100);}[/FONT][/SIZE]
    4.  [SIZE=3][FONT=Calibri]  else(SW1==1);[/FONT][/SIZE]
    5.  [SIZE=3][FONT=Calibri]  {__delay_ms(100);}[/FONT][/SIZE]
    6.  [SIZE=3][FONT=Calibri]  if(SW1==1)[/FONT][/SIZE]
    7.  [SIZE=3][FONT=Calibri]  [/FONT][/SIZE]
    8.  [SIZE=3][FONT=Calibri]  {LED1=1;[/FONT][/SIZE]
    9.  [SIZE=3][FONT=Calibri] [/FONT][/SIZE]
    10.  [SIZE=3][FONT=Calibri]__delay_ms(1000);[/FONT][/SIZE]
    11.  [SIZE=3][FONT=Calibri]          [/FONT][/SIZE]
    12.  [SIZE=3][FONT=Calibri] LED1=0;} [/FONT][/SIZE]
    13.  [SIZE=3][FONT=Calibri]  }[/FONT][/SIZE]
    14.  
     
  9. takao21203

    Distinguished Member

    Apr 28, 2012
    3,577
    463
    you should get a compiler warning about this:

    Code ( (Unknown Language)):
    1.  
    2. else(SW1==1)
    3.  
    I'd recommend to write C language with proper indention,
    and always use the opening/closing braces.

    Later you can omit them.

    But this practice makes it easier to "read" C language source.

    What is SW1? A variable, or does it point to a port bit?
    What version of MPLAB do you use? MPLABX?

    I'd recommend it, and if so, you can use project templates. All the neccessary files are generated, including for the interrupt.


    You only need to:
    -Enable GIE and TMR0IE
    -Set the TIMER0 options
    -Test in the ISR if TMR0IF was set, and reset

    You could then program something like that in the main rountine:

    -in the ISR you set a flag: tmr_flag|=1

    -in the main routine, you test for this flag, and branch.

    -if it was set, you reset it: tmr_flag&=0xfe
    Then you increase a counter each time in this branch.

    -later in main you test this counter for let's say, 0x30
    So you can get a 16bit timer with software help.

    You can blink a LED with that!

    -If the test was true, you branch.
    Reset the counter to 0. Toggle a LED flag:

    Code ( (Unknown Language)):
    1.  
    2. if(tmr_flag&0x02)tmr_flag&=0xfd;else tmr_flag|=0x02;
    3. if(tmr_flag&0x02)PORTB.PORTBbits=1;else PORTB.PORTBbits=0;
    4.  
    As a result of this, you don't need to use any delay anymore.

    I'd also recommend to select the Software Simulator in the project options, and then do single step debugging.

    Latest MPLAB will display the variable values, if you hover over them. with F8, you can single step each C line (after setting an initial breakpoint).

    So you can learn about what your code is doing.

    Honestly, sometimes I am not exactly sure, and need to use the single step debugger + variables watch. It is all built into MPLABX now for free.
     
  10. jjw

    Member

    Dec 24, 2013
    173
    31
    You can detect the switch press assuming sw1==0 when pressed:

    Code ( (Unknown Language)):
    1. while (sw1==1);  /* wait switch pushed */
    2. delay();   /* debounce*/
    3. if (sw1==0)  /* still pressed ? */
    4. {    led1=1;
    5.       ...  and so on
    6.  
    7. }
    and the whole block inside forever loop.
     
  11. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    Since you are having trouble, let's take a step back and make a very simple "press button LED goes on" program. It would look like so:

    Code ( (Unknown Language)):
    1.     while(1)
    2.     {
    3.         if (SW1 == 0)        // switch pushed
    4.         {
    5.             LED1 = 1;        // turn on LED1
    6.         }
    7.         else
    8.         {
    9.             LED1 = 0;        // Turn LED1 off
    10.         }
    11.     }
    Now mind you, several important pieces are missing here:

    1 - There are no configuration settings

    B - The symbols SW1 and LED are not defined.

    iii - There is no main() function that is called when the program starts.

    IV - The number zero sometimes means the button is pressed, sometimes means the LED is off, but in both cases it's effect seems magical. A symbol (or three) would better serve here.
     
Loading...