PDA

View Full Version : i2c non-eeprom examples?



justDIY
- 17th June 2004, 05:03
Hi All

just found this forum with google - deffinately will be having a good time 'catching up' on all the old posts.

Has anyone worked with Maxim MAX6650 (or 6651) fan speed regulator?

I think I understand using i2c read and write with a serial eeprom, and it looks very straight forward.

however, I'm wondering about interfacing with more 'complex' i2c devices.

Even if you haven't worked with the 6650 or 6651, can anyone share example or rough starting points on how to control a similar device?

thanks a lot!

Gordon

datasheet for 6650/1

http://pdfserv.maxim-ic.com/en/ds/MAX6650-MAX6651.pdf

Melanie
- 18th June 2004, 10:09
Here's an example snippet... reads the time from a DS1307...

I2CRead SDApin,SCLpin,$D0,$00,[RTCSec,RTCMin,RTCHour,RTCWDay,RTCDay,RTCMonth,RTCY ear,RTCCtrl]

Melanie

oops... it's all supposed to be on one line... but won't edit as such!

justDIY
- 19th June 2004, 17:25
Originally posted by Melanie
I2CRead SDApin,SCLpin,$D0,$00,[RTCSec,RTCMin,RTCHour,RTCWDay,RTCDay,RTCMonth,RTCY ear,RTCCtrl]


ok, so this is basicly just a multibyte read... all the named variables were declared as bytes ?

$d0 is the device's address, with the read / write bit set to read 1101000 + 0 ?

$00 is the location (register?) the read starts at?

I assume then that a write to that device would be similar, but the address would be $D1 (1101000 + 1) and the variables would be loaded with bytes properly formatted as per the datasheet?

sorry to ask such a novice question, but, how do I take apart a byte and figure out what the individual bits are, like reading the RTCCtrl byte?

Melanie
- 19th June 2004, 18:30
OK, you've posed a whole heap of questions... so let's take this apart...

1. Yes, all the variables were prevoiuly decalred as bytes. You can send words, they are sent highbyte first which can conflict with the usual default memory storage arrangements. If in doubt use the highbyte or lowbyte modifier and send bytes to ensure your target device gets data in the arrangement it expects.

2. $D0 (always do Hex in capitals as some assemblers will turn around and bite you if you use lower-case). Yes, it's the device address. I didn't do it in this example, but ideally you will have previously defined this as either an 8-bit or 16-bit variable (to suit your device) and preloaded ($D0 in my case) into it. No, don't worry about changing bit 0 of the address to a '1' or a '0' (depending on Read or Write) as the I2C commands will automatically handle that bit for you. I usually always leave it as '0'.

3. $00. Yes this is the Register address. My example showed me reading eight bytes starting with address $00. If I only wanted to read the Hours Register, I could have executed...

I2CRead SDApin,SCLpin,$D0,$02,[RTCHour]

4. Writing would be the opposite of reading (including my new example above). The Data bytes would have been preloaded with the information targeting the registers I wanted loaded with that data. As I said before, don't worry about bit 0 of the Address, it's handled for you. If you do include it, no harm done as the I2C commands will ignore it and do their own thing anyway.

5. Strip a byte apart using the bit manipulation facilities of PICBasic.

Example 1. Let me use the Seconds Byte RTCSec in my example. When you first power-up a DS1307 (you just got it fresh from Dallas), and you apply power to it (either by slotting-in a Battery or from it's main +5v Supply, or both, or if it's been powered off without Battery Backup), then the chip basically is brainless. It has no Date, no Time, and everything (including it's NVRam which is only NV if there's a battery connected - kinda like my Laptop!) is in an unpredicatable state. Worse, the chip isn't even ticking. The only thing that you DO know is that bit 7 of the Seconds Register is set to '1'. So, you read the Seconds Register and do this...

If RTCSec.7=1 goto SetDateandTime

Example 2. You want the DS1307 to output a 1 second tick on it's SQW/OUT pin. This is done by setting bit 4 to 1, and bits 1 and 0 of the Control Register to zero. Two ways to do this... either...

(a) Read the Control Register Byte first, then do this...

RTCCtrl.4=1
RTCCtrl.1=0
RTCCtrl.0=0

and then write the Byte back out again into the Control Register (which will not affect the setting of the other five bits), or,

(b) Preset the entire Control Register BYTE (all eight bits of it)...

RTCCtrl=%00010011

and again write the whole byte out...

You will notice we can only do BYTE I2CREAD/WRITE operations, and cannot manipulate a single individual bit. The method you chose is up to you. This chip requires method (b) to initialise because you can't rely on Dallas's engineers to have built it properly to initialise itself into any predetermined state - therefore you have to do it. The Datasheet of your chosen I2C device should tell you the state of all it's internals at Power-Up.

The I2C bit is really easy - but study the Datasheet of your chosen device. See what state it's in and what it needs to initialise it from Power Up. Once you've done that, everything is as sweet as Mom's Apple Pie...

Melanie

Melanie
- 19th June 2004, 19:03
I'm just going to add to my previous posting to give you a nudge in the right direction... looking at the datasheet for your fan controller, it looks like you cannot address all the Registers sequentially in one hit (like I do with the DS1307 example). For a start, they're not sequential - it looks like Maxim designed this on a Friday afternoon and they went home early... so each Register will have to be addressed on an individual basis with it's own I2CRead/Write instruction.... example...

FanAddress var Byte
FanControl var Byte
FanData var Byte

FanControl=$02:FanData=%00001010:Gosub SetFanA
FanControl=$04:FanData=%11110101:Gosub SetFanA

.. ..

SetFanA:
FanAddress=$90
I2CWrite SDApin,SCLpin,FanAddress,FanControl,[FanData]
Return

I'll let you figure what I've set, and how I connected the chip to give it a $90 address...

Melanie

justDIY
- 20th June 2004, 07:26
Originally posted by Melanie
I'm just going to add to my previous posting to give you a nudge in the right direction... looking at the datasheet for your fan controller, it looks like you cannot address all the Registers sequentially in one hit (like I do with the DS1307 example). For a start, they're not sequential - it looks like Maxim designed this on a Friday afternoon and they went home early... so each Register will have to be addressed on an individual basis with it's own I2CRead/Write instruction.... example...

FanAddress var Byte
FanControl var Byte
FanData var Byte

FanControl=$02:FanData=%00001010:Gosub SetFanA
FanControl=$04:FanData=%11110101:Gosub SetFanA

.. ..

SetFanA:
FanAddress=$90
I2CWrite SDApin,SCLpin,FanAddress,FanControl,[FanData]
Return

I'll let you figure what I've set, and how I connected the chip to give it a $90 address...

Melanie

wow - great replies Melanie - thanks a ton!

always type hex values in caps - noted!

no need to specify read or write bit in the address - noted!

about the ds1307:

from reading the datasheet, I see what you mean about $00 bit 7 ... assuming a fresh (or disconnected) clock chip, that bit will be high, so I can tell whether I need to initialize the chip or not.

bit manipulation:

well I'm real sorry I had to ask that! I've spent all this time reading datasheets but haven't given the pbp manual any attention.

about the max6650:

$90 - ok I'll answer the easy one first, wiring for the address!

Address $90 hex = 1001000 ... tie ADD pin 5 to ground

now, for my 100th time reading the 6650 datasheet, all the talk of register this ... bit that... is starting to make sense!

FanControl=$02=%00000010 ... select the CONFIG register

byte fandata=%00001010

bits 7 to 6 always 00 according to data sheet
bits 5 to 4 set to 00 = software full-on
bit 3 set to 1 = 12 volt fan
bits 2 to set to 010 = Prescaler divide by 4

next, FanControl=$04=%00000100 ... select GPIO configuration

byte fandata=%11110101

bit 7 set to 1 = gpio 4 high/input
bit 6 set to 1 = gpio 3 high/input
bits 5,4 set to 11 = gpio 2 high/input
bits 3,2 set to 01 = gpio 1 set to FULL ON input
bits 1,0 set to 01 = gpio 0 set to ALERT output


thanks A LOT for your help!

i'm in an optimistic mood already, as I tested my pair of max6650s that I had hand soldered to DIP 10 to µSOP adapters (max6650 is about the size of two grains of white rice!) ... both passed with flying colors connected directly to my PC's smbus

your responses to my questions makes me even more optimistic that I'll be able to complete my project easily! pbp is powerfull stuff, and so is the microchip pic!

my serial programmer just arrived saturday, cant wait to try some code against the real pic now!

have a good week,

Gordon

Melanie
- 20th June 2004, 11:58
Spot On. See - that was easy... the forum has just got a new fan expert!

RubenR
- 11th March 2005, 23:45
I've read and followed the example/explanation above and it looked great to me. I've got a problem wich looks like this. I'm trying to control the MAX6953. (Datasheet: MAX6953 http://pdfserv.maxim-ic.com/en/ds/MAX6953.pdf )

The MAX6953 is an I2C-controlled LED-matrix driver for 4 segments of 5*7 LED's.
I'm using a PIC16f870 to control one MAX6953. I thought it would be simple to try to use the display test mode first. In this test-mode, all LED's will light up.

This is the code I'm using:

Include "modedefs.bas"
DEFINE OSC 20

SCL VAR PORTB.0
SDA VAR PORTB.1

CommandByte VAR BYTE
SlaveAddress VAR BYTE
DataByte VAR BYTE

Main:
'Set the device address at the I2C-bus (datasheet page 10)
SlaveAddress = $50

'Set the Command Byte ($07 = displaytestmode. Datasheet page 11)
CommandByte = $07

'Set the Data Byte
DataByte = $01

'Write the data to the I2C-device
I2CWRITE SDA, SCL, SlaveAddress, CommandByte, [DataByte]

end


The problem is that there is nothing happening. Does anybody know what I'm doing wrong?

justDIY
- 12th March 2005, 14:30
first let me blow the dust off this thread... *sneeze*

It might have been a better idea to start a new thread than dig up one thats 9 months old :)


I thought it would be simple to try to use the display test mode first. In this test-mode, all LED's will light up.

Main:
'Set the device address at the I2C-bus (datasheet page 10)
SlaveAddress = $50

The problem is that there is nothing happening. Does anybody know what I'm doing wrong?

Looks like you wanted slave address = $A0 not $50 ... i2c address uses the 7 most significant bits of a byte, leaving the LSB for the read/write indicator ... see page 7 on the datasheet under slave address for the nitty gritty details

so $50 = 0101000x , but you need $A0 = 1010000x

the command and command data look a-ok

looks like a really feature packed chip - hope to hear more about it!

RubenR
- 12th March 2005, 16:59
Thanks! The address looks better now, but it still doesn't work yet.

I'll keep trying and will let you know when it works. If someone else got a good idea, I would like to here it too!

justDIY
- 13th March 2005, 00:25
hmm all i can think of is make sure the various decalres and registers are setup properly for i2c writes

if your pic has an MSSP module, you could try HBUSOUT and HBUSIN

also, make sure your i2c bus is wired properly, sda and scl need to be pulled high.

you can try breaking your commands down to their basics, write the address byte and wait for an ack, write the command byte, wait for an ack, data byte, ack .... etc ... just to troubleshoot your communications.

RubenR
- 13th March 2005, 21:15
Thanks for the reply. I've pulled up the ports and it look like it works now! It is possible to put the LED-driver into the test-mode and to set it back to normal operation.

The only problem is that I can't get a character on the display. To find te problem I've attached a serial cable to the PIC and added some debug commands.

The code I've used:


Include "modedefs.bas"
DEFINE OSC 20
'DEFINE I2C_HOLD 1

SCL VAR PORTB.4
SDA VAR PORTB.5

CommandByte VAR BYTE
SlaveAddress var BYTE
DataByte VAR BYTE
ReadData VAR BYTE
Character VAR BYTE

'Set Debug pin port
DEFINE DEBUG_REG PORTC
'Set Debug pin bit
DEFINE DEBUG_BIT 5
'Set Debug baud rate
DEFINE DEBUG_BAUD 2400
'Set Debug mode: 0 = true, 1 = inverted
DEFINE DEBUG_MODE 1


Init:

Debug "-->> Start <<--", 10 ,13

Debug "Test mode", 10 ,13
SlaveAddress = $A0 'Set the device address at the I2C-bus (datash. p. 10)
CommandByte = $07 'Set the Command Byte ($07 = displaytestmode. Datasheet page 11)
DataByte = $01 'Set the Data Byte
I2CWRITE SDA, SCL, SlaveAddress, CommandByte, [DataByte] 'Write the data to the I2C-device
I2CREAD SDA, SCL, SlaveAddress, [ReadData]
Debug "ReadData = ", dec ReadData ,10 ,13 ,10 ,13

pause 500

Debug "Normal mode", 10 ,13
SlaveAddress = $A0 'Set the device address at the I2C-bus (datash. p. 10)
CommandByte = $07 'Set the Command Byte ($07 = Normal mode. Datasheet page 11)
DataByte = $00 'Set the Data Byte
I2CWRITE SDA, SCL, SlaveAddress, CommandByte, [DataByte] 'Write the data to the I2C-device
I2CREAD SDA, SCL, SlaveAddress, [ReadData]
Debug "ReadData = ", dec ReadData ,10 ,13 ,10 ,13

pause 500

Debug "Set LED intensity 1", 10 ,13
SlaveAddress = $A0 'Set the device address at the I2C-bus (datash. p. 10)
CommandByte = $01 'Set the Command Byte ($01 = Intensity10. Datasheet page 11)
DataByte = $FF 'Intensity of all segments set to maximum (Page 20)
I2CWRITE SDA, SCL, SlaveAddress, CommandByte, [DataByte] 'Write the data to the I2C-device
I2CREAD SDA, SCL, SlaveAddress, [ReadData]
Debug "ReadData = ", dec ReadData ,10 ,13 ,10 ,13

pause 500

Debug "Set LED intensity 2", 10 ,13
SlaveAddress = $A0 'Set the device address at the I2C-bus (datash. p. 10)
CommandByte = $02 'Set the Command Byte ($02 = Intensity32. Datasheet page 11)
DataByte = $FF 'Intensity of all segments set to maximum (Page 20)
I2CWRITE SDA, SCL, SlaveAddress, CommandByte, [DataByte] 'Write the data to the I2C-device
I2CREAD SDA, SCL, SlaveAddress, [ReadData]
Debug "ReadData = ", dec ReadData ,10 ,13 ,10 ,13

pause 500

Debug "Set Scan-Limit", 10 ,13
SlaveAddress = $A0 'Set the device address at the I2C-bus (datash. p. 10)
CommandByte = $03 'Set the Command Byte ($01 = Intensity10. Datasheet page 11)
DataByte = $01 'Intensity of all segments set to maximum (Page 20)
I2CWRITE SDA, SCL, SlaveAddress, CommandByte, [DataByte] 'Write the data to the I2C-device
I2CREAD SDA, SCL, SlaveAddress, [ReadData]
Debug "ReadData = ", dec ReadData ,10 ,13 ,10 ,13

pause 500

Debug "Character 'I'D0,P0&P1", 10 ,13
SlaveAddress = $A0 'Set the device address at the I2C-bus (datash. p. 10)
CommandByte = $60 'Set the Command Byte ($60 = Digit 0 Plane P0 & P1. Datasheet page 11)
DataByte = $49 'Display Character 'I'
I2CWRITE SDA, SCL, SlaveAddress, CommandByte, [DataByte] 'Write the data to the I2C-device
I2CREAD SDA, SCL, SlaveAddress, [ReadData]
Debug "ReadData = ", dec ReadData ,10 ,13 ,10 ,13

Debug "-->> End <<--", 10 ,13 ,10 ,13 ,10 ,13

end


And this is the result at my serial port:


-->> Start <<--
Test mode
ReadData = 0

Normal mode
ReadData = 0

Set LED intensity 1
ReadData = 0

Set LED intensity 2
ReadData = 1

Set Scan-Limit
ReadData = 0

Character 'I'D0,P0&P1
ReadData = 0

-->> End <<--

While the chip is in test-mode, the LED's are all burning. After the testmode, no LED is burning.

justDIY
- 14th March 2005, 03:29
well, i had my basics confused ... hbusin/out is a proton command, not an melabs command - appologies


anyway the data sheet talks about "read-after-write verification" (pgs 7-9):


When performing read-after-write verification, reset the command byte's address because the stored byte address generally is autoincremented after the write (Table 4).

so I would try:

I2CWRITE SDA, SCL, SlaveAddress, CommandByte, [DataByte] ' write data to register
I2CREAD SDA, SCL, SlaveAddress, CommandByte, [ReadData] ' reset pointer and read register

depending how your program will end up, you can also use the auto-increment feature to write all the configuration with a single I2CWRITE command, just add more byte variables, after your DataByte

as far as no character showing up, not sure what to say there... from a cursory glance, I find no errors in what youve written compared to the datasheet. double, triple, quadruple check your wiring to the datahseet ... I experimented with maxim's 6956, a little simpler beast than what you have there, but it still took a lot of fiddling to make it work!

RubenR
- 25th April 2005, 12:06
Yes, it's working.
What I was doing wrong was not setting the intensity registers, so the LED's won't light up. Here's the configuration code I'm using now:


SetConfig:
SlaveAddressWrite = $A0
CommandByte = $04 'Set the Command Byte ($04 = Configuration Datasheet page 11)
DataByte = $81 '10000001 Tabel 7 page 12
FOR i = 0 to nAddress
I2CWRITE SDA, SCL, SlaveAddressWrite, CommandByte, [DataByte] 'Write the data to the I2C-device
I2CREAD SDA, SCL, SlaveAddressWrite, CommandByte, [RcvDataByte]
SlaveAddressWrite = SlaveAddressWrite + $02
NEXT i
return


LEDintensity: 'Set intensity of all LEDs
SlaveAddressWrite = $A0
CommandByte = $01 'Set the Command Byte ($01 = Intensity10. Datasheet page 11)
DataByte = Intensity '$FF 'Intensity of all segments set to maximum (Page 20)
I2CWRITE SDA, SCL, SlaveAddressWrite, CommandByte, [DataByte] 'Write the data to the I2C-device
I2CREAD SDA, SCL, SlaveAddressWrite, CommandByte, [RcvDataByte]
for i = 0 to nAddress
I2CWRITE SDA, SCL, SlaveAddressWrite, CommandByte, [DataByte] 'Write the data to the I2C-device
I2CREAD SDA, SCL, SlaveAddressWrite, CommandByte, [RcvDataByte]
SlaveAddressWrite = SlaveAddressWrite + $02
NEXT i

SlaveAddressWrite = $A0
CommandByte = $02 'Set the Command Byte ($01 = Intensity10. Datasheet page 11)
DataByte = Intensity '$FF 'Intensity of all segments set to maximum (Page 20)
I2CWRITE SDA, SCL, SlaveAddressWrite, CommandByte, [DataByte] 'Write the data to the I2C-device
I2CREAD SDA, SCL, SlaveAddressWrite, CommandByte, [RcvDataByte]
for i = 0 to nAddress
I2CWRITE SDA, SCL, SlaveAddressWrite, CommandByte, [DataByte] 'Write the data to the I2C-device
I2CREAD SDA, SCL, SlaveAddressWrite, CommandByte, [RcvDataByte]
SlaveAddressWrite = SlaveAddressWrite + $02
NEXT i
return

luxornet
- 22nd January 2010, 18:07
Hi RubenR!

Can you post entire code you used to control MAX6953 driver?
I try to use what is posted here but I have many error.
Thank you very much