PIC12f683 stops at the first statement of if condition

Discussion in 'Embedded Systems and Microcontrollers' started by guitchess, Feb 10, 2014.

  1. guitchess

    Thread Starter New Member

    Dec 28, 2013
    15
    1
    Please correct this noob if I'm completely missing something, but I thought in an if statement that "if" wasn't met, then the code continued to be processed.

    In the following code, when the pic is powered I thought that if GP3 == 0, which it does until I press the button I have in circuit, that the else statement would have GP5 set until the while loop came back around and found GP3 set.

    However, in actual practice, the pic does nothing til I hit the GP3 button which starts the ledloop function and then GP5 will go high.

    I'm a noob at uControllers and C so if you could point me in the right direction I would appreciate it.

    Thanks.

    void main(void) {
    TRISIO = 0b00001000;
    GPIO = 0b00000000;
    ANSEL = 0;
    CMCON0 = 0b00000111;
    OSCCON = 0b01110111;
    int ledloop();

    while(1){
    if(GP3 == 1){
    ledloop();
    }
    else{
    GP5 = 1;
    }
    }

    return;

    }
     
  2. JohnInTX

    Moderator

    Jun 26, 2012
    2,341
    1,022
    Where is the code for ledloop()? It looks like would enter there on reset.

    Which compiler are you using? It looks like MikroC.

    What are the PICs config settings? Presumably you are using the internal OSC?

    Have you stepped the code in the simulator (MPSIM or MikroC sim as applicable)? That should answer your question.

    EDIT: In MikroC, the port Bit3 is specified as GPIO.B3, Bit5 is GPIO.B5 When specified that way, the code will fail to build since ledloop() is not defined. When using the original GP3==1, it doesn't generate any code for that TRUE condition so ledloop is never called nor flagged as an error. Kind of weird but that's what it does here..

    Other than that, the IO inits look OK and the code steps right to GPIO.B5=1.

    Using code tags (the # button in the posting window) makes code easier to read - like this:
    Code ( (Unknown Language)):
    1. int ledloop();
    2.  
    3. void main(void) {
    4.     TRISIO = 0b00001000;
    5.     GPIO = 0b00000000;
    6.     ANSEL = 0;
    7.     CMCON0 = 0b00000111;
    8.     OSCCON = 0b01110111;
    9.  
    10.  
    11.    while(1){
    12.     if(GPIO.B3 == 1){
    13.       ledloop();
    14.     }
    15.    else {
    16.     GPIO.B5 = 1;
    17.    } // else
    18.   }// while
    19. }
     
    Last edited: Feb 11, 2014
  3. guitchess

    Thread Starter New Member

    Dec 28, 2013
    15
    1
    Ok here's the whole thing. Far from elegant or efficient I'm sure. I'm using MPLAB X and it's included sim. Just as the last issue I had, the code works as expected, just not on the hardware.

    Currently, I'm suspecting interrupt issues, but I haven't had enough time to check that out.

    Also, if anyone has a suggestion of how to more efficiently implement the ledloop, I would be happy to hear it. I'm trying to come up with a timer method, but since I'm a noob, it's not obvious.

    #pragma config FOSC = INTOSCIO // Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN)
    #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
    #pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
    #pragma config MCLRE = OFF // MCLR Pin Function Select bit (MCLR pin function is digital input, MCLR internally tied to VDD)
    #pragma config CP = OFF // Code Protection bit (Program memory code protection is disabled)
    #pragma config CPD = OFF // Data Code Protection bit (Data memory code protection is disabled)
    #pragma config BOREN = ON // Brown Out Detect (BOR enabled)
    #pragma config IESO = ON // Internal External Switchover bit (Internal External Switchover mode is enabled)
    #pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is enabled)


    #include <xc.h>
    #include <stdlib.h>

    #define _XTAL_FREQ 8000000

    #define l1 150
    #define l2 125
    #define l3 100
    #define l4 75
    #define l5 50
    #define l6 40
    #define l7 30
    #define l8 20
    #define l9 10

    int ledloop();

    void main(void) {
    TRISIO = 0b00001000;
    GPIO = 0b00000000;
    ANSEL = 0;
    CMCON0 = 0b00000111;
    OSCCON = 0b01110111;
    int ledloop();

    while(1){
    if(GP3 == 1){
    ledloop();

    }
    else{
    GP5 = 1;
    }
    }

    return;

    }


    int ledloop (){
    GP0 = 1;
    __delay_ms(l1);
    GP1 = 1;
    __delay_ms(l1);
    GP2 = 1;
    GP0 = 0;
    __delay_ms(l1);
    GP4 = 1;
    GP1 = 0;
    __delay_ms(l1);
    GP2 = 0;
    __delay_ms(l1);
    GP4 = 0;
    __delay_ms(l1);

    GP0 = 1;
    __delay_ms(l2);
    GP1 = 1;
    __delay_ms(l2);
    GP2 = 1;
    GP0 = 0;
    __delay_ms(l2);
    GP4 = 1;
    GP1 = 0;
    __delay_ms(l2);
    GP2 = 0;
    __delay_ms(l2);
    GP4 = 0;
    __delay_ms(l2);


    GP0 = 1;
    __delay_ms(l3);
    GP1 = 1;
    __delay_ms(l3);
    GP2 = 1;
    GP0 = 0;
    __delay_ms(l3);
    GP4 = 1;
    GP1 = 0;
    __delay_ms(l3);
    GP2 = 0;
    __delay_ms(l3);
    GP4 = 0;
    __delay_ms(l3);


    GP0 = 1;
    __delay_ms(l4);
    GP1 = 1;
    __delay_ms(l4);
    GP2 = 1;
    GP0 = 0;
    __delay_ms(l4);
    GP4 = 1;
    GP1 = 0;
    __delay_ms(l4);
    GP2 = 0;
    __delay_ms(l4);
    GP4 = 0;
    __delay_ms(l4);


    GP0 = 1;
    __delay_ms(l5);
    GP1 = 1;
    __delay_ms(l5);
    GP2 = 1;
    GP0 = 0;
    __delay_ms(l5);
    GP4 = 1;
    GP1 = 0;
    __delay_ms(l5);
    GP2 = 0;
    __delay_ms(l5);
    GP4 = 0;
    __delay_ms(l5);


    GP0 = 1;
    __delay_ms(l6);
    GP1 = 1;
    __delay_ms(l6);
    GP2 = 1;
    GP0 = 0;
    __delay_ms(l6);
    GP4 = 1;
    GP1 = 0;
    __delay_ms(l6);
    GP2 = 0;
    __delay_ms(l6);
    GP4 = 0;
    __delay_ms(l6);


    GP0 = 1;
    __delay_ms(l7);
    GP1 = 1;
    __delay_ms(l7);
    GP2 = 1;
    GP0 = 0;
    __delay_ms(l7);
    GP4 = 1;
    GP1 = 0;
    __delay_ms(l7);
    GP2 = 0;
    __delay_ms(l7);
    GP4 = 0;
    __delay_ms(l7);

    GP0 = 1;
    __delay_ms(l8);
    GP1 = 1;
    __delay_ms(l8);
    GP2 = 1;
    GP0 = 0;
    __delay_ms(l8);
    GP4 = 1;
    GP1 = 0;
    __delay_ms(l8);
    GP2 = 0;
    __delay_ms(l8);
    GP4 = 0;
    __delay_ms(l8);


    GP0 = 1;
    __delay_ms(l8);
    GP1 = 1;
    __delay_ms(l8);
    GP2 = 1;
    GP0 = 0;
    __delay_ms(l8);
    GP4 = 1;
    GP1 = 0;
    __delay_ms(l8);
    GP2 = 0;
    __delay_ms(l8);
    GP4 = 0;
    __delay_ms(l8);


    GP0 = 1;
    __delay_ms(l9);
    GP1 = 1;
    __delay_ms(l9);
    GP2 = 1;
    GP0 = 0;
    __delay_ms(l9);
    GP4 = 1;
    GP1 = 0;
    __delay_ms(l9);
    GP2 = 0;
    __delay_ms(l9);
    GP4 = 0;
    __delay_ms(l9);


    GP0 = 1;
    __delay_ms(l9);
    GP1 = 1;
    __delay_ms(l9);
    GP2 = 1;
    GP0 = 0;
    __delay_ms(l9);
    GP4 = 1;
    GP1 = 0;
    __delay_ms(l9);
    GP2 = 0;
    __delay_ms(l9);
    GP4 = 0;
    __delay_ms(l9);



    GPIO = 0b00010111;
    __delay_ms(1500);
    GPIO = 0;
    }
     
  4. JohnInTX

    Moderator

    Jun 26, 2012
    2,341
    1,022
    OK- It builds and sims in XC8.

    Why do you suspect interrupts when there aren't any? To be sure, add INTCON = 0 to the init.

    Try PWRTE=ON and BOREN=OFF. Do you have adequate Vdd and decoupling at the power pins?

    EDIT:
    Here's how to use TIMER1 interrupts to generate time tiks and flags to trigger events like toggling LEDs. Its a quick port from another project but hopefully you'll get the idea.

    Code ( (Unknown Language)):
    1. /*
    2.  * File:   Guichess.c
    3.  * Author: John
    4.  *
    5.  * Created on February 10, 2014, 11:49 PM
    6.  */
    7.  
    8. #pragma config FOSC = INTOSCIO // Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN)
    9. #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
    10. #pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled)
    11. #pragma config MCLRE = OFF // MCLR Pin Function Select bit (MCLR pin function is digital input, MCLR internally tied to VDD)
    12. #pragma config CP = OFF // Code Protection bit (Program memory code protection is disabled)
    13. #pragma config CPD = OFF // Data Code Protection bit (Data memory code protection is disabled)
    14. #pragma config BOREN = OFF // Brown Out Detect (BOR disabled)
    15. #pragma config IESO = ON // Internal External Switchover bit (Internal External Switchover mode is enabled)
    16. #pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is enabled)
    17.  
    18.  
    19. #include <xc.h>
    20. #include <stdlib.h>
    21.  
    22.  
    23. /************************************************************/
    24. //              HARDWARE CONFIGURATION
    25. /************************************************************/
    26. #define _XTAL_FREQ 8000000
    27. #define usTcyc ((_XTAL_FREQ / 1000000) / 4) // how many uS 1 Tcyc is
    28.  
    29. //*****************  CODE CONFIGURATION  ********************
    30. #define usSysTik 10000      // 10msec systik
    31. #define ms100PSset 10       // 10 * systik = 100ms
    32.  
    33.  
    34. /************************************************************/
    35. //              TIMERS
    36. /************************************************************/
    37. #if 0
    38.     Timer 1 is used to generate a 10msec system tik. Its the
    39.     smallest derived time available.
    40.     Timer 0 is reserved to free up the prescaler for the WDT.
    41.  
    42.     The timer runs w/o prescaler so that we can load it with
    43.     an adjusted time without having to worry about clearing the PS
    44. #endif
    45.  
    46. #define T1CONinit 0b00000000    // No gate, 1:1ps, Internal, OFF
    47. #define TMR1adj 9               // Number of Tcyc it takes to stop-load-start TMR1
    48.                                 // determined by looking at disassembly.
    49.     //Calculate reload value for timer counting up to rollover. Result is
    50.     // number of counts based on Tcyc, adjustment, SysTik value etc.
    51. #define TMR1setTiks (2^16-(usSysTik / usTcyc) + TMR1adj)
    52.  
    53. unsigned char  ms100PreScaler;
    54. bit ms10_happened;      // bits get set by IRQ at the noted time interval
    55. bit ms100_happened;
    56.  
    57. //Derived timers
    58. // These get loaded with count by main program. They count to 00 and stay there
    59. // When main sees they are 00, it knows to do something
    60.  
    61. unsigned char Timer10ms_A;
    62. unsigned char Timer100ms_A;
    63.  
    64. void interrupt isr(void)
    65. {
    66.     //---------------- MAINTAIN SYSTIK  ---------------------
    67.     if(TMR1IF){
    68.         TMR1IF = 0;     // ack the IRQ
    69.  
    70.         TMR1ON = 0;     // stop the timer, reload it, restart it
    71.         TMR1 += TMR1setTiks;  // any accumulated time + the reload value
    72.         TMR1ON = 1;
    73.  
    74.         //------------- PROCESS SYSTIK  ------------------------
    75.         // do 10msec stuff here
    76.         // Flag that systik happened
    77.         ms10_happened = 1;                 // flag 10 ms happened
    78.         if (Timer10ms_A) Timer10ms_A--;   // count 10ms timer to 0
    79.  
    80.         //---------------- 100 ms TIMERS --------------------------
    81.         // 10ms systik is prescaled to 100ms..
    82.         ms100PreScaler--;
    83.         if(ms100PreScaler == 0){
    84.             ms100PreScaler = ms100PSset;        // reset prescaler
    85.             ms100_happened = 1;         // flag 100ms happened
    86.             //--------------- SERVICE 100ms TIMERS  ----------------
    87.             // These timers run at 100ms tiks.
    88.             if (Timer100ms_A) Timer100ms_A--; // maintain Timer100ms_A timer
    89.         }
    90.     } // TMR1IF
    91. }//END OF INTERRUPT SERVICE ROUTINE
    92.  
    93. void main(void) {
    94. TRISIO = 0b00001000;
    95. GPIO = 0b00000000;
    96. ANSEL = 0;
    97. CMCON0 = 0b00000111;
    98. OSCCON = 0b01110111;
    99.  
    100.     //--------------- INIT SYSTIK -------------------------------
    101.     // Timer 1 is the master timer.
    102.     // Timer 0 is not used so far.
    103.  
    104.     T1CON = T1CONinit;  // stop timer, configure it
    105.     TMR1 = TMR1setTiks; // load it
    106.                         // init timer chain
    107.     ms100PreScaler = ms100PSset;
    108.  
    109.     TMR1IF = 0;         // clear IRQ
    110.     TMR1IE = 1;         // then enable TMR1 interrupt
    111.     PEIE = 1;           // and peripherial IRQ
    112.     TMR1ON = 1;         // start the timer
    113.  
    114.     //--------------- FIRE UP THE SYSTEM -------------------------
    115.     GIE = 1;            //GLOBAL INTERRUPTS ENABLED
    116.  
    117.     while(1){
    118.         // Toggle GP1 at 500ms uning a derived timer
    119.         if(Timer10ms_A == 0){
    120.              GP1 = !GP1;
    121.              Timer10ms_A = 50;   // reload timer for next time
    122.         }
    123.  
    124.         // Toggle GP0 at 100ms using flag
    125.         if(ms100_happened){
    126.             ms100_happened = 0;  // reset flag for next time
    127.             GP0 = !GP0;
    128.         }
    129.     }// while
    130.  
    131. }//main
    132.  
    133.  
     
    Last edited: Feb 11, 2014
  5. guitchess

    Thread Starter New Member

    Dec 28, 2013
    15
    1
    No luck with config bits or disabling the interrupts. Also tried setting GP5 directly in the while loop, and it still waits till GP3 goes high
     
  6. JohnInTX

    Moderator

    Jun 26, 2012
    2,341
    1,022
    Add ADCON0 = 0; to the init.

    You also might try adding a short delay before the while loop to ensure that the voltage on GP3 has time to settle.

    Add a little flasher in the else part
    GP5=1;
    delay 100ms
    GP5=0;

    so that you can tell if it reenters the else after any power up issues.

    Otherwise the while logic is OK and the disassembled code looks right too.

    As in your other thread, it would be most helpful to see a schematic or photo of your wiring. What makes your switch input a 0? Pull down resistor or a normally closed contact to ground. What makes it a 1? Have you measured the voltage on the input to Vss to ensure solid logic levels? You DO have series resistors on the LEDs, yes?

    Good luck.
     
    Last edited: Feb 11, 2014
  7. guitchess

    Thread Starter New Member

    Dec 28, 2013
    15
    1
    I hate breadboards!/I guess I'm going to have to take more care when breadboarding a circuit.

    I had played with the code so much that I had messed something up, but instead of searching out a new error, I just hit the undo button till I was back where I started. I thought a fresh take may help me. However, when loading the original code, it worked just as it should.

    I had changed some of the circuit, but now it is back as it was originally.

    This is why I go straight to home brew pcb when working with an analog circuit. I'd rather waste a $.10 piece of copper clad than deal with bad breadboard connections.

    My next project is definitely going to be a development board of some type. Anyone one have any thoughts on that?
     
    Last edited: Feb 11, 2014
  8. JohnInTX

    Moderator

    Jun 26, 2012
    2,341
    1,022
    Glad you got it working!

    If you are staying with PIC, Microchip and MikroElectronica both have lots of development boards of varying complexities. There are oodles of others on the intertoobs as well but I haven't used any of those.
     
Loading...