PDA

View Full Version : I2C with 18F2685



MikeBZH
- 15th July 2009, 15:13
Hello,

I am trying, unsuccessuly up to now, to make some I2C communications between a 18F2685, a DAC (MAX517) and two I/O expanders (23008), everybody is on the same I2C bus, the DAC receiving data from the PIC and the I/O expanders being read by the PIC.

I would like to use the PBP commands I2CREAD and I2CWRITE but they look to be written for older PICS.

Do they also work with 18F PICS ? If yes, do I need to make some kind of preliminary initialisation, for example set up the I2C pins via TRISC or configure the MSSP registers ? Do I need to setup the bus speed or anything else (address width for example ?)

I have an other question about the addresses. They are supposed to be 7 bits width, but they look as being left justified. So, do they need to be passed to the PBP instructions as left justified or right justified variables. For example how should I pass the address $2c : $2c or $58 ?

Any help greatly appreciated

Best regards

MikeBZH

Dave
- 15th July 2009, 15:52
MikeBZH, Its in the manual.... And there is no difference whether its for an 16 series or 18 series..

Dave Purola,
N8NTA

aratti
- 15th July 2009, 17:53
I use both I2CRead and I2CWrite with pic18F4680 without any problem.

In my code I use always the following two declarations:

DEFINE I2C_SLOW 1
DEFINE I2C_HOLD 1

Al.

MikeBZH
- 15th July 2009, 18:13
Dave, Aratti

So it is so simple ?
I'll try this tomorrow.

Many thanks for your help

MikeBZH (also F8DFN, 73's Dave)

MikeBZH
- 16th July 2009, 18:38
Good evening !

No way with this problem !
I have spent the whole day on it with no result...

The circuit is yet very simplified : only the 18F2685 + the MAX517 + 2 pull-up resistors. The PIC is running at 32 MHz.

The program is also very simple and starts with :

DEFINE I2C_SLOW 1
DEFINE I2C_HOLD 1
....

AppGain:

Gain = $55
RESET517 = $10
CTRL517 = $00

Re2 : I2CWRITE PORTC.4,PORTC.3,CTRL517,ADR517,[Gain],Re1
PAUSE 10
GOTO Re3

Re1: ADR517 = ADR517 + 1
if (ADR517 <> $FF) then
goto Re2
else
endif

Re3: RETURN

All the variables are bytes.
AppGain is called by a test section of my program.

The hereabove version was adapted to scan the addresses in search of a response from the MAX517. According to the manual, the program jumps to Re1 if no ACK was received from the slave. And there is never any ACK received, the program always ends with $FF in ADR517. The slave address should be $2c but I got no answer from there.

I have checked the SDA and SCL lines with my scope. The signals look fine but no ACK is visible. I have even changed the MAX517 for a new one : same behaviour.

Any idea ?

MikeBZH

Dave
- 17th July 2009, 11:59
MikeBZH, What values are you using for the pullup reststors on the SDA/SCL lines... I have found in the past that 4.7 k resistors are too large and slow the current flow for passive pullup when I use more than 4 devices on a bus... I would use 2.2 k resistors and try that.. It should cleanup the data signal a bit.. I'm not sure if the statement DEFINE I2C_HOLD 1 is required or not.. I have never used it in the past and I have used 100 khz. parts and 400 khz. parts with no issues.. Just make sure you use the statement DEFINE I2C_SLOW 1 if the part is only good for 100 khz. and you are running the processor at more than 4 mhz..

Dave Purola,
N8NTA

MikeBZH
- 26th July 2009, 15:11
Hi,

I fixed it, but the result is very strange.
Resistors values or Defines have no influence but it seems that there is bug in the PBP documentation (or in the compiler, as you prefer).

I found that the instruction :
I2CWRITE DataPin, ClockPin, Control, [Address,] ...

should be written
I2CWRITE DataPin, ClockPin, [Address,] Control...

In other words everything works if one pass first the Address and then the Control instead of what is written in the documentation. This is very clear with a dual trace scope on SDA and SCL.

My compiler version is 2.50L

MikeBZH / F8DFN

MikeBZH
- 26th July 2009, 16:53
Moreover,

The physical address has to be shifted left once (multiplied by 2) to cope with the I2C format. In my case the physical address is $2C : I have to pass $58 to I2CWRITE.

MikeBZH / F8DFN

Melanie
- 26th July 2009, 22:51
Strange... I use PBP v2.50 I2C to talk to EEPROM 24LC64, DS1307 and MCP23008 and other devices on the same board and it all behaves as expected per the Manual...

MikeBZH
- 28th July 2009, 22:57
Hi Melanie,

Please note that I use PBPL. Maybe the behaviour of this version is different from the others. I have no more time to make some comparison tests but I will do them when I come back from vacation by the end of August.

MikeBZH / F8DFN

MikeBZH
- 11th January 2010, 12:43
Hi,

Coming back after some time spent with other business...
I have no more MAX517 in my circuit but the MCP23008 are still there and I need to use I2CWRITE and I2CREAD with them.
The issue is still there. I confirm that with my PBPL v2.50, I need to invert the address and the control fields and to multiply the address by 2 to make I2CWRITE work. And from the experiments done this morning I know that I need to do the same thing for I2CREAD !

Best regards

MikeBZH / F8DFN

Dave
- 11th January 2010, 13:08
MikeBZH, I hope you had a nice vacation in August... I have been currently using a pair of 24LC1025's to log data from my Solar Tracker which uses an 18F2620 running @ 40 Mhz. I have had no problem with them even in the below zero temperatures we have up here in Michigan...
I do not compile with PBPL as I have used the internal flash to about 3/4"s of its capacity. It's nice to see you back...

Dave Purola
N8NTA

Melanie
- 11th January 2010, 14:16
I need to invert the address and the control fields and to multiply the address by 2


Then you are doing something very strange in either your Hardware connections or in Software!

If fact, I believe you've not realised how the chip is to be addressed (refer to Datasheet 1.4.1). If you have GROUNDED pins A0,A1 and A2, then you would address the chip as $40, but if for example A1 and A2 are GROUNDED and you tie A0 to VDD, then you would address the chip as $42. Note that Bit 0 must be left alone, because it determines if this is a READ or WRITE operation!!!! YOU don't touch BIT-0, it is set for you elsewhere by the I2C commands (which also determines that your ADDRESS must be a BYTE VARIABLE and NOT a Constant).

I use MCP23008's in several designs with both 16F's and 18F's. PBP Ver 2.46 thru 2.50 has no problems and no issues and allows me to port software across several PIC families which may not have I2C hardware capability. I commonly mix MCP23008's with EEPROM's and RTC's all on the same bus, and up to five devices on the same bus pins are good with 4K7 Pull-Up's.

I2CWrite SDA,SCL,I2CAddress,I2CRegister,[I2CData]

Where I2CAddress, I2CRegister and I2CData are all BYTES and previously (for example)...

I2CAddress=$42 ' Hardware Address of selected MCP23008 Device
I2CRegister=9 ' Device Register Address being written to

There is no Hardware initialisation required on the PIC side (other than defining your SCL and SDA pins), but yes, you DO have to initialise your MCP23008's before you use them!

Here is a typical initialisation sequence at initial Power-On for TWO MCP's being configured for OUTPUT (with different inital ON states)...



For CounterA=0 to 1
If CounterA=1 then
I2CAddress=GPA
else
I2CAddress=GPB
endif
For I2CRegister=0 to 9
I2CData=0
If I2CRegister=9 then
If CounterA=0 then
I2CData=%11111111
else
I2CData=%00001100
endif
endif
I2CWrite SDA,SCL,I2CAddress,I2CRegister,[I2CData]
Next I2CRegister
Next CounterA

Refer to the MCP's Datasheet for configuring for your own requirements.

MikeBZH
- 14th January 2010, 19:36
Hi Melanie,

In fact this is only a matter of definition of the addresses in a specific context.

If one consider the MCP23008 "as it", its address is determined by A2, A1, A0 and the higher bits which are predetermined for this specific component. At this level of the design nobody knows in which context (program, compiler, hardware) the component is going to be used and the address has to be written as : 20H + (A2,A1,A0). For example, if (A2,A1,A0) = (0,0,1) then the address is 21H. We can call it a physical address and it is only component dependant.

Now, if we want to pass this address to a PBP program, we have to shift it once left to leave some room for the R/W bit. Therefore this specific byte field value will be obtained by multiplying the physical component address by two (shift left once) and leaving the R/W to 0. At this level and for the hereabove example the field value is equal to 42H.

Formally speaking, it is not very logical to pass an already shifted physical address to the program but once this is known and clear, no problem, it works.

Best regards

MikeBZH / F8DFN