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

I2C Master - Slave problem

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



Joined: 20 Jan 2011
Posts: 3

View user's profile Send private message

I2C Master - Slave problem
PostPosted: Thu Jan 20, 2011 8:14 am     Reply with quote

Hello.
I want to connect 2 PIC16F876A motors with I2C protocol.
On the breadboard I have 2 resistors 2.2 Kohms, one IC by Philips called PCF8574, 4 Yellow LEDS and the 2 PICS.
I have setup one as a master and the other one as a slave.
Also the IC is slave with address 0x40.

MASTER CODE:
Code:

#include <16f876A.H>
#device adc=8
#fuses HS, NOWDT, NOBROWNOUT, NOPROTECT, PUT, NOLVP
#use delay(clock=40000000)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3)
#define SLAVE1_WRT_ADDR   0x40
#define BUF_SIZE 8

//====================================
int trans;
void main()
{
trans=0;
while(1){
  trans = trans + 1;
   delay_ms(300);
   i2c_start();
   i2c_write(SLAVE1_WRT_ADDR);
   i2c_write(trans);
   i2c_stop();
   delay_ms(300);
   i2c_start();
   i2c_write(0xA0);
   i2c_write(trans);
   i2c_stop();
}
     
}
 


SLAVE
Code:

#include <16F876A.H>
#device adc=8
#fuses HS, NOWDT, NOBROWNOUT, NOPROTECT, PUT, NOLVP
#use delay(clock=4000000)
BYTE address, buffer[0x10];
#include <lib_mot_moway.h>
void motor_move_for();
void motor_move_back();

#INT_SSP
void ssp_interupt ()
{
   BYTE incoming, state;
   state = i2c_isr_state(TB);
   if(state <= 0x80)                     //Master is sending data
   {
      incoming = i2c_read(TB);
      if(state == 1)                     //First received byte is address
         {address = incoming;
         motor_move_for();}
      if(state == 2){
      motor_move_back();
      buffer[address] = incoming;}
   }
   if(state == 0x80)                     //Master is requesting data
   {
      i2c_write(TB,buffer[address]);
   }
}


void main ()
{
   enable_interrupts(GLOBAL);
   enable_interrupts(INT_SSP);

   while (TRUE) {}
}

void motor_move_for()
{
MOT_STR(30, FWD, TIME, 10);
   while(!input(MOT_END)){}
}

void motor_move_back(){
MOT_STR(30, BACK, TIME, 10);
   while(!input(MOT_END)){}
}


The leds connected on the PCF 8574, light on like a charm(count right) but the slave PIC has a problem. It doesn't get interrupted at once. It gets after several times (if it does) and only executes the routine move_motor_forward.
I have no clue why this is happening. Thanks.

edit
_
Even without the part where I send to pcf I still have the same problem.
_________________
sins can't be undone
Ttelmah



Joined: 11 Mar 2010
Posts: 19328

View user's profile Send private message

PostPosted: Thu Jan 20, 2011 9:09 am     Reply with quote

You don't appear to have a #use I2C, telling the slave that it's address is 0x40....

Take the movement commands out of the I2C handler. Set a flag, to say move forwards/back, and have the main code do this. Problem here is that your movements could last 'for ever', and the I2C slave receive code is _hung_ while this is happening. The bus is effectively 'jammed'....
Old 'mantra' repeated here many times. In an interrupt handler _handle_ the hardware event, and get out again ASAP. This is _essential_....

Best Wishes
elb0m



Joined: 20 Jan 2011
Posts: 3

View user's profile Send private message

PostPosted: Thu Jan 20, 2011 10:12 am     Reply with quote

The use #i2c is included in the .h file that I have.
So I must set a flag, in the int_ssp and in the main program check the flag?
Ok I will do that as soon as I get back home!
Didn't understand what you said about that old mantra:/
And on that interrupt handler you mean the int_ssp right?
_________________
sins can't be undone
elb0m



Joined: 20 Jan 2011
Posts: 3

View user's profile Send private message

PostPosted: Fri Jan 21, 2011 6:37 am     Reply with quote

OK.
I've changed the code as you told me.
Some problems occur though.
Here is the code.


MASTER
Code:

#include <16f876A.H>
#device adc=8
#fuses HS, NOWDT, NOBROWNOUT, NOPROTECT, PUT, NOLVP
#use delay(clock=40000000)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3)
#define SLAVE1_WRT_ADDR   0x40
#define BUF_SIZE 8

//====================================
void main()
{

   i2c_start();
   i2c_write(0xA0);
   i2c_write(0x13);
   i2c_stop();

     
   }


SLAVE
Code:

#include <16F876A.H>
#device adc=8
#fuses HS, NOWDT, NOBROWNOUT, NOPROTECT, PUT, NOLVP
#use delay(clock=4000000)
BYTE address,data, buffer[0x10];
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0xA0,stream=TB)
#include <lib_sen_moway.h>
int flag;

#INT_SSP
void ssp_interupt ()
{
   BYTE incoming, state;
   state = i2c_isr_state(TB);
   if(state <= 0x80)                     //Master is sending data
   {
      incoming = i2c_read(TB);
      if(state == 1)   //First received byte is address
         {
         flag = 1;
         address = incoming;
         }
      if(state == 2){
      flag = 2;
      data = incoming;}
   }
   if(state == 0x80)                     //Master is requesting data
   {
      i2c_write(TB,buffer[address]);
   }
}


void main ()
{  flag =0;
   enable_interrupts(GLOBAL);
   enable_interrupts(INT_SSP);

   while (TRUE) {
   if (flag==1){ LED_R_ON(); }
   
   if (flag==2){ LED_L_ON(); if (data==0x13){LED_TOP_GREEN_ON();} }
               
      }
}



So, i have both processors OFF.
I turn the slave ON(while(TRUE) loop waits for the flag, and the interrupt).
then
I turn the master ON.
Results:
Sometimes on the first time i turn the master ON the LED Right(LED_R_ON) turns on. I may have to turn several times master on-off-on-off to get that LED Right on. It doesn't get INTERRUPTED at once. When i have in while loop it works(LED_R_ON).
I don't see thought the LED_L to be turning on,neither the TOP_GREEN.
I can't understand the problem.
It might be the voltage, the resistors?
2.8V and 2.2K Resistors.
Thanks
_________________
sins can't be undone
Ttelmah



Joined: 11 Mar 2010
Posts: 19328

View user's profile Send private message

PostPosted: Fri Jan 21, 2011 10:55 am     Reply with quote

First, what powers the pull-ups?.
If it is the master, then the slave _needs_ to wait for the lines to go high, before enabling the bus. So something like:

Code:

while ( (input(PIN_C4)==0 || input(PIN_C3)==0) ;
//Now start the interrupt

Otherwise it could easily see the bus as in an indeterminate start/stop condition, and get into a hung state, before starting.....

2.2K, is 'highish', if your bus really is at 2.8v. Depends on your likely bus capacitance, but for 2.8v, the minimum value for the pull-ups, is just 800R. I'd suggest something like 1.2K, would be safer at such a low voltage.

When the 876A, was designed, the _minimum_ specified voltage for I2C, was 3V (it has since been reduced), and I'd be significantly worried whether this chip is actually going to be happy running I2C at such a low voltage...

Best Wishes
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