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 CCS Technical Support

i2c_write side effect?

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



Joined: 18 Oct 2004
Posts: 41
Location: Newark, CA

View user's profile Send private message

i2c_write side effect?
PostPosted: Thu Sep 21, 2006 8:24 am     Reply with quote

I am developing I2C slave code and am experimenting with the CCS functions & PIC variables. I created a very simple slave transmitter program that sends a series of characters to a master. The I2C function works fine, but somehow the characters in the character string are changed. I have pulled my hair out trying to figure out why, but haven't been able to.

The master issues a read command to the slave, reads out 10 characters, sends the NAK and then a STOP. This works fine and the master receives "ABCDEFGHIJ". But on the second pass, instead of getting the expected string, the master receives "@BBDD.FGGH". On each subsequent read the same bogus string is received.

The basic code is posted below. I have tried versions where I write the string to EEPROM which verified that the i2c_write function is changing the characters as each one is transmitted to the master. Also if I add a strcpy(mystr, "ABCDEFGHIJ"); statement in the reset counter section, the correct characters are sent each time.

I am using PCM-3.212.

Code:

#include <16F87.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP, INTRC_IO
#use delay(clock=8000000)
#use i2c(SLAVE, SDA=PIN_B1, SCL=PIN_B4, address=0xa0, FORCE_HW)

#byte SSPSTAT=0x94


int cntr;
int mystr[10];

#INT_SSP
void ssp_interupt ()
{
   if (SSPSTAT & 0x04) {   //master sent  NAK or STOP ?
     i2c_write(mystr[cntr]);  //no, send character
     cntr++;
   }
   else {      // yes, reset counter
     cntr = 0;
   }
}

void main ()
{
   
   strcpy(mystr, "ABCDEFGHIJ");
   enable_interrupts(GLOBAL);
   enable_interrupts(INT_SSP);
   cntr = 0;
   while (TRUE) {
  }
}


Thanks,
Ttelmah
Guest







PostPosted: Thu Sep 21, 2006 8:40 am     Reply with quote

The first big error I can see, is that 'mystr' is not large enough. A string, requires the length of the characters _plus one_, for the terminating '\0'. As such, the string copy, will be overwriting the next location in RAM, which may cause all sorts of problems...
The second 'glaring error', is in the masking of the SSPSTAT register. SSPSTAT & 4, checks bit 2 of the SSPSTAT register, which is the R/W status bit, not the 'stop' bit. The stop bit, is _bit 4_, which is SSPSTAT & 0x10.

Best Wishes
Barney



Joined: 18 Oct 2004
Posts: 41
Location: Newark, CA

View user's profile Send private message

PostPosted: Thu Sep 21, 2006 11:37 pm     Reply with quote

1. My bad on the array length. However even when it is set correctly, I still have the mysterious array re-write problem.

2. I ran a number of trials looking at the status registers and found that either a NAK, STOP, or a NAK & STOP from the master sets this bit. I used it because want to catch all I2C termination conditions. The I2C communications itself works fine.

I did some more testing, and the problem does not seem to be a I2C issue, but more likely a compiler bug of some sort. I changed the code to try and localize the problem:

A. I added a local char variable as an intermediary between reading the array and calling the i2c_write() function. The array value was still changed.

B. I used a different counter for the array index and still had the problem.

C. I used a number instead of a variable (ie mystr[0]) for the index and did not have the problem.

D. I added a second array and the problem moved to the second array. The interrupt is shown below. mystr[] remains "ABCDEFGHIJ" and is transmitted to the master OK. However, now stringa[] is changed from "ABCDEFGHIH" to the @BB......

Code:

#INT_SSP
void ssp_interupt ()
{
  int temp;
  int temp1;

   temp = mystr[cntr];
   temp1=stringa[cntr]';
   if (SSPSTAT & 0x04) {   //master sent  NAK or STOP ?
     i2c_write(temp);  //no, send character
     cntr++;
   }
   else {      // yes, reset counter
     cntr = 0;
   }
}



E. I added another array "stringb" and put it as the third assignment in the interrupt routine: temp2 = stringb[cntr]. Now mystr[] & stringa[] are OK, and stringb[] has the bogus characters.

F. I switched the order of stringa and stringb and the bogus problem moved to stringa.

E. I looked at the assemby listing and did not see any smoking gun that was re-writing the array. However there is an address range, 0036 to 004C, that is missing from the list file. I have no idea what is happening in this range.

As best I can tell, the last array referenced is always affected. The effect occurs one character at a time as I move through the array reading each character.
Barney



Joined: 18 Oct 2004
Posts: 41
Location: Newark, CA

View user's profile Send private message

Complier Bug?
PostPosted: Sun Sep 24, 2006 3:49 pm     Reply with quote

To close out this thread, I finally found the problem, likely a complier bug. In the listing file, there is a statement

Code:

BCF 00.0


in the section that is reading the character from the array. Since register 0 is set to point to the current index position in the character array, this clears the LSB and explains why "ABCDEFGHIJ" turns into "@BBDDFFHHJ".

Code:

....................      i2c_write(mystr[cntr]); 
003A:  MOVLW  2A                    2A = address of mystr
003B:  BCF    03.5
003C:  ADDWF  29,W                     29 = address of cntr
003D:  MOVWF  04
003E:  MOVF   00,W
003F:  MOVWF  36
0040:  MOVF   36,W
0041:  MOVWF  13
0042:  BSF    14.4
0043:  BCF    00.0      <<<<< this is the problem !!!!!!!
0044:  BSF    03.5
0045:  BTFSS  14.0
0046:  GOTO   049
0047:  BCF    03.5
0048:  GOTO   044
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