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 and port b in 16f78
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
karun211



Joined: 06 Feb 2006
Posts: 8

View user's profile Send private message

i2c and port b in 16f78
PostPosted: Mon Feb 06, 2006 8:34 pm     Reply with quote

Hi

It has been a wonderful experience using the CCSC compiler for my PIC projects . Thanks for the amazing compiler . Of late I have sort of run into a problem where in when the I2C communication is enabled and used in PIC16F87 , I am unable to use Port B pins for input . I have also disabled the interrupt on change and all other interrupts but for I2C . When the program reads an input from the Port B , the I2C communication gets killed in the board . I have not been able to figure out any solution to this . I am just wondering if there is a known bug in using I2C and Port B for inputs ( even when trying to read each pin at a time ) on the 16F87 .Any kind of advice on this would be very helpful .

Thanks
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Feb 06, 2006 9:40 pm     Reply with quote

1. Do you have a debugger (ICD2) connected to the PIC ?

2. Do you have NOLVP in your #fuses statement ?
If not, then add it.
karun211



Joined: 06 Feb 2006
Posts: 8

View user's profile Send private message

thanks
PostPosted: Mon Feb 06, 2006 11:06 pm     Reply with quote

[quote="PCM programmer"]1. Do you have a debugger (ICD2) connected to the PIC ?

2. Do you have NOLVP in your #fuses statement ?
If not, then add it.[/quote]

i dont have a debugger connected and i never tried NOLVP in #fuses , i will give it a shot ASAP tomm morning and let you know the results..
thanks for the support
karun211



Joined: 06 Feb 2006
Posts: 8

View user's profile Send private message

Re: thanks
PostPosted: Tue Feb 07, 2006 2:12 pm     Reply with quote

[quote="karun211"][quote="PCM programmer"]1. Do you have a debugger (ICD2) connected to the PIC ?

2. Do you have NOLVP in your #fuses statement ?
If not, then add it.[/quote]

I tried it using NOLVP in #fuses , it didnot work. do you have any other thoughts?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Feb 07, 2006 2:26 pm     Reply with quote

1. Post a short but complete program that demonstrates the problem.
Show all #include, #device, #fuses, and #use statements.

2. Post your compiler version.
Humberto



Joined: 08 Sep 2003
Posts: 1215
Location: Buenos Aires, La Reina del Plata

View user's profile Send private message

PostPosted: Tue Feb 07, 2006 2:55 pm     Reply with quote

Two comments:

1) PIC16F87 share some portB pins with ANALOGS inputs, if one of those pins are not assigned
properly as DIGITAL inputs in your header, by default they wake up as analog inputs.

2) You are using I2C. What about the pull ups resistors ?


Humberto
karun211



Joined: 06 Feb 2006
Posts: 8

View user's profile Send private message

PostPosted: Tue Feb 07, 2006 3:52 pm     Reply with quote

Iam attaching what you asked for,

1)
#include <16F87.H>
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP,NOMCLR
#use delay(clock = 20000000)
#use i2c(slave, sda=PIN_B1, scl=PIN_B4)

2) iam using PCM version 3.174

thanks
karun211



Joined: 06 Feb 2006
Posts: 8

View user's profile Send private message

PostPosted: Tue Feb 07, 2006 4:07 pm     Reply with quote

[quote="Humberto"]Two comments:

1) PIC16F87 share some portB pins with ANALOGS inputs, if one of those pins are not assigned
properly as DIGITAL inputs in your header, by default they wake up as analog inputs.

2) You are using I2C. What about the pull ups resistors ?


Humberto[/quote]

1)thanks for the pointer, even some of port A pins take ANALOG inputs.

2)i2c bus is working fine when i use Port A pins as inputs, and it only hangs if i use any of the port B pins as inputs ( obviously iam not using I2C rb4 and rb1 pins) so i came to a conclusion that my i2c bus is pure and nothing wrong with the pullup registers. I think i am leaving out a simple obvious point and i need to figure it out soon.

thanks for the support
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Feb 07, 2006 4:15 pm     Reply with quote

I didn't mean post only the pre-processor statements. I meant
post a small program, and don't forget to also show pre-processor
statements. Post the entire test program. (But keep it short).
karun211



Joined: 06 Feb 2006
Posts: 8

View user's profile Send private message

PostPosted: Tue Feb 07, 2006 4:28 pm     Reply with quote

ooops, sorry about that.
here comes the program. This is the shortest i can give you, cause you need to know the i2c routine interrupts and anything shorter than this will not be much useful i guess. thanks

[code]
#include <16F87.H>
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP,NOMCLR
#use delay(clock = 20000000)
#use i2c(slave, sda=PIN_B1, scl=PIN_B4)


unsigned char read_i2c(void);
void i2c_interrupt_handler(void);
void i2c_initialize(void);
void i2c_error(void);
void write_i2c(unsigned char transmit_byte);

#INT_SSP
void ssp_interupt ()
{
i2c_interrupt_handler();
}


/* 16f87X bytes */
/* Change it per chip */
#byte PIC_SSPBUF=0x13
#byte PIC_SSPADD=0x93
#byte PIC_SSPSTAT=0x94
#byte PIC_SSPCON1=0x14

/* Bit defines */
#define PIC_SSPSTAT_BIT_SMP 0x80
#define PIC_SSPSTAT_BIT_CKE 0x40
#define PIC_SSPSTAT_BIT_DA 0x20
#define PIC_SSPSTAT_BIT_P 0x10
#define PIC_SSPSTAT_BIT_S 0x08
#define PIC_SSPSTAT_BIT_RW 0x04
#define PIC_SSPSTAT_BIT_UA 0x02
#define PIC_SSPSTAT_BIT_BF 0x01

#define PIC_SSPCON1_BIT_WCOL 0x80
#define PIC_SSPCON1_BIT_SSPOV 0x40
#define PIC_SSPCON1_BIT_SSPEN 0x20
#define PIC_SSPCON1_BIT_CKP 0x10
#define PIC_SSPCON1_BIT_SSPM3 0x08
#define PIC_SSPCON1_BIT_SSPM2 0x04
#define PIC_SSPCON1_BIT_SSPM1 0x02
#define PIC_SSPCON1_BIT_SSPM0 0x01


//#define RX_BUF_LEN 32
#define RX_BUF_LEN 3
#define NODE_ADDR 0x44 /* I2C address of the slave node */
#define S1 PIN_A0
#define S2 PIN_A1
#define S3 PIN_A2
#define S4 PIN_A3
#define S5 PIN_A4
#define S6 PIN_B2
#define S7 PIN_B6
#define S8 PIN_B7

unsigned char slave_buffer[RX_BUF_LEN];
int buffer_index;
int comms_error;
int debug_state;


void i2c_initialize(void)
{
/* Set up SSP module for 7-bit */
PIC_SSPCON1 = 0x36; /* 0011 0101 */
PIC_SSPADD = NODE_ADDR; /* Set the slave's address */
PIC_SSPSTAT = 0x00; /* Clear the SSPSTAT register. */
enable_interrupts(INT_SSP); /* Enable MSSP interrupts. */
// printf("initializing i2c/n");
}

void i2c_interrupt_handler(void)
{
unsigned char i2c_mask = 0x2D; /* 0010 1101 */
unsigned char temp_sspstat;
unsigned char this_byte;
unsigned char tx_byte;
int x;
/* Mask out the unnecessary bits */
temp_sspstat = PIC_SSPSTAT & i2c_mask;

switch (temp_sspstat)
{
/* Write operation, last byte was an address, buffer is full */
case 0x09: /* 0000 1001 */
/* Clear the receive buffer */
for (x=0; x<RX_BUF_LEN; x++)
{
slave_buffer[x] = 0x00;
}
buffer_index = 0; /* Clear the buffer index */
this_byte = read_i2c(); /* Do a dummy read of PIC_SSPBUF */

debug_state = 1;
break;

/* Write operation, last byte was data, buffer is full */
case 0x29: /* 0010 1001 */
/* Point to the buffer */
this_byte = read_i2c(); /* Get the byte from the SSP */
slave_buffer[buffer_index] = this_byte; /* Put it into the buffer */
buffer_index++; /* Increment the buffer pointer */
/* Get the current buffer index */
/* Subtract the buffer length */
/* Has the index exceeded the buffer length? */
if (buffer_index >= RX_BUF_LEN)
{
buffer_index = 0; /* Yes, clear the buffer index. */
}
debug_state = 2;
break;

/* Read operation; last byte was an address, buffer is empty */
case 0x0C: /* 0000 1100 */
buffer_index = 0; /* Clear the buffer index */
/* Point to the buffer */
tx_byte = slave_buffer[buffer_index]; /* Get byte from the buffer */
write_i2c(tx_byte); /* Write the byte to PIC_SSPBUF */
buffer_index++; /* increment the buffer index */
debug_state = 3;
break;

/* Read operation; last byte was data, buffer is empty */
case 0x2C: /* 0010 1100 */
/* Get the current buffer index */
/* Subtract the buffer length */
/* Has the index exceeded the buffer length? */
if (buffer_index >= RX_BUF_LEN)
{
buffer_index = 0; /* Yes, clear the buffer index */
}
/* Point to the buffer */
/* Get the byte */
tx_byte = slave_buffer[buffer_index];
write_i2c(tx_byte); /* Write to PIC_SSPBUF */
buffer_index++; /* increment the buffer index */
debug_state = 4;
break;

/* A NACK was received when transmitting data back from the master. */
/* Slave logic is reset in this case. R_W=0, D_A=1, and BF=0. */
/* If we don't stop in this state, then something is wrong!! */
case 0x28: /* 0010 1000 */
debug_state = 5;
break;

/* Something went wrong!! */
default:
i2c_error();
break;
}
}

void i2c_error(void)
{
comms_error = 1;
// printf ("Iam stupid I2C ERROR!\r\n");
}

void write_i2c(unsigned char transmit_byte)
{
unsigned char write_collision = 1;

while (PIC_SSPSTAT & PIC_SSPSTAT_BIT_BF) /* Is BF bit set in PIC_SSPSTAT? */
{
/* If yes, then keep waiting */
}

while (write_collision)
{
/* If not, then do the i2c_write. */
PIC_SSPCON1 &= ~PIC_SSPCON1_BIT_WCOL; /* Clear the WCOL flag */
PIC_SSPBUF = transmit_byte;

/* Was there a write collision? */
if (PIC_SSPCON1 & PIC_SSPCON1_BIT_WCOL)
{
/* Yes there was a write collision. */
write_collision = 1;
}
else
{
/* NO, there was no write collision. */
/* The transmission was successful */
write_collision = 0;
}
}
PIC_SSPCON1 |= PIC_SSPCON1_BIT_CKP; /* Release the clock. */
}

/* This function returns the byte in SSPBUF */
unsigned char read_i2c(void)
{
return PIC_SSPBUF;
}



void main(void)
{ int j,temp,t;
debug_state = 0;
i2c_initialize();
enable_interrupts(GLOBAL);
disable_interrupts(INT_RB);
slave_buffer[0]=0x62;
output_low_all();
while (1)
{
if (INPUT(S8)==0)slave_buffer[2]=88;
if (debug_state==2)
{
j=read_i2c();
slave_buffer[0]=j;
debug_state = 0;
}
}

}

[/code]
Humberto



Joined: 08 Sep 2003
Posts: 1215
Location: Buenos Aires, La Reina del Plata

View user's profile Send private message

PostPosted: Tue Feb 07, 2006 9:26 pm     Reply with quote

In your code you didn't post the function definition of:
output_low_all();

This statement is wrong:
Code:

   if (INPUT(S8)==0) slave_buffer[2]=88;


Surelly you wanted to write:
Code:

    if (!INPUT(S8)) slave_buffer[2]=88;


Just to see the difference it is a good practice to see the compiler .lst output file.

Your way generate this code:
Code:

....................          if (INPUT(S8)==0)
00D5:  MOVLW  00
00D6:  BTFSC  PORTB.7
00D7:  MOVLW  01
00D8:  XORLW  00
00D9:  BTFSS  STATUS.2
00DA:  GOTO   0DD
....................              slave_buffer[2]=88;
00DB:  MOVLW  58
00DC:  MOVWF  slave_buffer+2



Right way generate this code:
Code:

....................          if (!input(S8))
00DD:  BTFSC  PORTB.7
00DE:  GOTO   0E1
....................              slave_buffer[2]=88;
00DF:  MOVLW  58
00E0:  MOVWF  slave_buffer+2
....................


Humberto
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Feb 07, 2006 10:49 pm     Reply with quote

I have a question about that same line of code.
I assume that's the line you are referring to, when you say
doing an input from Port B causes i2c to stop working.


There are two possibilities:

1. It could be some low-level problem with TRIS or a Read-Modify-Write
problem, that affects the hardware i2c port.

2. It could be a design error in your program.

Your post implied that #1 is the problem, but it really could be #2.

Can you test this theory by inserting a line of code into your program
that just reads pin RB7, and doesn't control anything else ?
See if the i2c still stops working. Example:

Quote:


while (1)
{
// if (INPUT(S8)==0)slave_buffer[2]=88; // Comment this line.

temp = input(S8); // Add this line.

if (debug_state==2)
{
j=read_i2c();
slave_buffer[0]=j;
debug_state = 0;
}
}
karun211



Joined: 06 Feb 2006
Posts: 8

View user's profile Send private message

PostPosted: Wed Feb 08, 2006 9:57 am     Reply with quote

[quote="Humberto"]In your code you didn't post the function definition of:
[b]output_low_all();[/b]

i thought its not imp, this funcion pulls all the pins low. anyways iam posting it here.
void output_low_all(void)
{
output_low(S1);
output_low(S2);
output_low(S3);
output_low(S4);
output_low(S5);
output_low(S6);
output_low(S7);
output_low(S8);
}

This statement is wrong:
[code]
if (INPUT(S8)==0) slave_buffer[2]=88;
[/code]

Surelly you wanted to write:
[code]
if (!INPUT(S8)) slave_buffer[2]=88;
[/code]

thanks for correcting me, but it works if i read inputs from port A. it hangs only when i use port B pins for inputs.
Humberto[/quote]
karun211



Joined: 06 Feb 2006
Posts: 8

View user's profile Send private message

PostPosted: Wed Feb 08, 2006 10:05 am     Reply with quote

There are two possibilities:

1. It could be some low-level problem with TRIS or a Read-Modify-Write
problem, that affects the hardware i2c port.

2. It could be a design error in your program.

Your post implied that #1 is the problem, but it really could be #2.


1) I tried the above code before and came to conclusion that there is some problem with i2c and port b, as it worked fine when i used port A as inputs. I burned the code again to double check and its the same old story, i2c didnt work.

2)I still strongly belive there is some low level tris B operation which is killing my i2c when i use port B as input.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Feb 08, 2006 1:31 pm     Reply with quote

Quote:
it hangs only when i use port B pins for inputs.

In the line above, you refer to "pins". But in the code you posted,
you are only reading one pin, PIN_B7 (S8).

1. If you are reading other pins on Port B, which ones are they ?
I'm concerned that the code you posted does not show everything
you are doing. So it might be difficult for us to solve the problem.

2. Do you guarantee that there is no ICD2 or ICD or anything similar
plugged into your board ? I ask that question because Pin B7
is used by those units to communicate with the PIC. (Also pin B6).
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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