|
|
View previous topic :: View next topic |
Author |
Message |
ragp
Joined: 19 Jan 2004 Posts: 2
|
#use i2c preprocessor |
Posted: Mon Jan 19, 2004 5:48 am |
|
|
I seem to be having trouble with the preprocessor command #use i2C. To switch paths between two i2C buses I had written the #use lines to direct the comms to either pins on B or pins on C. However the code only seems to use the first #use i2C that it encounters.
Is this a common problem? What is the solution? |
|
|
neil
Joined: 08 Sep 2003 Posts: 128
|
I?C is multidrop |
Posted: Mon Jan 19, 2004 7:05 am |
|
|
Hi, why have 2 I2C buses? It is a multidrop bus, which uses addressing to distinguish between different devices! You can only use one bus at a time anyway.
However, if you mean that you are putting both buses in your code and deciding to use one or the other at compile time, you can use a #ifdef to use the appropriate line.
eg: Code: | #define USE_I2C_B // comment this out and it will use second I2C on port C.
#ifdef USE_I2C_B
#use I2C(master, sda=PIN_B0, scl=PIN_B1)
#else
#use I2C(master, sda=PIN_C4, scl=PIN_C3, FORCE_HW)
#endif
| This is all Preprocessor and does compile. I haven't checked whether it works on a chip, but I don't see why not.
HTH, Neil. |
|
|
Guest
|
Re: I�C is multidrop |
Posted: Mon Jan 19, 2004 7:21 am |
|
|
Thanks for the help.
One bus is fully populated with eeprom memory (addresses 0-7). I'd like to add two chips, one for time and one for temperature. The high address of one of these chips is the same as the eemprom memory (0xa0). To get over this I had hoped to use two i2c buses and switch between them in the code by using one of two #use i2c, changing to bus 2 to get time and temperature and then back to bus1 for most of the work The sequence would be to get time and temperature and record it to memory, get a swathe of data and record it to memory and then finish off with time and temperature recorded to memory.
Andrew
neil wrote: | Hi, why have 2 I�C buses? It is a multidop bus, which uses addressing to distinguish between different devices! You can only use one bus at a time anyway.
However, if you mean that you are putting both buses in your code and deciding to use one or the other at compile time, you can use a #ifdef to use the appropriate line.
eg: Code: | #define USE_I2C_B // comment this out and it will use second I2C on port C.
#ifdef USE_I2C_B
#use I2C(master, sda=PIN_B0, scl=PIN_B1)
#else
#use I2C(master, sda=PIN_C4, scl=PIN_C3, FORCE_HW)
#endif
| This is all Preprocessor and does compile. I haven't checked whether it works on a chip, but I don't see why not.
HTH, Neil. |
|
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Mon Jan 19, 2004 7:35 am |
|
|
You always have the option to bit bang the second i2c port. That is what I do. We have several pics communicating on i2c and data is stored in serial eeproms. The eeproms are bit banged on a separate port because the other devices are writing configuration data on the first port which is being saved on the second. This keeps the bus traffic down and reduces collision errors. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jan 19, 2004 1:44 pm |
|
|
Quote: | I seem to be having trouble with the preprocessor command #use i2C. To switch paths between two i2C buses I had written the #use lines to direct the comms to either pins on B or pins on C. However the code only seems to use the first #use i2C that it encounters. |
The solution is two use two different "#use i2c" statements, and
then to put all the routines that pertain to a particular i2c bus, below
the proper #use i2c statement for that bus.
The compiler will then generate two complete sets of the i2c
library code, but with the ASM code setup to use different pins
for each set of code.
You can't just have one set of i2c library code, and then magically
tell it to change the pins at run-time. The instructions that use the
specified i2c pins are hard-coded by the compiler at compile-time.
So you will end up with two instances of the library code, but with
each one tailored to the specified i2c pins.
See the example below:
(Note: This is not a full driver of any sort. It's just an example
of how to specify which i2c bus to use for each set of i2c functions).
#include "16F877.h"
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock = 8000000)
#use rs232(baud = 9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#define EEPROM_I2C_WRITE_ADDR 0xA0
#define EEPROM_I2C_READ_ADDR 0xA1
void init_ext_eeprom(void);
void write_eeprom_byte(int16 addr, char data);
int8 read_eeprom_byte(int16 addr);
void init_temp(void);
void temp_config(int8 data);
int8 read_temp(void);
//============================================
main()
{
int8 value;
int8 current_temp;
// Do some EEPROM operations on the i2c bus on pins B0 and B1.
init_ext_eeprom();
write_eeprom_byte(0, 0x55);
value = read_eeprom_byte(0);
// Do some operations with the temperature chip on the
// i2c bus that is on pins C4 and C3.
init_temp();
current_temp = read_temp();
while(1);
}
//==================================
// The external EEPROM (24LC256) is on the i2c
// bus that is on Pins B0 and B1. For the next
// three functions, the compiler will generate
// "bit-banged" i2c code on pins B0 and B1.
#use i2c (Master, sda = PIN_B0, scl = PIN_B1)
void init_ext_eeprom(void)
{
output_float(PIN_B0);
output_float(PIN_B1);
}
//-------------------------------------------
void write_eeprom_byte(int16 addr, int8 data)
{
i2c_start();
i2c_write(EEPROM_I2C_WRITE_ADDR);
i2c_write((char)(addr >> 8));
i2c_write((char)addr);
i2c_write(data);
i2c_stop();
delay_ms(6);
}
//------------------------------------
int8 read_eeprom_byte(int16 addr)
{
char data;
i2c_start();
i2c_write(EEPROM_I2C_WRITE_ADDR);
i2c_write((char)(addr >> 8));
i2c_write((char)addr);
i2c_start();
i2c_write(EEPROM_I2C_READ_ADDR);
data = i2c_read(0);
i2c_stop();
return(data);
}
//====================================
// The temperature chip is on the i2c bus
// that is on pins C4 and C3. Because we now
// have a new "#use i2c" statement below, which
// defines different pins, all calls to i2c functions
// that are below this statement will have "bit-banged"
// i2c code generated for pins C4 and C3.
#use i2c(Master, SDA = PIN_C4, SCL = PIN_C3)
void init_temp()
{
output_high(PIN_C4);
output_high(PIN_C3);
i2c_start();
i2c_write(0x90);
i2c_write(0xee);
i2c_stop();
temp_config(8);
}
//------------------------------------
void temp_config(int8 data)
{
i2c_start();
i2c_write(0x90);
i2c_write(0xac);
i2c_write(data);
i2c_stop();
}
//-----------------------------------
// Returns degrees F (0-255)
int8 read_temp(void)
{
int8 datah, datal;
int16 data;
i2c_start();
i2c_write(0x90);
i2c_write(0xaa);
i2c_start();
i2c_write(0x91);
datah=i2c_read();
datal=i2c_read(0);
i2c_stop();
data=datah;
data=data*9;
if((datal & 0x80)!=0)
data=data+4;
data=(data/5) + 32;
datal=data;
return(datal);
} |
|
|
|
|
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
|