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 support@ccsinfo.com

WORKING I2C MASTER AND SLAVE LOGGER : MULTI-BYTE
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
snibbe



Joined: 06 Jan 2005
Posts: 4

View user's profile Send private message

WORKING I2C MASTER AND SLAVE LOGGER : MULTI-BYTE
PostPosted: Sun Jan 09, 2005 2:05 pm     Reply with quote

I have had a very difficult time getting 2 pics to communicate via I2C. After working several weeks on and off, I've modified two examples and now have working code I would like to share in the hopes it save some of you time! The code allows one 16-bit word to be read and written from the slave. You can easily modify this to transmit and receive more data, or change the first piece of data to a command byte. The key to multi-byte reading is to read requesting an ACK: i2c_read(1) for every byte but the last: i2c_read(0).
This is pasted straight from my working programs. Thanks especially to "valemike". The slave is primarily his code. The master is modified from EX_EXTEE.

SLAVE CODE:

Code:
#include <16F876A.H>

// 10-bit A/D conversion
#device ADC=10
#fuses HS,NOWDT,NOPROTECT,NOLVP

#use Delay(Clock=20000000)
#use rs232(baud=9600,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 0101 */
   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 09 Jan 2005\n\r\n\r");
   
    while (1)
    {
        if (debug_state)
        {
            // printf ("debug state = %d\r\n", debug_state);
            debug_state = 0;
        }

      
    }
}


MASTER CODE:

Code:
#include <16F876A.H>

// 10-bit A/D conversion
#device ADC=10
#fuses HS,NOWDT,NOPROTECT,NOLVP

#use Delay(Clock=20000000)
#use rs232(baud=9600,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_ms(1);
   i2c_write(SLAVE_ADDRESS);  /* Device Address */
   //delay_ms(1);
   i2c_write(word & 0x00ff);
   //delay_ms(1);
   i2c_write((word & 0xff00) >> 8);
   //delay_ms(1);
   i2c_stop();
}

INT16
readI2C()
{
   BYTE b1=0, b2=0;
   i2c_start();   // restart condition
   i2c_write(SLAVE_ADDRESS + 1);
   b1 = i2c_read(1);
   //delay_ms(1);
   b2 = i2c_read(0);
   //delay_ms(1);
   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 09 Jan 2005\n\r\n\r");

   do {
      do {
         printf("\r\nRead or Write: ");
         cmd=getc();
         cmd=toupper(cmd);
         putc(cmd);
      } 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: ");
         value = gethexword();
         printf("\n\r");
         writeI2C(value);
      }

   } while (TRUE);
}
picer



Joined: 25 Jan 2005
Posts: 28
Location: Taxahoma

View user's profile Send private message

PostPosted: Tue Feb 08, 2005 12:42 pm     Reply with quote

I just loaded both of these, slave in 819, master in 877A. I get the READ/WRITE from rs232 and when I hit W and put a value in it never returns and I have to reset the pic. If I disconnect the two I see a quick clock pulse from the 877A and it returns to read/write, if I reconnect I see nothing at all and read/write don't work. Looks like both data and clock on the 877A are high, both on the 819 are low with a scope on those pins. I changed the values to the 819, looks like the only difference is the 819 doesn't have sspcon2. Any idea on where to go from here to trouble shoot, never done i2c before. I used the examples unmodified other than commenting out sspcon2 stuff for the 819.
fuzzy



Joined: 26 Feb 2005
Posts: 64

View user's profile Send private message

PostPosted: Fri Mar 04, 2005 7:39 pm     Reply with quote

when connected how is bus voltage? high or low? if low you have to put a pullup resistor on both lines, i use 5,6K and if still low you have to set TRIS high for these pins. I had problem with TRIS and i had to force CK pin high using this command: variable=input(pin_c3); in this case this pin was used as input and remained high. In normal condition I2C bus have to stay high.
raf



Joined: 13 Mar 2005
Posts: 3
Location: Paris

View user's profile Send private message

PostPosted: Sun Mar 13, 2005 9:15 am     Reply with quote

I've load these examples for my apllication (two 18f4431 in I2c) i've changed register values and some other things but it still doesn't work. I try (in first) to send a byte from the master to the slave. I use CCS with mplab and an ICD2 programmer.
I've a problem with interruption. when SSPCON=0x36 (slave mode) the interruption never happen. And when SSPCON=0x3E (slave mode + start and stop interuption) an interrupton happen with a start but it seems that SSPBUF does not receive data (BF is never set).

Please if someone knows what I can do to resolve this tell me!!!!
UFAnders



Joined: 13 Apr 2005
Posts: 36
Location: Michigan

View user's profile Send private message Send e-mail Visit poster's website AIM Address

SSP Interrupt not executing
PostPosted: Sat Jun 25, 2005 3:48 pm     Reply with quote

Snibbe, I have no idea why I can't get your routine to work on my chip...

I have re-defined the SSP control registers to match that of the 18F2520, but for some reason the SSP interrupt always goes to the default case once I try to read data back from the slave. I can send it values fine as hyperterminal shows the correct hex numbers contained in the slave (as entered on the master side). Once I try to read anything from the slave, however, I get the "I2C ERROR".

Here are my slave's SSP registers upon trying to read from the slave:
Quote:
I2C ERROR!
SSPBUF=11
SSPADD=10
SSPSTAT=0C
SSPCON1=66
SSPCON2=00


Anyone ever run into this? Thanks for your help!
Phil



Joined: 09 Sep 2003
Posts: 12

View user's profile Send private message

PostPosted: Mon Jul 04, 2005 7:41 am     Reply with quote

Just a quick note!

For some reason I've experienced the same when trying to write to the slave. I redeclared my #use i2c to use software I2C ( took out "FORCE_HW") and that seems to do the trick.
treitmey



Joined: 23 Jan 2004
Posts: 1094
Location: Appleton,WI USA

View user's profile Send private message Visit poster's website

PostPosted: Wed Oct 26, 2005 7:21 am     Reply with quote

If clearing the buffer is taking too much time,.. don't do it. It should be just a matter of reseting the indexes. Try it and see.
mcpublic



Joined: 01 Nov 2005
Posts: 10

View user's profile Send private message

Advice on porting i2c master slave example
PostPosted: Tue Nov 01, 2005 1:30 pm     Reply with quote

Snibbe's "WORKING I2C MASTER AND SLAVE LOGGER : MULTI-BYTE" works great at 20MHz, but at slower clock speeds, you have to do one of the following:

a) Master: insert delay after i2c_write(SLAVE_ADDRESS) in writeI2C() function (a 100us delay seems to work okay at 10Mhz)
b) Slave: read SSPBUF before clearing slave_buffer[] in i2c_interrupt_handler() case 0x09 -- (should fix problem in theory, but I haven't tested this myself)
c) Slave: choose a smaller value for RX_BUF_LEN (4 works nicely). When len=32 at 10MHz the interrupt handler takes a whopping 150us to service the address byte. If the master sends data too fast, a fatal i2c error occurs in the slave.

I have successfully ported the slave code to an 16F876A running at 10MHz and to a 16F819 running off its internal 8MHz oscillator. I am still debugging the 18F2525 port. Alas, I have yet to witness an an SSP interrupt.
sonicdeejay



Joined: 20 Dec 2005
Posts: 112

View user's profile Send private message

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

guys,,,any update on 18F2525??


I am planning to comunicate 2 PIC18F2525 ...


Code:
* 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



how can I change those info to suit my PIC18F2525..
mcpublic



Joined: 01 Nov 2005
Posts: 10

View user's profile Send private message

Porting to 18F2525/4525
PostPosted: Tue Feb 07, 2006 8:01 am     Reply with quote

I do have an update for the 18F2525/4525. I'm sure you can read the datasheet to get the 18F SSP register addresses.

The key difference between the 876A SSP module wrt i2c slave is that addresses below 0x20 don't work. Microchip tech support says the engineers were just trying to adhere better to the spec, but I'm sure they wish it had been done with better documentation.
sonicdeejay



Joined: 20 Dec 2005
Posts: 112

View user's profile Send private message

Re: Porting to 18F2525/4525
PostPosted: Fri Feb 10, 2006 10:12 pm     Reply with quote

mcpublic wrote:
I do have an update for the 18F2525/4525. I'm sure you can read the datasheet to get the 18F SSP register addresses.

The key difference between the 876A SSP module wrt i2c slave is that addresses below 0x20 don't work. Microchip tech support says the engineers were just trying to adhere better to the spec, but I'm sure they wish it had been done with better documentation.



This is I needa change rite?? the image is taken from PIC18F2525 datasheet.



Last edited by sonicdeejay on Sat Feb 11, 2006 1:36 pm; edited 1 time in total
mcpublic



Joined: 01 Nov 2005
Posts: 10

View user's profile Send private message

Re: Porting to 18F2525/4525
PostPosted: Fri Feb 10, 2006 11:09 pm     Reply with quote

Yes, this is the right table of register addresses.
Let me know if you have any more questions.
FYI, almost every problem I ran into was solved
by adding delays between i2c master commands.
mcpublic



Joined: 01 Nov 2005
Posts: 10

View user's profile Send private message

PIC18F4525 port code
PostPosted: Mon Feb 13, 2006 2:54 pm     Reply with quote

Here is the stripped-down hardware i2c slave code
ported to a PIC18f4525 running at 10MHz (no 4x PLL!)
Below is the master code with some commentary

--Tim

Code:

//// i2c 16-BIT SLAVE CODE

// Author: valemike

#define UNIT_TEST

// Assumes PIC18F4525 @ 10MHz

#ifdef UNIT_TEST
  #include <18f4525.h>

  #fuses HS,NOLVP,NOWDT,PUT

  // Pins

  // RS-232
  #define RX_PIN        PIN_C7
  #define TX_PIN        PIN_C6

  // config

  #use delay(clock=10000000, restart_wdt)
  #use rs232(baud=9600, xmit=TX_PIN, rcv=RX_PIN) //+++ up baud rate?

  void main (void);

#endif // UNIT_TEST

// Prototypes

unsigned char read_i2c(void);
void i2c_interrupt_handler(void);
void i2c_initialize(void);
void i2c_error(unsigned int temp_sspstat);
void write_i2c(unsigned char transmit_byte);
void toggle_light(void);
void wait_for_bf_low(void);

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

/* PIC Registers */

#byte PIC_SSPBUF   = 0xfc9
#byte PIC_SSPADD   = 0xfc8
#byte PIC_SSPSTAT  = 0xfc7
#byte PIC_SSPCON1  = 0xfc6
#byte PIC_PIE1     = 0xf9d
#byte PIC_TRISC    = 0xf94

#byte PIC_SSPCON2  = 0xfc5

/* 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

/* Parameters */

#define RX_BUF_LEN  4 //8 //32
#define LOGBUF_MASK 0x07
#define NODE_ADDR   0x20 /* I2C address of the slave node (avoid addr masking) */

unsigned char slave_buffer[RX_BUF_LEN];

int buffer_index;
int comms_error;
int debug_state;

void i2c_initialize(void)
{
  debug_state = 0;

  /* Set up SSP module for 7-bit */
  while (PIC_SSPCON2 & 0x1f) {
    // ACKEN RCEN PEN RSEN SEN all must be zero
  };
  PIC_SSPSTAT = 0x00;     /* Clear the SSPSTAT register. */
  PIC_SSPCON1 = 0x36;   /* 0011 0101 */
  PIC_SSPADD = NODE_ADDR;  /* Set the slave's address */
  /* init buffers */
  buffer_index = 0;
  /* Go */
  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;
   
    //toggle_light(); //DBG

    /* log SSPSTAT */

    /* 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 */
#ifdef I2C_DAEMON
      // If enough data is in, this would move it to application's double buffer
      i2c_double_buffer_daemon();
#endif // I2C_DAEMON
      /* 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 */
    label_0c:
      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 [to] 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;
       
      /* Read operation; last byte was address, buffer is full */
    case 0x0d:
      this_byte = read_i2c();   // Do a dummy read of PIC_SSPBUF to clear it
      wait_for_bf_low();
      goto label_0c; // reduced to the normal case
      /* Something went wrong!! */
    default:
      debug_state = 0xe;
      break;
    }
    //red_light(); //DBG
}

unsigned int error_sspstat;

void i2c_error(unsigned int temp_sspstat)
{
    comms_error = 1;
    error_sspstat = temp_sspstat;
}

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;
}

#ifdef UNIT_TEST
void main (void)
{
  debug_state = 0;
  i2c_initialize();
  enable_interrupts(GLOBAL);
   
 main_loop:
  //while (1)
  {
    if (debug_state)
      {
   debug_state = 0;
      }
  goto main_loop;
  }
}
#endif // UNIT_TEST

void wait_for_bf_low(void)
{
 bf_loop:
  if (PIC_SSPSTAT & 0x1) { //BF=1
    goto bf_loop;
  }
  else {
  }
}


Here is the stripped-down master code.
In UNIT_TEST mode, it automatically tests
to see if the whole system works.
If it sees nacks, it reports that.
Usually this means the slave missed
some or all the commands sent by the
master. If it missed all the commands
(3 nacks) then maybe the slave is totally dead
or wrong address. If it only misses one
or two commands (e.g. 1 nack) then it is
probably a timing issue. Add delays in the
master.

Code:

//// i2c 16-BIT MASTER CODE

// Author: snibbe

/* This is pasted straight from my working programs. Thanks especially
to "valemike". The slave is primarily his code. The master is modified
from EX_EXTEE. */

#define UNIT_TEST
//#define SYNC_TEST // test double buffering

// Assumes PIC18F4525 @ 10MHz

#ifdef UNIT_TEST

  #include <18f4525.h>

  #fuses HS,NOLVP,NOWDT,PUT

  // Pins

  // RS-232
  #define RX_PIN        PIN_C7
  #define TX_PIN        PIN_C6

  // config

  #use delay(clock=10000000, restart_wdt)
  #use rs232(baud=9600, xmit=TX_PIN, rcv=RX_PIN) //+++ up baud rate?

  // conditional proto

  void main (void);

#endif // UNIT_TEST

#define SLAVE_ADDRESS 0x20 // addr=2 reserved, note address masking

#define EEPROM_SDA  PIN_C4
#define EEPROM_SCL  PIN_C3

#use i2c(master, sda=EEPROM_SDA, scl=EEPROM_SCL, FORCE_HW)

#byte PIC_SSPCON2  = 0xfc5

// 1/9/2006 ** needed longer delay to work at 10MHz
#define I2C_DELAY_US           16 // worked 20 //Worked 32 //75 //100
#define I2C_INTERBYTE_DELAY_US 60 // worked 80

int i2c_nack;

// Protos

void initI2C (void);
void writeI2C (int16 word, unsigned int slave_addr);
int16 readI2C (unsigned int slave_addr);

// code

void initI2C (void)
{
   output_float(EEPROM_SCL);
   output_float(EEPROM_SDA);
}

void writeI2C (int16 word, unsigned int slave_addr)
{
   i2c_nack=0;
   i2c_start();
   delay_us(I2C_DELAY_US);
   i2c_write(slave_addr);  /* Device Address */
   if (PIC_SSPCON2 & 0x40) i2c_nack++;
   delay_us(I2C_INTERBYTE_DELAY_US);
   i2c_write(word & 0x00ff);            //LSB first
   if (PIC_SSPCON2 & 0x40) i2c_nack++;
   delay_us(I2C_INTERBYTE_DELAY_US);
   i2c_write((word & 0xff00) >> 8);     //MSB second
   if (PIC_SSPCON2 & 0x40) i2c_nack++;
   delay_us(I2C_DELAY_US);
   i2c_stop();
}

int16 readI2C (unsigned int slave_addr)
{
   BYTE b1=0, b2=0;
   i2c_nack=0;
   i2c_start();   // restart condition
   delay_us(I2C_DELAY_US);
   i2c_write(slave_addr + 1);
   if (PIC_SSPCON2 & 0x40) i2c_nack++;
   delay_us(I2C_INTERBYTE_DELAY_US);
   b1 = i2c_read(1);
   if (PIC_SSPCON2 & 0x40) i2c_nack++;
   delay_us(I2C_INTERBYTE_DELAY_US);
   b2 = i2c_read(0);
   if (PIC_SSPCON2 & 0x40) i2c_nack++;
   delay_us(I2C_DELAY_US);
   i2c_stop();
   return make16(b2, b1);
}

#ifdef UNIT_TEST
  #ifndef SYNC_TEST
    #define TEST_VAL 0x1234
  #else // SYNC_TEST
    #define TEST_VAL1 0xfb2d // LSB: distance=45 MSB: slope=-5
    #define TEST_VAL2 0x0d19 // LSB: distance=25 MSB: slope=13
    #define TEST_VAL3 0xe019 // LSB: distance=25 MSB: slope=-20
  #endif //~SYNC_TEST

void main ()
{
#ifndef SYNC_TEST
  int16 value;
#endif //~SYNC_TEST

  // wait for LCD to boot
  putc('4');
  delay_ms(1000);
  putc('3');
  delay_ms(1000);
  putc('2');
  delay_ms(1000);
  putc('1');
  delay_ms(1000);

  puts ("");
  puts ("i2c unit test");
  puts (__DATE__ " " __TIME__);

  // Initialize
  initI2C();

#ifdef SYNC_TEST

 sync_loop:

  writeI2C(TEST_VAL1, SLAVE_ADDRESS);
  if (i2c_nack) {
    printf("%d nacks on write 1\r\n", i2c_nack);
  }
  else {
    puts("Successful write 1");
  }
  delay_us(333);

  writeI2C(TEST_VAL2, SLAVE_ADDRESS);
  if (i2c_nack) {
    printf("%d nacks on write 2\r\n", i2c_nack);
  }
  else {
    puts("Successful write 2");
  }
  delay_us(333);

  writeI2C(TEST_VAL3, SLAVE_ADDRESS);
  if (i2c_nack) {
    printf("%d nacks on write 3\r\n", i2c_nack);
  }
  else {
    puts("Successful write 3");
  }
  delay_us(333);

  goto sync_loop;

#else //~SYNC_TEST

  // Write
  value = TEST_VAL;
  writeI2C(value, SLAVE_ADDRESS);
  if (i2c_nack) {
    printf("%d nack(s) on write\r\n", i2c_nack);
  }
  else {
    puts("Successful write");
  }

  // Read
  value = 0;
  value = readI2C(SLAVE_ADDRESS);
  if (value == TEST_VAL) {
    puts("Successful read!");
  }
  else {
    printf("Failed read: %lX\r\n", value);
  }
  if (i2c_nack) {
    printf("%d nack(s) on read\r\n", i2c_nack);
  }
#endif // SYNC_TEST
}
#endif // UNIT_TEST
mcpublic



Joined: 01 Nov 2005
Posts: 10

View user's profile Send private message

Debugging this i2c code -- you will want to use a scope!
PostPosted: Mon Feb 13, 2006 3:13 pm     Reply with quote

I would not have gotten anywhere porting this i2c code to different processors and different clock speeeds if I didn't (a) have an understanding of i2c signalling (especially the ack/clock-stretching at the end of each "packet"), and (b) if I didn't have a scope to watch the i2c clock and data lines.

You might get lucky, and this will all "just work" but I feel obliged to warn folks who don't have much hardware experience that this code is not really "plug-and-play." In particular, the PIC i2c hardware is incredible timing sensitive.

Also, not all PIC SSP modules are the same. There was a significant "upgrate" from the PIC16F876A to the later PIC18F series. This is why the code originally posted on this forum didn't work without changing the slave address.

Note that some SSP modules are "slave only" meaning they expect you to do all the master stuff in software. This is fine as long as you aren't doing multiple-master stuff. The nack detection is probably not doable in software, but if it is, it would be a pain.

I found the following technique useful. It let me see with a scope if the slave's interrupt routine was taking too long. Three probes: SDA_PIN, SCL_PIN, and RED_LED_PIN. If the interrupt routine doesn't finish until the next packet, you need to shorten it. E.g. don't clear buffer, just reset pointer, as previously noted. (Yes, I noticed that interrupt is misspelled as "interupt", but the compiler doesn't care).

Code:
#INT_SSP
void ssp_interupt ()
{
  #use fast_io(LED_PORT)
  output_high(RED_LED_PIN);
  i2c_interrupt_handler();
  output_low(RED_LED_PIN);
  #use standard_io(LED_PORT)
}
Ken481



Joined: 27 Mar 2006
Posts: 5

View user's profile Send private message

I2C works fine when ICD is plugged in, but not without
PostPosted: Mon Mar 27, 2006 12:37 pm     Reply with quote

I can Write any 16-bit word to the slave and Read it back just fine on the master when the ICD is plugged in to the slave board. But when I unplug the ICD from the slave board, I Read FFFF. The slave is a 16F877A running at 20Mhz and the master is a 18F252 running at 10Mhz. Whether the ICD program is launched or closed, I get this same result. Is the #byte PIC_TRISC = 0x87 statement correct? Also, I don't know if it is relevant but the voltage on the MCLR pin to Gnd is 4.00V when the ICD is plugged in and 5.00V when not plugged in.

[code][ i2c 16-BIT SLAVE CODE

// Author: valemike

#define UNIT_TEST

// Assumes PIC18F4525 @ 10MHz

#ifdef UNIT_TEST
//#include <18f4525.h>
#include <16F877A.h>

#fuses HS,NOLVP,NOWDT,PUT

// Pins

// RS-232
#define RX_PIN PIN_C7
#define TX_PIN PIN_C6

// config

#use delay(clock=10000000, restart_wdt)
#use rs232(baud=9600, xmit=TX_PIN, rcv=RX_PIN) //+++ up baud rate?
//#use rs232(DEBUGGER)
void main (void);

#endif // UNIT_TEST

// Prototypes

unsigned char read_i2c(void);
void i2c_interrupt_handler(void);
void i2c_initialize(void);
void i2c_error(unsigned int temp_sspstat);
void write_i2c(unsigned char transmit_byte);
void toggle_light(void);
void wait_for_bf_low(void);

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

/* PIC Registers */
#byte PIC_SSPBUF=0x13
#byte PIC_SSPADD=0x93
#byte PIC_SSPSTAT=0x94
#byte PIC_SSPCON1=0x14
#byte PIC_SSPCON2=0x91

#byte PIC_PIE1 = 0x8c
#byte PIC_TRISC = 0x87



/* 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

/* Parameters */

#define RX_BUF_LEN 8 //8 //32
#define LOGBUF_MASK 0x07
#define NODE_ADDR 0x02 /* I2C address of the slave node (avoid addr masking) */

unsigned char slave_buffer[RX_BUF_LEN];

int buffer_index;
int comms_error;
int debug_state;

void i2c_initialize(void)
{
debug_state = 0;

/* Set up SSP module for 7-bit */
while (PIC_SSPCON2 & 0x1f) {
// ACKEN RCEN PEN RSEN SEN all must be zero
};
PIC_SSPSTAT = 0x00; /* Clear the SSPSTAT register. */
PIC_SSPCON1 = 0x36; /* 0011 0101 */
PIC_SSPADD = NODE_ADDR; /* Set the slave's address */
/* init buffers */
buffer_index = 0;
/* Go */
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;

//toggle_light(); //DBG

/* log SSPSTAT */

/* 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 */
#ifdef I2C_DAEMON
// If enough data is in, this would move it to application's double buffer
i2c_double_buffer_daemon();
#endif // I2C_DAEMON
/* 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 */
label_0c:
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 [to] 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;

/* Read operation; last byte was address, buffer is full */
case 0x0d:
this_byte = read_i2c(); // Do a dummy read of PIC_SSPBUF to clear it
wait_for_bf_low();
goto label_0c; // reduced to the normal case
/* Something went wrong!! */
default:
debug_state = 0xe;
break;
}
//red_light(); //DBG
}

unsigned int error_sspstat;

void i2c_error(unsigned int temp_sspstat)
{
comms_error = 1;
error_sspstat = temp_sspstat;
}

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;
}

#ifdef UNIT_TEST
void main (void)
{
debug_state = 0;
i2c_initialize();
enable_interrupts(GLOBAL);

main_loop:
//while (1)
{
if (debug_state)
{
debug_state = 0;
}
goto main_loop;
}
}
#endif // UNIT_TEST

void wait_for_bf_low(void)
{
bf_loop:
if (PIC_SSPSTAT & 0x1) { //BF=1
goto bf_loop;
}
else {
}
}
]





master code:


//// i2c 16-BIT MASTER CODE

// Author: snibbe

/* This is pasted straight from my working programs. Thanks especially
to "valemike". The slave is primarily his code. The master is modified
from EX_EXTEE. */

#define UNIT_TEST
//#define SYNC_TEST // test double buffering

// Assumes PIC18F4525 @ 10MHz

#ifdef UNIT_TEST

//#include <18f4525.h>
#include <18f252.h>
#fuses HS,NOLVP,NOWDT,PUT

// Pins

// RS-232
#define RX_PIN PIN_C7
#define TX_PIN PIN_C6

// config

#use delay(clock=10000000, restart_wdt)
#use rs232(baud=9600, xmit=TX_PIN, rcv=RX_PIN) //+++ up baud rate?

// conditional proto

void main (void);

#endif // UNIT_TEST

#define SLAVE_ADDRESS 0x02 // addr=2 reserved, note address masking

#define EEPROM_SDA PIN_C4
#define EEPROM_SCL PIN_C3

#use i2c(master, sda=EEPROM_SDA, scl=EEPROM_SCL, FORCE_HW)

#byte PIC_SSPCON2 = 0x91

// 1/9/2006 ** needed longer delay to work at 10MHz
#define I2C_DELAY_US 16 // worked 20 //Worked 32 //75 //100
#define I2C_INTERBYTE_DELAY_US 60 // worked 80

int i2c_nack;

// Protos

void initI2C (void);
void writeI2C (int16 word, unsigned int slave_addr);
int16 readI2C (unsigned int slave_addr);

// code

void initI2C (void)
{
output_float(EEPROM_SCL);
output_float(EEPROM_SDA);
}

void writeI2C (int16 word, unsigned int slave_addr)
{
i2c_nack=0;
i2c_start();
delay_us(I2C_DELAY_US);
i2c_write(slave_addr); /* Device Address */
if (PIC_SSPCON2 & 0x40) i2c_nack++;
delay_us(I2C_INTERBYTE_DELAY_US);
i2c_write(word & 0x00ff); //LSB first
if (PIC_SSPCON2 & 0x40) i2c_nack++;
delay_us(I2C_INTERBYTE_DELAY_US);
i2c_write((word & 0xff00) >> 8); //MSB second
if (PIC_SSPCON2 & 0x40) i2c_nack++;
delay_us(I2C_DELAY_US);
i2c_stop();
}

int16 readI2C (unsigned int slave_addr)
{
BYTE b1=0, b2=0;
i2c_nack=0;
i2c_start(); // restart condition
delay_us(I2C_DELAY_US);
i2c_write(slave_addr + 1);
if (PIC_SSPCON2 & 0x40) i2c_nack++;
delay_us(I2C_INTERBYTE_DELAY_US);
b1 = i2c_read(1);
if (PIC_SSPCON2 & 0x40) i2c_nack++;
delay_us(I2C_INTERBYTE_DELAY_US);
b2 = i2c_read(0);
if (PIC_SSPCON2 & 0x40) i2c_nack++;
delay_us(I2C_DELAY_US);
i2c_stop();
return make16(b2, b1);
}

#ifdef UNIT_TEST
#ifndef SYNC_TEST
#define TEST_VAL 0x1234
#else // SYNC_TEST
#define TEST_VAL1 0xfb2d // LSB: distance=45 MSB: slope=-5
#define TEST_VAL2 0x0d19 // LSB: distance=25 MSB: slope=13
#define TEST_VAL3 0xe019 // LSB: distance=25 MSB: slope=-20
#endif //~SYNC_TEST

void main ()
{
#ifndef SYNC_TEST
int16 value;
#endif //~SYNC_TEST

// wait for LCD to boot
putc('4');
delay_ms(1000);
putc('3');
delay_ms(1000);
putc('2');
delay_ms(1000);
putc('1');
delay_ms(1000);

puts ("");
puts ("i2c unit test");
puts (__DATE__ " " __TIME__);

// Initialize
initI2C();

#ifdef SYNC_TEST

sync_loop:

writeI2C(TEST_VAL1, SLAVE_ADDRESS);
if (i2c_nack) {
printf("%d nacks on write 1\r\n", i2c_nack);
}
else {
puts("Successful write 1");
}
delay_us(333);

writeI2C(TEST_VAL2, SLAVE_ADDRESS);
if (i2c_nack) {
printf("%d nacks on write 2\r\n", i2c_nack);
}
else {
puts("Successful write 2");
}
delay_us(333);

writeI2C(TEST_VAL3, SLAVE_ADDRESS);
if (i2c_nack) {
printf("%d nacks on write 3\r\n", i2c_nack);
}
else {
puts("Successful write 3");
}
delay_us(333);

goto sync_loop;

#else //~SYNC_TEST

// Write
value = TEST_VAL;
writeI2C(value, SLAVE_ADDRESS);
if (i2c_nack) {
printf("%d nack(s) on write\r\n", i2c_nack);
}
else {
puts("Successful write");
}

// Read
value = 0;
value = readI2C(SLAVE_ADDRESS);
if (value == TEST_VAL) {
puts("Successful read!");
}
else {
printf("Failed read: %lX\r\n", value);
}
if (i2c_nack) {
printf("%d nack(s) on read\r\n", i2c_nack);
}
#endif // SYNC_TEST
}
#endif // UNIT_TEST
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library 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