|
|
View previous topic :: View next topic |
Author |
Message |
Ringo42
Joined: 07 May 2004 Posts: 263
|
I2C weirdness |
Posted: Fri Aug 08, 2008 11:02 am |
|
|
I'm using the latest compiler (4.077?) and a PIC 18F452.
I'm talking to the pic using I2C. I'm sending it data about every 30-40ms. There are 7 identical setups on the bus(except for address). After a few minutes the one or 2 of the boards will randomly stop responding. Timer 2 is still firing, and the Serial interrupt still works. I put in some code so that after it quits responding I send a serial packet to the board and it responds with the data in the I2C buffer. It seems that whenever it gets in this condition then all the data in the buffer is the same, it is the address of the PIC.
Code: | #INT_SSP
void ssp_interupt()
{
int i;
BYTE incoming, state;
// int pinnumber,pinstate;
state = i2c_isr_state();
currentstate=1;
if(state < 0x80) //Master is sending data
{
incoming = i2c_read();
buffer[bytecounter]=incoming;
bytecounter++;
if(bytecounter ==7 ) //First received byte is address
{
bytecounter=0;
if(buffer[1]==16) //PWM
{
bigcounter++;
// printf("pwm %ld\r\n",bigcounter);
ramp=buffer[2];
ID1 =buffer[3];
pwm1=buffer[4];
ID2 =buffer[5];
pwm2=buffer[6];
// sprintf(SERIAL_BUFFER,"pwm r:%d %d:%d %d:%d\0",ramp,ID1,pwm1,ID2,PWM2);
sprintf(SERIAL_BUFFER,"pwm %d:%d %d:%d\0",ID1,pwm1,ID2,PWM2);
pwm();
if(debug==1)
printf("%s",SERIAL_BUFFER);
}
else {}
}
if(bytecounter>7)// too many bytes, something is wrong
{
bytecounter=0;
return;
}
}
if(state == 0x80) //Master is requesting data
{
for(i=0;i<15;i++)
{
delay_ms(1);
// i2c_write(values[i]);
}
actionflag=1; //0 = nothing, 1 = read, 2 = change address
bytecounter=0;
}
currentstate=2;
} |
So when I get a serial packet I'm doing this
Code: | printf("bytecounter = %d \r\n",bytecounter);
for(i=0;i<7;i++)
printf("buffer%d = %d \r\n",i,buffer[i]); |
and it comes back with something like
buffer0 = 68
buffer1 = 68
buffer2 = 68
buffer3 = 68
buffer4 = 68
buffer5 = 68.... and 68 is the address to the board.
So to me it looks like
incoming = i2c_read(); is always returning the same thing (after it gets in this weird mode)
Any idea what would cause this?
Or any way to get out of it if I detect I'm in it?
It works for anywhere from 30 seconds to 30 minutes then a board will randomly get this way. resetting the board brings it back to operational.
Any help will be greatly appreciated. _________________ Ringo Davis |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Aug 08, 2008 11:23 am |
|
|
I don't really know, but just scanning your code, it has massive delays
throughout the isr. It has sprintf, printf, delay_ms() in a loop, and it calls
a pwm() routine.
I would start by commenting all of these massive delays, and then see
if you still get the lockup. Get rid of that loop. Change it so it just
transmits one byte. In other words, strip down the program to the
minimum and test it. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Fri Aug 08, 2008 11:29 am |
|
|
From the release notes: Quote: | 4.077 Some problems with slave I2C have been fixed, see the newest EX_SLAVE.C |
I haven't checked the changes CCS made to i2c_isr_state function but looking at the new ex_slave.c example it requires a (minimal) change to your ISR function.
Code: | if(state < 0x80) //Master is sending data
| to: Code: | if(state <= 0x80) //Master is sending data
|
|
|
|
Ringo42
Joined: 07 May 2004 Posts: 263
|
|
Posted: Fri Aug 08, 2008 11:34 am |
|
|
Thanks, I'll make minor change using the <= and I'll start stripping out stuff and see if minimal code works ok.
Ringo _________________ Ringo Davis |
|
|
Ringo42
Joined: 07 May 2004 Posts: 263
|
|
Posted: Sat Aug 09, 2008 1:09 pm |
|
|
The new ex_slave shows
Code: | The latest version of ex_slave.c has something I don't understand.
if(state <= 0x80) //Master is sending data
{
incoming = i2c_read();
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(buffer[address]);
}
|
How can it be master sending if it is <=80 and
master requesting if it is =80
80 would trigger both, is this correct?
I took out all the delay stuff now It has been running for about an hour with no issues, so I'm hoping it is fixed.
It would be nice however to have code in place so that if it happens again it can correct itself. Is there a way to reset the I2C port without resetting the entire pic?
Thanks
Ringo _________________ Ringo Davis |
|
|
Ttelmah Guest
|
|
Posted: Sat Aug 09, 2008 3:12 pm |
|
|
If I2C_ISR_STATE, returns '0x80', then the slave has _received_ the address byte, from the master saying 'I want to read'.
Basically, for the master writing, the first time through, the state will be '0', corresponding to the I2C address byte saying 'I want to write' this results in a read, and nothing else. Then the next time, the state will be '1', which results in the read byte being stored as the internal address to talk to. Then a '2', results in the data being transferred to this address.
For the reading, state 0, says 'I want to read', but still needs to the address byte to be read from the input register. Then after this is read, the new byte wanted has to be read from the local memory, and written to the register, ready for the master to read it.
As shown, the code example is only capable of handling a single byte, not allowing automatic incrementing for states 81, 82 etc..
Code: |
I2C_ISR_STATE Byte to be read Byte to be written
0 Yes No
1 Yes - I2C Address No
2 Yes - data No
3 Yes - data No
.....
0x80 Yes - I2C Address Yes
0x81 No Yes
.......
|
The code takes advantage of the first part to automatically perform the reads for state 0, and 80, but just ignores the data read.
Best Wishes |
|
|
Ringo42
Joined: 07 May 2004 Posts: 263
|
|
|
|
|
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
|