View previous topic :: View next topic |
Author |
Message |
JacquesB
Joined: 22 Aug 2008 Posts: 21
|
Compiling problem with I2C |
Posted: Wed Feb 04, 2009 12:13 pm |
|
|
HI,
I'm trying to use the I2C port to communicate with a slave. But I get a compiler error with a build in function. My code looks like this :
Code: | #use I2C(MASTER, FORCE_HW, SLOW)
main
{
int8 i;
int8 buffer[6];
while(1){
RdData(6);
}
}
void RdData(int8 NbBytes)
{
int8 iBuffer;
iBuffer=0;
i2c_start(); // Start condition
i2c_write(COMPASSADDR|0x01);
while(iBuffer!=NbBytes) {
while(!i2c_poll()) ;
Buffer[iBuffer++]= i2c_read();
}
i2c_stop();
} |
and I get the error message:
Quote: | *** Error 12 "compass.c" Line 162(16,17): Undefined identifier -- i2c_poll |
I can't see why the compiler doesn't find the i2c_poll() function?
Can you help?/
thanks |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Feb 04, 2009 12:41 pm |
|
|
Always post your PIC and compiler version. |
|
|
JacquesB
Joined: 22 Aug 2008 Posts: 21
|
|
Posted: Wed Feb 04, 2009 12:44 pm |
|
|
Sorry,
It compiles for PIC18F2525 and use compiler PCH 4.071 |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Feb 04, 2009 1:02 pm |
|
|
You need to specify the pins that are used for SDA and SCL.
Add that to your #use i2c statement. Use the hardware i2c pins.
Look at the pin diagram in the PIC data sheet to find them. |
|
|
JacquesB
Joined: 22 Aug 2008 Posts: 21
|
|
Posted: Wed Feb 04, 2009 1:29 pm |
|
|
I thought that by specifying FORCE_HW I didn't have to also specify the real pins.
I replaced :
Code: | #use I2C(MASTER, FORCE_HW, SLOW, STREAM=COMPASS ) |
with :
Code: | #use I2C(MASTER, SCL= PIN_C3, SDA=PIN_C4,FORCE_HW, SLOW) |
and it compiled OK
thanks for the hint ! |
|
|
JacquesB
Joined: 22 Aug 2008 Posts: 21
|
Detection of slave |
Posted: Fri Feb 06, 2009 12:46 pm |
|
|
Hi,
Is there a way with the I2C functions to detect the absence of a slave?
In the function below the program goes all the way thru even when there is no slave.
I use a PIC18F2525 with PCH C Compiler, Version 4.071
...
Code: | #use I2C(MASTER, SCL= PIN_C3, SDA=PIN_C4,FORCE_HW, SLOW, STREAM=COMPASS )
...
int8 WrCompassData(int8 EEPromAddr,int8 Data){
i2c_start(COMPASS); // Start condition
i2c_write(COMPASS,COMPASSADDR); // Addresses the Compass chip
i2c_write(COMPASS,WRITEEEPROMCMD);
i2c_write(COMPASS,EEPromAddr); // Send the pointer (address) in the EEPROM
i2c_write(COMPASS,Data); // write the data byte
i2c_stop(COMPASS); //Stop
} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Feb 06, 2009 1:14 pm |
|
|
Quote: | Is there a way with the I2C functions to detect the absence of a slave? |
Here is a test program that finds i2c slaves on a bus.
On a PicDem2-Plus board, it finds the TC74 at 0x9A and the 24LC256
at 0xA0:
Quote: |
Searching for i2c slaves in address range 0x10 to 0xF6:
Found i2c slave at address: 9A
Found i2c slave at address: A0
Number of slaves found: 2
|
You can call the get_ack_status() routine with your slave address.
If it returns a 0x00, then it found the slave.
Code: | #fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3)
int8 get_ack_status(int8 address)
{
int8 status;
i2c_start();
status = i2c_write(address);
i2c_stop();
return(status);
}
//============================
void main()
{
int8 addr;
int8 count;
int8 status;
count = 0;
// Valid i2c slave addresses can be in
// the range from 0x10 to 0xF6.
printf("Searching for i2c slaves in address range 0x10 to 0xF6:\n\r\n\r");
for(addr=0x10; addr < 0xF8; addr+=2)
{
status = get_ack_status(addr);
if(status == 0)
{
printf("Found i2c slave at address: %X \n\r", addr);
count++;
}
}
printf("\n\rNumber of slaves found: %u \n\r", count);
while(1);
} |
|
|
|
JacquesB
Joined: 22 Aug 2008 Posts: 21
|
|
Posted: Fri Feb 06, 2009 1:59 pm |
|
|
I didn't noticed that i2c_write() would returned the ack bit
thanks |
|
|
JacquesB
Joined: 22 Aug 2008 Posts: 21
|
|
Posted: Mon Feb 09, 2009 9:45 am |
|
|
Hi,
I'm having another problem regarding the function i2c_poll.
I was able to communicate with an I2C chip but unable to read data from it. Every time the program went into rddata() it run indefinitively on the line i2c_poll.
Here is the test program:
Code: | #include <18F2525.h>
#define FRQ 4000000
#use delay(clock=FRQ)
#use I2C(MASTER, SCL= PIN_C3, SDA=PIN_C4,FORCE_HW, SLOW, STREAM=CHIP )
#define READEEPROMCMD 0xE1
#define WRITEEEPROMCMD 0XF1
#define CHIPADDR 0x32
int8 Buffer[6];
int8 RdData(int8 NbBytes);
void main(void)
{
int8 EEPromAddr,i2cbuff[4],ack,i;
setup_oscillator(OSC_4MHZ|OSC_INTRC);
EEPromAddr=0x08;
i2cbuff[0]=CHIPADDR;
i2cbuff[1]=READEEPROMCMD;
i2cbuff[2]=EEPromAddr;
i2c_start(CHIP);
for (i=0;i<3;i++)
{
ack= i2c_write(i2cbuff[i]);
if (ack!=0) break;
}
i2c_stop(CHIP);
if (ack!=0)
while(1);
if (RdData(1)==1)
while(1);
while(1){
}
}
int8 RdData(int8 NbBytes)
{
int8 iBuffer;
iBuffer=0;
i2c_start(CHIP,0);
if (i2c_write(CHIP,(CHIPADDR|0x01))!=0)
{
i2c_stop(CHIP);
return 1;
}
while(iBuffer!=NbBytes) {
// while(!i2c_poll(CHIP)) ;
Buffer[iBuffer++]= i2c_read(CHIP);
}
i2c_stop(CHIP);
return 0;
}
|
When I rem the line : while(!i2c_poll(CHIP)) ; the chip responds with valid data.
Does anyone knows what's happenning with i2c_poll() or what's wrong with my program?
Also when the program works with the i2c_poll() removed, I can read data but after the i2c_stop() the data line is stuck at 0. I need to shut off the power of the slave chip. !! If I write data to the chip both lines goes high after the i2c_stop.
I don't know how to make that bus work properly. What's wrong.
The chip is HMC6343 electronic compass working @ 3V and I'm using 2 Mosfet on SCL & SDA lines for level shifting. I can measure on the scope that the microprocessor's SDA line is back at 5V but the slave pulls it down at 0. |
|
|
JacquesB
Joined: 22 Aug 2008 Posts: 21
|
|
Posted: Mon Feb 09, 2009 10:25 am |
|
|
I just find out the solution for SDA line stuck at 0 after i2c_read().
On last byte to read i must not acknowledge it so that slave doesn't wait indefinitively for transmitting another byte.
So I used i2c_read(0) on last byte to read instead of i2c_read() which default to send an Ack.
I still have the question with the I2c_poll() problem... |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Feb 18, 2009 12:16 pm |
|
|
I think i2c_poll() is only intended for use by an i2c slave program.
Why do you want to use it in a Master ? The only way the master
will get data from a slave is by issuing an i2c_read(). Data does
not accidently get into the Master PIC. It has to explicitly read it
from the slave. |
|
|
JacquesB
Joined: 22 Aug 2008 Posts: 21
|
|
Posted: Wed Feb 18, 2009 1:10 pm |
|
|
Your're probably right. I did look at it like this.
But I started my program using an example from CCS manual: (p.172)
Code: | i2c_start(); // Start condition
i2c_write(0xc1); // Device address/Read
count=0;
while(count!=4) {
while(!i2c_poll()) ;
buffer[count++]= i2c_read(); //Read Next
}
i2c_stop(); // Stop condition
|
This doesn't look like a code for a slave unit...
thanks |
|
|
|