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 - slave State 6??

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







I2C - slave State 6??
PostPosted: Tue Feb 25, 2003 2:06 pm     Reply with quote

Hi all..
I am trying to implement a one master(16F877) multi-slave (16F872/876) and I am using some code I got off of here to test with.. I get a sucessful write and read of a set of numbers back from the slave to the master for the first set of numbers, then on the second set of numbers the slave goes into the "default case" and hangs. The SSPTEST = 0x20 at this point (STATE #6?? = D/A = DATA, Start not detected).

Any clues why it is bombing at this point? And why it did not do this for the first iteration of numbers?

Below is the slave code:

#include <16F876x.h>
#priority ssp
#use delay(clock=3686400)
#fuses HS,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP
#use fast_io(b) // For testing
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)





#define SLAVE_ADDR 0x40 // Even number, must match address sent by Master
// Read address from Master is Slave address + 1.

#define BUF_LEN 32
int buf[BUF_LEN]; // Buffer for data to be received or transmitted
int buf_index;

/* Possible i2c states, SSPSTAT for the four relevant bits */
#define STATE1 0x09 // D/A=0,S=1,R/W=0,BF=1. Master tx, slave addr
#define STATE2 0x29 // D/A=1,S=1,R/W=0,BF=1. Master tx, data
#define STATE3 0x0C // D/A=0,S=1,R/W=1,BF=0. Master rx, slave addr+1
#define STATE4 0x2C // D/A=1,S=1,R/W=1,BF=0. Master rx, data with /ack
#define STATE5 0x28 // D/A=1,S=1,R/W=0,BF=0. Master rx, data with not /ack

/* i2c interrupt handler */
#int_SSP
SSP_isr()
{
int8 ssptest, ssp;

PORTBbits.RB1 = 1; // Show that we are in an interrupt

PIR1.SSPIF = FALSE; // Clear the SSP interrupt flag as last thing
if (PIR2.BCLIF == TRUE) // Check if bus collision error & clear
{

PIR2.BCLIF = FALSE;
// set error flag of some kind here

}


ssp = SSPSTAT;
ssptest = (ssp & 0x2D);

switch (ssptest) // Keep only bits D/A, S, R/W, BF
{


case(STATE1):
/* Master write operation, address byte in SSPBUF */

/* Clear the data buffer */
for (buf_index = 0; buf_index < BUF_LEN; buf_index++)
{
buf[buf_index] = 0;
}

buf_index = 0; // Reset the data buffer index
SSPCON.SSPOV = 0; // Clear address overflow flag, could be set from last
// time because after not /ack, SSPBUF was still full.
buf[buf_index] = SSPBUF; // Dummy read to clear BF (read only bit)
break;


case(STATE2):
/* Master write operation, data byte in SSPBUF */


/* Get data byte (also clears BF) */
SSPCON.SSPOV = 0;
buf[buf_index] = SSPBUF;
output_b(buf[buf_index]); // For debugging
buf_index++;

/* Wrap around, should never occur */
if (buf_index > BUF_LEN) buf_index = 0;
break;


case(STATE3):
/* Master has begun new read operation by initiating a START or RESTART
then sending Slave address (read) byte (now in SSPBUF).
Looks like clock enable bit CKP cleared on interrupt, so must
set it again to allow Master to clock data byte out
*/

/* SCL held low, Master can be kept waiting here if necessary */
// delay_ms(5000); // For testing clock stretching only

buf_index = 0; // Reset buffer index
SSPBUF = buf[buf_index]; // Load 1st byte from data buffer
SSPCON.CKP = 1; // Releases "Clock Low" hold & Enables Master to clock data in
buf_index++;
break;


case(STATE4):
/* Master read operation, last byte was data, SSPBUF empty */
/* Move next byte to SSPBUF and SSPSR. Same comment for CKP bit as in STATE3. */


SSPBUF = buf[buf_index]; // Get next byte from data buffer
SSPCON.CKP = 1; // Releases "Clock Low" hold & Enables Master to clock data in
buf_index++;

if (buf_index > BUF_LEN) buf_index = 0;
break;

case(STATE5):
/* A not /ack (high) was received from Master in response to data
byte received from Slave (last byte). Slave i2c logic is reset,
and waits for next Master operation. */
break;

default:
/* Error, trap here. Watchdog will reset pic (must be enabled, and
watchdog timer cleared in other loops) */
printf("SSP ERR\r\n");
printf("SSPTEST = \%X\r\n",ssptest);
PORTCbits.RC2 = 1; //turn on COMM LED if I got here
while(1);
break;
} // end of switch/case

PORTBbits.RB1 = 0;
// printf("\%X ",SSPBUF);






} // end of SSP_ISR


// Example set up functions:
void init_i2c()
{
PORTB = 0x00;
PORTC = 0x00; // Set SDA, SCL low
SSPCON = 0b00110110; // i2c slave mode, 7-bit address
SSPADD = SLAVE_ADDR; // Set slave address
TRISC = 0x18; // Set SCL and SDA as inputs
}


void main()
{
int i;
set_tris_b(0b11111001); // Set port b for output for debugging
set_tris_c(0b10011011);
init_i2c();
enable_interrupts(int_ssp);
disable_interrupts(INT_RTCC);
disable_interrupts(INT_EXT);
disable_interrupts(INT_TBE);
disable_interrupts(INT_RDA);
disable_interrupts(INT_TIMER1);
disable_interrupts(INT_TIMER2);
enable_interrupts(global);
while(1);
}


//==================================

// Master Code:
/**************************************************************************/
/* Example program for testing i2c slave pic. This i2c master outputs i2c
data to slave pic, then reads it back to port b for viewing.
Bit A0 is toggled to show program is cycling */

#include <16F877x.h>
#use delay(clock=3686400)
#fuses HS,NOWDT,PUT,NOLVP // Enable watchdog when debugging complete
#use i2c(master,sda=PIN_C4,scl=PIN_C3)
#define SLAVE_ADDR 0x40 // Even number, address to be sent to slave pic,
// must match. Note read address is slave address + 1.

#byte PORTC = 0x07

#define TEST_LED PIN_B2 // Used to confirm pic is cycling

void init_i2c() {
PORTC = 0; // Set SDA, SCL low
output_float(pin_C3);
output_float(pin_C4);
}

void main() {
int i; // Index to receive buffer
int rxbuf[32]; // Buffer for data received back from the slave pic
setup_spi(FALSE);
set_tris_b(0x00); // Port b output
init_i2c();

/* Program loops forever */
while(1) {
delay_ms(500);
output_bit(TEST_LED,1);

/* Clear the Master receive buffer */
for(i=0;i<32;i++) {
rxbuf[i] = 0;
}

/* Send some numbers to the slave pic buffer. Slave buffer is
cleared each time round */
i2c_start();
i2c_write(SLAVE_ADDR); // Must match address of slave pic

for (i=0;i<=20;i++) {
i2c_write(i);
}

/* Now read back the numbers without releasing i2c bus */
i2c_start();
i2c_write(SLAVE_ADDR + 1); // Slave read address

for(i=0;i<=19;i++) {
rxbuf[i] = i2c_read(); // Note that Slave may be delaying response
// by holding SCL low. Apparently i2c_read()
// monitors SCL and takes care of this.
}

rxbuf[20] = i2c_read(0); // Last one nack (high), resets slave i2c
// logic. Very important, i2c bus will hang
// otherwise.
i2c_stop(); // Release the i2c bus

/* Output the numbers from the receive buffer to port b for viewing.
Should be counting up. */
for(i=0;i<=20;i++) {
output_b(rxbuf[i]);
delay_ms(300);
}

delay_ms(500);
output_bit(TEST_LED,0);
}
}
___________________________
This message was ported from CCS's old forum
Original Post ID: 12095
john Goss
Guest







Re: I2C - slave State 6?? - update
PostPosted: Tue Feb 25, 2003 3:11 pm     Reply with quote

So far I have found it has something to do with the releasing of the bus. Before, the master wrote numbers to the slave and then read them back without releasing the bus. I installed a i2c_stop() after I loaded the numbers and then did a i2c_start() before reading them and it bombed...it would not read during the first go around now.

I'm still plugging away scratching my head!
___________________________
This message was ported from CCS's old forum
Original Post ID: 12098
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