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 support@ccsinfo.com

I2C between 16F877s

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







I2C between 16F877s
PostPosted: Tue Feb 26, 2002 6:30 pm     Reply with quote

I wonder if anyone can help with this problem. I have two 16F877s, one master, one slave. I'm trying to get the master to read two bytes from the slave, with no success. The code is attached below.

I've scoped the I2C bus: it runs uite happily when the slave is disconnected, and you can se the master sending out the slave read address byte and clocking in the two bytes (which aren't actually there in this case). The master acks each byte.

Then I attach the slave. I can see the address byte, with the read bit set, gets sent by the master and acked by the slave. The first byte gets read and acked by the master. But the clock pulses for the second byte are never seen. Both PICs lock up: the matser is supposed to keep flashing a LED from its main loop, but that stops. If I unplug things one by one, it looks like the bus is held low by the slave (?). If I take the slave reset line low, the master starts running again and getting FF bytes back as you'd expect.

Whats going on? Why do the clock pulses for the second byte never appear?

Hope someone can help. Thanks,

Arthur

Arthur Richards
MIT

************* MASTER CODE *****************


#if defined(__PCM__)
#include <16f877.h>
#fuses HS,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=38400, xmit=PIN_C6, rcv=PIN_C7) // Jumpers: 8 to 11, 7 to 12
#use i2c(MASTER, sda=PIN_C4, scl=PIN_C3, SLOW)

#include<stdlib.h>

// between transmitted bytes
#define I2CTXPAUSE 50

// between transmitted address and byte read
#define I2CTXRXPAUSE 1000

// between byte reads
#define I2CRXPAUSE 50

// light flash
#define FLASHTIME 50

void main ()
{

byte firstByte; // I2C received bytes
byte secondByte;

// say hello to the world
printf("MSR001.C\n\r");

// initialise interrupts
//enable_interrupts(GLOBAL);
//enable_interrupts(INT_SSP);

while (TRUE) {

// read packet size back from slave
i2c_start();
delay_us(I2CTXPAUSE);
i2c_write(0xb1);
delay_us(I2CTXRXPAUSE);
firstByte = i2c_read(1);
delay_us(I2CRXPAUSE);
secondByte = i2c_read(0);
delay_us(I2CRXPAUSE);
i2c_stop();
delay_us(I2CTXPAUSE);

output_high(PIN_B5);
delay_ms(FLASHTIME);
output_low(PIN_B5);
delay_ms(FLASHTIME);

} //while (TRUE)
}

******************** SLAVE CODE ****************************


#if defined(__PCM__)
#include <16f877.h>
#fuses HS,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=19200, xmit=PIN_C6, rcv=PIN_C7) // Jumpers: 8 to 11, 7 to 12
#use i2c(SLAVE, sda=PIN_C4, scl=PIN_C3, SLOW, address=0xb0)

#include<stdlib.h>

#define I2CTXPAUSE 10

int i2c_state; // 0 = ready, 1 = got address, 2 = got first command

int reply_state; // 0 = send default, 1 = error, 2 = send buffer byte, 3 = send packet size

byte firstByte; // bytes in I2C message
byte secondByte;

#INT_SSP
void ssp_interupt ()
{

byte gotByte;

if(i2c_poll() == TRUE) {
gotByte = i2c_read(1);
output_b(gotByte);
}
else {
i2c_write('o');
delay_us(I2CTXPAUSE);
i2c_write('k');
delay_us(I2CTXPAUSE);
}
}


void main ()
{

// say hello to the world
printf("Waiting for I2C character\n\r");

// initialise interrupts
enable_interrupts(GLOBAL);
enable_interrupts(INT_SSP);

while (TRUE) {
}
}
___________________________
This message was ported from CCS's old forum
Original Post ID: 2833
Kam Yip
Guest







Re: I2C between 16F877s
PostPosted: Mon Mar 04, 2002 7:20 am     Reply with quote

:=I wonder if anyone can help with this problem. I have two 16F877s, one master, one slave. I'm trying to get the master to read two bytes from the slave, with no success. The code is attached below.
:=
:=I've scoped the I2C bus: it runs uite happily when the slave is disconnected, and you can se the master sending out the slave read address byte and clocking in the two bytes (which aren't actually there in this case). The master acks each byte.
:=
:=Then I attach the slave. I can see the address byte, with the read bit set, gets sent by the master and acked by the slave. The first byte gets read and acked by the master. But the clock pulses for the second byte are never seen. Both PICs lock up: the matser is supposed to keep flashing a LED from its main loop, but that stops. If I unplug things one by one, it looks like the bus is held low by the slave (?). If I take the slave reset line low, the master starts running again and getting FF bytes back as you'd expect.
:=
:=Whats going on? Why do the clock pulses for the second byte never appear?
:=
:=Hope someone can help. Thanks,
:=
:= Arthur
:=
:=Arthur Richards
:=MIT
:=
:=************* MASTER CODE *****************
:=
:=
:=#if defined(__PCM__)
:=#include <16f877.h>
:=#fuses HS,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP
:=#use delay(clock=20000000)
:=#use rs232(baud=38400, xmit=PIN_C6, rcv=PIN_C7) // Jumpers: 8 to 11, 7 to 12
:=#use i2c(MASTER, sda=PIN_C4, scl=PIN_C3, SLOW)
:=
:=#include<stdlib.h>
:=
:=// between transmitted bytes
:=#define I2CTXPAUSE 50
:=
:=// between transmitted address and byte read
:=#define I2CTXRXPAUSE 1000
:=
:=// between byte reads
:=#define I2CRXPAUSE 50
:=
:=// light flash
:=#define FLASHTIME 50
:=
:=void main ()
:={
:=
:= byte firstByte; // I2C received bytes
:= byte secondByte;
:=
:= // say hello to the world
:= printf("MSR001.C\n\r");
:=
:= // initialise interrupts
:= //enable_interrupts(GLOBAL);
:= //enable_interrupts(INT_SSP);
:=
:= while (TRUE) {
:=
:= // read packet size back from slave
:= i2c_start();
:= delay_us(I2CTXPAUSE);
:= i2c_write(0xb1);
:= delay_us(I2CTXRXPAUSE);
:= firstByte = i2c_read(1);
:= delay_us(I2CRXPAUSE);
:= secondByte = i2c_read(0);
:= delay_us(I2CRXPAUSE);
:= i2c_stop();
:= delay_us(I2CTXPAUSE);
:=
:= output_high(PIN_B5);
:= delay_ms(FLASHTIME);
:= output_low(PIN_B5);
:= delay_ms(FLASHTIME);
:=
:= } //while (TRUE)
:=}
:=
:=******************** SLAVE CODE ****************************
:=
:=
:=#if defined(__PCM__)
:=#include <16f877.h>
:=#fuses HS,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP
:=#use delay(clock=20000000)
:=#use rs232(baud=19200, xmit=PIN_C6, rcv=PIN_C7) // Jumpers: 8 to 11, 7 to 12
:=#use i2c(SLAVE, sda=PIN_C4, scl=PIN_C3, SLOW, address=0xb0)
:=
:=#include<stdlib.h>
:=
:=#define I2CTXPAUSE 10
:=
:=int i2c_state; // 0 = ready, 1 = got address, 2 = got first command
:=
:=int reply_state; // 0 = send default, 1 = error, 2 = send buffer byte, 3 = send packet size
:=
:=byte firstByte; // bytes in I2C message
:=byte secondByte;
:=
:=#INT_SSP
:=void ssp_interupt ()
:={
:=
:= byte gotByte;
:=
:= if(i2c_poll() == TRUE) {
:= gotByte = i2c_read(1);
:= output_b(gotByte);
:= }
:= else {
:= i2c_write('o');
:= delay_us(I2CTXPAUSE);
:= i2c_write('k');
:= delay_us(I2CTXPAUSE);
:= }
:=}
:=
:=
:=void main ()
:={
:=
:= // say hello to the world
:= printf("Waiting for I2C character\n\r");
:=
:= // initialise interrupts
:= enable_interrupts(GLOBAL);
:= enable_interrupts(INT_SSP);
:=
:= while (TRUE) {
:= }
:=}


Arthur,

try
1) Setting the tris port C to all input
2) Setting the SSPCON with the slave setting u want ie slave 7bit etc etc.

This should get the slave kicking.

However, if u r serious in writing codes for I2C slave, forget about using the CCS I2C software function. U r in beeter control writing up the routine by yuorself. Just refer to the PIC16C7x datasheets on I2c page, figure 11-27 will guide u on how it works.

Good luck
Kam
___________________________
This message was ported from CCS's old forum
Original Post ID: 2950
Pukar
Guest







Re: I2C between 16F877s
PostPosted: Thu Mar 07, 2002 9:43 pm     Reply with quote

Hi Arthur,

I am very similar problem between PIC16C73 and an I2C device, where PIC is the Slave. PIC hold the Clock low and does not release it. When the I2C device tries to read from the PIC, the PIC is able to get up to the point where it reads the read address and then chokes.

Please let me know if you find any solution. My e-mail is pmalla1@swarthmore.edu

Thanks.

Regards,
Pukar

:=I wonder if anyone can help with this problem. I have two 16F877s, one master, one slave. I'm trying to get the master to read two bytes from the slave, with no success. The code is attached below.
:=
:=I've scoped the I2C bus: it runs uite happily when the slave is disconnected, and you can se the master sending out the slave read address byte and clocking in the two bytes (which aren't actually there in this case). The master acks each byte.
:=
:=Then I attach the slave. I can see the address byte, with the read bit set, gets sent by the master and acked by the slave. The first byte gets read and acked by the master. But the clock pulses for the second byte are never seen. Both PICs lock up: the matser is supposed to keep flashing a LED from its main loop, but that stops. If I unplug things one by one, it looks like the bus is held low by the slave (?). If I take the slave reset line low, the master starts running again and getting FF bytes back as you'd expect.
:=
:=Whats going on? Why do the clock pulses for the second byte never appear?
:=
:=Hope someone can help. Thanks,
:=
:= Arthur
:=
:=Arthur Richards
:=MIT
:=
:=************* MASTER CODE *****************
:=
:=
:=#if defined(__PCM__)
:=#include <16f877.h>
:=#fuses HS,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP
:=#use delay(clock=20000000)
:=#use rs232(baud=38400, xmit=PIN_C6, rcv=PIN_C7) // Jumpers: 8 to 11, 7 to 12
:=#use i2c(MASTER, sda=PIN_C4, scl=PIN_C3, SLOW)
:=
:=#include<stdlib.h>
:=
:=// between transmitted bytes
:=#define I2CTXPAUSE 50
:=
:=// between transmitted address and byte read
:=#define I2CTXRXPAUSE 1000
:=
:=// between byte reads
:=#define I2CRXPAUSE 50
:=
:=// light flash
:=#define FLASHTIME 50
:=
:=void main ()
:={
:=
:= byte firstByte; // I2C received bytes
:= byte secondByte;
:=
:= // say hello to the world
:= printf("MSR001.C\n\r");
:=
:= // initialise interrupts
:= //enable_interrupts(GLOBAL);
:= //enable_interrupts(INT_SSP);
:=
:= while (TRUE) {
:=
:= // read packet size back from slave
:= i2c_start();
:= delay_us(I2CTXPAUSE);
:= i2c_write(0xb1);
:= delay_us(I2CTXRXPAUSE);
:= firstByte = i2c_read(1);
:= delay_us(I2CRXPAUSE);
:= secondByte = i2c_read(0);
:= delay_us(I2CRXPAUSE);
:= i2c_stop();
:= delay_us(I2CTXPAUSE);
:=
:= output_high(PIN_B5);
:= delay_ms(FLASHTIME);
:= output_low(PIN_B5);
:= delay_ms(FLASHTIME);
:=
:= } //while (TRUE)
:=}
:=
:=******************** SLAVE CODE ****************************
:=
:=
:=#if defined(__PCM__)
:=#include <16f877.h>
:=#fuses HS,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP
:=#use delay(clock=20000000)
:=#use rs232(baud=19200, xmit=PIN_C6, rcv=PIN_C7) // Jumpers: 8 to 11, 7 to 12
:=#use i2c(SLAVE, sda=PIN_C4, scl=PIN_C3, SLOW, address=0xb0)
:=
:=#include<stdlib.h>
:=
:=#define I2CTXPAUSE 10
:=
:=int i2c_state; // 0 = ready, 1 = got address, 2 = got first command
:=
:=int reply_state; // 0 = send default, 1 = error, 2 = send buffer byte, 3 = send packet size
:=
:=byte firstByte; // bytes in I2C message
:=byte secondByte;
:=
:=#INT_SSP
:=void ssp_interupt ()
:={
:=
:= byte gotByte;
:=
:= if(i2c_poll() == TRUE) {
:= gotByte = i2c_read(1);
:= output_b(gotByte);
:= }
:= else {
:= i2c_write('o');
:= delay_us(I2CTXPAUSE);
:= i2c_write('k');
:= delay_us(I2CTXPAUSE);
:= }
:=}
:=
:=
:=void main ()
:={
:=
:= // say hello to the world
:= printf("Waiting for I2C character\n\r");
:=
:= // initialise interrupts
:= enable_interrupts(GLOBAL);
:= enable_interrupts(INT_SSP);
:=
:= while (TRUE) {
:= }
:=}
___________________________
This message was ported from CCS's old forum
Original Post ID: 3038
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

Re: I2C between 16F877s
PostPosted: Thu Mar 14, 2002 11:59 am     Reply with quote

:=I wonder if anyone can help with this problem. I have two 16F877s, one master, one slave. I'm trying to get the master to read two bytes from the slave, with no success. The code is attached below.
:=
:=I've scoped the I2C bus: it runs uite happily when the slave is disconnected, and you can se the master sending out the slave read address byte and clocking in the two bytes (which aren't actually there in this case). The master acks each byte.
:=
:=Then I attach the slave. I can see the address byte, with the read bit set, gets sent by the master and acked by the slave. The first byte gets read and acked by the master. But the clock pulses for the second byte are never seen. Both PICs lock up: the matser is supposed to keep flashing a LED from its main loop, but that stops. If I unplug things one by one, it looks like the bus is held low by the slave (?). If I take the slave reset line low, the master starts running again and getting FF bytes back as you'd expect.
:=
:=Whats going on? Why do the clock pulses for the second byte never appear?
:=
:=Hope someone can help. Thanks,
:=
:= Arthur
:=
:=Arthur Richards
:=MIT
:=
:=************* MASTER CODE *****************
:=
:=
:=#if defined(__PCM__)
:=#include <16f877.h>
:=#fuses HS,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP
:=#use delay(clock=20000000)
:=#use rs232(baud=38400, xmit=PIN_C6, rcv=PIN_C7) // Jumpers: 8 to 11, 7 to 12
:=#use i2c(MASTER, sda=PIN_C4, scl=PIN_C3, SLOW)
:=
:=#include<stdlib.h>
:=
:=// between transmitted bytes
:=#define I2CTXPAUSE 50
:=
:=// between transmitted address and byte read
:=#define I2CTXRXPAUSE 1000
:=
:=// between byte reads
:=#define I2CRXPAUSE 50
:=
:=// light flash
:=#define FLASHTIME 50
:=
:=void main ()
:={
:=
:= byte firstByte; // I2C received bytes
:= byte secondByte;
:=
:= // say hello to the world
:= printf("MSR001.C\n\r");
:=
:= // initialise interrupts
:= //enable_interrupts(GLOBAL);
:= //enable_interrupts(INT_SSP);
:=
:= while (TRUE) {
:=
:= // read packet size back from slave
:= i2c_start();
:= delay_us(I2CTXPAUSE);
:= i2c_write(0xb1);
:= delay_us(I2CTXRXPAUSE);
:= firstByte = i2c_read(1);
:= delay_us(I2CRXPAUSE);
:= secondByte = i2c_read(0);
:= delay_us(I2CRXPAUSE);
:= i2c_stop();
:= delay_us(I2CTXPAUSE);
:=
:= output_high(PIN_B5);
:= delay_ms(FLASHTIME);
:= output_low(PIN_B5);
:= delay_ms(FLASHTIME);
:=
:= } //while (TRUE)
:=}
:=
:=******************** SLAVE CODE ****************************
:=
:=
:=#if defined(__PCM__)
:=#include <16f877.h>
:=#fuses HS,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP
:=#use delay(clock=20000000)
:=#use rs232(baud=19200, xmit=PIN_C6, rcv=PIN_C7) // Jumpers: 8 to 11, 7 to 12
:=#use i2c(SLAVE, sda=PIN_C4, scl=PIN_C3, SLOW, address=0xb0)
:=
:=#include<stdlib.h>
:=
:=#define I2CTXPAUSE 10
:=
:=int i2c_state; // 0 = ready, 1 = got address, 2 = got first command
:=
:=int reply_state; // 0 = send default, 1 = error, 2 = send buffer byte, 3 = send packet size
:=
:=byte firstByte; // bytes in I2C message
:=byte secondByte;
:=
:=#INT_SSP
:=void ssp_interupt ()
:={
:=
:= byte gotByte;
:=
:= if(i2c_poll() == TRUE) {
:= gotByte = i2c_read(1);
:= output_b(gotByte);
:= }
:= else {
:= i2c_write('o');
:= delay_us(I2CTXPAUSE);
:= i2c_write('k');
:= delay_us(I2CTXPAUSE);
:= }
:=}
:=
:=
:=void main ()
:={
:=
:= // say hello to the world
:= printf("Waiting for I2C character\n\r");
:=
:= // initialise interrupts
:= enable_interrupts(GLOBAL);
:= enable_interrupts(INT_SSP);
:=
:= while (TRUE) {
:= }
:=}

You must set the CKP bit in the SSPCON reg to release the clock. You might have to separate the two slave writes. I only read one byte from the PIC when in slave mode so I am unsure if you will get another INT after the first byte is clocked out.

i2c_write('o'); //Make sure that the compiled code is setting *SSPBUF = 'o' and not trying to write out the byte in master mode
bit_set(*SSPCON, CKP); //Release the clock
___________________________
This message was ported from CCS's old forum
Original Post ID: 3229
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