|
|
View previous topic :: View next topic |
Author |
Message |
russk2txb
Joined: 30 Mar 2008 Posts: 109 Location: New Jersey
|
SSP2 problem |
Posted: Thu Feb 18, 2010 6:13 pm |
|
|
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
|
|
Posted: Fri Feb 19, 2010 12:47 am |
|
|
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
|
|
Posted: Fri Feb 19, 2010 7:21 am |
|
|
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
|
|
Posted: Fri Feb 19, 2010 12:39 pm |
|
|
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
|
|
Posted: Tue Feb 23, 2010 10:19 am |
|
|
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
|
|
Posted: Tue Feb 23, 2010 12:08 pm |
|
|
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
|
|
Posted: Tue Feb 23, 2010 1:46 pm |
|
|
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
|
|
Posted: Tue Feb 23, 2010 1:51 pm |
|
|
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
|
|
Posted: Wed Feb 24, 2010 8:34 am |
|
|
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 |
|
|
|
|
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
|