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 Communication problems between 2 PIC's
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
bestbuylvr



Joined: 31 Jan 2007
Posts: 27
Location: Pittsburgh, PA

View user's profile Send private message

I2C Communication problems between 2 PIC's
PostPosted: Thu Mar 08, 2007 8:29 am     Reply with quote

I am currently trying to get two Pic 18F452's to send data back and forth between each other through an I2C connection. I have wired then together, pulling the SDA and SCL wires up to +5V through 1K resistors. I have both Pic's connected through serial connections to the computer, and the master displays "Outputting: 66" and the slave displays "Running." If anybody has had experience with this task, please let me know. I have tried the code pointed to in another forum with the EX_SLAVE.c program unsuccessfully. Here is the code I am using:

Master
Code:
#include <protoalone_1.h>

#use I2C(MASTER, sda=PIN_C4, scl=PIN_C3, SLOW)

main()
{
   int8 i2c_command = 66;

   while (true)
   {
      delay_ms(1000);
      printf("Outputting: %d\n\r", i2c_command);

      /* Master */
      i2c_start();      // Start condition
      i2c_write(0xa0);      // Device address
      i2c_write(i2c_command);   // Write Command
      i2c_stop();         // Stop condition

   }
}

Slave


Code:
#include <protoalone_1.h>

/* Setup I2C */
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0xa0, SLOW, FORCE_HW)

#INT_SSP
void ssp_interupt ()
{
   byte incoming;
   incoming = i2c_read();
   printf("\n\rRead byte 1: %d\n\r", incoming);
   incoming = i2c_read();
   printf("Read byte 2: %x\n\r\n\r", incoming);
}


main()
{
      delay_ms(250);
      printf("Running\n\r");

      enable_interrupts(INT_SSP);
      enable_interrupts(GLOBAL);
     
      while (true)
   {

   }
}

and the protoalone_1.h code:

Code:
#include <18f452.h>
#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES HS                       //High speed Osc (> 4mhz)
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOOSCSEN                 //Oscillator switching is disabled, main oscillator is source
#FUSES BROWNOUT                 //Reset when brownout detected
#FUSES BORV20                   //Brownout reset at 2.0V
#FUSES NOPUT                    //No Power Up Timer
#FUSES STVREN                   //Stack full/underflow will cause reset
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOLVP                      //Low Voltage Programming on B3(PIC16) or B5(PIC18)
#FUSES NOWRT                    //Program memory not write protected
#FUSES NOWRTD                   //Data EEPROM not write protected
#FUSES NOWRTB                   //Boot block not write protected
#FUSES NOWRTC                   //configuration not registers write protected
#FUSES NOCPD                    //No EE protection
#FUSES NOCPB                    //No Boot Block code protection
#FUSES NOEBTR                   //Memory not protected from table reads
#FUSES NOEBTRB                  //Boot block not protected from table reads
#use delay (clock=20000000)

#define GREEN_LED PIN_A5
#define YELLOW_LED PIN_B4
#define RED_LED PIN_B5
#define PUSH_BUTTON PIN_A4
#define delay_seconds(x) delay_ms(x*1000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)


Thank you.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Mar 08, 2007 12:11 pm     Reply with quote

Put the Ex_Slave.c program into your slave PIC.

Use the code in this post for your Master PIC:
http://www.ccsinfo.com/forum/viewtopic.php?t=28097&start=9

This will provide a test environment that should work.
Also make sure you have a ground connection between the
the two PIC boards.

If you can't make the setup above work, then post your compiler version.
bestbuylvr



Joined: 31 Jan 2007
Posts: 27
Location: Pittsburgh, PA

View user's profile Send private message

Still Having Problems
PostPosted: Mon Mar 12, 2007 6:28 am     Reply with quote

I have tried both the programs I have posted here and the programs you suggested, and I cannot seem to get the PIC's to communicate. I tried using different pins just in case it was a pin problem, but I still am not able to get the PIC's to talk. I am using compiler version 3.223, but am actually using DIP chips of the PIC now instead of the prototype boards. I have established communication between both PIC's and the DS1631 I2C temperature sensor that came with the PIC prototype board. I am using the MPLAB IDE program to program the PIC's, but the PIC C Compiler does sucessfully compile the programs I am using also. If you have any suggestions, I would appreciate any guidance you can provide. Thank you.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Mar 12, 2007 9:14 am     Reply with quote

Quote:
I tried using different pins just in case it was a pin problem,

Ex_Slave must use the hardware i2c pins.
bestbuylvr



Joined: 31 Jan 2007
Posts: 27
Location: Pittsburgh, PA

View user's profile Send private message

Success, new problem
PostPosted: Tue Mar 13, 2007 12:03 pm     Reply with quote

I actually managed to figure out the I2C communications between 2 pics. I then expanded that to 3 PICs and got one to send characters. I am trying to transmit a float variable over the I2C, but have not been successful. I will post the master code, and for the slave, I am just using the EX_SLAVE.c program. This program does not correctly transmit the float, but does transmit the character to the other slave PIC. I am probably just missing something simple. If you have a moment, please look over this code and let me know what I am doing wrong. Thank you.

Code:
#include <18F452.h>
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#use i2c(Master, SDA=PIN_C4, SCL=PIN_C3)

//====================================
void main()
{
int8 data; //int8
int32 data_float;
float data_1, i;
char j;

i=1;
j='Z';
while(1){

// Write to the slave 1 board.
i2c_start();
i2c_write(0xA0);
i2c_write(0x00);
i2c_write(i);
i2c_stop();
delay_ms(200);

//Write to the slave 2 board.
i2c_start();
i2c_write(0xB0);
i2c_write(0x00);
i2c_write(j);
i2c_stop();
delay_ms(200);

// Read from the slave 1 board and display the data.
i2c_start();
i2c_write(0xA0);
i2c_write(0x00);
i2c_start();
i2c_write(0xA1);
data_float = i2c_read(0);
i2c_stop();
data_1=data_float;
printf("read from 1: %u \n\r", data_1); //also tried %c and %f
delay_ms (200);

//Read from the slave 2 board and display the data.
i2c_start();
i2c_write(0xB0);
i2c_write(0x00);
i2c_start();
i2c_write(0xB1);
data = i2c_read(0);
i2c_stop();
printf("read from 2: %c \n\r\n\r", data);
delay_ms (200);


i=i+1;
j--;
}
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Mar 13, 2007 12:10 pm     Reply with quote

Look at this article in the CCS FAQ:
Quote:
Compiler Behavior

What is the format of floating point numbers?


http://www.ccsinfo.com/faq.php
bestbuylvr



Joined: 31 Jan 2007
Posts: 27
Location: Pittsburgh, PA

View user's profile Send private message

PostPosted: Tue Mar 13, 2007 12:21 pm     Reply with quote

I understand that a floating point variable uses a 4 byte size, I just don't know how to send 4 bytes over the I2C as one number. I am assuming the error in the code is in the writing and reading of the variable over I2C, but I don't know how to go about sending it as a group of 4 related bytes.
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Tue Mar 13, 2007 12:36 pm     Reply with quote

You can only send one byte at a time. You'll have to split it up and send four i2c_write() commands and then re-assemble the bytes at the receiving end.

Ronald
bestbuylvr



Joined: 31 Jan 2007
Posts: 27
Location: Pittsburgh, PA

View user's profile Send private message

PostPosted: Tue Mar 13, 2007 12:37 pm     Reply with quote

how do you go about splitting it and re-assembling it?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Mar 13, 2007 1:02 pm     Reply with quote

There are several threads on this. Here's one of them:
http://www.ccsinfo.com/forum/viewtopic.php?t=24074&highlight=float+union


This CCS FAQ article has some code to split a float.
http://www.ccsinfo.com/faq.php?page=write_eeprom_not_byte
Unfortunately, it's no longer functional after vs. 4.021, where
they made this change:
Quote:
4.021 The & unary operator by default no longer returns a generic (int8 *)


To fix it, you have to cast the address of the floating point data
to a byte pointer, as shown in bold below.
Quote:

WRITE_FLOAT_EXT_EEPROM(long int n, float data) {
int i;

for (i = 0; i < 4; i++)
write_ext_eeprom(i + n, *((int8*)&data + i) ) ;
}

float READ_FLOAT_EXT_EEPROM(long int n) {
int i;
float data;

for (i = 0; i < 4; i++)
*((int8*)&data + i) = read_ext_eeprom(i + n);

return(data);
}
bestbuylvr



Joined: 31 Jan 2007
Posts: 27
Location: Pittsburgh, PA

View user's profile Send private message

PostPosted: Thu Mar 15, 2007 7:05 am     Reply with quote

OK, so I attempted to apply that to what I am doing with the I2C communications between the PICs. I am just trying to see if it works by sending a 1 and seeing what it sends back. I recieve a -.000000 and don't know why. I assume it has something to do with how I am pointing to the memory locations to send them and then reading them. I will post the code I have now, but be advised, I have sections commented out that are about converting 32 bit ints to 8 bit and sending them, but this does not work with floats. If someone with more expertise in the pointer field could give me a hand, I would appreciate it. And by the way, thank you PCM Programmer for your help so far.

Code:
#include <18F452.h>
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#use i2c(Master, SDA=PIN_C4, SCL=PIN_C3)

//====================================
/*
I2C_WRITE_FLOAT(long int n, float data) {
int i;

i = 0;
i2c_start();    // Start condition
i2c_write(0xa0);// Device address
i2c_write(0x00);// Low byte of command
i2c_write((int8*)&data + i)); // High byte of command
i2c_stop();     // Stop condition

i = 1;
i2c_start();    // Start condition
i2c_write(0xa0);// Device address
i2c_write(0x01);// Low byte of command
i2c_write(*((int8*)&data + i) )); // High byte of command
i2c_stop();     // Stop condition

i=2;
i2c_start();    // Start condition
i2c_write(0xa0);// Device address
i2c_write(0x02);// Low byte of command
i2c_write(*((int8*)&data + i) )); // High byte of command
i2c_stop();     // Stop condition

i=3;
i2c_start();    // Start condition
i2c_write(0xa0);// Device address
i2c_write(0x03);// Low byte of command
i2c_write(*((int8*)&data + i) )); // High byte of command
i2c_stop();     // Stop condition

}
//-------------------------------------
float READ_FLOAT_EXT_EEPROM(long int n) {
int i;
float data;

for (i = 0; i < 4; i++)
*((int8*)&data + i) = read_ext_eeprom(i + n);

return(data);
}
*/
//=====================================

void main()
{
//int8 f0, f1, f2, f3, g0, g1, g2, g3; //int8 for int32 conversion
int8 data_1;
float i, data, data_read;
char j;

data=1;
j='Z';
while(1){

/*//Convert 32 bit int to 1 byte ints.
f3 = MAKE8(i,3);
f2 = make8(i,2);
f1 = make8(i,1);
f0 = make8(i,0);
*/

// Write float to the slave 1 board.
i2c_start();
i2c_write(0xA0);
i2c_write(0x00);
i2c_write(*(&data+0));
i2c_write(0x01);
i2c_write(*(&data+1));
i2c_write(0x02);
i2c_write(*(&data+2));
i2c_write(0x03);
i2c_write(*(&data+3));
i2c_stop();
delay_ms(200);

//Write to the slave 2 board.
i2c_start();
i2c_write(0xB0);
i2c_write(0x00);
i2c_write(j);
i2c_stop();
delay_ms(200);

// Read float bytes from the slave 1 board and display the data.
i2c_start();
i2c_write(0xA0);
i2c_write(0x00);
i2c_start();
i2c_write(0xA1);
*(&data_read+0) = i2c_read(0);
*(&data_read+1) = i2c_read(1);
*(&data_read+2) = i2c_read(2);
*(&data_read+3) = i2c_read(3);
i2c_stop();
//data_1=make32(g0, g1, g2, g3); For reassembling int32
printf("read from 1: %f \n\r", data_read); //also tried %c and %f
delay_ms (200);

//Read from the slave 2 board and display the data.
i2c_start();
i2c_write(0xB0);
i2c_write(0x00);
i2c_start();
i2c_write(0xB1);
data_1 = i2c_read(0);
i2c_stop();
printf("read from 2: %c \n\r\n\r", data_1);
delay_ms (200);


//i=i+1;
j--;
}
}

Thank you
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Mar 15, 2007 11:37 am     Reply with quote

Quote:
i2c_start();
i2c_write(0xA0);
i2c_write(0x00);
i2c_start();
i2c_write(0xA1);
*(&data_read+0) = i2c_read(0);
*(&data_read+1) = i2c_read(1);
*(&data_read+2) = i2c_read(2);
*(&data_read+3) = i2c_read(3);
i2c_stop();

This is not the correct way to read sequential bytes. The i2c_read()
function doesn't take an address. The parameter can be either a
0 or a 1.

1 -- means to do an "ACK". (acknowledge)
0 -- means to do a "NAK" (no acknowledge)

In the i2c protocol, the last read operation must do a NAK.
The read operations prior to the last one must do ACKs.

Also, to do an ACK, you don't have to supply the 1. It's understood
to be a 1 if you don't put in a parameter.

So delete all the parameters in that group of four i2c_read() statements,
except for the last one, and give it a parameter of 0.
bestbuylvr



Joined: 31 Jan 2007
Posts: 27
Location: Pittsburgh, PA

View user's profile Send private message

PostPosted: Thu Mar 15, 2007 12:26 pm     Reply with quote

OK, so here is the story. I tried to take the numbers out and put only a zero in the last i2c_read, but now the program just freezes and does not output anything. I did research this a bit, and tried to use the i2c_poll function with no success. Here is the modified section of code I tried with no luck:

Code:
// Read float bytes from the slave 1 board and display the data.
i2c_start();
i2c_write(0xA0);
i2c_write(0x00);
i2c_start();
i2c_write(0xA1);
*(&data_read+0) = i2c_read();
*(&data_read+1) = i2c_read();
*(&data_read+2) = i2c_read();
*(&data_read+3) = i2c_read(0);
i2c_stop();
printf("read from 1: %f \n\r", data_read); //also tried %c and %f
delay_ms (200);
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Mar 15, 2007 12:36 pm     Reply with quote

What I would do is:

1. Forget trying to send and receive floats (for now).
Get it working with just sending, receiving, and displaying
four sequential bytes (such as 0x01, 0x02, 0x03, 0x04).
Don't even involve floats in any way in the testing.

2. Don't add tests to talk to a 2nd Slave PIC when the primary
problem hasn't been solved yet. Remove all code that talks
to the 2nd slave and remove the hardware for the 2nd slave.

Strip everything down to essentials and solve the main problem.
bestbuylvr



Joined: 31 Jan 2007
Posts: 27
Location: Pittsburgh, PA

View user's profile Send private message

PostPosted: Thu Mar 15, 2007 12:48 pm     Reply with quote

Is the method I'm using to write the data correct?
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