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 works fine when ICD is plugged in, but not without

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



Joined: 27 Mar 2006
Posts: 5

View user's profile Send private message

I2C works fine when ICD is plugged in, but not without
PostPosted: Tue Mar 28, 2006 10:55 am     Reply with quote

I can Write any 16-bit word to the slave and Read it back just fine on the master when the ICD is plugged in to the slave board. But when I unplug the ICD from the slave board, I Read FFFF. The slave is a 16F877A running at 20Mhz and the master is a 18F252 running at 10Mhz. Whether the ICD program is launched or closed, I get this same result. Any ideas?

Slave Code

Code:
i2c 16-BIT SLAVE CODE

// Author: valemike

#define UNIT_TEST

// Assumes PIC18F4525 @ 10MHz

#ifdef UNIT_TEST
//#include <18f4525.h>
#include <16F877A.h>

#fuses HS,NOLVP,NOWDT,PUT

// Pins

// RS-232
#define RX_PIN PIN_C7
#define TX_PIN PIN_C6

// config

#use delay(clock=20000000, restart_wdt)
#use rs232(baud=9600, xmit=TX_PIN, rcv=RX_PIN) //+++ up baud rate?
//#use rs232(DEBUGGER)
void main (void);

#endif // UNIT_TEST

// Prototypes

unsigned char read_i2c(void);
void i2c_interrupt_handler(void);
void i2c_initialize(void);
void i2c_error(unsigned int temp_sspstat);
void write_i2c(unsigned char transmit_byte);
void toggle_light(void);
void wait_for_bf_low(void);

#INT_SSP
void ssp_interupt ()
{
i2c_interrupt_handler();
}

/* PIC Registers */
#byte PIC_SSPBUF=0x13
#byte PIC_SSPADD=0x93
#byte PIC_SSPSTAT=0x94
#byte PIC_SSPCON1=0x14
#byte PIC_SSPCON2=0x91

#byte PIC_PIE1 = 0x8c
#byte PIC_TRISC = 0x87



/* Bit defines */
#define PIC_SSPSTAT_BIT_SMP 0x80
#define PIC_SSPSTAT_BIT_CKE 0x40
#define PIC_SSPSTAT_BIT_DA 0x20
#define PIC_SSPSTAT_BIT_P 0x10
#define PIC_SSPSTAT_BIT_S 0x08
#define PIC_SSPSTAT_BIT_RW 0x04
#define PIC_SSPSTAT_BIT_UA 0x02
#define PIC_SSPSTAT_BIT_BF 0x01

#define PIC_SSPCON1_BIT_WCOL 0x80
#define PIC_SSPCON1_BIT_SSPOV 0x40
#define PIC_SSPCON1_BIT_SSPEN 0x20
#define PIC_SSPCON1_BIT_CKP 0x10
#define PIC_SSPCON1_BIT_SSPM3 0x08
#define PIC_SSPCON1_BIT_SSPM2 0x04
#define PIC_SSPCON1_BIT_SSPM1 0x02
#define PIC_SSPCON1_BIT_SSPM0 0x01

#define PIC_SSPCON2_BIT_GCEN 0x80
#define PIC_SSPCON2_BIT_ACKSTAT 0x40
#define PIC_SSPCON2_BIT_ACKDT 0x20
#define PIC_SSPCON2_BIT_ACKEN 0x10
#define PIC_SSPCON2_BIT_RCEN 0x08
#define PIC_SSPCON2_BIT_PEN 0x04
#define PIC_SSPCON2_BIT_RSEN 0x02
#define PIC_SSPCON2_BIT_SEN 0x01

/* Parameters */

#define RX_BUF_LEN 8 //8 //32
#define LOGBUF_MASK 0x07
#define NODE_ADDR 0x02 /* I2C address of the slave node (avoid addr masking) */

unsigned char slave_buffer[RX_BUF_LEN];

int buffer_index;
int comms_error;
int debug_state;

void i2c_initialize(void)
{
debug_state = 0;

/* Set up SSP module for 7-bit */
while (PIC_SSPCON2 & 0x1f) {
// ACKEN RCEN PEN RSEN SEN all must be zero
};
PIC_SSPSTAT = 0x00; /* Clear the SSPSTAT register. */
PIC_SSPCON1 = 0x36; /* 0011 0101 */
PIC_SSPADD = NODE_ADDR; /* Set the slave's address */
/* init buffers */
buffer_index = 0;
/* Go */
enable_interrupts(INT_SSP); /* Enable MSSP interrupts. */
}

void i2c_interrupt_handler(void)
{

unsigned char i2c_mask = 0x2D; /* 0010 1101 */
unsigned char temp_sspstat;
unsigned char this_byte;
unsigned char tx_byte;
int x;

//toggle_light(); //DBG

/* log SSPSTAT */

/* Mask out the unnecessary bits */
temp_sspstat = PIC_SSPSTAT & i2c_mask;

switch (temp_sspstat) {
/* Write operation, last byte was an address, buffer is full */
case 0x09: /* 0000 1001 */
/* Clear the receive buffer */
for (x=0; x<RX_BUF_LEN; x++)
{
slave_buffer[x] = 0x00;
}
buffer_index = 0; /* Clear the buffer index */
this_byte = read_i2c(); /* Do a dummy read of PIC_SSPBUF */

debug_state = 1;
break;

/* Write operation, last byte was data, buffer is full */
case 0x29: /* 0010 1001 */
/* Point to the buffer */
this_byte = read_i2c(); /* Get the byte from the SSP */
slave_buffer[buffer_index] = this_byte; /* Put it into the buffer */
buffer_index++; /* Increment the buffer pointer */
#ifdef I2C_DAEMON
// If enough data is in, this would move it to application's double buffer
i2c_double_buffer_daemon();
#endif // I2C_DAEMON
/* Get the current buffer index */
/* Subtract the buffer length */
/* Has the index exceeded the buffer length? */
if (buffer_index >= RX_BUF_LEN)
{
buffer_index = 0; /* Yes, clear the buffer index. */
}
debug_state = 2;
break;

/* Read operation; last byte was an address, buffer is empty */
case 0x0C: /* 0000 1100 */
label_0c:
buffer_index = 0; /* Clear the buffer index */
/* Point to the buffer */
tx_byte = slave_buffer[buffer_index]; /* Get byte from the buffer */
write_i2c(tx_byte); /* Write the byte to PIC_SSPBUF */
buffer_index++; /* increment the buffer index */
debug_state = 3;
break;

/* Read operation; last byte was data, buffer is empty */
case 0x2C: /* 0010 1100 */
/* Get the current buffer index */
/* Subtract the buffer length */
/* Has the index exceeded the buffer length? */
if (buffer_index >= RX_BUF_LEN)
{
buffer_index = 0; /* Yes, clear the buffer index */
}
/* Point to the buffer */
/* Get the byte */
tx_byte = slave_buffer[buffer_index];
write_i2c(tx_byte); /* Write to PIC_SSPBUF */
buffer_index++; /* increment the buffer index */
debug_state = 4;
break;

/* A NACK was received when transmitting data back [to] the master. */
/* Slave logic is reset in this case. R_W=0, D_A=1, and BF=0. */
/* If we don't stop in this state, then something is wrong!! */
case 0x28: /* 0010 1000 */
debug_state = 5;
break;

/* Read operation; last byte was address, buffer is full */
case 0x0d:
this_byte = read_i2c(); // Do a dummy read of PIC_SSPBUF to clear it
wait_for_bf_low();
goto label_0c; // reduced to the normal case
/* Something went wrong!! */
default:
debug_state = 0xe;
break;
}
//red_light(); //DBG
}

unsigned int error_sspstat;

void i2c_error(unsigned int temp_sspstat)
{
comms_error = 1;
error_sspstat = temp_sspstat;
}

void write_i2c(unsigned char transmit_byte)
{
unsigned char write_collision = 1;

while (PIC_SSPSTAT & PIC_SSPSTAT_BIT_BF) /* Is BF bit set in PIC_SSPSTAT? */
{
/* If yes, then keep waiting */
}

while (write_collision)
{
/* If not, then do the i2c_write. */
PIC_SSPCON1 &= ~PIC_SSPCON1_BIT_WCOL; /* Clear the WCOL flag */
PIC_SSPBUF = transmit_byte;

/* Was there a write collision? */
if (PIC_SSPCON1 & PIC_SSPCON1_BIT_WCOL)
{
/* Yes there was a write collision. */
write_collision = 1;
}
else
{
/* NO, there was no write collision. */
/* The transmission was successful */
write_collision = 0;
}
}
PIC_SSPCON1 |= PIC_SSPCON1_BIT_CKP; /* Release the clock. */
}

/* This function returns the byte in SSPBUF */
unsigned char read_i2c(void)
{
return PIC_SSPBUF;
}

#ifdef UNIT_TEST
void main (void)
{
debug_state = 0;
i2c_initialize();
enable_interrupts(GLOBAL);

main_loop:
//while (1)
{
if (debug_state)
{
debug_state = 0;
}
goto main_loop;
}
}
#endif // UNIT_TEST

void wait_for_bf_low(void)
{
bf_loop:
if (PIC_SSPSTAT & 0x1) { //BF=1
goto bf_loop;
}
else {
}
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Mar 28, 2006 1:03 pm     Reply with quote

1. Does this problem happen only with this program, or does it happen
with any program that you put in the 16F877A ?

2. Does the ICD supply power to your board ? In other words, when
you unplug the ICD, are you removing the power source for the board ?

3. I don't see it in your program, but do you have the "DEBUG" fuse
enabled ? In other words, you want to run the program in
standalone mode. Are you accidently still trying to run it in debug
mode ?
Ken481



Joined: 27 Mar 2006
Posts: 5

View user's profile Send private message

Problem Resolved
PostPosted: Thu Mar 30, 2006 8:04 am     Reply with quote

I found out what the problem was:
The two PICs needed to share a common signal reference i.e.- common ground. I am using two seperate boards each with it's own power supply. The two boards had only the two I2C wires (SDA and SCL) in common. The CCS ICD-U40 was providing a common voltage reference between the two boards, when it was connected to either board, allowing the I2C the work properly.

When the ICD was disconnected, the SDA and SCL pins floated to a high state and the I2C communications no longer worked. The problem was resolved by adding a 3rd wire connected to the ground of each board.

In my final application, the two boards will be using the same power supply anyway (12V sealed battery) so the 3rd wire shouldn't be necessary.

Thanks for your thoughts on this, PCM programmer

-Ken 481
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