Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Can i use two I2C device in 16F877A?

Status
Not open for further replies.

Hesam Kamalan

New Member
Hi,

i want to use DS1307(RTC) and DS1820(Temprature Sensor) in my project. my micro is 16F877A and compiler is MikroC. this micro has one I2C bus but i have 2 I2C device.

can i use this 2 device in my project?
 
You can use quite a few devices on the same I2C bus as long as they have different addresses.
But the DS18S20 is not an I2C device, it's a 1-wire device and not I2C bus compatible.
 
If it wasn't a one-wire and you still wanted 2 I2C controls you could also do so by using the mikroC Soft_I2C library. This allows you to specify the SDA, SCL pins to be whatever you like. So you could have one using the default SDA/SCL pins RC4 and RC3 and then you could wire up two others as well e.g. RB4 and RB5.
 
Last edited:
If it wasn't a one-wire and you still wanted 2 I2C controls you could also do so by using the mikroC Soft_I2C library. This allows you to specify the SDA, SCL pins to be whatever you like. So you could have one using the default SDA/SCL pins RC4 and RC3 and then you could wire up two others as well e.g. RB4 and RB5.

But that would rather defeat the object of I2C, which is that you only need a single bus, and all devices have their own address on that bus. I'm not saying that under extremely rare circumstances it might be useful, but it would be rare.
 
Thank you very much.

i was worked with one I2C bus but i did not work with two I2C device.

i have a question.
when i assign one address on my bus, witch device take first address?
 
You don't 'assign addresses', each device has it's own address assigned when the chip is made - although many have external pins you can use to select one of a number of addresses. Eight pin EEPROM's are a prime example.
 
thanks Nigel,

imagin that i want to use one DS1307. i use this code for writeing data:
//----------------------------------------------------------------
void write_DS1307(unsigned short address, unsigned short data)
{
I2C_Start();
I2C_Wr(0xd0);
I2C_Wr(address);
I2C_Wr(data);
I2C_Stop();
}
//----------------------------------------------------------------

i wrote my own address in code. now, if i had two DS1307, how can i assign address?
witch Device take first address?
 
thanks Nigel,

imagin that i want to use one DS1307. i use this code for writeing data:
//----------------------------------------------------------------
void write_DS1307(unsigned short address, unsigned short data)
{
I2C_Start();
I2C_Wr(0xd0);
I2C_Wr(address);
I2C_Wr(data);
I2C_Stop();
}
//----------------------------------------------------------------

i wrote my own address in code. now, if i had two DS1307, how can i assign address?
witch Device take first address?

Are there any other printed numbers on the DS1307's..?
 
You can only have 1 DS1307 on the I²C bus as it doesn't have any address pins but why would you want two? You can put 8 serial EEPROMS, a DS1307, an MCP9800 temperature sensor, a battery monitor etc. on the same bus. Send the correct address and the device assigned that address will answer.

Mike.
 
Hi Heasm,
yes, you can use two I2C devices,but a little tricky. You must spend one pin of your controller. Use a digital switch like 74HC157. This has 4 switches with 2 inputs (A, B) and one output (Q) each. It can be triggered through Select A/B. It would be sufficient to switch the CLK only, but you have 4 switches, so you can switch CLK and Data Line of the I2C bus.

Some remarks to your code example.

You must first configure the MSSP as I2C operation. It ist done with the following code sequence, I call it ConfigI2C:

void ConfigI2C(void)
{
INTCON2 = 0x80; // Disable port B pullups
PIR1bits.SSPIF = 0; // Clear MSSP Interrupt Flag bit
PIR2bits.BCLIF = 0; // Clear Bus Collision Interrupt Flag bit
DDRBbits.RB1 = 1; // Configure SCL as input
DDRBbits.RB0 = 1; // Configure SDA as input
OpenI2C(MASTER, SLEW_OFF);
SSPADD = I2C_BaudRate; // I2C transfer rate 100 kc
}

Don't forget the external pullups for RB0 and RB1. I use 4.7 kOhms for 100 kHz bus speed.

Next I miss the IDLE calls in your example. This is a working routine. Reading one byte from the device. You can use it as a template.

unsigned char PCF8574_inp(unsigned char subaddr)
{
unsigned char cw;

StartI2C();
while(SSPCON2bits.SEN);
WriteI2C(PCF8574_addr+subaddr*2+Read);
IdleI2C();
cw = ReadI2C();
NotAckI2C();
while(SSPCON2bits.ACKEN);
StopI2C();
while(SSPCON2bits.PEN);
CloseI2C();
return(cw);
}

With greetings
ERhard
 
Last edited:
Sorry, I made an error.
The device for switching must be bi-directional. So one cannot use the 74HC157. I don't know whether a bidirectional device exists, so the circuit would become some difficult. May be it will work by only switching the CLK line, without clock stretching, but I'm not sure. Sorry again.
Erhard
 
Sorry, I made an error.
The device for switching must be bi-directional. So one cannot use the 74HC157. I don't know whether a bidirectional device exists, so the circuit would become some difficult. May be it will work by only switching the CLK line, without clock stretching, but I'm not sure. Sorry again.
Erhard

hi,
It would be possible to use an analog bidirectional gate, if it was required for selection.:)
 
Hello Eric,
yes, I had the same thought. But I rejected it with reference to the slew rate requirements of the I2C signals. But I didn't check it.

Even if my hair ist raising, if it is a serious problem that must be solved, one can use a mini relay to switch. There is no problem with the load or voltage. There are relays which can be controlled directly by the MPU, but one can also use a transistor to drive it. In the net there are a lot of examples available. This solution needs a short delay for debouncing (some ms)between selection of the desired device and the call of the I2C - routine.

I hope, this could be a little help for Hesam.
With regards
Erhard
 
hi Erhard,
The analog selectors can be used with Video signals, at +5V, my data shows switching times in the order of a few tens of nanoSecs.

Which 'slew rate' are you quoting.?? Look at the HEF series.

I know of other users that have connected analog selectors to PIC's/I2C with success.:)
 
Hello Eric,
yes, I had the same thought. But I rejected it with reference to the slew rate requirements of the I2C signals. But I didn't check it.

Even if my hair ist raising, if it is a serious problem that must be solved, one can use a mini relay to switch. There is no problem with the load or voltage. There are relays which can be controlled directly by the MPU, but one can also use a transistor to drive it. In the net there are a lot of examples available. This solution needs a short delay for debouncing (some ms)between selection of the desired device and the call of the I2C - routine.

First off, why do you feel the need to do this?, do you have clashing I2C addresses?.

If you do, then simply use another pair of pins to create a second I2C bus, but generally if you've got a clash, it's because you've chosen your devices badly.
 
The OP can put a DS1307 (add 0xD0) and a MCP9800 (add 0x90) on the same bus and have no clashes. Should he want to measure 8 different temperatures then he can use the MCP9801 (add 0b1001NNN0) and put 8 of them on the same bus as the 1307 without a clash. You cannot put two DS1307s on the same bus but why would you want two real time clocks in the same system!

If you wanted to measure 16 temperatures and have two real time clocks on your poor little PIC then you can do as Nigel says and implement a software bus. He even has the routines in his tutorial.

Mike.
 
Hello,

Can you look at my code and guess what i am doing wrong with my code.

I cannot read neither write to ds1307.

connected through port d bits 5 and 6

crystall oscillator 10Mhz but using hspll

have pull up resistors on both lines sda and scl



//************************************************************************************//
//************************************************************************************//
// //
// Header: 8722 Project //
// PIC used: PIC18F8722 //
// Start Date: 1st Dec 2009
// Function for I2C //
//************************************************************************************//
//************************************************************************************//
//** HEADER FILES ********************************************************************/
#include <p18F8722.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <usart.h>
#include <timers.h>
#include <delays.h>
#include <i2c.h>
//** CONFIGURATION BITS **************************************************************/
#pragma config OSC = HSPLL
#pragma config WDT = OFF
#pragma config LVP = OFF
#pragma config DEBUG = ON
//** FUNCTION PROTOTYPES *************************************************************/
void Init_Ports(void);
void Configure_I2C2(void);

void I2C2_Write(unsigned char Add, unsigned char Data);
void Write(unsigned char Input_Data);
unsigned char I2C2_Read(unsigned char add);

void SCL_high(void);
void SCL_low(void);
//** DEFINITIONS *********************************************************************/
#define IniDs1307 0x00
#define AddRDs1307 0xD1
#define AddWDs1307 0xD0
#define CLEAR 0
#define SET 1
#define BRGValue 0x63

//** GLOBALS *************************************************************************/

unsigned char Second, Minutes, Hours, Day, Date, Month, Year;
//** MAIN CODE ***********************************************************************/
void main(void)
{
Init_Ports();
Configure_I2C2 ();


I2C2_Write(0x07,0x00); // control register add 07, 00 as i am not using swqe, rs0, rs1

I2C2_Write(0x00,0x05);// control register for seconds,also CH=0 initialized for first time (bit 7), add = 0x00, value assigned 0x05
I2C2_Write(0x01,0x07);// control register for minutes, add = 0x01, value assigned 0x07 (just to see whther the RTC works)
I2C2_Write(0x02,0x06);// control register for Hours, add = 0x02, value assigned 0x06

I2C2_Write(0x03,0x02);// control register for Day, add = 0x03, value assigned 0x02

I2C2_Write(0x04,0x03);// control register for Day, add = 0x04, value assigned 0x03
I2C2_Write(0x05,0x02);// control register for Month, add = 0x05, value assigned 0x02
I2C2_Write(0x06,0x04);// control register for Year, add = 0x06, value assigned 0x04

Second = I2C2_Read(0x00);
Minutes = I2C2_Read(0x01);
Hours = I2C2_Read(0x02);

Day = I2C2_Read(0x03);
Date = I2C2_Read(0x04);
Month = I2C2_Read(0x05);
Year = I2C2_Read(0x06);
StopI2C2();

while(SET)
{
Nop();
}
}

//*************************************************************************************
void Init_Ports(void)
{
PORTD = CLEAR;
LATD = 0b01100000;
TRISD = 0b01100000; // intialized RD6(SCL2) AND RD5(SDA2).
}
//*************************************************************************************
void Configure_I2C2 (void)
{
SSP2CON1 = 0b00001000;
SSP2STAT = 0b10000000;
SSP2ADD = 0x63;

//SSP2ADD = (BYTE) _I2C_BAUD_COUNT;
SSP2CON2bits.ACKSTAT = 1;
SSP2CON1bits.SSPEN = 1;
OpenI2C2(MASTER, SLEW_OFF);
}
//***********************************writes data to add***************************************************
void I2C2_Write(unsigned char Add, unsigned char Data)
{
PIR3bits.SSP2IF= CLEAR;

StartI2C2();

Write(0xD0);
IdleI2C2();

Write(Add);
IdleI2C2();

Write(Data);
IdleI2C2();

StopI2C2();
}
//***********************function of write***********************************
void Write(unsigned char Input_Data)
{
unsigned char data, i, Outbit;
data = Input_Data;

for (i = 0; i <= 7; i++)
{
Outbit=data&0x80;
PORTDbits.RD5 = Outbit;
data = data << 1;
SCL_high();
SCL_low();
}

while (SSP2CON2bits.ACKSTAT == 1) { }



}
//**************reads add and returs data**********************************
unsigned char I2C2_Read(unsigned char add)
{
unsigned char dataa;

StartI2C2();
Write(0xd1); // to write
IdleI2C2();



Write(add); // address to read
IdleI2C2();



if (DataRdyI2C2())
{
getcI2C2();
}
dataa = SSP2BUF;

while (SSP2CON2bits.ACKSTAT == 1) { }
PIR1bits.SSPIF = 0; // clear flag


NotAckI2C2();
StopI2C2();

//dataa = (dataa & 0x0f) + (dataa>>4)*10; // chuyenthanh so thap phan
return (dataa);
}
//*************************************************
void SCL_high(void)
{
PORTDbits.RD6 = 1;
Delay1KTCYx(1000);
}

//*************************************************
void SCL_low(void)
{
PORTDbits.RD6= 0;
Delay1KTCYx(1000);
}
 
Status
Not open for further replies.

Latest threads

Back
Top