RE: [bascom] AVR Frequency reading and I2C EEPROM 24c64
Don't know anything about the frequency part but,
The 24C64 I2C address is 1010 A2 A1 A0 R/W
What that means is the address starts with 1010 (binary).
A2 to A0 are the states of the address pins. If all three are grounded then
the address is
1010000R/W - Write=0 and Read=1
If you want to Write to the EEPROM with all three address pins grounded, the
address is &B10100000 in binary, &HA0 in hex, or 60 in decimal. To read its
&B10100001 in binary, &HA1 in hex, or 161 in decimal.
If you had pulled A1 high and left A2, A0 grounded, the addresses would have
been &B10100100 and &B10100101.
You can use any of the three number systems for the address. I use the
binary form simply because the end but (R/W) reminds me which operation I'm
doing.
Writes are straightforward.
wAddress=243
bDataByte=120
I2CStart
I2Cwbyte &B10100000 ' Write mode command to the 24C64
bByte=High(wAddress) 'Send the address high byte
I2Cwbyte bByte
bByte=Low(wAddress) 'Send the address low byte
I2Cwbyte bByte
I2Cwbyte bDataByte ' Send the data
I2Cstop ' Finished!
waitms 10
Reads are a bit different in that you have to start with a write command in
order to send the address you want to read from, then you switch to a read
command and retrieve the data. To switch, you issue another I2Cstart -
WITHOUT issuing an I2CStop. If you do stop, its possible that some other I2C
master could gain control of the bus (probably not an issue in
99.9999999999% of the cases but hey, its good practice. After reading a byte
you have to either Acknowledge (ACK) or Not Acknowledge (NACK). For reading
a single byte, only NACK. If you forget to Nack, it simply won't work.
I2CStart
I2Cwbyte &B10100000 ' Write mode command to the 24C64
bByte=High(wAddress) 'Send the address high byte
I2Cwbyte bByte
bByte=Low(wAddress) 'Send the address low byte
I2Cwbyte bByte
I2CStart ' Critical that you start, not stop!
I2Cwbyte &B10100001 ' Read mode command to the 24C64
I2Crbyte bDataByte,Nack ' Read the data - note the Nack for reading.
I2Cstop ' Finished!
waitms 10
I also find that if you're doing multiple operations on the chip that you
put a tiny delay after. If you don't wait long enough you'll just get 255s.
I forget the actual time required but probably 10ms is more than enough.
You can also use page mode reads and writes. Instead of writing or reading a
single byte then quitting, you can do several. For writes you just add
I2Cwbyte statements. For reads, you have to ACK all but the last byte read.
The last byte MUST have a NACK or the chip thinks you want another byte and
won't finish up.
One BIG gotcha with page mode writes. Whenever you write to the EEPROM, you
actually write to a little 64 byte ram buffer. When you're done writing
(I2CStop), the chip then stores the data away in EEPROM (that's why the
little waits when you're done). The gotcha is that the buffer doesn't simply
start at ram location 1. Its a copy of an EEPROM page and whatever you send
will start at the same location in ram as it would be in EEPROM.
For example: If you send an EEPROM address of &H3D (61 decimal), it'll start
storing the data at location 61 in the ram buffer. Its ram locations only go
to 63 (starts at 0 remember). If you send 3 bytes you're fine. If you send a
4th, the buffer location will wrap back to 0 and write it there. When it
stores all this on the EEPROM, It just plops the whole 64 bytes down on the
appropriate EEPROM page. That 4th byte will end up in EEPROM location 0
instead of EEPROM location 64 like you intended. When you go to read
location 64 of the EEPROM, your data isn't there.
Soooooo, if you use page writes. Keep this in mind! Write blocks that are
sized in powers of two and START at a location that is a power of two - 2,
4, 8, 16, 32 etc. Either that or stick to writing single byte writes. Use a
loop to call the write routine as many times as you like.