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 not working in 18F4520[error]

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



Joined: 27 Mar 2007
Posts: 33

View user's profile Send private message

I2C not working in 18F4520[error]
PostPosted: Wed Apr 04, 2007 6:45 am     Reply with quote

The below program work fine for 18F4520 master with 16F877A slave.
When i replace 16F877A with 18F4520 as slave, i got the i2c_read() value display in hyperterminal is FFFF, no matter what value i enter, master display FFFF.

p/s: I have re-configure those special function register value for different chips

Appreciate if someone can help to solve this.

This code is taken from code library i2c master and slave multibyte

Code:

//master.c
#include <18F4520.H>
// 10-bit A/D conversion
#device ADC=10
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use Delay(Clock=20000000)
#use rs232(baud=19200,xmit=PIN_C6,rcv=PIN_C7,brgh1ok)
#include <input.c>
#define EEPROM_SDA  PIN_C4
#define EEPROM_SCL  PIN_C3
#define SLAVE_ADDRESS 0x02
#use i2c(master, sda=EEPROM_SDA, scl=EEPROM_SCL, FORCE_HW)
void
initI2C()
{
 output_float(EEPROM_SCL);
 output_float(EEPROM_SDA);
}
void
writeI2C(INT16 word)
{
 i2c_start();
 delay_us(16);
 i2c_write(SLAVE_ADDRESS);  /* Device Address */
 delay_us(16);
 i2c_write(word & 0x00ff);
 delay_us(16);
 i2c_write((word & 0xff00) >> 8);
 delay_us(16);
 i2c_stop();
}
INT16
readI2C()
{
 BYTE b1=0, b2=0;
 i2c_start();   // restart condition
 i2c_write(SLAVE_ADDRESS + 1);
 b1 = i2c_read(1);
 delay_us(16);
 b2 = i2c_read(0);
 delay_us(16);
 i2c_stop();
 return make16(b2, b1);
}
INT16 gethexword() {
 BYTE lo,hi;
 hi = gethex();
 lo = gethex();
 return make16( hi,lo );
}
void main() {
 int cmd;
 INT16 value;
 initI2C();
 printf("i2c master 01 APRIL 2007\n\r\n\r");
 do {
    do
    {
       printf("\r\n[R]ead or [W]rite: ");
       cmd=getc();
       cmd=toupper(cmd);
       putc(cmd);
       if(cmd!='R' && (cmd!='W'))
    {
    value =0;
   
    printf("\r\nStupid ah! Please retype!!");
    }
    } while ( (cmd!='R') && (cmd!='W') );
   
   if(cmd=='R')
   {
      value = 0;
      value = readI2C();
      printf("\r\nValue: %lX\r\n",value );
   } else if(cmd=='W')
    {
       printf("\r\nNew 16-bit value: ");//2 bytes
       value = gethexword();
       printf("\n\r");
       writeI2C(value);
    }

 } while (TRUE);
}




slave
Code:

#include <16F877A.H>
// 10-bit A/D conversion
#device ADC=10
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use Delay(Clock=20000000)
#use rs232(baud=19200,xmit=PIN_C6,rcv=PIN_C7,brgh1ok)
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
#byte PIC_SSPCON2=0x91
/* 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 PIC_SSPCON2_BIT_GCEN    0x80
#define PIC_SSPCON2_BIT_ACKSTAT 0x40
#define PIC_SSPCON2_BIT_ACKDT   0x20
#define PIC_SSPCON2_BIT_ACKEN   0x10
#define PIC_SSPCON2_BIT_RCEN    0x08
#define PIC_SSPCON2_BIT_PEN     0x04
#define PIC_SSPCON2_BIT_RSEN    0x02
#define PIC_SSPCON2_BIT_SEN     0x01

#define RX_BUF_LEN  32
#define NODE_ADDR   0x02    /* I2C address of the slave node */
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 0110 */
 PIC_SSPADD = NODE_ADDR;  /* Set the slave's address */
 PIC_SSPSTAT = 0x00;     /* Clear the SSPSTAT register. */
 enable_interrupts(INT_SSP);  /* Enable MSSP interrupts. */
}
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 ("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)
{
  debug_state = 0;
  i2c_initialize();
  enable_interrupts(GLOBAL);
 printf("i2c slave 01 APRIL 2007\n\r\n\r");
  while (1)
  {
      if (debug_state)
      {
           printf ("debug state = %d\r\n", debug_state);
          debug_state = 0;
      }

  }
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Apr 04, 2007 11:20 am     Reply with quote

Quote:
p/s: I have re-configure those special function register value for different chips

Post those statements so we can see if they are correct.
funmix



Joined: 27 Mar 2007
Posts: 33

View user's profile Send private message

PostPosted: Wed Apr 04, 2007 5:30 pm     Reply with quote

Code:


#byte PIC_SSPBUF=0xfc9
#byte PIC_SSPADD=0xfc8
#byte PIC_SSPSTAT=0xfc7
#byte PIC_SSPCON1=0xfc6
#byte PIC_SSPCON2=0xfc5


I used 4.7k pullup register for I2C bus. Crystal running at 20Mhz.
tom_hanks



Joined: 04 Apr 2007
Posts: 20

View user's profile Send private message

PostPosted: Tue Apr 24, 2007 4:02 am     Reply with quote

i guess you need to do following change...
and may be you need to remove a while loop of BF in write_I2C...


Code:

unsigned char read_i2c(void)                      
{
  if(PIC_SSPSTAT & PIC_SSPSTAT_BIT_BF)             
     {
      PIC_PIR1  = 0x47 & PIC_PIR1;            
      return PIC_SSPBUF;
   }
}
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