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 Again !
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Zulander



Joined: 04 Dec 2006
Posts: 14

View user's profile Send private message

I2c MASTER/SLAVE Again !
PostPosted: Wed Mar 14, 2007 4:56 pm     Reply with quote

Hi, guys
I am having a problem with I2c master and slave communication. I’ve searched the whole forum for master slave example I’ve tried all of them, my master can’t see to read the data form the SLAVE, I know that the slave is sending data because I am pulsing an LED (pulselight();)
My SCL/SDA are connected to each other with a pull-up resistors (4.7K each)
So is my code wrong or my HW ?
thank you

Code:

-----------------Salve.h--------------
#include <16F690.h>
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES RC                       //Resistor/Capacitor Osc with CLKOUT
#FUSES NOPROTECT                //Code not protected from reading
#FUSES BROWNOUT                 //Reset when brownout detected
#FUSES NOMCLR                     //Master Clear pin enabled
#FUSES NOCPD                    //No EE protection
#FUSES NOPUT                    //No Power Up Timer
#FUSES IESO                     //Internal External Switch Over mode enabled
#FUSES FCMEN                    //Fail-safe clock monitor enabled

#use delay(clock=4000000)
#use i2c(Slave,sda=PIN_B4,scl=PIN_B6,address=0xa0,FORCE_HW, SLOW)



Code:

-----------------Salve.c--------------

#include "slave.h"
#INT_SSP
void ssp_interupt ()
{
   BYTE incoming, state;

   state = i2c_isr_state();

   if(state < 0x80)                     //Master is sending data
   {
      incoming = i2c_read();
      if(state == 1)                     //First received byte is address
         address = incoming;
      if(state == 2)                     //Second received byte is data
         buffer[address] = incoming;
   }
   if(state == 0x80)                     //Master is requesting data
   {
   stepup();
      i2c_write(buffer[address]);
      pulselight();
   }
}


void main(){

  setup_adc_ports(NO_ANALOGS | VSS_VDD);
  setup_adc(PIN_A0);
  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);
  // This device COMP currently not supported by the PICWizard
  enable_interrupts(INT_SSP);
  enable_interrupts(GLOBAL);
  setup_oscillator(False);
       
while(1){}
}


Code:

------------Controller.h----------------
#include <16F690.h>
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES BROWNOUT                 //Reset when brownout detected
#FUSES MCLR                     //Master Clear pin enabled
#FUSES NOCPD                    //No EE protection
#FUSES NOPUT                    //No Power Up Timer
#FUSES IESO                     //Internal External Switch Over mode enabled
#FUSES FCMEN//Fail-safe clock monitor enabled
#use delay(clock=4000000)

#use rs232(baud=9600,parity=N,xmit=PIN_B7,rcv=PIN_B5,bits=8)
#use i2c(MASTER,sda=PIN_B4,scl=PIN_B6,FORCE_HW, SLOW)

// ***************** COMMUNICATION VARIABLE *****************


Code:

---------------------------------- MASTER.C -------------------------------
#include "Controller.h"

void main()
{
int8 data;

// Write the letter 'B' to the slave board.
i2c_start();
i2c_write(0xA0);
i2c_write(0x00);
i2c_write('B');
i2c_stop();

// Read from the slave board and display the data.
i2c_start();
i2c_write(0xA0);
i2c_write(0x00);
i2c_start();
i2c_write(0xA1);
data = i2c_read(0);
i2c_stop();
printf("read %c \n\r", data);
     
while(1);     
}     
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Mar 14, 2007 4:59 pm     Reply with quote

What's your compiler version ?
Zulander



Joined: 04 Dec 2006
Posts: 14

View user's profile Send private message

PostPosted: Wed Mar 14, 2007 5:56 pm     Reply with quote

PCM programmer wrote:
What's your compiler version ?


The compiler version is 4.023
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Mar 14, 2007 6:51 pm     Reply with quote

Quote:
-----------------Slave.h--------------
#include <16F690.h>
#device adc=8

#FUSES NOWDT //No Watch Dog Timer
#FUSES RC //Resistor/Capacitor Osc with CLKOUT

Before we go any further, is there a reason why you're using an
external R-C oscillator, instead of the internal oscillator ?
The external oscillator requires a resistor and a capacitor, and it's
not a very accurate.


Quote:
------------Controller.h----------------
#include <16F690.h>
#device adc=8

#FUSES NOWDT //No Watch Dog Timer
#FUSES BROWNOUT //Reset when brownout detected

For the Master PIC, you have not specified an oscillator fuse.
Zulander



Joined: 04 Dec 2006
Posts: 14

View user's profile Send private message

PostPosted: Wed Mar 14, 2007 8:51 pm     Reply with quote

PCM programmer wrote:
is there a reason why you're using an
external R-C oscillator


Yes, i have used it for testing and i have removed it and i am no longer using it !

PCM programmer wrote:
For the Master PIC, you have not specified an oscillator fuse.


Yes, I have forgot end the oscillator fuse and i have fixed the problem with the fallowing segment:
Code:
#FUSE INTRC          //Internal RC Osc
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Mar 14, 2007 9:54 pm     Reply with quote

I looked at the .LST file for vs. 4.023 and the compiler is using the
correct register addresses, so I don't see a problem there.

There are two things in your code that are wrong.
Quote:
void main(){
setup_adc_ports(NO_ANALOGS | VSS_VDD);
setup_adc(PIN_A0);
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);
// This device COMP currently not supported by the PICWizard
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
setup_oscillator(False);
while(1){}
}

1. The parameter for setup_adc() should be ADC_OFF, not a pin number.

2. The setup_oscillator() statement writes 0x00 to the OSCCON register.
This tells the internal oscillator to run at 31 KHz. That's not what you
want. Delete that line.

The compiler will automatically put in code to setup the OSCCON
register to program the internal oscillator to the same frequency
that you specify in your #use delay() statement. This works if
the #use delay() statement is placed after the #fuses statement
that specifies INTRC or INTRC_IO. (Which you are correctly doing).
You don't need a setup_oscillator() statement. Delete it.
Zulander



Joined: 04 Dec 2006
Posts: 14

View user's profile Send private message

PostPosted: Thu Mar 15, 2007 6:10 am     Reply with quote

OK, let me try what you suggested and ill get back to you
Zulander



Joined: 04 Dec 2006
Posts: 14

View user's profile Send private message

PostPosted: Fri Mar 16, 2007 12:45 pm     Reply with quote

So, I got my communication to work but, the data is not synchronizing.

I am sending 0x0C using i2c_write(0x0C);
And I am reading D7
am i using the wrong switch ?

it's really wired, I've used a power supply to power up the chip and i am reading DD now !
thank
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Mar 16, 2007 1:13 pm     Reply with quote

Post your current master and slave test code. (Fully compilable, with
the actual #fuses statements, etc.)
Zulander



Joined: 04 Dec 2006
Posts: 14

View user's profile Send private message

PostPosted: Fri Mar 16, 2007 1:22 pm     Reply with quote

Code:

//slave.h
#include <16F690.h>
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES NOPROTECT                //Code not protected from reading
#FUSES BROWNOUT                 //Reset when brownout detected
#FUSES NOMCLR                     //Master Clear pin enabled
#FUSES NOCPD                    //No EE protection
#FUSES NOPUT                    //No Power Up Timer
#FUSES IESO                     //Internal External Switch Over mode enabled
#FUSES FCMEN                    //Fail-safe clock monitor enabled
#FUSES INTRC 

#use delay(clock=4000000)
#use i2c(Slave,sda=PIN_B4,scl=PIN_B6,address=0xa0)




Code:

//Slave.c
#include "slave.h"

BYTE address, buffer[0x10];
void pulsepin(void){

  output_high(PIN_C0);
  delay_us(100);
  output_low(PIN_C0);
}

#INT_SSP
void ssp_interupt ()
{
   BYTE incoming, state;

   state = i2c_isr_state();

   if(state < 0x80)                     //Master is sending data
   {
      incoming = i2c_read();
      if(state == 1)                     //First received byte is address
         address = incoming;

      if(state == 2)                     //Second received byte is data
         buffer[address] = incoming;

   }
   if(state == 0x80)                     //Master is requesting data
   {
         i2c_write(buffer[address]);
      pulsepin();
   }
}


void main(){

  setup_adc_ports(NO_ANALOGS | VSS_VDD);
  setup_adc(ADC_OFF);
  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);
  // This device COMP currently not supported by the PICWizard
  enable_interrupts(INT_SSP);
  enable_interrupts(GLOBAL);

       
while(1){}
}


Code:

//Master.h
#include <16F690.h>
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES BROWNOUT                 //Reset when brownout detected
#FUSES MCLR                     //Master Clear pin enabled
#FUSES NOCPD                    //No EE protection
#FUSES NOPUT                    //No Power Up Timer
#FUSES IESO                     //Internal External Switch Over mode enabled
#FUSES FCMEN//Fail-safe clock monitor enabled
#FUSES INTRC   
#use delay(clock=4000000)

#use rs232(baud=9600,parity=N,xmit=PIN_B7,rcv=PIN_B5,bits=8)
#use i2c(Master,sda=PIN_B4,scl=PIN_B6,fast)

// ***************** COMMUNICATION VARIABLE *****************



Code:

//master.c
#include "master.h"


static int Sensor3_Add=0xa0;

void read_temp(int add)
{
   int data,lsb,lsba;
   //char xRETURN[4];
   i2c_start();
i2c_write(0xA0);
i2c_write(0x00);
i2c_write('B');
i2c_stop();
delay_ms(1000);
i2c_start();
i2c_write(0xA0);
i2c_write(0x00);
i2c_start();
i2c_write(0xA1);
data = i2c_read(0);
i2c_stop();
printf("read %x \n\r", data);
}


void main(void){
int x;

while (1){
//delay_ms(1000);
read_temp(Sensor3_Add);

}
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Mar 16, 2007 2:07 pm     Reply with quote

I don't have any 16F690's at the moment. I tested your software
with two PicDem2-Plus boards, with a 16F877 running at 4 MHz on
each board. I used vs. 4.023, and I made as few changes as
possible to your posted code to make it compile for a 16F877.
I have a 4.7K pull-up to +5v on SDA and on SCL.

It worked. It displays this:
Quote:

read 42
read 42
read 42
read 42
read 42
read 42
read 42


Things to try:
1. Don't run the master in "fast" mode. Remove the FAST parameter
from the #use i2c() statement.

2. Check your pull-up resistor size. Use 2.2K to 4.7K.

If you can't make it work, I ordered a 16F690 a few days ago.
It should come in early next week and I can test it as the slave chip then.
Zulander



Joined: 04 Dec 2006
Posts: 14

View user's profile Send private message

PostPosted: Fri Mar 16, 2007 2:32 pm     Reply with quote

Hi,
I don't understand why you are reading 42 ?

Code:
i2c_write('B');

isn't 42 a *, we should get 66 for B

p.s: i went from 4.7 to 1k resistor and i have updated the compiler version to 4.029
Thanks PCM for helping me !!!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Mar 16, 2007 2:41 pm     Reply with quote

Quote:
printf("read %x \n\r", data);

The printf statement uses "%x" as the format specifier. This means
the output is displayed in Hex, and 'B' = 0x42 in hex.


Quote:
i went from 4.7 to 1k resistor

In my post I said to use anything from 2.2K to 4.7K.
How did that get turned into "change it to 1k" ?

1K might work with PICs, because they have a strong pull-down
capability on the pin drivers. But for normal i2c chips, 1K violates
the specification. For a 5v i2c bus, 1.6K is about the lowest value
allowed.
http://www.maxim-ic.com/appnotes.cfm?appnote_number=476
Zulander



Joined: 04 Dec 2006
Posts: 14

View user's profile Send private message

PostPosted: Fri Mar 16, 2007 8:10 pm     Reply with quote

Quote:
The printf statement uses "%x" as the format specifier.

Ahh yes, my fault i should have double checked for the printf which was HEX and not DEC,

Quote:
How did that get turned into "change it to 1k" ?

After hours of testing, I was tired; I thought that changing the pull-up value of the resistor world help, and it got me nowhere. But Monday will go with 4.7k.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Mar 16, 2007 8:30 pm     Reply with quote

On Tuesday I should have a 16F690 and can test it with the Ex_Slave.c program.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion 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