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

PIC18F66K80 CAN Rx Interrupt Not Working

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



Joined: 19 Jun 2016
Posts: 22

View user's profile Send private message

PIC18F66K80 CAN Rx Interrupt Not Working
PostPosted: Sun Apr 22, 2018 6:19 pm     Reply with quote

I have been trying for days to get CANBus interrupts to work, but I am having no success. I looked over the older posts and tried some code that seemed relevant, but it didn't work.

My PIC is running off 5V using a 40MHz powered oscillator. I am using a Peak Systems CAN-USB converter to communicate with the PIC board. Termination is OK and all the CANBus connections are solid.

The PIC's CAN transmissions work well and it receives incoming CAN frames fine via the polled if (can_kbhit()) in the main(). This confirms the HW side of things is ok.

However, no matter what I try, I can't get the RX interrupts to trigger.

I am using PCH v5.077. If anyone has any tips please let me know.

Here is my code

Code:

#include <18F66K80.h>
#device adc=12

#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES NOWDT                    //No Watch Dog Timer
#FUSES ECH_IO                   //External clock
#FUSES NOPLLEN                  //4X HW PLL disabled, 4X PLL enabled in software
#FUSES NOFCMEN                  //Fail-safe clock monitor disabled
#FUSES NOIESO                   //Internal External Switch Over mode disabled
#FUSES PUT                      //Power Up Timer
#FUSES BROWNOUT
#FUSES BORV30                   //Brownout reset at 3.0V
#FUSES MCLR                   //Master Clear pin enabled
#FUSES STVREN                 //Stack full/underflow will cause reset
#FUSES NODEBUG
#FUSES PROTECT

#use delay(clock=40000000)

//
#define CAN_USE_EXTENDED_ID FALSE
#define CAN_BRG_SEG_2_PHASE_TS TRUE 
#define CAN_BRG_PRESCALAR 4
#define CAN_BRG_SYNCH_JUMP_WIDTH 1
#define CAN_BRG_PROPAGATION_TIME 1
#define CAN_BRG_PHASE_SEGMENT_1 2
#define CAN_BRG_PHASE_SEGMENT_2 1
#define CAN_BRG_WAKE_FILTER TRUE
#define CAN_BRG_SAM TRUE

#include <can-18F4580.c>


//CAN Variables
int32 rx_id;
int rx_len, can_rx_buffer[8];
struct rx_stat rxstat;
int32 tx_id;
int tx_len = 8;
int can_tx_buffer[8];
int can_rx_message_byte_0 = 0;
int can_B_reply = 0;
int32 can_B_tx_id = 0xAA;
int current_control_byte = 0xFF;
int CAN_frame_count = 0;
long CAN_msg_idx = 9;


#int_canrx0
void canrx0_int ( )
{
   usb_forward(0xA0);
   can_getd(rx_id, &can_rx_buffer[0], rx_len, rxstat);
}

#int_canrx1
void canrx1_int ( )
{
   usb_forward(0xA1);
   can_getd(rx_id, &can_rx_buffer[0], rx_len, rxstat);
}

void main()
{

   can_init();
   
   can_set_mode(CAN_OP_CONFIG);
   
   can_set_functional_mode(CAN_FUN_OP_ENHANCED);
   
   can_set_id(RX0MASK,0,CAN_USE_EXTENDED_ID);
   can_set_id(RX1MASK,0,CAN_USE_EXTENDED_ID);
   can_set_id(RXFILTER0,0,CAN_USE_EXTENDED_ID);
   can_set_id(RXFILTER1,0,CAN_USE_EXTENDED_ID);
   can_set_id(RXFILTER2,0,CAN_USE_EXTENDED_ID);
   can_set_id(RXFILTER3,0,CAN_USE_EXTENDED_ID);
   can_set_id(RXFILTER4,0,CAN_USE_EXTENDED_ID);
   can_set_id(RXFILTER5,0,CAN_USE_EXTENDED_ID);
   can_set_id(RXFILTER6,0,CAN_USE_EXTENDED_ID);
   can_set_id(RXFILTER7,0xAA,CAN_USE_EXTENDED_ID);
   can_set_id(RXFILTER8,0,CAN_USE_EXTENDED_ID);
   can_set_id(RXFILTER9,0,CAN_USE_EXTENDED_ID);
   can_set_id(RXFILTER10,0,CAN_USE_EXTENDED_ID);
   can_set_id(RXFILTER11,0,CAN_USE_EXTENDED_ID);
   can_set_id(RXFILTER12,0,CAN_USE_EXTENDED_ID);
   can_set_id(RXFILTER13,0,CAN_USE_EXTENDED_ID);
   can_set_id(RXFILTER14,0,CAN_USE_EXTENDED_ID);
   can_set_id(RXFILTER15,0,CAN_USE_EXTENDED_ID);
   can_associate_filter_to_buffer(ARXB0,F0BP);
   can_associate_filter_to_buffer(ARXB0,F1BP);
   can_associate_filter_to_buffer(ARXB0,F2BP);
   can_associate_filter_to_buffer(ARXB0,F3BP);
   can_associate_filter_to_buffer(ARXB0,F4BP);
   can_associate_filter_to_buffer(ARXB0,F5BP);
   can_associate_filter_to_buffer(ARXB0,F6BP);
   can_associate_filter_to_buffer(ARXB0,F7BP);
   can_associate_filter_to_buffer(ARXB0,F8BP);
   can_associate_filter_to_buffer(ARXB0,F9BP);
   can_associate_filter_to_buffer(ARXB0,F10BP);
   can_associate_filter_to_buffer(ARXB0,F11BP);
   can_associate_filter_to_buffer(ARXB0,F12BP);
   can_associate_filter_to_buffer(ARXB0,F13BP);
   can_associate_filter_to_buffer(ARXB0,F14BP);
   can_associate_filter_to_buffer(ARXB0,F15BP);
   can_enable_filter(RXF0EN|RXF1EN|RXF2EN|RXF3EN|RXF4EN|RXF5EN|RXF6EN|RXF7EN|RXF8EN|RXF9EN|RXF10EN|RXF11EN|RXF12EN|RXF13EN|RXF14EN|RXF15EN);

   can_set_mode(CAN_OP_NORMAL);
 
   clear_interrupt(int_canrx0);
   enable_interrupts(int_canrx0);
   
   clear_interrupt(int_canrx1);
   enable_interrupts(int_canrx1);
 
   enable_interrupts(GLOBAL);
 
   while(TRUE)
   {
   if (can_kbhit())
         {
             if(can_getd(rx_id, &can_rx_buffer[0], rx_len, rxstat))
             {               
                 usb_forward(0xF1);     
             }
         }
   }

}
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Mon Apr 23, 2018 2:03 am     Reply with quote

can_getd, polls the interrupt flags and clears them inside the function. I hate to think what is happening, trying to call this both inside and outside an interrupt. Since it does it by direct access to the flags (not using the CCS functions), I don't think the compiler will automatically disable interrupts round the function in the external code. Result may well be deadlock.....
matthewsachs



Joined: 19 Jun 2016
Posts: 22

View user's profile Send private message

PostPosted: Mon Apr 23, 2018 10:04 am     Reply with quote

I deleted the polling code from the main() function

Code:

if (can_kbhit())
         {
             if(can_getd(rx_id, &can_rx_buffer[0], rx_len, rxstat))
             {               
                 usb_forward(0xF1);     
             }
         }
   }


and replaced it with a delay_cycles(1); but the RX interrupts never trigger.
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Mon Apr 23, 2018 10:13 am     Reply with quote

OK. The question is how the FIFO is actually configured?. You are going to have to go through the code and find how this is configured. These are the FIFO interrupts and obviously depend on how this is actually configured.
matthewsachs



Joined: 19 Jun 2016
Posts: 22

View user's profile Send private message

PostPosted: Mon Apr 23, 2018 10:23 am     Reply with quote

I assume that implies analyzing the CCS' #include <can-18F4580.c> file, which I will go and do right away.

Last edited by matthewsachs on Mon Apr 23, 2018 10:52 am; edited 1 time in total
matthewsachs



Joined: 19 Jun 2016
Posts: 22

View user's profile Send private message

PostPosted: Mon Apr 23, 2018 10:51 am     Reply with quote

So I looked over the datasheet and noticed that RXBnIF behaves differently depending on what mode ECAN is configured for.
Quote:

When the receive interrupt is enabled, an interrupt will
be generated when a message has been successfully
received and loaded into the associated receive buffer.
This interrupt is activated immediately after receiving
the End-of-Frame (EOF) field.
In Mode 0, the RXBnIF bit is set to indicate the source
of the interrupt. The interrupt is cleared by the MCU,
resetting the RXBnIF bit to a ‘0’.
In Mode 1 and 2, all receive buffers share RXBnIE,
RXBnIF and RXBnIP in PIE5, PIR5 and IPR5, respectively.
Bits, RXBnIE, RXBnIF and RXBnIP, are not
used. Individual receive buffer interrupts can be controlled
by the TXBnIE and BIE0 registers. In Mode 1,
when a shared receive interrupt occurs, user firmware
must poll the RXFUL bit of each receive buffer to detect
the source of interrupt. In Mode 2, a receive interrupt
indicates that the new message is loaded into FIFO.
FIFO can be read by using FIFO Pointer bits, FP.


I initially used Mode 1 because it gave me more filters, but I can get by with the smaller number.

So I changed this line in my init section

Code:

//can_set_functional_mode(CAN_FUN_OP_ENHANCED);
   can_set_functional_mode(CAN_FUN_OP_LEGACY);


and #int_canrx0 started firing.

Based on the datasheet info I can't tell why the interrupts didn't fire in Mode 1 since the only difference seems to be that in Mode 1 the user's FW must determine the source of interrupt.
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Mon Apr 23, 2018 11:02 am     Reply with quote

Well done.
The standard code is very much setup on the assumption it'll be polled rather than interrupt driven, so I'm not surprised it needed a tweak!...
It's a long time since I looked at it.

I think in mode1, you don't get the separate interrupts for the FIFO buffers, just the main can interrupt.
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