| 
	
	|  |  |  
	
		| View previous topic :: View next topic |  
		| Author | Message |  
		| ZackM 
 
 
 Joined: 14 Jun 2006
 Posts: 6
 Location: Manhattan, Ks
 
 
			    
 
 | 
			
				| CAN and SPI interrupt do not work together? |  
				|  Posted: Mon Jun 19, 2006 3:28 pm |   |  
				| 
 |  
				| Hello, I’m trying to get a PIC18F2680 to run can_rx interrupt, along with ssp interrupt. I have both of these interrupts working fine on the same PIC individually. The problem occurs when I combine the 2, sspbuf dominates the PIC. With the SPI on, no CAN packet comes in or out of that PIC. 
 I’m out of ideas, is there something I’m missing?
 
 The layout:
 ___
 |18F| ---- SPI ---- > ADCs & MAX3100
 ----
 |  |
 |   \--------CAN-----> Another 18F & PC w/ PCMCIA-CAN/2
 \
 \------RS232---> PC monitoring
 |  |  
		|  |  
		| PCM programmer 
 
 
 Joined: 06 Sep 2003
 Posts: 21708
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon Jun 19, 2006 3:33 pm |   |  
				| 
 |  
				| Use the #priority statement to give the CAN interrupt priority over the SSP interrupt.
 |  |  
		|  |  
		| ZackM 
 
 
 Joined: 14 Jun 2006
 Posts: 6
 Location: Manhattan, Ks
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon Jun 19, 2006 3:59 pm |   |  
				| 
 |  
				| Wow, you were quick. I gave #priority a run, and I also tried the fast extension with #device high_ints =true. No luck with either. 
 CAN packets from the 18F are also not going out. The routine that sends the CAN packets are not on a CAN interrupt but TIMER0. I can see that the timer0 interrupt works and runs the code with the debugger. Unfortunately, with SPI on, the packet never gets sent. I'm using the CAN-18F4580.c library. I can see that all the register get loaded and the transmit flag set. For some reason, having activity on SPI doesn't let anything go through. I don't know what the deal is. Does this bring any ideas to mind?
 
 
  Thanks for your speedy response! 
 -Zack
 |  |  
		|  |  
		| PCM programmer 
 
 
 Joined: 06 Sep 2003
 Posts: 21708
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon Jun 19, 2006 5:16 pm |   |  
				| 
 |  
				| 1.  Are you using SPI as a master or slave ?   Is the SSP interrupt for an SPI slave or a master ?   If you are using it as a Master
 and you if enable interrupts and the buffer is empty, you will get
 continuous interrupts.   The program will appear to lock up.
 To prevent this, when you're in the isr, you need to check if there
 is any data remaining to be sent, and if not, then disable SSP
 interrupts.
 
 2.  Are you testing all this by trying to single-step through it with the
 debugger, or are you testing it at full speed operation with the
 program running in stand-alone mode ?   There are limitations
 to the ICD2 debugger.   For example, the help file in MPLAB
 says "You cannot single step through an interrupt".
 
 3.  When you enable interrupts, are you using two separate
 enable_interrupts() statements to do so ?   You need to do it that
 way.   Don't try to bitwise "OR" the interrupt constants together in
 one statement.
 |  |  
		|  |  
		| ZackM 
 
 
 Joined: 14 Jun 2006
 Posts: 6
 Location: Manhattan, Ks
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon Jun 19, 2006 7:42 pm |   |  
				| 
 |  
				| Thanks, PCM Programmer for your time. 
 The answer to your questions,
 
 #1) The program is running as Master on SPI, I wasn’t aware that SPI interrupt always went off. This code I’m developing is for telemetry and motor contol system on an electric car. There is always ADCs to be polled over SPI. To allow time for other things to be processed, I set the SPI clock to 1/64th of internal. It seems to work, as the main while loop works (There’s a code snippet below with the main while loop labeled).
 
 #2) I’ve been testing the program with and without the Debugger. I make the clam that no packet are being sent or received with the chip running without the debugger. I make the claim that the CAN receive interrupt never gets ran from observation of setting a stop in the CAN receive interrupt routine with the debugger.
 
 #3) All interrupts are enabled with their own and separate command.
 
 I’ll include a cut down (snippet) of my code, as the actual thing is rather big ..
 
 
  	  | Code: |  	  | #include <18f2680.h>
 #device high_ints=true
 #use delay(clock=20000000)
 #fuses HS,NOWDT,PUT,NOPROTECT,NOLVP
 #include <can-18F4580.c>
 #priority CANRX1
 #use rs232(baud=19200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
 
 //The main routine
 void main()
 {
 printf("Hello");
 //Starting up the process
 delay_ms(1000);
 
 SET_TRIS_B(0x00);
 SET_TRIS_C(0x4A);    //Inputs: RX, SDO, PIN_C2
 
 spi_setup();
 can_setup();
 serial_setup();
 
 //Gonna set the world in motion
 enable_interrupts(GLOBAL);
 
 delay_ms(1000);
 
 //Da main funky loop
 while (1)
 {
 //Blinky light, purdy light
 output_bit(PIN_C1,!INPUT_STATE(PIN_C1));
 
 Display_windmill();  //A  routine that produces a windmill on a display
 //connected to a display on a MAX3110
 delay_ms(17);
 }
 }
 
 void can_setup(){
 can_init();
 
 //Change baud to 500k
 can_set_mode(CAN_OP_CONFIG);
 BRGCON1=0x01;        //These values were created using a calc from Microchip
 BRGCON2=0xA0;
 BRGCON3=0x02;
 can_set_mode(CAN_OP_NORMAL);
 
 //Set additional buffers to be receivers
 can_set_functional_mode(10);        //Set ECAN to run FIFO mode
 can_enable_b_receiver(B0);
 can_enable_b_receiver(B1);
 can_enable_b_receiver(B2);
 can_enable_b_receiver(B3);
 can_enable_b_receiver(B4);
 can_enable_b_receiver(B5);
 
 //Code to setup up timer0 snipped
 
 enable_interrupts(INT_CANRX1);
 enable_interrupts(INT_TIMER0);
 enable_interrupts(INT_TIMER1);
 }
 
 void spi_setup()
 {
 setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_XMIT_L_TO_H|SPI_CLK_DIV_64);
 
 //Setup MAX3110 for Display
 CHNL_SEL(CHNL_DISPLAY);
 spi_read(MAX_WRITE_CONFIG | MAX_TBE_ON);
 spi_read(MAX_96BAUD);
 CHNL_SEL(CHNL_NONE);
 
 //Additional so TBE interrupt starts going
 CHNL_SEL(CHNL_DISPLAY);
 spi_read(MAX_WRITE_DATA);
 spi_read('_');
 CHNL_SEL(CHNL_NONE);
 
 //Time for the display to powerup
 delay_ms(500);
 
 enable_interrupts(INT_SSP);
 
 //Allow for spi to pick a task
 spi_root();
 }
 
 spi_root(){
 //Snipped
 //Code here assigns what to talk to on SPI, every option ends with
 //loading the SSPBUF
 }
 
 #INT_SSP
 void spi_isr()
 {  //Snipped
 //Stores data, and also loads SSPBUF when required, when finished
 //talking to device it calls spi_root again.
 }
 
 #INT_TIMER0
 void can_isr_timer(){
 can_tx();   //Code that decides what to send, and ends with a
 //can_putd();
 }
 
 #INT_CANRX1 FAST
 void can_rx_isr(){
 can_fifo_getd(rx_id,&rxdata[0],rx_len,rxstat);
 
 //Code that processes this data was snipped
 }
 
 void serial_setup()
 {
 //Snip
 enable_interrupts(INT_RDA);
 }
 
 #INT_RDA
 void serial_rda_isr()
 {  ser_rx_buf = RCREG;
 ser_tx_char(ser_rx_buf); //This enables INT_TBE
 if (ser_rx_buf == '`')
 {  serMode = 1;   //Starts a process of unloading the data on the serial
 
 }
 }
 
 #INT_TBE
 void serial_tbe()
 {
 TXREG = ser_tx_buf[ser_tx_tail];
 //Snip
 //Unloads all the data it has stored
 //Ends with disable_interrupt(INT_TBE);
 }
 
 | 
 
 There is serial, in this code. It has never been a problem and it only executes when I send it a backtick for testing. I've seen no change in the problem with the serial added/removed from the code.
 
 Thanks, PCM for looking at this thread and trying to help. I'm very grateful for that.
 |  |  
		|  |  
		| PCM programmer 
 
 
 Joined: 06 Sep 2003
 Posts: 21708
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon Jun 19, 2006 8:32 pm |   |  
				| 
 |  
				| I see one immediate problem.   You have declared this isr to be FAST. 
  	  | Quote: |  	  | #INT_CANRX1 FAST void can_rx_isr(){
 can_fifo_getd(rx_id,&rxdata[0],rx_len,rxstat);
 
 //Code that processes this data was snipped
 }
 | 
 Here is what the CCS manual says about this:
 
  	  | Quote: |  	  | An interrupt marked FAST is performed without saving or
 restoring any registers. You should do as little as possible
 and save any registers that need to be saved on your own.
 | 
 But you're not doing that.
 
 I think that you actually want to use the 'HIGH' keyword instead of 'FAST'.
 
 Read Ttelmah's article on interrupts near the end of this thread:
 http://www.ccsinfo.com/forum/viewtopic.php?t=26093
 |  |  
		|  |  
		| ZackM 
 
 
 Joined: 14 Jun 2006
 Posts: 6
 Location: Manhattan, Ks
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon Jun 19, 2006 9:39 pm |   |  
				| 
 |  
				| I add FAST by accident. I was just trying to set some priority to the routine so I could recieve some CAN messages. 
 I switch it to HIGH. My problem still exists, the PIC can neither send or recieve when it uses it SPI routines.
 
 Thanks for the information, though. I didn't know that about FAST.
 |  |  
		|  |  
		| PCM programmer 
 
 
 Joined: 06 Sep 2003
 Posts: 21708
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon Jun 19, 2006 10:13 pm |   |  
				| 
 |  
				| In your code, you have set_tris_x() statements.  But you don't have a #use fast_io() statement.   So the compiler's functions, which you use
 after the set_tris_x() statements, will change the TRIS.
 
 In the code below, you set the TRIS for port C to 0x4A.
 
  	  | Quote: |  	  | SET_TRIS_C(0x4A);  //Inputs: RX, SDO, PIN_C2 spi_setup();
 can_setup();
 serial_setup();
 | 
 
 But in the .LST file shown below, the setup_spi() function sets up
 the TRIS for the hardware SPI pins.   These TRIS values don't match
 what you have specified in set_tris_c(0x4A).   Are you trying to use
 non-hardware pins for the SPI ?   The CCS spi functions only work
 with the hardware pins.
 
  	  | Code: |  	  | bit:         7654 3210
 set_tris_c:  0100 1010
 setup_spi:     01 0
 | 
 
 
  	  | Code: |  	  | ... setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_XMIT_L_TO_H|SPI_CLK_DIV_64); 00138:  BCF    SSPCON.5
 0013A:  BCF    TRISC.5  // TRISC5 = 0
 0013C:  BSF    TRISC.4  // TRISC4 = 1
 0013E:  BCF    TRISC.3  // TRISC3 = 0
 00140:  MOVLW  22
 00142:  MOVWF  SSPCON
 00144:  MOVLW  40
 00146:  MOVWF  SSPSTAT
 | 
 |  |  
		|  |  
		|  |  
  
	| 
 
 | 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
 
 |