CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug Reports on this forum. Send them to support@ccsinfo.com

18F26K83 CAN interrupt confusion

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
pmuldoon



Joined: 26 Sep 2003
Posts: 204
Location: Northern Indiana

View user's profile Send private message

18F26K83 CAN interrupt confusion
PostPosted: Wed Jul 21, 2021 7:20 am     Reply with quote

ccs ver 5.105
18f26K83 chip
can-pic18f_ecan.c/h

What is the proper way to use the CAN RX interrupt?
I had the strangest thing happen.

Everything worked fine until I tried to add a pace delay to the main loop. Then it acted like my timer1 interrupt wasn't running.

I also broke it by adding a LampTest() before the main loop. In this case the LampTest simply wouldn't run. It ran fine in the main loop, but not before the main loop.

The whole problem seems to revolve around the CAN interrupts. All I want to to is fire an interrupt whenever a CAN msg is rec'd. If I do a

Code:

enable_interrupts(INT_TIMER1 | INT_CANRXB0 | INT_CANRXB1);

it breaks. But if I just enable the TMR1 interrupt and enable the CAN interrupts in the main loop (as a test) then the CAN interrupts activate and everything works properly.


I don't really understand how the can_enable_interrupts() function plays into this, it doesn't seem to be necessary for what I'm doing. And I only really intend to use 2 rx buffers, to keep things simple.

So, what is the proper way to set that up?


Also, can I use both #INT_CANRXBx labels to point to the same function?
It seemed to work fine when the program worked, but I can't find any reference to tell me if that's acceptable or not. Would it clear the int flags properly or just be a bad practice? I can do it with separate functions - just curious.
Code:

#INT_CANRXB0
#INT_CANRXB1
void    CanRxB0Interrupt()
{
   can_ec_t CanError;
   
   CanError = can_getd(&LastCanMsg, CanDataBuf, CAN_RX_BUFFER_ANY);
   if(LastCanMsg.Id == 0xCF00400)
    MoveCanData(0);
   else if(LastCanMsg.Id == 0x18FEDF00)
    MoveCanData(1); 
   else if(LastCanMsg.Id == 0x18FEF700)
    MoveCanData(2);
   
 
}

Here is the MAIN. Sorry for the mess. I just don't have time to send a clean demo of the issue. I'm hoping my clues will help. You can see the context of the locations of the enable_interrupts(). The LampTest() is just outputs and delays, so I didn't show it. I'm really just interested in how to setup for 2 rx buffers and an rx interrupt.
[
Code:

/******************************* MAIN *****************************************/
void   main()
{
    uint16_t    TerminalCntr = 0;   // sets the update rate for the terminal display
   
   
    InitializeOutputs();
    SetDefaults();
   
    // setup SPI for display TLC5925
    // 30MHz clock max; reads data on L->H clk transition
    setup_spi(SPI_MASTER | SPI_SCK_IDLE_LOW | SPI_CLK_FOSC | SPI_TX_ONLY_MODE | SPI_XMIT_L_TO_H, 16000000);
    // setup Timers
    setup_timer_1(T1_FOSC | T1_DIV_BY_8);   // 16MHz / 8 = 2 counts per uS
    set_timer1(0xFFFF - 20000);             // 20000 = 10ms
 
   

    // setup ADC
    // ADC_CLOCK_DIV_16 for 16MHz xtal = 1us per Tad
    //setup_adc(ADC_LEGACY_MODE | ADC_CLOCK_DIV_16 | ADC_TAD_MUL_8);  // ADC_CLOCK_DIV_16 for 16MHz xtal = 1us per Tad
    setup_adc(ADC_LOW_PASS_FILTER_MODE | ADC_CLOCK_DIV_16 | ADC_TAD_MUL_8, 5, 255);
    //setup_adc(ADC_ACCUMULATE_MODE | ADC_CLOCK_DIV_16 | ADC_TAD_MUL_8, 5, 255);
   
    setup_adc_ports(sAN0|sAN1|sAN4|sAN5|sAN16, VREF_VREF );     
    // setup CAN
    can_init(CAN_OP_NORMAL);
    can_set_baud(16000000, 250000);
    can_enable_interrupts(CAN_INTERRUPT_RXB0 | CAN_INTERRUPT_RXB1);
   // setup interrupts
    enable_interrupts(INT_TIMER1);
//    enable_interrupts(INT_TIMER1 | INT_CANRXB0 | INT_CANRXB1);
    enable_interrupts(GLOBAL);
#if USE_TERMINAL == TRUE
    // setup debug terminal
    printf("\x1B[2J");      // VT100 clear screen
    printf("\n press SPACE to activate terminal");
#endif
    output_low(OUT_IGN);
    LampTest();
    //**************************** MAIN LOOP ***********************************
   while(TRUE){
        output_low(TESTPIN);             // test interrupt timing   
        // pace the main loop
        while(MyLoopDelayMs < 10);
        MyLoopDelayMs = 0;
        output_high(TESTPIN);             // test interrupt timing
enable_interrupts(INT_TIMER1 | INT_CANRXB0 | INT_CANRXB1);


        // test ADC by doing a channel read
//        output_high(TESTPIN);             // test interrupt timing
        ReadAnalog();
//        output_low(TESTPIN);             // test interrupt timing
        // test 7-segment display
        DisplayValue(TimeSeconds, 0);
        // calculate units
        FuelOhms     = Count2Ohms(FuelCnt);
        CompPresPsi  = Count2Psi(CompPresCnt);
        ExtPotOhms   = Count2Ohms(ExtPotCnt);
        CompTempOhms = Count2Ohms(CompTempCnt);
        VbattMv      = Count2Mv(VbattCnt);
       
#if USE_TERMINAL == TRUE
        if(TerminalActive & (TerminalCntr++ > 50)){
            TerminalCntr = 0;
            // update debug terminal
            printf("\x1B[10;10f");      //VT100 move cursor to screen location LINE,COL
            printf("\n TimeSeconds   :  %3u  ", TimeSeconds);
            printf("\n Vbatt count   : %4lu : %5lu mV", VbattCnt, VbattMv);
            printf("\n Fuel count    : %4lu : %5lu ohms", FuelCnt, FuelOhms);
            printf("\n CompPres count: %4lu : %5lu psi ", CompPresCnt,CompPresPsi);
            printf("\n ExtPot count  : %4lu : %5lu ohms", ExtPotCnt, ExtPotOhms);
            printf("\n CompTemp count: %4lu : %5lu ohms", CompTempCnt, CompTempOhms);
            printf("\n Oil Pressure  : %u",    input(IN_OIL_PRES));
       
        // display CAN msgs
            printf("\n CAN Real ENG Revolution  :");
            for (int i =0; i<8; i++)  printf(" %x",CanRxDataBuf[0][i]);
           
            printf("\n CAN Target ENG Revolution:");
            for (int i =0; i<8; i++)  printf(" %x",CanRxDataBuf[1][i]);
           
            printf("\n CAN Battery Voltage      :");
            for (int i =0; i<8; i++)  printf(" %x",CanRxDataBuf[2][i]);
           
            printf("\n 1-Starter  2-Fan  3-Inlet  4-Ign  5-InletB");         
        }

        // check for keypress
         if(kbhit()){
            switch(getc()){
             case '1': output_toggle(OUT_STARTER); break;
             case '2': output_toggle(OUT_FAN);     break;
             case '3': output_toggle(OUT_INLET);   break;
             case '4': output_toggle(OUT_IGN);     break;
             case '5': output_toggle(OUT_INLET_B); break;
             case ' ': TerminalActive = TRUE;      break;
            }
        }
#endif   
    }
}
Ttelmah



Joined: 11 Mar 2010
Posts: 17478

View user's profile Send private message

PostPosted: Wed Jul 21, 2021 7:38 am     Reply with quote

Key critical error:

enable_interrupts(INT_TIMER1 | INT_CANRXB0 | INT_CANRXB1);

You cannot OR together interrupts in the enable line. In the header, it tells you
where things 'can' be ored together. This is not such a place.

In fact the CANRX interurpts will probably OR together without causing a
problem, but when you add the timer interrupt, the result of the OR is
to enable timer5, not timer1, for which you don't have a handler. Result
'disaster'.

Interrupt enables should/must be separate.
pmuldoon



Joined: 26 Sep 2003
Posts: 204
Location: Northern Indiana

View user's profile Send private message

PostPosted: Wed Jul 21, 2021 7:59 am     Reply with quote

Great catch, T.
Thanks. That seems to have fixed it.

I've only been programming PIC's for about 25 yrs. How did I not know that? I must be getting old!
Ttelmah



Joined: 11 Mar 2010
Posts: 17478

View user's profile Send private message

PostPosted: Thu Jul 22, 2021 12:07 am     Reply with quote

Historically, none could be ored here. However more recently, some stuff
can be ored (for example on the interrupt edge commands you can or in the
edge involved). Result it gets more and more confusing!. It really would
be worth CCS adding a bit note saying 'must not be ored' for these values.
Glad I got it!... Very Happy
pmuldoon



Joined: 26 Sep 2003
Posts: 204
Location: Northern Indiana

View user's profile Send private message

PostPosted: Thu Jul 22, 2021 5:19 am     Reply with quote

Yes, it's working great now.

And thanks for the quick response. That kept a rush project from going sideways on me.

Half of my mistakes are something so incredibly obvious I just can't see the problem, the other half are so insidiously obscure I can't find them.
The third half I can usually figure out pretty quickly on my own.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group