|
|
View previous topic :: View next topic |
Author |
Message |
jetlang Guest
|
slave holding SCL LOW! |
Posted: Wed Apr 17, 2002 7:06 am |
|
|
hi,
i am using a EMICROS FLASH 12c232 to help develope this i2c communication within the 16f877,slave, i am able to send data(byte) to the 16f877 and have that data be written to portD where its connected to an LED array,its works fine. i am using PMC C 3.082
heres my trouble, i want the slave to send back specific data bytes base on what the master asks. right now i am testing for 1 byte at a time. when the master sends a request to read, i can see the address-R/W-not/ack on the oscope but after the ningth clock, the SCL is held low forever.
so i understand it to be a valid address and the pic is acking it, i believe the pic is hold it low and this is what i dont understand, i write to SSPBUF and set CKP then exit the isr as the literature stated, here is my code:
#include "includes\16F877.H" //CCS HEADER
#include "includes\16F877MC.H" //MICROCHIP HEADER
#fuses HS,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP
#use delay(clock=4000000)
#use I2C(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0xa0)
typedef enum {START, ADDRESS_READ, READ, WRITE} I2C_STATE;
I2C_STATE nextState=START;
byte incoming = 0x00,
address = 0x00,
command = 0x00,
errorCount = 0x00,
temp = 0x00;
#int_ssp
void ssp_interupt (){
if(i2c_poll() == TRUE){
incoming = i2c_read();
switch(nextState){
case START:
nextState = START;
address = incoming;
//if(bit_test(*_SSPSTAT, _WRITE)){
//nextState = WRITE;
//i2c_write(0xAA);
_SSPBUF = 0xAA;
bit_set(*_SSPCON, _CKP);
//bit_clear(*_PIR1, _SSPIF);
//}
//else nextState = READ;
break;
case READ:
nextState = START;
command = incoming;
break;
case WRITE:
nextState = START;
command = 0xFF;
i2c_write(0xAA);
_SSPBUF = 0xAA;
bit_set(*_SSPCON, _CKP);
bit_clear(*_PIR1, _SSPIF);
break;
default:
nextState = START;
break;
}
}
}
void main() {
#use fast_io(d)
set_tris_d(0x00);
#use fast_io(e)
set_tris_e(0x00);
enable_interrupts(GLOBAL);
enable_interrupts(INT_SSP);
while (TRUE) {
output_d(address);
delay_ms(1500);
output_d(command);
delay_ms(1500);
}
}
any help would be greatly apreciated!
___________________________
This message was ported from CCS's old forum
Original Post ID: 3834 |
|
|
Tomi Guest
|
Re: slave holding SCL LOW! |
Posted: Wed Apr 17, 2002 10:39 am |
|
|
I don't think that a slave can hold down the SCL line. Take a look on Figure 9-10 (Page#71): in the slave mode SCL is an input-only line.
One important thing is that i2c_poll() returns true only if you have a RECEIVED byte. It could be a control or address byte or a data byte to store. To read out the slave you will get an IT without a pending data. See "ex_slave.c" for an i2c slave example:
if (i2c_poll() == FALSE) {
if (fState == ADDRESS_READ) { //i2c_poll() returns false on the
i2c_write (buffer[address]);//interrupt receiving the second
fState = NOTHING; //command byte for random read operation
}
}
:=hi,
:=
:=i am using a EMICROS FLASH 12c232 to help develope this i2c communication within the 16f877,slave, i am able to send data(byte) to the 16f877 and have that data be written to portD where its connected to an LED array,its works fine. i am using PMC C 3.082
:=
:=heres my trouble, i want the slave to send back specific data bytes base on what the master asks. right now i am testing for 1 byte at a time. when the master sends a request to read, i can see the address-R/W-not/ack on the oscope but after the ningth clock, the SCL is held low forever.
:=
:=so i understand it to be a valid address and the pic is acking it, i believe the pic is hold it low and this is what i dont understand, i write to SSPBUF and set CKP then exit the isr as the literature stated, here is my code:
:=
:=
:=
:=#include "includes\16F877.H" //CCS HEADER
:=#include "includes\16F877MC.H" //MICROCHIP HEADER
:=
:=#fuses HS,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP
:=#use delay(clock=4000000)
:=#use I2C(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0xa0)
:=
:=typedef enum {START, ADDRESS_READ, READ, WRITE} I2C_STATE;
:=
:=I2C_STATE nextState=START;
:=
:=byte incoming = 0x00,
:= address = 0x00,
:= command = 0x00,
:= errorCount = 0x00,
:= temp = 0x00;
:=
:=
:=#int_ssp
:=void ssp_interupt (){
:=
:= if(i2c_poll() == TRUE){
:= incoming = i2c_read();
:=
:= switch(nextState){
:= case START:
:= nextState = START;
:= address = incoming;
:= //if(bit_test(*_SSPSTAT, _WRITE)){
:= //nextState = WRITE;
:= //i2c_write(0xAA);
:= _SSPBUF = 0xAA;
:= bit_set(*_SSPCON, _CKP);
:= //bit_clear(*_PIR1, _SSPIF);
:= //}
:= //else nextState = READ;
:= break;
:= case READ:
:= nextState = START;
:= command = incoming;
:= break;
:= case WRITE:
:= nextState = START;
:= command = 0xFF;
:= i2c_write(0xAA);
:= _SSPBUF = 0xAA;
:= bit_set(*_SSPCON, _CKP);
:= bit_clear(*_PIR1, _SSPIF);
:=
:= break;
:= default:
:= nextState = START;
:= break;
:= }
:= }
:=}
:=
:=
:=void main() {
:=
:= #use fast_io(d)
:= set_tris_d(0x00);
:= #use fast_io(e)
:= set_tris_e(0x00);
:=
:= enable_interrupts(GLOBAL);
:= enable_interrupts(INT_SSP);
:=
:= while (TRUE) {
:= output_d(address);
:= delay_ms(1500);
:= output_d(command);
:= delay_ms(1500);
:= }
:=}
:=
:=any help would be greatly apreciated!
___________________________
This message was ported from CCS's old forum
Original Post ID: 3841 |
|
|
Bob McWilliams Guest
|
Re: slave holding SCL LOW! |
Posted: Wed Apr 17, 2002 11:15 am |
|
|
The Slave WILL hold the clock line low until it can process the data. This is documented in the PIC's data sheet under the I2C specifications.
One thing that I noticed in your code is inside the SWITCH statement(case WRITE). You call I2C_WRITE(), which stuffs SSPBUF with the data to transmit, then you manually stuff SSPBUF
with another byte of data. This may/will cause an OVERFLOW condition, in which case the SSP needs to be reset.
I'm sorry but I'm not as apt at I2C communication using CCS's I2C commands, I like to code it all out myself.
___________________________
This message was ported from CCS's old forum
Original Post ID: 3843 |
|
|
jetlang Guest
|
Re: slave holding SCL LOW! |
Posted: Wed Apr 17, 2002 11:43 am |
|
|
:=The Slave WILL hold the clock line low until it can process the data. This is documented in the PIC's data sheet under the I2C specifications.
:=
:=One thing that I noticed in your code is inside the SWITCH statement(case WRITE). You call I2C_WRITE(), which stuffs SSPBUF with the data to transmit, then you manually stuff SSPBUF
:=with another byte of data. This may/will cause an OVERFLOW condition, in which case the SSP needs to be reset.
:=
:=I'm sorry but I'm not as apt at I2C communication using CCS's I2C commands, I like to code it all out myself.
the switch statement case WRITE: should not happen becuase i use "//" to comment out code so i can test reading from the pic16f877 with just case START and that it should happen in just one trigger of INT that is for one byte read. the case WRITE is for 1+x bytes read.
from figure 9-7 p.76, once the address byte is recieved and INT is trigger on the nineth clock, we enter the ISR, so i go ahead and verify there is a byte-using i2c_poll(), which i think is redundant, then read in the address using i2c_read(), and then process to write to the SSPBUF with data then enable the CKP and exit ISR - like from figure 9-7 illustrates
enter isr:
f(i2c_poll() == TRUE){
incoming = i2c_read();
address = incoming;
_SSPBUF = 0xAA;
bit_set(*_SSPCON, _CKP);
exit isr:
thanks,
___________________________
This message was ported from CCS's old forum
Original Post ID: 3846 |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
Re: slave holding SCL LOW! |
Posted: Wed Apr 17, 2002 11:45 am |
|
|
Yes the slave will hold the SCL line low (its called clock stretching) in order for the PIC to have time to process the int.
Mark
:=I don't think that a slave can hold down the SCL line. Take a look on Figure 9-10 (Page#71): in the slave mode SCL is an input-only line.
:=
:=One important thing is that i2c_poll() returns true only if you have a RECEIVED byte. It could be a control or address byte or a data byte to store. To read out the slave you will get an IT without a pending data. See "ex_slave.c" for an i2c slave example:
:= if (i2c_poll() == FALSE) {
:= if (fState == ADDRESS_READ) { //i2c_poll() returns false on the
:= i2c_write (buffer[address]);//interrupt receiving the second
:= fState = NOTHING; //command byte for random read operation
:= }
:= }
:=
:=
:=
:=:=hi,
:=:=
:=:=i am using a EMICROS FLASH 12c232 to help develope this i2c communication within the 16f877,slave, i am able to send data(byte) to the 16f877 and have that data be written to portD where its connected to an LED array,its works fine. i am using PMC C 3.082
:=:=
:=:=heres my trouble, i want the slave to send back specific data bytes base on what the master asks. right now i am testing for 1 byte at a time. when the master sends a request to read, i can see the address-R/W-not/ack on the oscope but after the ningth clock, the SCL is held low forever.
:=:=
:=:=so i understand it to be a valid address and the pic is acking it, i believe the pic is hold it low and this is what i dont understand, i write to SSPBUF and set CKP then exit the isr as the literature stated, here is my code:
:=:=
:=:=
:=:=
:=:=#include "includes\16F877.H" //CCS HEADER
:=:=#include "includes\16F877MC.H" //MICROCHIP HEADER
:=:=
:=:=#fuses HS,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP
:=:=#use delay(clock=4000000)
:=:=#use I2C(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0xa0)
:=:=
:=:=typedef enum {START, ADDRESS_READ, READ, WRITE} I2C_STATE;
:=:=
:=:=I2C_STATE nextState=START;
:=:=
:=:=byte incoming = 0x00,
:=:= address = 0x00,
:=:= command = 0x00,
:=:= errorCount = 0x00,
:=:= temp = 0x00;
:=:=
:=:=
:=:=#int_ssp
:=:=void ssp_interupt (){
:=:=
:=:= if(i2c_poll() == TRUE){
:=:= incoming = i2c_read();
:=:=
:=:= switch(nextState){
:=:= case START:
:=:= nextState = START;
:=:= address = incoming;
:=:= //if(bit_test(*_SSPSTAT, _WRITE)){
:=:= //nextState = WRITE;
:=:= //i2c_write(0xAA);
:=:= _SSPBUF = 0xAA;
:=:= bit_set(*_SSPCON, _CKP);
:=:= //bit_clear(*_PIR1, _SSPIF);
:=:= //}
:=:= //else nextState = READ;
:=:= break;
:=:= case READ:
:=:= nextState = START;
:=:= command = incoming;
:=:= break;
:=:= case WRITE:
:=:= nextState = START;
:=:= command = 0xFF;
:=:= i2c_write(0xAA);
:=:= _SSPBUF = 0xAA;
:=:= bit_set(*_SSPCON, _CKP);
:=:= bit_clear(*_PIR1, _SSPIF);
:=:=
:=:= break;
:=:= default:
:=:= nextState = START;
:=:= break;
:=:= }
:=:= }
:=:=}
:=:=
:=:=
:=:=void main() {
:=:=
:=:= #use fast_io(d)
:=:= set_tris_d(0x00);
:=:= #use fast_io(e)
:=:= set_tris_e(0x00);
:=:=
:=:= enable_interrupts(GLOBAL);
:=:= enable_interrupts(INT_SSP);
:=:=
:=:= while (TRUE) {
:=:= output_d(address);
:=:= delay_ms(1500);
:=:= output_d(command);
:=:= delay_ms(1500);
:=:= }
:=:=}
:=:=
:=:=any help would be greatly apreciated!
___________________________
This message was ported from CCS's old forum
Original Post ID: 3847 |
|
|
jetlang Guest
|
Re: slave holding SCL LOW! |
Posted: Wed Apr 17, 2002 11:52 am |
|
|
<font face="Courier New" size=-1>:=I don't think that a slave can hold down the SCL line. Take a look on Figure 9-10 (Page#71): in the slave mode SCL is an input-only line.
:=
:=One important thing is that i2c_poll() returns true only if you have a RECEIVED byte. It could be a control or address byte or a data byte to store. To read out the slave you will get an IT without a pending data. See "ex_slave.c" for an i2c slave example:
:= if (i2c_poll() == FALSE) {
:= if (fState == ADDRESS_READ) { //i2c_poll() returns false on the
:= i2c_write (buffer[address]);//interrupt receiving the second
:= fState = NOTHING; //command byte for random read operation
:= }
:= }
this example i really cant understand, i think it conflicts with figure 9-7 p.76, it shows that there was 1 INT occured(the address read) before the 2nd INT to write the data out, so a total to 2 INT.
what i think should happen is, that when address is recieved, on the 9th clock the INT happends, then invokes ISR, thus in the SSPBUFF is the address along with the R/W_not, so the address is stored and write to SSPBUF with data and re-enable SLC,all in one INT
thanks,</font>
___________________________
This message was ported from CCS's old forum
Original Post ID: 3850 |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
Re: slave holding SCL LOW! |
Posted: Wed Apr 17, 2002 11:54 am |
|
|
How is _SSPBUF declared? The same way as _SSPCON. Like
#define _SSPBUF 0x13
if so then you need the following
*_SSPBUF = 0xAA;
instead of
_SSPBUF = 0xAA;
I have also found that the compiler now treats this as a 16bit number so actually you will have to cast it:
(int)*_SSPBUF = 0xAA;
Let me know if this helps. I did not go through the code very well. I usually don't use CCS's built in functions simply because they tend to get "broken".
Mark
:=hi,
:=
:=i am using a EMICROS FLASH 12c232 to help develope this i2c communication within the 16f877,slave, i am able to send data(byte) to the 16f877 and have that data be written to portD where its connected to an LED array,its works fine. i am using PMC C 3.082
:=
:=heres my trouble, i want the slave to send back specific data bytes base on what the master asks. right now i am testing for 1 byte at a time. when the master sends a request to read, i can see the address-R/W-not/ack on the oscope but after the ningth clock, the SCL is held low forever.
:=
:=so i understand it to be a valid address and the pic is acking it, i believe the pic is hold it low and this is what i dont understand, i write to SSPBUF and set CKP then exit the isr as the literature stated, here is my code:
:=
:=
:=
:=#include "includes\16F877.H" //CCS HEADER
:=#include "includes\16F877MC.H" //MICROCHIP HEADER
:=
:=#fuses HS,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP
:=#use delay(clock=4000000)
:=#use I2C(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0xa0)
:=
:=typedef enum {START, ADDRESS_READ, READ, WRITE} I2C_STATE;
:=
:=I2C_STATE nextState=START;
:=
:=byte incoming = 0x00,
:= address = 0x00,
:= command = 0x00,
:= errorCount = 0x00,
:= temp = 0x00;
:=
:=
:=#int_ssp
:=void ssp_interupt (){
:=
:= if(i2c_poll() == TRUE){
:= incoming = i2c_read();
:=
:= switch(nextState){
:= case START:
:= nextState = START;
:= address = incoming;
:= //if(bit_test(*_SSPSTAT, _WRITE)){
:= //nextState = WRITE;
:= //i2c_write(0xAA);
:= _SSPBUF = 0xAA;
:= bit_set(*_SSPCON, _CKP);
:= //bit_clear(*_PIR1, _SSPIF);
:= //}
:= //else nextState = READ;
:= break;
:= case READ:
:= nextState = START;
:= command = incoming;
:= break;
:= case WRITE:
:= nextState = START;
:= command = 0xFF;
:= i2c_write(0xAA);
:= _SSPBUF = 0xAA;
:= bit_set(*_SSPCON, _CKP);
:= bit_clear(*_PIR1, _SSPIF);
:=
:= break;
:= default:
:= nextState = START;
:= break;
:= }
:= }
:=}
:=
:=
:=void main() {
:=
:= #use fast_io(d)
:= set_tris_d(0x00);
:= #use fast_io(e)
:= set_tris_e(0x00);
:=
:= enable_interrupts(GLOBAL);
:= enable_interrupts(INT_SSP);
:=
:= while (TRUE) {
:= output_d(address);
:= delay_ms(1500);
:= output_d(command);
:= delay_ms(1500);
:= }
:=}
:=
:=any help would be greatly apreciated!
___________________________
This message was ported from CCS's old forum
Original Post ID: 3851 |
|
|
jetlang Guest
|
Re: slave holding SCL LOW! |
Posted: Wed Apr 17, 2002 1:24 pm |
|
|
:=How is _SSPBUF declared? The same way as _SSPCON. Like
:=#define _SSPBUF 0x13
:=
:=if so then you need the following
:=*_SSPBUF = 0xAA;
:=instead of
:=_SSPBUF = 0xAA;
:=
:=I have also found that the compiler now treats this as a 16bit number so actually you will have to cast it:
:=(int)*_SSPBUF = 0xAA;
:=
:=Let me know if this helps. I did not go through the code very well. I usually don't use CCS's built in functions simply because they tend to get "broken".
:=
:=Mark
:=
hey mark,
_SSPBUF and others are declared as #bytes, well i found that if i read data u using i2c_read() somehow hold SLC low in my code, so i read from _SSPBUF instead, now i have a clock after the firstbyte but the data i loaded into _SSPBUF is not xfering out, maybe i have to set SDA to output now.
___________________________
This message was ported from CCS's old forum
Original Post ID: 3858 |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
Re: slave holding SCL LOW! |
Posted: Wed Apr 17, 2002 2:07 pm |
|
|
If they are #byte then
bit_set(*_SSPCON, _CKP);
bit_clear(*_PIR1, _SSPIF);
should not be using pointer notation. You should use
bit_set(_SSPCON, _CKP);
bit_clear(_PIR1, _SSPIF);
_CKP & _SSPIF should be #define
Mark
:=:=How is _SSPBUF declared? The same way as _SSPCON. Like
:=:=#define _SSPBUF 0x13
:=:=
:=:=if so then you need the following
:=:=*_SSPBUF = 0xAA;
:=:=instead of
:=:=_SSPBUF = 0xAA;
:=:=
:=:=I have also found that the compiler now treats this as a 16bit number so actually you will have to cast it:
:=:=(int)*_SSPBUF = 0xAA;
:=:=
:=:=Let me know if this helps. I did not go through the code very well. I usually don't use CCS's built in functions simply because they tend to get "broken".
:=:=
:=:=Mark
:=:=
:=
:=hey mark,
:=
:=_SSPBUF and others are declared as #bytes, well i found that if i read data u using i2c_read() somehow hold SLC low in my code, so i read from _SSPBUF instead, now i have a clock after the firstbyte but the data i loaded into _SSPBUF is not xfering out, maybe i have to set SDA to output now.
___________________________
This message was ported from CCS's old forum
Original Post ID: 3860 |
|
|
Kam Yip Guest
|
Re: slave holding SCL LOW! |
Posted: Wed Apr 17, 2002 9:03 pm |
|
|
I've similar experience using I2C_Poll routines. To minimise your pain, pls avoid using this routine because u have no idea what is happening. I have done my own routine for slave I2C receive and it is working well! U can refer to the 16c78 datasheet for some guideline.
___________________________
This message was ported from CCS's old forum
Original Post ID: 3864 |
|
|
jetlang Guest
|
Re: slave holding SCL LOW! |
Posted: Thu Apr 18, 2002 6:18 am |
|
|
:=I've similar experience using I2C_Poll routines. To minimise your pain, pls avoid using this routine because u have no idea what is happening. I have done my own routine for slave I2C receive and it is working well! U can refer to the 16c78 datasheet for some guideline.
found that out the hard way, thus i am re-coding everything myself, besides i learn i2c much more that way, thanks,
___________________________
This message was ported from CCS's old forum
Original Post ID: 3876 |
|
|
|
|
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
|