3
\$\begingroup\$

I'm new to PIC's and PIC programming but I'm working on a little project to try get a PIC24F32KA301 to communicate with a Raspberry Pi using I2C. The Raspberry Pi is the master and the PIC is the slave. I have created a little Python program on the Raspberry Pi and tested that it works by successfully communicating with an Arduino, what I want to do now is replace the Arduino with a PIC.

Just for completeness I've included the python program below:

import smbus
import time
bus = smbus.SMBus(1)
address = 0x22
def writeNumber(value):
 bus.write_byte(address, value)
 return -1
def readNumber():
 number = bus.read_byte(address)
 return number
while True:
 var = input("Enter 1 - 9: ")
 if not var:
 continue
 writeNumber(var)
 print "RPI: Hi Arduino, I sent you ", var
 time.sleep(1)
 number = readNumber()
 print "Arduino: Hey RPI, I received a digit ", number
 print

I'm pretty sure I've connected the PIC and Raspberry Pi correctly:

GND <---> Vss (pin 19)
SCL <---> SCL1 (pin 12)
SDA <---> SDA1 (pin 13)

The Raspberry Pi is powered over USB (I think it's 5V, but it might be 3V) and the PIC is powered separately using a 3V battery. The Arduino didn't have any pull up resistors so I assume it's ok to not have any on the PIC (maybe this is wrong?).

I'm using C with the XC16 compiler and the i2c.h library to program the PIC but I'm not really sure what I'm doing, I've tried my best to piece things together from I2C examples and little bits I've read on various forums etc:

#define USE_AND_OR // not sure what this is!
#include <p24Fxxxx.h>
#include <i2c.h>
unsigned char I2C_RECV[1]
void main(void) {
 unsigned int temp, i;
 for(i=0; i<1; i++)
 I2C_RECV[i]=0;
 TRISA = 0b0000000000000000;
 PORTA = 0b0000000000000001;
 /* INITIALISE I2C MODULE */
 CloseI2C1(); // close i2c if it was operating earlier
 while(1) {
 OpenI2C1((I2C_ON | I2C_7BIT_ADD | I2C_CLK_REL | I2C_STR_EN), 0);
 I2C1ADD = 0x22; // initialze slave address to 1E
 // receive data from master
 while(DataRdyI2C1() == 0); // wait until data is transmitted from master
 temp = SlaveReadI2C1(); // read address to empty buffer
 SlavegetsI2C1(I2C_RECV, 1); // receive data
 if(I2C_RECV[0] == 9) {
 PORTA = 0b0000000000000011;
 }
 CloseI2C1();
 }
}

The code is quite simple (but probably wrong!). Basically I initialise the I2C module and turn on an LED, then I enter a loop, open the I2C connection using address 0x22 and wait for the master to send some data. When data is received I check it's value, if it's 9 I turn on another LED.

On the Raspberry Pi I can confirm that the PIC is accessible by running i2cdetect -y 1. I can see the PIC at address 0x22, which gives me some confidence that I'm at least heading in the right direction! However, when I run the python program I receive an IO error, the error number is 5. I've looked around to find out what that means, but it's a very vague error, basically anything could have gone wrong!

I'm not sure if it's my circuit that's incorrect (i.e. do I need pull up resistors, if so how do I calculate what resistance they need to be?) or my PIC program. If anyone can check the program makes sense or has any advice I'd be very grateful.

Thanks.

asked Jul 24, 2013 at 16:13
\$\endgroup\$
2
  • \$\begingroup\$ As you noticed the RPI has 1.8k pullups integrated, so you should not need to add any \$\endgroup\$ Commented Sep 17, 2013 at 6:24
  • \$\begingroup\$ Why are you reopening the I2C and reinitializing the address in your while loop? Shouldn't that happen outside the loop? \$\endgroup\$ Commented Nov 27, 2013 at 12:28

1 Answer 1

-2
\$\begingroup\$

Test this:

unsigned char I2C_RECV[1]
void main(void) {
 unsigned int temp=0,temp2=0, i;
 for(i=0; i<1; i++)
 I2C_RECV[i]=0;
 TRISA = 0b0000000000000000;
 PORTA = 0b0000000000000001;
 /* INITIALISE I2C MODULE */
 CloseI2C1(); // close i2c if it was operating earlier
 while(1){
 config1 = (I2C_ON | I2C_7BIT_ADD | I2C_CLK_REL | I2C_STR_EN );
 config2 = 0; //This defines I2C to be slave
 OpenI2C1(config1,config2); //configure I2C1
 I2C1ADD = 0x22; //I2C address set to 1E 
 I2C1CONbits.I2CEN = 1; // ENABLE I2C!!
 I2C1CONbits.DISSLW = 1; // Disable slew rate control
 I2C1CONbits.GCEN = 1; // Enable interrupt when a general call address is received (enable for reception)
 while(IFS1bits.SI2C1IF==0){asm ("clrwdt");}; //wait untill the data is transmitted from master
 temp = SlaveReadI2C1(); //Read address to empty buffer
 temp2 = SlaveReadI2C1(); //Read data to empty buffer
 SlavegetsI2C1(I2C_RECV,1);
 if(temp2 == 0x09) PORTA = 0b0000000000000011;
 else PORTA = 0b0000000000000000; 
 CloseI2C1(); //Disable I2C
 } 
}
PeterJ
17.3k37 gold badges58 silver badges91 bronze badges
answered Nov 27, 2013 at 8:11
\$\endgroup\$
2
  • 2
    \$\begingroup\$ You should include some additional information and not just paste code. \$\endgroup\$ Commented Nov 27, 2013 at 8:41
  • 1
    \$\begingroup\$ Rev1.0 is right: maybe you could highlight the changes from the previous code, explaining how they make it work. \$\endgroup\$ Commented Nov 27, 2013 at 8:43

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.