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 master and i2c slave implementation problems

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



Joined: 16 Jan 2008
Posts: 61

View user's profile Send private message

i2c master and i2c slave implementation problems
PostPosted: Thu Feb 18, 2010 7:13 pm     Reply with quote

Hi All,

I am bit stuck now. I want to implement PIC18F25k20 controller in both master and slave mode. And with CCS functions I am not able to do that.

I have to use
Code:

#use i2c(Master,Slow,sda=PIN_C4,scl=PIN_C3,force_hw)

#use I2C(slave,sda=PIN_C4,scl=PIN_C3, address=0xa0,FORCE_HW)

Now these use statements cannot be modified during run time, and I can't switch back to master mode to slave mode and vice versa.

Does anyone know how to implement this requirement?

Please let me know.

Thank you,
nehal
_________________
nehal
Wayne_



Joined: 10 Oct 2007
Posts: 681

View user's profile Send private message

PostPosted: Fri Feb 19, 2010 2:58 am     Reply with quote

What you want is multi master mode.

I too had trouble finding the information on how to do this and in the end wrote my own routines. I use i2c interrupts for slave mode and switch to master mode when needed to send data.

I have listed the code snippets below. I know this is not a full program but it should show you how I managed to get it working.

I have cut out some of the irrelevent code so hopefully you will get the idea of how it works and be able to impliment your own!
There are also some defines, globals etc missing. If you have trouble understanding it I will try and help.

Code:

// from a i2c.h file
#byte SSP1CON2   = 0xFC5
#byte SSP1CON1   = 0xFC6
#byte SSP1STAT   = 0xFC7
#byte SSP1ADD   = 0xFC8
#byte SSP1BUF   = 0xFC9

#bit SSP1STAT_BF   = SSP1STAT.0   // Buffer Full                                 
#bit SSP1STAT_UA   = SSP1STAT.1   // Update Address bit (10 bit slave address)
#bit SSP1STAT_RW   = SSP1STAT.2   // Read (1), Write (0)
#bit SSP1STAT_S      = SSP1STAT.3   // Start
#bit SSP1STAT_P      = SSP1STAT.4   // Stop
#bit SSP1STAT_DA   = SSP1STAT.5   // Data (1), Address Match (0)
#bit SSP1STAT_CKE   = SSP1STAT.6   // SMBus Select Bit
#bit SSP1STAT_SMP   = SSP1STAT.7   // Slew Rate Control 100kHz (1), 400kHz (0)

#bit SSP1CON1_CKP   = SSP1CON1.4

#define I2C_NO_CMD         0
#define I2C_ESE_CMD         1
#define I2C_AUDIO_CMD      2
#define I2C_STATUS_REQ      3
#define I2C_CONFIG_REQ      4
#define I2C_SOFTWARE_UPD   5
#define I2C_ADDRESS_REQ      6
#define I2C_DONE_REQ       7

int1 bus_collision = false;

int8 i2c_state;
int8 i2c_data[80];
int8 i2c_cmd[80];
int8 i2c_data_len;
int8 i2c_data_pos;
int1 i2c_command_flag = false;


Code:

#use i2c(MULTI_MASTER, ADDRESS=0xA0, sda=PIN_C4, scl=PIN_C3, FORCE_HW, STREAM=I2C)

#INT_BUSCOL
void buscol_isr() {
   bus_collision = true;
}

#INT_SSP
void i2c_isr() {
   int c;
   int8 sign_bit, carry_bit;
   
   union {
      float grad;
      int8 array[4];
   } grad_u;

   if (!SSP1STAT_DA)    // Address Match
   {
      i2c_data_pos = 0;
      c = SSP1BUF;         // c = Address, Clears BF flag!
      if (!SSP1STAT_RW) {      // Colibri Write Data                     
         SSP1CON1_CKP = 1;       
         return;
      }
   }

   if (SSP1STAT_DA && SSP1STAT_BF)      // BF is low for a read                               
   {
      c = SSP1BUF;   // Clears BF flag!
      switch(i2c_state)
      {
         case 0:         // Command state         
            switch(c)
            {
               case I2C_AUDIO_CMD:
                  i2c_data_pos = 0;
                  i2c_state = 2;
                  break;
               case I2C_DONE_REQ:
                  i2c_data[0] = i2c_command_flag;
                  i2c_data_len = 1;
                  i2c_state = 1;      
                  break;
               default:
                  i2c_data_pos = 0;
                  i2c_state = 0;
                  break;
            }
            break;
         case 1:         // Data request state        
            break;
         case 2:         // Command state
            i2c_cmd[i2c_data_pos++] = c;
            if (i2c_data_pos == i2c_cmd[0])
            {
               i2c_state = 0;
               i2c_command_flag = true;
            }
            break;
         case 3:         // Software update data
            break;
         default:
            i2c_state = 0;   // Reset state, used to bypass data
            break;
      }
   } 

   // Load data if we have some to send back
   if (SSP1STAT_RW)      // CPU Read Data                 
   {
      SSP1BUF = i2c_data[i2c_data_pos++];
      if (i2c_data_pos == i2c_data_len)   // Last byte
      {
         i2c_data_pos = 0;
         i2c_data_len = 0;
         if (i2c_state != 3)
            i2c_state = 0;
      }
   }
   SSP1CON1_CKP = 1;       
}

void i2c_init() {
   i2c_state = 0;   
   i2c_data_len = 0;
   i2c_data_pos = 0;
   
   baud_rate = SSP1ADD;
   if (ese_mode == REPEATER) {
      SSP1CON1 = (SSP1CON1 & 0xF0) | 0x06;   //0x0E;   // Slave mode
      SSP1CON2 |= 0x01;   // Slave mode clock stretching
      SSP1ADD = I2C_ADDRESS;
      enable_interrupts(INT_BUSCOL);
      enable_interrupts(INT_SSP);
   }
}

// I2C multiMaster start
int8 i2c_mm_start(int8 address)
{
   int8 ack;
   
   disable_interrupts(INT_SSP);
   SSP1CON2 &= ~0x01;
   SSP1CON1 = (SSP1CON1 & 0xF0) | 0x08;   // Master mode
   SSP1ADD = baud_rate;
   do {
      i2c_start(I2C, 1);
      ack = i2c_write(address);   // Send address with WE (returns 0 = ACK, 1 = NOACK, 2 = Collision)
   } while (ack == 2);   // Bus Collision
   return(ack);
}

// I2C multiMaster stop
void i2c_mm_stop()
{
   i2c_stop();
   while (SSP1ADD != baud_rate) {}
   SSP1CON1 = (SSP1CON1 & 0xF0) | 0x06;   //0x0E;   // Slave mode
   SSP1CON2 |= 0x01;   // Slave mode clock stretching
   SSP1ADD = I2C_ADDRESS;   // Slave mode
   clear_interrupt(INT_SSP);
   enable_interrupts(INT_SSP);
}


void func()
{
        int val = 123;
   i2c_mm_start(COLIBRI_ADDRESS << 1);
   ack = i2c_write(val);   // ack (0=ACK, 1=NOACK, 2=Collision)                                
   i2c_mm_stop();
}


This seems to work quite well for my system.
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