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

Can't seem to make I2C Master - Slave work

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



Joined: 01 Oct 2003
Posts: 172
Location: Punta Gorda, Florida USA

View user's profile Send private message Send e-mail

Can't seem to make I2C Master - Slave work
PostPosted: Mon Apr 06, 2009 7:35 pm     Reply with quote

Hello,

I am posting the code below because I seem to be lost as to why my Master and Slave configuration does not seem to be working
For this particular test I am using two PIC16F88's and using the internal USART to do the I2C communications. What I need to do is the following:

For the master; all I need to do is to send to the slave a single byte command whenever the master gets a single byte char from the rs232 serial port, that is all the master does.

For the Slave all I need to do is to read its I2C port address from a 10 pos bcd switch on port a0-a3, that becomes it's address which is conveyed to the master. I use a 3 byte buffer where the first location is the slave address and the second location is the data or command I receive from the master. After that, all I do is just sit on a loop waiting for a I2C interrupt (which does not seem to work, in other words I never go into the interrupt, first clue) when I come out of the interrupt I set a flag, and on the main loop if this flag is set I then decode the data the master sent to me and turn on or off one of three leds....That is it!

Sounds very simple and I am sure it is, but I cannot seem to get the slave to do anything, although the master seems to be sending the correct data. I have looked at various samples here and I still can't seem to see what I am missing. If anyone can look at this and give me a clue it would be of great help.

Thank you Confused


Master code:
Code:

unsigned char Command,result,Address;
int8 RCVFlag = 0;

#define EPPHVREAD   (Address << 1) | 0x1
#define EPPHVWRITE  (Address << 1) | 0x0

void Init()
{
   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_OFF);
   port_b_pullups(TRUE);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   setup_oscillator(OSC_8MHZ|OSC_TIMER1);
   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);
}

#int_RDA
void RDA_isr()
{
  Command = getc();
  RCVFlag = 1;
  restart_wdt();
}

int8 Read_Device(int8 register_address)
{
  unsigned char data;
     
  restart_wdt();
  i2c_start();
  i2c_write(EPPHVWRITE);
  i2c_write(register_address);
  i2c_write(EPPHVREAD);
  data = i2c_read(0);
  i2c_stop();
  return(data);     
}


void Write_Register(int8 register_address, int8 register_data)
{
  i2c_start();
  i2c_write(EPPHVWRITE);
  i2c_write(register_address);
  i2c_write(register_data);
  i2c_stop();
}


void main()
{
  Init();
   
  Address = 0x9;
  result = Read_Device(0);
  delay_ms(50);
     
  while(1)
   {
      if(RCVFlag)
      {
        i2c_write (1,Command);
        RCVFlag = 0;
      }
      restart_wdt();
   }

}


Slave Code:
Code:

#include "C:\PICOMP\FILES\Sage\PIPPIN\EPPSMOD.h"
#ZERO_RAM

int8 I2CFlag = 0;
unsigned int8 state,address,data,portvalue, buffer[3];   

#define PORTADDRESS buffer[0]
#define COMMAND buffer[1]

void Init()
{
   #use i2c(Slave,Fast,sda=PIN_B1,scl=PIN_B4,address=0x09,force_hw,restart_wdt)
   port_b_pullups(TRUE);
   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_OFF);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_wdt(WDT_576MS|WDT_DIV_16);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   setup_oscillator(OSC_8MHZ|OSC_TIMER1);
   output_high(VICTRL);
   delay_ms(1000);
   output_high(HVCTRL);
   delay_ms(1000);
   output_high(ECNTRL);
   delay_ms(1000);
   output_low(VICTRL); //comes up in CV mode
   output_low(HVCTRL); //comes up with electrodes innactive
   output_low(ECNTRL); //comes up with DRAIN electrode active
   enable_interrupts(INT_SSP);      //enable I2C interrupts
   enable_interrupts(GLOBAL);
}

 
#INT_SSP
void sspinterupt ()
{
  state = i2c_isr_state();
 
  if(state < 0x80) //Master is sending data
  {
    if(state == 0)
    {
    }
    if(state == 1)  //First received byte is address
    {
      data = i2c_read();
      address = data;
    }
    if(state == 2)  //Second received byte is data
    {
      data = i2c_read();
      buffer[address] = data;
    }
  }
  if(state == 0x80)  //Master is requesting data
  {
    i2c_write (buffer[address]);
  }
  I2CFlag = 1;
}


void main()
{
  Init();
   
   PORTADDRESS = portA & 0x0F;
 
   //PortAddress = 9;
  // i2c_SlaveAddr(PORTADDRESS);
     
   while(1)
   { 
      if(I2CFlag)
      {        output_high(HVCTRL); DELAY_MS(100); output_low(HVCTRL);
        switch (COMMAND)
        {    case 'V':
             output_low(VICTRL); // turn off CI LED
             I2CFlag = 0;
             break;
             case 'I':
             output_high(VICTRL); //turn on CI LED
             I2CFlag = 0;
             break;
             case 'X':
             output_low(HVCTRL); //turn off HVCTRL LED
             I2CFlag = 0;
             break;
             case 'O':
             output_high(HVCTRL); //turn on HVCTRL LED
             I2CFlag = 0;
             break;
             case 'D':
             output_low(ECNTRL); //turn off DRAIN LED
             I2CFlag = 0;
             break;
             case 'S':
             output_high(ECNTRL); //turn on DRAIN LED
             I2CFlag = 0;
             break;
             default:
             output_low(VICTRL); //comes up to init mode
             output_low(HVCTRL);
             output_low(ECNTRL);
             I2CFlag = 0;
             break;
            }
       }
      restart_wdt();
   }

}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Apr 06, 2009 7:57 pm     Reply with quote

Quote:

Address = 0x9;

#define EPPHVREAD (Address << 1) | 0x1
#define EPPHVWRITE (Address << 1) | 0x0

You can't use 0x09 for the Slave address. It's reserved. See this post:
http://www.ccsinfo.com/forum/viewtopic.php?t=33966&start=3


Quote:
#use i2c(Slave,Fast,sda=PIN_B1,scl=PIN_B4,address=0x09,force_hw,restart_wdt)

The Slave address specified in the #use i2c() statement must be in
pre-shifted byte format. This is different from the Philips 7-bit unshifted
format. If you were allowed to use 0x09 (in Philips format) for the
slave address, you would specifiy it as 0x12 in the #use i2c() statement.
But you can't use that address.
cbarberis



Joined: 01 Oct 2003
Posts: 172
Location: Punta Gorda, Florida USA

View user's profile Send private message Send e-mail

PostPosted: Mon Apr 06, 2009 8:24 pm     Reply with quote

Thank You pcm programmer, I totally forgot that there were reserved addresses, I tried adding 10 (decimal) to my slave address field, I think that would get me out of the conflicting addresses? but I still seem to have the same problem; the slave will not recognise any commands.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Apr 06, 2009 9:01 pm     Reply with quote

Quote:
I tried adding 10 (decimal) to my slave address field

Post your revised code.
bsturm



Joined: 23 Feb 2009
Posts: 29

View user's profile Send private message

PostPosted: Mon Apr 06, 2009 9:19 pm     Reply with quote

I think you have to use even numbers for the address, as the LSB is reserved for the read/write bit.
cbarberis



Joined: 01 Oct 2003
Posts: 172
Location: Punta Gorda, Florida USA

View user's profile Send private message Send e-mail

PostPosted: Tue Apr 07, 2009 6:42 am     Reply with quote

I tried changing the slave address by doing the following:

ON the Slave:
#use i2c(Slave,Fast,sda=PIN_B1,scl=PIN_B4,address=0x13,force_hw,restart_wdt)
PORTADDRESS = portA & 0x0F;
PORTADDRESS += 10;

On the master:
Address = 0x13;

I believe this takes me away from the conflicting addresses?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Apr 07, 2009 8:44 am     Reply with quote

No. Don't use odd i2c slave addresses.

My advice is to get rid of the "Address" variable. Also get rid of the
shifting and OR'in in your code. Create the addresses (slave read
and write) with constants.

In the Slave:
Quote:
#use i2c(Slave,Fast,sda=PIN_B1,scl=PIN_B4,address=0x14,force_hw,restart_wdt)


In the Master:
Quote:
#define EPPHVWRITE 0x14
#define EPPHVREAD 0x15

If you do it this way, everything will be very clean, at least with regard
to the addresses.
cbarberis



Joined: 01 Oct 2003
Posts: 172
Location: Punta Gorda, Florida USA

View user's profile Send private message Send e-mail

PostPosted: Tue Apr 07, 2009 3:52 pm     Reply with quote

Once again; Thank you pcm programmer
I tried using the fixed constants as you outlined in your previous post but I seem to be getting the same results. Why is this so difficult? I never had any issues with any other serial protocol working a slave master combination.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Apr 07, 2009 3:57 pm     Reply with quote

Quote:
if(state < 0x80) //Master is sending data
{
if(state == 0)
{
}
if(state == 1) //First received byte is address
{
data = i2c_read(); address = data;
}
if(state == 2) //Second received byte is data
{
data = i2c_read();
buffer[address] = data;
}
}

Your code is different from the CCS example file Ex_Slave.c in an
essential way. They always do the i2c_read() operation if the state
is less than or equal to 0x80. Furthermore, you have modified the
test, to make it be only "less than 0x80".

My suggestion: Put everything back the way it was in the CCS example.
Don't change anything until you get the basic example working. Then
make only very carefully considered changes.
bsturm



Joined: 23 Feb 2009
Posts: 29

View user's profile Send private message

PostPosted: Tue Apr 07, 2009 4:58 pm     Reply with quote

Does any info from this thread help? http://www.ccsinfo.com/forum/viewtopic.php?t=38091&highlight=i2c+16f886

I had to add some short delays in strategic places. I also started with Ex_Slave.c and a short master program that I found on this board. The master was not much longer than the examples in the help file. Like PCM Programmer said, start with a simple program that has been known to work, then build on it.
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