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

SSP2 problem

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



Joined: 30 Mar 2008
Posts: 109
Location: New Jersey

View user's profile Send private message

SSP2 problem
PostPosted: Thu Feb 18, 2010 6:13 pm     Reply with quote

Hi all. Trying to use SSP1 and SSP2 for two I2C slaves. SSP1 works fine, but although it compiles, no interrupt was generated for the SSP2 slave. In fact sending data to the second channel causes the program to lock up. I discovered that no code is generated to initialize.
Code:

#use i2c (slave, I2C1, address=0xA0, FORCE_HW, stream=IC_PHASE)
#use i2c (slave, I2C2, address=0xA2, FORCE_HW, stream=IC_MAG)

Looking at the list file I see the code for I2C1, but nothing for I2C2. Specifying the pins (instead of using I2C1/2) makes no difference. Even if I remove the SSP1 channel, no code for SSP2 is generated. Anyone know why? (PIC18F6723, Compiler version 4.083)

Russ
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Feb 19, 2010 12:47 am     Reply with quote

Did you enter the stream ID as parameter in all the i2c routines ?
Did you create copies of the variables associated with the #int_ssp
routine when you made the #int_ssp2 routine ?
Try that and look at the .LST file again.

Example:
Code:

#include <18F6723.h>
#fuses XT,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

#use i2c (slave, I2C1, address=0xA0, FORCE_HW, stream=IC_PHASE)
#use i2c (slave, I2C2, address=0xA2, FORCE_HW, stream=IC_MAG)

BYTE address, buffer[0x10];
BYTE address2, buffer2[0x10];

//-------------------------------
#INT_SSP
void ssp_interrupt()
{
   BYTE incoming, state;

   state = i2c_isr_state(IC_PHASE);
   
   if(state <= 0x80)     // Master is sending data
   {
      incoming = i2c_read(IC_PHASE, 1);
      if(state == 1)     // First received byte is address
         address = incoming;
      if(state == 2)     // Second received byte is data
         buffer[address] = incoming;
   }
   if(state == 0x80)     // Master is requesting data
   {
      i2c_write(IC_PHASE, buffer[address]);
   }
}

//-------------------------------
#INT_SSP2
void ssp2_interrupt()
{
   BYTE incoming, state;

   state = i2c_isr_state(IC_MAG);
   
   if(state <= 0x80)     // Master is sending data
   {
      incoming = i2c_read(IC_MAG, 1);
      if(state == 1)     // First received byte is address
         address2 = incoming;
      if(state == 2)     // Second received byte is data
         buffer2[address2] = incoming;
   }
   if(state == 0x80)     // Master is requesting data
   {
      i2c_write(IC_MAG, buffer2[address2]);
   }
}

//======================================
void main ()
{
enable_interrupts(INT_SSP);
enable_interrupts(INT_SSP2);
enable_interrupts(GLOBAL);

while(1);
}
russk2txb



Joined: 30 Mar 2008
Posts: 109
Location: New Jersey

View user's profile Send private message

PostPosted: Fri Feb 19, 2010 7:21 am     Reply with quote

Yes, that is exactly what I did, except that the 'guts' of the interrupt routines are different. That is because the i2c data that I am receiving always contains 3 bytes, the address, a sub address and then the data byte. The routine works perfectly for ssp1, but if I set a breakpoint in ssp2 it is never reached.

As I said, no init data is generated for ssp2. Here is the code:

Code:

.................... #use i2c (slave, I2C1, address=0xA0, FORCE_HW, stream=IC_PHASE)
*
0434C:  MOVF   FC9,W
0434E:  MOVFF  2DA,FC9
04352:  BSF    FC6.4
04354:  BCF    F9E.3
04356:  BTFSC  FC7.0
04358:  BRA    4356
0435A:  CLRF   01
0435C:  BTFSC  FC6.4
0435E:  INCF   01,F
04360:  GOTO   43A6 (RETURN)
.................... #use i2c (slave, I2C2, address=0xA2, FORCE_HW, stream=IC_MAG)
.................... #use spi (DI=PIN_C1, DO=PIN_C5, CLK=PIN_C0, MODE=0, stream=SPI_PORT)
*
010C0:  MOVLB  4
010C2:  MOVF   x23,W
010C4:  SUBLW  20
010C6:  BZ    10D6
...

Notice that no code is emitted for the second #use i2c statement. I tried removing the use spi statement but still no ssp2 code. I think this issue has to be resolved before worrying about whether the interrupt routines work or not. I did some searching in this forum and found postings where the ssp2 init code was wrong in earlier compilers, in that it was using some of the variables for ssp1. But that was supposedly fixed in compiler version 4.017, and there was no mention of failure to emit init code.

Russ
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Feb 19, 2010 12:39 pm     Reply with quote

I installed vs. 4.083 and compiled the program that I posted above.
Here is the start of the .LST file. I compiled it just now:
Code:

CCS PCH C Compiler, Version 4.083, xxxxx        19-Feb-10 10:38

               Filename: PCH_Test.lst

               ROM used: 502 bytes (0%)
                         Largest free fragment is 65536
               RAM used: 62 (2%) at main() level
                         66 (2%) worst case
               Stack:    2 worst case (0 in main + 2 for interrupts)


Then I look in the .LST file, and go down to the #use i2c() statements.
It shows there is code for both statements:
Code:

.... #use i2c (slave, I2C1, address=0xA0, FORCE_HW, stream=IC_PHASE) 
000B2:  MOVF   FC9,W
000B4:  MOVFF  41,FC9
000B8:  BSF    FC6.4
000BA:  BCF    F9E.3
000BC:  BTFSC  FC7.0
000BE:  BRA    00BC
000C0:  CLRF   01
000C2:  BTFSC  FC6.4
000C4:  INCF   01,F
000C6:  GOTO   0128 (RETURN)
.... #use i2c (slave, I2C2, address=0xA2, FORCE_HW, stream=IC_MAG) 
*
0012E:  MOVF   F66,W
00130:  MOVFF  41,F66
00134:  BSF    F63.4
00136:  BCF    FA4.7
00138:  BTFSC  F64.0
0013A:  BRA    0138
0013C:  CLRF   01
0013E:  BTFSC  F63.4
00140:  INCF   01,F
00142:  GOTO   01A4 (RETURN)
.................... 
russk2txb



Joined: 30 Mar 2008
Posts: 109
Location: New Jersey

View user's profile Send private message

PostPosted: Tue Feb 23, 2010 10:19 am     Reply with quote

Ok, Thanks. I had to take a break from this for a few days, but today I compiled your source and indeed it does supply init code for both I2C streams. I started putting my code into the test program and when I put in the interrupt routines the init code dissappeared. I finally figured out what was going on. The init code is generated ONLY if the program contains an I2C_WRITE call. I had not got around to coding that yet in my SSP2 code and so the init code was not generated. And it turns out that you don't need that init code if all you are doing is reading.

I had got to that point (of looking at the init code) when trying to figure out why SSP2 interrupts are not working. It turned out to be a dead end because once I added the I2C write call and got init code, the interrupt still does not work. It works fine for SSP1 though.

I have the I/O lines for IC21 and IC22 tied in parallel (one bus). Is there any reason that would not work? Interrupt and all other code for IC21 and IC22 code is identical (except for the stream identifier). Both interrupts are enabled.

I do have one possible clue. I have the following #use spi statements after my two #use I2C statements:
Code:

#use spi (DI=PIN_C1, DO=PIN_C5, CLK=PIN_C0, MODE=0, stream=SPI_PORT)
#use spi (DO=PIN_E0, CLK=PIN_E1, MODE=0, stream=SYN_PORT)


Then in my main function:
Code:

  setup_spi (SPI_MASTER | SPI_L_TO_H | SPI_XMIT_L_TO_H | SPI_CLK_DIV_16);

If the above line is not commented out, then neither of the I2C channels will get an interrupt. If it is commented out then the SSP1 I2C channel works properly. Note that the 2 SPI channels are for software SPI and do not use the hardware pins. Am I setting up the SPI interfaces properly? They seem to work...

Do you have any suggestions?

Thanks, Russ
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Feb 23, 2010 12:08 pm     Reply with quote

Quote:

I have the following #use spi statements after my two #use I2C statements:
Code:
#use spi (DI=PIN_C1, DO=PIN_C5, CLK=PIN_C0, MODE=0, stream=SPI_PORT)
#use spi (DO=PIN_E0, CLK=PIN_E1, MODE=0, stream=SYN_PORT)

Then in my main function:
Code:
setup_spi (SPI_MASTER | SPI_L_TO_H | SPI_XMIT_L_TO_H | SPI_CLK_DIV_16);

setup_spi() always uses the hardware MSSP module. That's the same
hardware that is used by your #use i2c(I2C1... ) library code. Therefore
if you call setup_spi(), you are taking the 1st MSSP channel away from
the i2c bus. That's why your i2c doesn't work. Delete the setup_spi()
statement.
russk2txb



Joined: 30 Mar 2008
Posts: 109
Location: New Jersey

View user's profile Send private message

PostPosted: Tue Feb 23, 2010 1:46 pm     Reply with quote

Ok, then I assume that setup_spi is not to be used with #use spi, one or the other - correct? It would be nice if the compiler manual indicated that. Hmm, went back and reread the info on setup_spi. It says "This function is only available on devices with SPI hardware". I guess that's a round about way of saying "don't use it for software SPI".

I changed over from hardware to software SPI so I could use both hardware channels for I2C slave mode and commented out the setup_spi line, but in all the trying I forgot why it was commented out and tried to enable it again.

That takes care of that, but still no idea why my second I2C channel will not interrupt???

Thanks, Russ
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Feb 23, 2010 1:51 pm     Reply with quote

Write a short test program for the Slave PIC that only contains code for
the 2nd hardware i2c channel. Also, write a test program for the Master
PIC that only talks to the 2nd i2c channel on the Slave board.

Don't include any code (such as #use statements) for the first i2c channel.
Isolate the problem to the 2nd channel.

Test it. If it fails, then post the Master and Slave programs.
russk2txb



Joined: 30 Mar 2008
Posts: 109
Location: New Jersey

View user's profile Send private message

PostPosted: Wed Feb 24, 2010 8:34 am     Reply with quote

Thanks for the suggestion. Over the years I have become less and less dependent on debugging code by such means as inserting test statements and writing simplified programs. I guess it is because the VC++ debugger is so good. So I never thought to try that.

Once I did that both interrupts worked. Then I started adding my code back in and found that when I added #int_ext HIGH, that was when I2C2 stopped working. Changing to using normal priority interrupts, including removing the line "#device HIGH_INTS=true", solved the problem.

Now the question; why? Reading documentation I can see no reason why this should happen.

Thanks, Russ
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