2

I am using the following:

  • pic18f4550,
  • xc8 compiler,
  • mplab x ide v3.20,
  • a transmitter and receiver module (tested with a main program without any interruptions and works).
  • LED's connected to RD0,RD1 and RD2 (1 = light up)
  • Buttons connected to RB0,RB1 and RB2 (0 = button is pressed)//does not matter at this point

Apparently everything in this code works fine but with interrupts "void interrupt SerialComm(void)"
(I have made a program without interrupt and led lights up).

The main does not even load up; I have put "PORTD = 0x0F",
(line 3 of main program).

So if the led lights up it means that at least the 3rd line of the main program works.
(at least until that line, but the led didn't.)

Is there any register I have to disable first that I missed out for this?
Also, i have followed most tutorials could there be something i have missed?, i have seen many programs with #pragma but i'm not sure if i need then when i am using XC8 compiler.

    /*
 * File:   transmit.c
 * Author: steve 
 *
 * Created on September 25, 2016, 12:36 AM
 */
#define _XTAL_FREQ 48000000

#include <xc.h>
#include <pic18f4550.h>
void DelayMs(int x);
char ButtonsChecker();
char ButtonsCheckValue = 0; //returned value
char data_received = 0;


void main(void) {
    TRISB = 0x0F;
    TRISD = 0b00000000;

    TRISCbits.TRISC2 = 0; //TXD Power
    TRISCbits.TRISC6 = 0; //RC6 
    TRISCbits.TRISC7 = 1; //RC7
    PORTCbits.RC2 = 1;

    RCSTA = 0x90;
    TXSTA = 0x20;
    SPBRG = 77;

    RCREG = 0;
    RCIF = 0;


    PORTDbits.RD0 = 1;
    PORTDbits.RD1 = 1;
    PORTDbits.RD2 = 1;

    RCIE = 1;
    TXIE = 0;

    PEIE = 1;
    GIE = 1;

    while (1) {

        while (ButtonsChecker()) {

            TXREG = ButtonsChecker();
        }


        //while (!TRMT); // waiting for a whole data frame to be ready for a transmission
        //TXREG = PORTB;

        //while (!RCIF); // waiting for a whole data frame to be received
        //PORTD = RCREG;

    }
}

void DelayMs(int x) {
    while (x > 0) {
        __delay_ms(1);
        x--;
    }
}

char ButtonsChecker() {
    if (PORTBbits.RB0 == 0) {
        ButtonsCheckValue = 1;
    } else if (PORTBbits.RB1 == 0) {
        ButtonsCheckValue = 2;
    } else if (PORTBbits.RB2 == 0) {
        ButtonsCheckValue = 4;
    }//else if (PORTBbits.RB3 == 0) {
        // ButtonsCheckValue = 8;}
    else ButtonsCheckValue = 0;

    return (ButtonsCheckValue);
}


void interrupt ReceiveData() {
    if (RCIF == 1) {
        RCIF = 0;
        ~PORTDbits.RD1;
    }
}
Steve Quek
  • 21
  • 4
  • Did you register the interrupt in the interrupt vector table? – Lundin Jan 16 '17 at 11:50
  • At start you do PORTD = 0x0F, but sudden later this is overwritten by PORTD = 0x01. What is connected to PORTD.0 (lsb bit)? Check if you find a voltage on that pin (probably you will do, so you main enters the while()). – linuxfan says Reinstate Monica Jan 16 '17 at 12:07
  • @linuxfan actually there are 3 pins connected to leds if bit 0 = 1 one of the led will light up,bit1 and bit 2 do the same so 0x0F all 3 will light up, but if the main program launch perfectly the 0x0F will be overwrited really fast by the 0x01 in the while loop, so the led in RD0 will light up and the rest off, but instead nothing turns on, so i am assuming it's the interrupt function i have created. //what i think is something is trapping the cpu into the interrupt function i have created, but i don't know what – Steve Quek Jan 16 '17 at 13:33
  • @Lundin i have read the XC8 C Compiler manual about writing an interrupt function and there is this one part where they say **Code generated by the compiler will be placed at the interrupt vector address which will execute this function after any context switch that is required.** are you refering to this? – Steve Quek Jan 16 '17 at 13:46
  • 1
    I don't know this particular part, but almost every microcontroller has an interrupt vector table, which is a chunk of flash where the MCU goes looking for addresses to your ISRs. This chunk of flash can either be programmed automatically by the linker/linker script, or manually by the programmer as an array of function pointers allocated at a given address. If this vector table area is not properly programmed with the address of your ISR, and the interrupt is enabled+triggered, the MCU will attempt to jump at some garbage address, and then anything can happen. This is a very common mistake. – Lundin Jan 16 '17 at 13:53
  • @lundin Many PICs have only one IRQ vector (at location 4 if I well remember), so any code placed there will automatically be "THE interrupt handler"; this handler must check what was the cause of the interrupt and clear the flags appropriately. It seems that the XC8 compiler manages this when "void interrupt ...()" is used. – linuxfan says Reinstate Monica Jan 16 '17 at 18:15

1 Answers1

0

Everything looks O.K. except that you didn't enable TX and RC interrupts. So add at USART initiation:

PIE1bits.RCIE = 1;
PIE1bits.TXIE = 1;

At the end of initiation section also add:

INTCONbits.GIE = 1; 

...to enable global interrupts.

GJ.
  • 10,810
  • 2
  • 45
  • 62
  • omg thanks, i can't believe i forgotten that, i actually reused this old template i made quite some time ago, actually my previous version had something like that but with the TXIE bit disabled just to test the receiving part of the interrupt, i would try again tommorow – Steve Quek Jan 16 '17 at 15:38
  • i actually updated the code where it was the previous version of the one you have viewed that has "RCIE" bit enabled but didn't work too – Steve Quek Jan 16 '17 at 15:45
  • Amm? `RCREG` register should be read only so why you write in to? And `RCIE` is a bit variable so can you set it on that way? – GJ. Jan 16 '17 at 16:08
  • Oh i have seen some tutorial where they said that puting "RCREG = 0;" is a reset-ing the register forcing it to be '0' on start up or something, and the way i set RCIE might be thanks to xc.h or the pic18f4550.h file apparently some people on youtube were doing this too, as i see no error in building the project files i think it can be initialized that way"?" – Steve Quek Jan 16 '17 at 16:16
  • @Steve Quek: The proper method to reset `RCREG` buffer is to read from! – GJ. Jan 16 '17 at 23:10
  • oh i have try those earlier today but still doesn't work, i have also check the (assembly coding) program address the one that traps cpu and the one without the interrupt program. The program with interrupt starts at around 0x0000 to (length of program) and the program without interrupt jumps from zero to 7000H (approx) and starts from there, sorry tho my assembly programming is still very weak. – Steve Quek Jan 17 '17 at 11:29
  • @Steve Quek: the High Priority Interrupt Vector starts at address 0x0008 so check this address content! Interrupt start at this address. What about RC errors check RCSTA.OERR bit in main loop if set then read RCREG or clear RCSTA.CREN bit and set again RCSTA.CREN bit. Do you have any pullup resistor on RC pin? – GJ. Jan 17 '17 at 14:30
  • apparently at address 0x0008 there is the label `ReceiveData` so i guess it is loaded into the interrupt vector, and according to the debugger the `RCSTA.OERR ` bit is always a 0 ; // i use single stepping in the debugger from line one of the program memory – Steve Quek Jan 17 '17 at 15:10
  • oh ya and about `PORTC` pins port `RC6` is connecting to a transmitting pin of a transmiter module, `RC7` is receiving pin in the receiver module, and `RC2` is to control the power of the `Transmitter` because i may want to turn it off some time, but other than that nothing else is connected no other circuit is created and connected to `PORTC`. – Steve Quek Jan 17 '17 at 15:15
  • @Steve Quek: somewhere in main loop put `RCIF = 1;` sentence and enable break point on first sentence in interrupt. After executing `RCIF = 1;` the program must immediately jump to the interrupt if interrupts are initiated correctly! – GJ. Jan 17 '17 at 17:16
  • well i have tried and i get `Launching Initializing simulator User program stopped User program running` and it didn't go to that part the program just hangs there, i left it there for about 15 minutes already most likely it wont get there, in simulation this is keeps coming out : `W0004-CORE: Watchdog Timer has caused a Reset. W9201-UART: Write attempted to a full FIFO buffer, data lost.` – Steve Quek Jan 19 '17 at 06:23