|
|
View previous topic :: View next topic |
Author |
Message |
dtemplar
Joined: 16 Feb 2004 Posts: 5
|
I2C Slave SDA pulled low after writing to SSPBUF |
Posted: Thu Jun 30, 2005 4:43 am |
|
|
Hello Guys,
I am trying to make a library that would require me to implement I2C slave on the PIC16F876A without using the CCS-C functions (since these functions will be used on the main program)
However, upon getting an I2C read operation, the SDA line is pulled low after writing the data to SSPBUF. I verified that the program did went through the SSPBUF = data codes, but the SDA just went low during the clock transitions and after.
I tried checking all the errata (my F876A is rev B4) and I cant find anything that explains this.
Here's my code:
Code: |
//i2c register
#byte REG_INTERRUPT_FLAGS1 = 0x0C //PIR1
#bit FLAG_I2C_INTERRUPT = REG_INTERRUPT_FLAGS1.3
#byte REG_I2C_BUFFER = 0x13 //SSPBUF
#byte REG_I2C_ADDRESS = 0x93 //SSPADD
#byte REG_I2C_STATUS = 0x94 //SSPSTAT
#bit FLAG_I2C_BUFFER_FULL = REG_I2C_STATUS.0
#bit FLAG_I2C_UPDATE_ADDR_10BIT = REG_I2C_STATUS.1
#bit FLAG_I2C_READ_WRITE = REG_I2C_STATUS.2
#bit FLAG_I2C_START = REG_I2C_STATUS.3
#bit FLAG_I2C_STOP = REG_I2C_STATUS.4
#bit FLAG_I2C_DATA_ADDR = REG_I2C_STATUS.5
#bit FLAG_I2C_CKE = REG_I2C_STATUS.6
#bit FLAG_I2C_SMP = REG_I2C_STATUS.7
#byte REG_I2C_CONTROL = 0x14 //SSPCON
#bit FLAG_I2C_MODE_BIT0 = REG_I2C_CONTROL.0
#bit FLAG_I2C_MODE_BIT1 = REG_I2C_CONTROL.1
#bit FLAG_I2C_MODE_BIT2 = REG_I2C_CONTROL.2
#bit FLAG_I2C_MODE_BIT3 = REG_I2C_CONTROL.3
#bit FLAG_I2C_SCK_RELEASE = REG_I2C_CONTROL.4
#bit FLAG_I2C_ENABLE = REG_I2C_CONTROL.5
#bit FLAG_I2C_OVERFLOW = REG_I2C_CONTROL.6
#bit FLAG_I2C_WRITE_COLLISION = REG_I2C_CONTROL.7
#byte REG_I2C_CONTROL2 = 0x91 //SSPCON2
#bit FLAG_I2C_CLOCK_STRETCH = REG_I2C_CONTROL2.0
#bit FLAG_I2C_GEN_CALL_ENABLED = REG_I2C_CONTROL2.7
//port access
#byte REG_PORT_C_TRIS = 0x87 //TRISC
//#bit FLAG_PINC0_INPUT = REG_PORT_C_TRIS.0
#bit FLAG_PINC1_INPUT = REG_PORT_C_TRIS.1
//#bit FLAG_PINC2_INPUT = REG_PORT_C_TRIS.2
#bit FLAG_BUS_SCL_INPUT = REG_PORT_C_TRIS.3
#bit FLAG_BUS_SDA_INPUT = REG_PORT_C_TRIS.4
void main(void)
{
int8 i8ReceivedData;
//enable slave i2c
//init bus pins
FLAG_BUS_SCL_INPUT = FALSE;
FLAG_BUS_SDA_INPUT = FALSE;
PIN_BUS_SCL = 1;
PIN_BUS_SDA = 1;
FLAG_BUS_SCL_INPUT = TRUE;
FLAG_BUS_SDA_INPUT = TRUE;
//init registers
FLAG_I2C_GEN_CALL_ENABLED = FALSE;
FLAG_I2C_CLOCK_STRETCH = FALSE;
FLAG_I2C_WRITE_COLLISION = FALSE;
FLAG_I2C_OVERFLOW = FALSE;
FLAG_I2C_SCK_RELEASE = TRUE;
i8ReceivedData= REG_I2C_BUFFER;
//slave mode 7bit-address
FLAG_I2C_MODE_BIT0 = 0;
FLAG_I2C_MODE_BIT1 = 1;
FLAG_I2C_MODE_BIT2 = 1;
FLAG_I2C_MODE_BIT3 = 0;
//enable slave i2c
REG_I2C_ADDRESS = CONST_I2C_SLAVE_ADDRESS;
FLAG_I2C_ENABLE = TRUE;
//wait for commands
while(TRUE)
{
if (FLAG_I2C_INTERRUPT)
{
FLAG_I2C_SCK_RELEASE = FALSE;
//check buffer
if (FLAG_I2C_BUFFER_FULL)
{
// read buffer (SSPBUF)
i8ReceivedData = REG_I2C_BUFFER;
}
//check errors
if (FLAG_I2C_OVERFLOW || FLAG_I2C_WRITE_COLLISION)
{
FLAG_I2C_OVERFLOW = FALSE;
FLAG_I2C_WRITE_COLLISION = FALSE;
//reset bus
FLAG_I2C_ENABLE = FALSE;
FLAG_BUS_SCL_INPUT = TRUE;
FLAG_BUS_SDA_INPUT = TRUE;
FLAG_I2C_ENABLE = TRUE;
}
else
{
//check read operation
if (FLAG_I2C_READ_WRITE)
{
//check if to send first byte
if (FLAG_I2C_DATA_ADDR)
{
//send next byte
REG_I2C_BUFFER = 0xAA;
}
else
{
//send first byte
REG_I2C_BUFFER = 0x55;
}
}
}
FLAG_I2C_SCK_RELEASE = TRUE;
FLAG_I2C_INTERRUPT = FALSE;
}
}
}
|
By the way, I also tried recompiling a CCS-C program used for the PIC16F76 with working I2C slave implementation, for a PIC16F876A, but the I2C slave did not work.
Now I am not sure if its with CCS or with the PIC micro. |
|
|
Ttelmah Guest
|
|
Posted: Thu Jun 30, 2005 5:58 am |
|
|
You seem to only be handling three of the four normal conditions that can occur on an I2C slave. Your first byte received, will be the address byte.
Look at AN734 from Microchip. This shows the code needed in assembler, and is well documented, so conversion should be easy. Your slave handler needs to be able to handle the possibilities of both a read, and a write, with either data, or address bytes, and also Nack reset condition.
The SDO line being held low, implies that the slave thinks that it has not successfully completed the transaction, and is therefore holding ACK low.
Best Wishes |
|
|
|
|
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
|