|
|
View previous topic :: View next topic |
Author |
Message |
Barney
Joined: 18 Oct 2004 Posts: 41 Location: Newark, CA
|
i2c_write side effect? |
Posted: Thu Sep 21, 2006 8:24 am |
|
|
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
|
|
Posted: Thu Sep 21, 2006 8:40 am |
|
|
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
|
|
Posted: Thu Sep 21, 2006 11:37 pm |
|
|
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
|
Complier Bug? |
Posted: Sun Sep 24, 2006 3:49 pm |
|
|
To close out this thread, I finally found the problem, likely a complier bug. In the listing file, there is a statement
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
|
|
|
|
|
|
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
|