• AVR Freaks

Helpful ReplyHot!PIC16F877A I2C SEN BIT NOT CLEAR

Author
antesther
Starting Member
  • Total Posts : 33
  • Reward points : 0
  • Joined: 2019/06/04 09:44:13
  • Location: Juarez, Mexico
  • Status: offline
2020/04/09 14:13:02 (permalink)
0

PIC16F877A I2C SEN BIT NOT CLEAR

Hello everyone,
 
Hope somebody can help with this issue, I am interfacing two pic16f877a via I2C, this is my first time working with this protocol,
when i set SEN bit to send start bit, this bit never goes back to 0, according to the data sheet, once this bit is set and start condition takes place in the BUS this bit should be cleared by hardware, but i was doing some debugging using a 16x2 LCD and using a while loop to check for the bit to be false, but this never happens, hence the rest of the code doesn't execute.
 
 
This is the master code:
 
TRISCbits.TRISC3 = 1;
TRISCbits.TRISC4 = 1; //SCL AS IN
SSPADD = 9; //100 KBPS ACCORDIN TO DATA SPEED FORMULA
//SSPSTATbits.SMP = 1;

SSPCONbits.SSPM0 = 0;
SSPCONbits.SSPM0 = 1; //MASTER MODE (IT'LL RECEIVE ANSWER FROM SLAVE THOUGH)
SSPCONbits.SSPM0 = 1;
SSPCONbits.SSPM0 = 1;
void Request_RPM_Value(void)
{
//I2C COMM SEQUENCE INIT
SSPCONbits.SSPEN = 1; //ENABLE SDA AND SCL TO INIT COMMUNICATION
SSPSTAT = 0;
SSPCON2bits.SEN = 1; //START CONDITION
if (!SSPSTATbits.S && !SSPSTATbits.P) //IF BUS IS IDLE
{
while (SSPCON2bits.SEN); //WAIT 4 START CONDITION TO COMPLETE
Lcd_Print_String("START ON");
__delay_ms(2000);
Lcd_Clear();
SSPBUF = 0xC9; //LOAD SSPBUF WITH SLAVE ID AND SHIFT IT OUT 7 BIT ADDRESS (0x64) PLUS R/W BIT (0X64 + 1)
while (SSPSTATbits.BF); //WAIT TILL MESSAGE IS SENT
SSPCON2bits.RCEN = 1; //MASTER IN RECEIVE MODE
while (SSPCON2bits.ACKSTAT); //WAIT FOR ACK BIT TO GO LOW
while (SSPSTATbits.BF); //WAIT FOR BUFFER TO BE COMPLETELY FULL BEFORE READING IT
SSPCON2bits.ACKEN = 1; //ENABLE ACK BIT GENERATION
Received_RPM = SSPBUF; //RECEIVED RPM VALUE STORED IN RECEIVED RPM VARIABLE
SSPCON2bits.PEN = 1; //STOP CONDITION
}
//I2C COMM SEQUENCE END
}
 
this is the slave code (irrelevant at this point since im not able to send start condition with the master)
TRISCbits.TRISC3 = 1;
TRISCbits.TRISC4 = 1;
SSPADD = 0x64; //SSPADD = DEVICE I2C ID 7 BIT ADDRESSING
SSPCONbits.SSPEN = 1; //ENABLE SDA AND SCL TO INIT COMMUNICATION
SSPCONbits.SSPM0 = 0;
SSPCONbits.SSPM0 = 1; //SLAVE MODE 7-BIT ADDRESS
SSPCONbits.SSPM0 = 1;
SSPCONbits.SSPM0 = 1;
SSPCON2bits.GCEN = 0; ///GENERAL CALL DISABLED
SSPCON2bits.SEN = 1; //CLOCK STRETCHING IS ENABLED FOR BOTH TRASMITING AND RECEIVING
PIE1bits.SSPIE = 1; //I2C INTERRUPT ENABLE
if ((Master_RPM_Request) && (SSPSTATbits.BF) && (SSPBUF == 0xC9) && (SSPSTATbits.R_W)) //0xC9 7 BIT ADDRESS PLUS R/W BIT, R/W WILL BE 1, THUS ADDRESS + 1 WILL BE 0xC9
{
//IF IT DOESNT WORK, TRY A DIFF WAY OF READING, PUT SSPBUF VALUE IN VARIABLE
Send_RPM_I2C(&RPM);
}
 

Im using proteus to simulate this, and already added pull up resistors (4.7k), using the digital oscilloscope checked that both SCL and SDA lines remain high (5v), which means that bus is idle, but i dont see the start bit taking place.
 
Cheers.
 
 
post edited by antesther - 2020/04/09 14:17:39
#1
antesther
Starting Member
  • Total Posts : 33
  • Reward points : 0
  • Joined: 2019/06/04 09:44:13
  • Location: Juarez, Mexico
  • Status: offline
Re: PIC16F877A I2C SEN BIT NOT CLEAR 2020/04/09 14:36:33 (permalink)
0
I found my mistake

SSPCONbits.SSPM0 = 0;
SSPCONbits.SSPM0 = 1; //MASTER MODE (IT'LL RECEIVE ANSWER FROM SLAVE THOUGH)
SSPCONbits.SSPM0 = 1;
SSPCONbits.SSPM0 = 1;
 
Set the same bit multiple tiemes and didnt event set them for master mode lol
 
Now im not receiving ACK from slave, any ideas
#2
ric
Super Member
  • Total Posts : 26942
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: PIC16F877A I2C SEN BIT NOT CLEAR 2020/04/09 16:27:48 (permalink)
0
Please, rather than making your code all red, put code tags around it so it's easier to read.
i.e. [CODE] before, and [/CODE] after, but using lower case. Then it looks like this
SSPCONbits.SSPM0 = 0;
SSPCONbits.SSPM0 = 1; //MASTER MODE (IT'LL RECEIVE ANSWER FROM SLAVE THOUGH)
SSPCONbits.SSPM0 = 1;
SSPCONbits.SSPM0 = 1;

The safer way to do that same operation is:
SSPCONbits.SSPM = 0b1110;

 
In your slave, you enable interrupts. Do yo uhave an interrupt service routine?
In your slave, you enable clock stretching. Do you have code to release the clock?
 
In your Master, get rid of this code after you set SEN
if (!SSPSTATbits.S && !SSPSTATbits.P) //IF BUS IS IDLE

 
Do not test for ACK like this:
while (SSPSTATbits.BF); //WAIT TILL MESSAGE IS SENT
SSPCON2bits.RCEN = 1; //MASTER IN RECEIVE MODE
while (SSPCON2bits.ACKSTAT); //WAIT FOR ACK BIT TO GO LOW

Instead of waiting for SSPSTATbits.BF to go low, wait for SSPSTATbits.R_W to go low.
BF goes low when only the data has transferred, but not the ACK/NAK flag.
R_W goes low when ACK has been transferred as well.
At that time, read the ACKSTAT bit only once.
If it is low, you got an ACK. If it is high, you got a NAK (=>the slave is not responding)
Never ever just wait for the ACKSTAT bit.
 
Do you have pullups on SDA and SCL?
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#3
antesther
Starting Member
  • Total Posts : 33
  • Reward points : 0
  • Joined: 2019/06/04 09:44:13
  • Location: Juarez, Mexico
  • Status: offline
Re: PIC16F877A I2C SEN BIT NOT CLEAR 2020/04/09 17:37:16 (permalink)
0
Didnt know how to insert code in a neat way, thank you.
So when RW bit goes low means that both the address and ack/nak flag were sent?
 
This is my Slave ISR
 

 
 
 
 
 
INTCONbits.PEIE = 1;
INTCONbits.GIE = 1;
 
PIE1bits.SSPIE = 1; //I2C INTERRUPT ENABLE
PIR1bits.SSPIF = 0;
 
if ((PIR1bits.SSPIF) && (PIE1bits.SSPIE))
{
Master_RPM_Request = 1;
PIR1bits.SSPIF = ~PIR1bits.SSPIF;
}
 
 
 
 
 
 
 

after Master_RPM_Request flag has been set i just check it to be true inside main

 
 
 
 
 
 
 
if ((Master_RPM_Request)
{
Send_RPM_I2C(&RPM);
Master_RPM_Request = 0;
}
 
 
 
 
 
 
 

 
Im noticing that the interruption is never triggering.
 
Yes i have 2 pull up resistors, both be 4.7 k
 
 
 
 
 
 
 
post edited by antesther - 2020/04/09 17:48:09
#4
ric
Super Member
  • Total Posts : 26942
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: PIC16F877A I2C SEN BIT NOT CLEAR 2020/04/09 18:02:17 (permalink)
0
antesther
So when RW bit goes low means that both the address and ack/nak flag were sent?

Yes.
Examine "FIGURE 9-22: I2C MASTER MODE WAVEFORM (RECEPTION, 7-BIT ADDRESS)" in the PIC16F877A datasheet.
 

This is my Slave ISR...

I hope you mean "This is the initialisation code"
INTCONbits.PEIE = 1;
INTCONbits.GIE = 1;
 
 
 
PIE1bits.SSPIE = 1; //I2C INTERRUPT ENABLE
PIR1bits.SSPIF = 0;
 

and "this is a portion of the code inside my interrupt service routine"
if ((PIR1bits.SSPIF) && (PIE1bits.SSPIE))
{
Master_RPM_Request = 1;
PIR1bits.SSPIF = ~PIR1bits.SSPIF;
}

 
Note your init code is not good.
You should clear SSPIF before you enable interrupts. Leave setting GIE until after all other initialisation is complete.
 
In your ISR, this line is needlessly complicated.
PIR1bits.SSPIF = ~PIR1bits.SSPIF;
just do
PIR1bits.SSPIF = 0;
which the PIC can do in a single assembler instruction
 
Also note, if that is all you do inside the ISR, it's pointless using an ISR at all.
Don't enable interrupts, and just test the SSPIF flag in your main code. No need for an extra Master_RPM_Request variable at all.
post edited by ric - 2020/04/09 18:03:42

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#5
antesther
Starting Member
  • Total Posts : 33
  • Reward points : 0
  • Joined: 2019/06/04 09:44:13
  • Location: Juarez, Mexico
  • Status: offline
Re: PIC16F877A I2C SEN BIT NOT CLEAR 2020/04/09 18:10:55 (permalink)
0
Yeah it's very few code for an ISR, i did it that way under the assumption that once a interrupt is triggered other interrupts triggered during its execution would have to wait untill the first ISR is finished.
 
I was afraid of it being tested not regularly by the compiler because of more interrupts triggering, im not sure 100% of this, is is true right?

 
void __interrupt() InterruptISRs(void)
{
if ((PIR1bits.CCP1IF) && (PIE1bits.CCP1IE)) //CHECAR INTERRUPT SOURCE, INTERRUPT FLAG &&
{
Elapsed_Time += ((CCPR1H << 8) | (CCPR1L));
CaptureMade = 1;
PIR1bits.CCP1IF = ~PIR1bits.CCP1IF;
}
if ((PIR1bits.TMR1IF) && (PIE1bits.TMR1IE))
{
Elapsed_Time += 65535;
PIR1bits.TMR1IF = ~PIR1bits.TMR1IF;
}
if ((PIR1bits.ADIF) && (PIE1bits.ADIE))
{
ADC_Conversion_Complete = 1;
PIR1bits.ADIF = ~PIR1bits.ADIF;
}
if ((PIR1bits.SSPIF) && (PIE1bits.SSPIE))
{
Master_RPM_Request = 1;
PIR1bits.SSPIF = ~PIR1bits.SSPIF;

}

return;
}
 

 
 
 
post edited by antesther - 2020/04/09 18:12:21
#6
ric
Super Member
  • Total Posts : 26942
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: PIC16F877A I2C SEN BIT NOT CLEAR 2020/04/09 18:20:16 (permalink)
0
antesther
Yeah it's very few code for an ISR, i did it that way under the assumption that once a interrupt is triggered other interrupts triggered during its execution would have to wait untill the first ISR is finished.

Which is precisely what you normally do NOT want to happen.
Anyway, the way you have coded this, the other interrupts would continue to be serviced, so you have gained NOTHING by adding an interrupt just to set your own flag to mimic the SSPIF flag.
Just leave SSPIE clear, and test SSPIF directly in your main code.
 

I was afraid of it being tested not regularly by the compiler because of more interrupts triggering, im not sure 100% of this, is is true right?

I don't really understand what you are asking, but I suspect you don't have  aclear understanding of how interrupts work.
 
As I already mentioned, simplify your other interrupts by just setting the IF flags to zero. It's pointless using code to invert them instead, which is MORE work for the PIC.

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#7
antesther
Starting Member
  • Total Posts : 33
  • Reward points : 0
  • Joined: 2019/06/04 09:44:13
  • Location: Juarez, Mexico
  • Status: offline
Re: PIC16F877A I2C SEN BIT NOT CLEAR 2020/04/09 18:29:40 (permalink)
0
I do understand them, just my question is, what happens when you have multiple interrupts and u have them triggering constantly leaving main code very few time to execute other instructions before another interrupt takes place, the main code that doesnt depend on interrupts just executes less frequently?
 
Assuming there are no high or low priority interrupts
post edited by antesther - 2020/04/09 18:31:55
#8
ric
Super Member
  • Total Posts : 26942
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: PIC16F877A I2C SEN BIT NOT CLEAR 2020/04/09 18:39:21 (permalink)
4 (1)
Correct, main code does not run while an interrupt is being serviced, which is why interrupt code should be short and sweet, with no delays or blocking loops.
"Constant" triggering would still normally be at a much slower rate than it takes to run your whole ISR.
If not, you have a problem.
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#9
antesther
Starting Member
  • Total Posts : 33
  • Reward points : 0
  • Joined: 2019/06/04 09:44:13
  • Location: Juarez, Mexico
  • Status: offline
Re: PIC16F877A I2C SEN BIT NOT CLEAR 2020/04/20 17:06:23 (permalink)
0
Hello Im back with no good news, I tried to make the code much simpler, i double checked everything and still have no idea whats wrong
 

 
 
 
 
 
 
 
#include <xc.h>
unsigned int slaveAddress = 0xC1; // 7-bit slave address
 
 
 
 
 
 
 
void I2C_Initialize(void)
{
TRISCbits.TRISC3=1; //pin SCL como una entrada digital
TRISCbits.TRISC4=1; //pin SDA como una entrada digital
SSPSTATbits.SMP = 1; // Disable slew control
SSPSTATbits.CKE = 0; //DISABLE SMBUS INPUTS
SSPCONbits.SSPM = 0b0110; // 7-bit slave mode
SSPCON2bits.SEN = 1; // Enable clock stretching
//SSPCON3bits.SBCDE = 1; // Enable BCLIF
SSPADD = slaveAddress; // Load slave address
SSPCONbits.SSPEN = 1; // Enable the module
//PIR3bits.BCL1IF = 0; // Clear Bus Collision IF
PIR1bits.SSPIF = 0; // Clear SSP interrupt flag
//PIE3bits.BCL1IE = 1; // Enable BCLIF
PIE1bits.SSPIE = 1; // Enable SSPIF
INTCONbits.PEIE = 1; // Enable periph interrupts
INTCONbits.GIE = 1; // Enable global interrupts
SSPBUF = 0;
}
void __interrupt() ISR(void)
{
temp = SSPBUF;
if(PIR1bits.SSPIF) // Check for SSPIF
{
PORTDbits.RD7 = 1;
if(SSPSTATbits.R_nW == 1) // Master read (slave transmit)
{

SSPBUF = 0x78; // Load SSPBUF with data to be sent to the master pic
SSPCONbits.CKP = 1; // Release clock stretch
}
}
PIR1bits.SSPIF = 0; // Clear SSP1IF
}
 
 
 
 
 
 
 
void main(void)
{
I2C_Initialize();

while (1)
{

}
}
 
 
 
 
 
 
 

 
I have tried debugging the i2c comm using i2c debugger on proteus 8.7
this is what i have done so far:
-I configured the i2c debugger as Slave filling in the address byte 1 field with address 0xC1 and then connected both Master and the i2c debugger to check if i2c debugger acknowledged the address sent by the master and sent data back to the master, once it pulled SDA line low (ACK), it sent a test number and it was received and printed on the master side (using a 16x2 LCD).

So the problem is not with the master.
 
I did the same thing with the Slave pic, connected both the i2c debugger this time acting as a master and the pic acting as a slave, using the i2c debugger terminal i sent "S 0xC1 P" (Start, Slave Address, Stop) but the pic slave stil generated nak on the ninth bit. 
 
Im quite desperate I have read all of the app notes and my code complies with what is established in them, can anyone help me please?
post edited by antesther - 2020/04/20 17:14:35

Attached Image(s)

#10
ric
Super Member
  • Total Posts : 26942
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: PIC16F877A I2C SEN BIT NOT CLEAR 2020/04/20 17:42:22 (permalink) ☄ Helpfulby antesther 2020/04/20 18:56:42
5 (1)

unsigned int slaveAddress = 0xC1; // 7-bit slave address

"0xC1 is NOT a "7 bit slave address"
That is a full 8 bit read address.
Try changing it to
unsigned int slaveAddress = 0xC0; // 8-bit slave address

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#11
antesther
Starting Member
  • Total Posts : 33
  • Reward points : 0
  • Joined: 2019/06/04 09:44:13
  • Location: Juarez, Mexico
  • Status: offline
Re: PIC16F877A I2C SEN BIT NOT CLEAR 2020/04/20 18:20:50 (permalink)
0
Holy crap it was that!
 
I cant believe i had declared a bigger value than 127, it ws that all along, i feel so dumb, thank you ric, i thought the RW bit was taken into account for this but i remember having read that only the upper 7 bits are the ones that matter
#12
ric
Super Member
  • Total Posts : 26942
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: PIC16F877A I2C SEN BIT NOT CLEAR 2020/04/20 18:24:03 (permalink)
5 (1)
I'm not entirely sure that bit matters on the real device.
This may just be the Proteus simulator being overly pedantic.
 
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#13
antesther
Starting Member
  • Total Posts : 33
  • Reward points : 0
  • Joined: 2019/06/04 09:44:13
  • Location: Juarez, Mexico
  • Status: offline
Re: PIC16F877A I2C SEN BIT NOT CLEAR 2020/04/20 18:31:44 (permalink)
5 (1)
has it ever happened to you that something VERY simple may be the cause of all the problems u have, and then u spend a considerable amount of time thinking it may be something difiicult like timings, sync or etc
#14
ric
Super Member
  • Total Posts : 26942
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: PIC16F877A I2C SEN BIT NOT CLEAR 2020/04/20 18:43:14 (permalink)
0
Welcome to programming. :)
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#15
Jump to:
© 2020 APG vNext Commercial Version 4.5