1

I'm trying to get started on a project using a PIC18F24J10. Attempting to use SDCC for this. At this point I've reduced my code to simply trying to nail down what is happening, as I've been seeing bizarre behavior for a while now and can't really proceed until I figure out what is going on. Not sure if this is my only problem at this point, but I have no idea why this is happening. Timer interrupt fires off, coupled with a #defined for loop causes LEDs on PORTC to blink maybe twice a second. If I just do a PORTC=0xFF and PORTC=0 this works fine. But it gets weird when I try to go much beyond that.

    ...
    #define _RC0 31
    #define _RC1 32
    #define _RC2 33
    #define _RC3 34
    #define _RC4 35
    #define _RC5 36
    #define _RC6 37
    #define _RC7 38

    #define HI  1
    #define LO  0

    void why(unsigned char p, int z)
    {
        if(z == HI)
        {
            if(p == _RC0) PORTCbits.RC0 = 1;
            else if(p == _RC1) PORTCbits.RC1 = 1;
            else if(p == _RC2) PORTCbits.RC2 = 1;
            else if(p == _RC3) PORTCbits.RC3 = 1;
            else if(p == _RC4) PORTCbits.RC4 = 1;
            else if(p == _RC5) PORTCbits.RC5 = 1;
            else if(p == _RC6) PORTCbits.RC6 = 1;
            else if(p == _RC7) PORTCbits.RC7 = 1;
        }
        else if(z == LO)
        {
            PORTC = 0b11110000;
        }
        else
        {
            PORTC = 0b10101010;
        }
    }

    void timer_isr (void) __interrupt(1) __using (1)
    {
        TMR0H=0;
        TMR0L=0;
        why(_RC0, LO);
         why(_RC1, LO);
          why(_RC2, LO);
        WAIT_CYCLES(5000);
        why(_RC0, HI);
         why(_RC1, HI);
          why(_RC2, HI);
          WAIT_CYCLES(5000);
    }

    void main(void)
    {
        WDTCONbits.SWDTE = 0;
        WDTCONbits.SWDTEN = 0;
        TRISC = 0b00000000;
        PORTC=0b00000000;

        INTCONbits.GIE = 1;
        INTCONbits.PEIE = 1;
        INTCONbits.TMR0IF = 0;
        INTCONbits.TMR0IE = 1;
        T0CONbits.T08BIT = 0;
        T0CONbits.T0CS = 0;
        T0CONbits.PSA = 1;
        TMR0H = 0;
        TMR0L = 0;
        T0CONbits.TMR0ON = 1;

        while(1)
        {

        }
    }

In the code above, four of the LEDs should blink, while the other four stay on. Instead, the LEDs stay on in the 10101010 pattern that happens in the "else" block, which should happen when "why" is called with any value other than HI or LO. I never call it with anything else, so why does it ever reach that?

UPDATE - Further reduction, no more interrupts or unspecified includes/defines. This is now the entirety of the program, and I am still seeing the same behavior. Changed the pattern from 10101010 to 10101011 so that I could verify the chip is actually being programmed with the new code, and it appears to be.

    #include "pic16/pic18f24j10.h"

    #define WAIT_CYCLES(A)  for(__delay_cycle = 0;__delay_cycle < A;__delay_cycle++)
    int __delay_cycle;

    #define HI 1
    #define LO 0

    void why(int z)
    {
        if(z == HI)
        {
            PORTC = 0b11111111;
        }
        else if(z == LO)
        {
            PORTC = 0b11110000;
        }
        else
        {
            PORTC = 0b10101011;
        }

    }

    void main(void)
    {
        TRISC = 0b00000000;
        PORTC=0b00000000;

        while(1)
        {
        why(LO);
        WAIT_CYCLES(5000);
        why(HI);
        WAIT_CYCLES(5000);
        }
    }
Aglandiir
  • 31
  • 2

1 Answers1

1

Once the interrupt is asserted it is never cleared. That results in timer_isr() being called repeatedly. No other code is ever reached. The TMR0IF bit must be cleared in software by the Interrupt Service Routine.

Keep in mind you not only need to spend less time in the ISR than the period of the timer - it’s a good practice to spend the minimum amount of time necessary.

Remove the delays and simply toggle a flag or increment a register. In your main while (1) loop monitor the flag or counter and make your calls to why() from there.

jolati
  • 700
  • 11
  • 19
  • I wouldn't think that this would have explained why it ever reaches that last 'else' block. Just to be sure, though, I went ahead and made a shortened test file that does away with the interrupts and ran that. Still seeing the same behavior. I added in my shortened code in the original question. – Aglandiir Apr 22 '15 at 19:12
  • I ran the second bit of code in MPLAB SIM and, as expected, it never hits the line PORTC = 0b10101011; Are you sure WAIT_CYCLES(5000) produced a 1/4 second delay. What is your clock speed? – jolati Apr 22 '15 at 20:53
  • 20MHz external... However, I think I have stumbled onto a potential answer, still checking it out. I upgraded my sdcc version to 3.4, and compiling with that gives me a warning now that XINST is supported by this particular chip (and possibly enabled by default) but SDCC doesn't work with that. So, I'm trying to turn that off via "#pragma config XINST=OFF". Though, when I turn that off, it doesn't successfully program (Gives me Program Memory Errors). So, now I'm asking the electronics stack exchange what the fix for that might be :) Also, without the interrupt - more of a buzz than a blink. – Aglandiir Apr 22 '15 at 21:21