Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.
|
Forum Index : Microcontroller and PC projects : Talking to FRAM chips with I2C....
Page 1 of 4 | |||||
Author | Message | ||||
Grogster Admin Group Joined: 31/12/2012 Location: New ZealandPosts: 9066 |
Hi folks. My 256Kb FRAM chips arrived today, so I have been playing. Although writing seems to be working fine in my test code, I cannot read anything useful back - the results are always zero. I have a feeling I am addressing the thing wrong - could some of you I2C gurus prod me in the right direction? I thought I was getting the hang of I2C till I hit this brick wall. As this device is word-addressed, to keep things nice and simple for testing, I elected to just start at address zero, meaning that along with the slave address, I need to send bytes 2 and 3 to the device as memory address bytes - both being zero. I have a feeling I am stuffing my addressing up somehow. Writes complete fine, according to the test code, writing 1024 bytes in just 310mS - pretty good! Here is my test code: I2C OPEN 400,100 I2C WRITE &B1010000,0,2,0,0 'Set start address as decimal zero(start of FRAM) Timer=0 For X=1 To 1024 I2C WRITE &B1010000,0,1,Asc("*") Print "*"; Next I2C Close Print:Print Print "Bytes = 1024" Print "Write time = ";Timer;" ms" Pause 3000 Print:Print Print "Now reading back...":Print I2C OPEN 400,100 I2C WRITE &B1010000,0,2,0,0 'Reset start address for reading Timer=0 For X=1 To 1024 I2C READ &B1010000,0,1,B$ Print B$; Next I2C Close Print:Print Print "Bytes = 1024" Print "Read time = ";Timer;" ms" Print:Print Print "Test ended." End The PDF for the device can be found here EDIT: Before anyone asks - yes I have the 4k7 pull-ups on SDA and SCL. I have the device running from 3v3, which the datasheet lists as typical. I THINK I have a feeling what is going on - I am only sending address bytes as far as the FRAM is thinking. I THINK I need to set my read/write address, then hold on to the bus(option 1 rather then 0), so as NOT to send an automatic STOP. Following bytes should then be able to be sent, and THEN close the I2C bus. The testing continues..... Smoke makes things work. When the smoke gets out, it stops! |
||||
BobD Guru Joined: 07/12/2011 Location: AustraliaPosts: 935 |
I think the easiest solution is to include the starting memory address in each read or write. I think you are reading zeroes because you never wrote anything. This is theory only. Caveat emptor. |
||||
BobD Guru Joined: 07/12/2011 Location: AustraliaPosts: 935 |
Sorry, I'm a bit distracted trying to clone a GPT HDD on windoze 8.1 x64 to a new SSD and I'm not succeeding. The Samsung utility did not copy all partitions or all of the data. Now I'm trying Acronis and it can't boot because it's not in some table somewhere. arrgh. I would do this [code] I2C WRITE &B1010000,0,3,MSB,LSB,Asc("*") [/code] and [code] I2C READ &B1010000,0,3,MSB,LSB,B$ [/code] There is a bit of calculating and incrementing the MSB LSB or else you could do a multi byte write or read which would save the effort. Multi byte [code] I2C WRITE &B1010000,0,Len(A$)+2,MSB,LSB,A$ [/code] [code] I2C READ &B1010000,0,LengthToRead+2,MSB,LSB,B$ [/code] |
||||
Grogster Admin Group Joined: 31/12/2012 Location: New ZealandPosts: 9066 |
Here is my latest test: [code] TEST2: BYTE$="***" I2C open 400,100 I2C write &B1010000,0,5,0,0,BYTE$ I2C write &B1010000,0,2,0,0 I2C read &B1010000,0,3,A,B,C Print A,B,C End > goto test2 [45] I2C write &B1010000,0,5,0,0,BYTE$ Error: Incorrect argument count > [/code] Byte$ too long perhaps? [code] TEST2: BYTE$="*" I2C open 400,100 I2C write &B1010000,0,3,0,0,BYTE$ I2C write &B1010000,0,2,0,0 I2C read &B1010000,0,1,A Print A End > goto test2 [45] I2C write &B1010000,0,3,0,0,BYTE$ Error: Expected a number > [/code] Nope...... FRAM and/or MMBASIC don't like me. Smoke makes things work. When the smoke gets out, it stops! |
||||
Lee3 Regular Member Joined: 17/09/2014 Location: AustraliaPosts: 57 |
I can't help you out.... I'm keen to learn how these chips work though, keeping an eye on this thread.... :) |
||||
WhiteWizzard Guru Joined: 05/04/2013 Location: United KingdomPosts: 2794 |
I am playing too - got some success in MMBasic and will post code later when back home. For now Grogs, write a number (i.e. '123') rather than a string. Also play around with I2C option 1 (no stop condition) if setting address in one line of code and then writing the data in another line of code. We WILL solve this between us WW For everything Micromite visit micromite.org Direct Email: whitewizzard@micromite.o |
||||
Grogster Admin Group Joined: 31/12/2012 Location: New ZealandPosts: 9066 |
Thanks for the encouragement, WW - yep, will keep at it. NUMBER does seem to work ok: [code] TEST2: BYTE$="*" I2C open 400,100 I2C write &B1010000,0,3,0,0,42 I2C write &B1010000,0,2,0,0 I2C read &B1010000,0,1,A Print A End > goto test2 42 > [/code] The uM manual, page 59, says you can send a string, so I was expecting that to work. PERHAPS there is a small bug in the I2C command, when you are using strings? Smoke makes things work. When the smoke gets out, it stops! |
||||
TassyJim Guru Joined: 07/08/2011 Location: AustraliaPosts: 5914 |
I think you were trying to send a combination of bytes and strings. If the chip needs the address sent with each write, you will have to stick with all bytes. Jim VK7JH MMedit MMBasic Help |
||||
Grogster Admin Group Joined: 31/12/2012 Location: New ZealandPosts: 9066 |
Yes, I was, but I did not think that was an "Illegal request". I do really need to be able to send strings, so I will play around with the option 1 thing as hinted at by WW - set the address with a write using bytes, then hold onto the bus, and in the next command, send the string, then close the bus. Will keep the thread posted. Smoke makes things work. When the smoke gets out, it stops! |
||||
TassyJim Guru Joined: 07/08/2011 Location: AustraliaPosts: 5914 |
You could also try putting the address bytes in the front of the string as chr$(hibyte) etc There might be a problem with any zero value bytes - that would need to be checked. Otherwise a simple function to read the strings char at a time and place the values into an array (my preferred method). Jim VK7JH MMedit MMBasic Help |
||||
WhiteWizzard Guru Joined: 05/04/2013 Location: United KingdomPosts: 2794 |
Ok Grogs - Try the following code. When run, it simply waits for an input (string) and then writes it one byte at a time into FRAM. It then reads the memory contents back and displays the result. (i.e. echoes input) For reference I am using a 2048 x 8 FRAM (had one lying next to keyboard). It has the 3 LSBits in the I2C address (set to 000 in code below) to access the FRAM's 'segment', and then requires one byte to access the memory location within the Segment. Put it another way, it has an 11 bit address. Below I am using Segment 000 and locations 1 through to length of inputted string. May not be 'exactly' what you require but it shows a working example that can be 'expanded' upon. I2C open 100,100
input a$ for x = 1 to len(a$) I2C write &B1010000,0 ,2, x, asc(mid$(a$,x,1)) next x for x = 1 to len(a$) I2C write &B1010000,0, 1,x I2C READ &B1010000, 0, 1, rcvbuf print chr$(rcvbuf); next x Let me know how it goes for you! WW For everything Micromite visit micromite.org Direct Email: whitewizzard@micromite.o |
||||
Grogster Admin Group Joined: 31/12/2012 Location: New ZealandPosts: 9066 |
FRAM does not like me. [code] TEST3: I2C open 400,100 Input A$ I2C write &B1010000,1,2,0,0 'Set start address, and hold bus For Y=1 To Len(A$) I2C write &B1010000,1,1,Asc(Mid$(a$,Y,1)) 'Write byte, and keep holding bus Next Y. I2C write &B1010000,0,2,0,0 'Reset address, and send a STOP For Y=1 To Len(A$) I2C read &B1010000,0,1,B 'Suck a byte out of the FRAM Print Chr$(B); Next Y > goto test3 ? Hello [57] Next Y. Error: Cannot find variable > [/code] What's up with the "Can't find variable" error - it's freakin' there! EDIT: STUPID FULL-STOP ON LINE 57!!!!!!! Well, that fixed the "Can't find variable" problem, but I still can't read anything back. The only reply I get back from the read for/next, is a single * character. Smoke makes things work. When the smoke gets out, it stops! |
||||
WhiteWizzard Guru Joined: 05/04/2013 Location: United KingdomPosts: 2794 |
For now, I would personally write one byte at a time - don't do 'sequential' writes (or Reads) yet until you have the basics working. Have you tried my code (copy/paste)? WW For everything Micromite visit micromite.org Direct Email: whitewizzard@micromite.o |
||||
WhiteWizzard Guru Joined: 05/04/2013 Location: United KingdomPosts: 2794 |
Change your Write loop from: I2C write &B1010000,1,1,Asc(Mid$(a$,Y,1)) 'Write byte, and keep holding bus to I2C write &B1010000,0,2,Y,Asc(Mid$(a$,Y,1)) 'Write byte (i.e. address and data byte in one command (then stop condition sent) For everything Micromite visit micromite.org Direct Email: whitewizzard@micromite.o |
||||
Grogster Admin Group Joined: 31/12/2012 Location: New ZealandPosts: 9066 |
No-go. I expect this WON'T work for me, simply cos the 256's need a two-byte WORD address, so single byte addressing will not work. [code] TEST3: I2C open 100,100 Input A$ I2C write &B1010000,1,2,0,0 'Set start address, and hold bus For Y=1 To Len(A$) I2C write &B1010000,0,2,Y,Asc(Mid$(a$,Y,1)) 'Write byte, keep holding bus Next Y I2C write &B1010000,0,1,13 'Send final CR byte, and STOP I2C write &B1010000,0,2,0,0 'Reset address, and send a STOP A$="" For Y=1 To 25 I2C read &B1010000,1,1,B 'Suck a byte out of FRAM Print Chr$(B); A$=A$+Chr$(B) Next Y Print Len(A$) End > goto test3 ? Hello * 25 > [/code] I will have a play with the formula posted in the other FRAM thread, for calculating the MSB and LSB, and try merging that into the same line - stay tuned. Smoke makes things work. When the smoke gets out, it stops! |
||||
WhiteWizzard Guru Joined: 05/04/2013 Location: United KingdomPosts: 2794 |
If TWO byte word then change to: TEST3: I2C open 100,100 Input A$ 'I2C write &B1010000,1,2,0,0 'Set start address, and hold bus For Y=1 To Len(A$) I2C write &B1010000,0,3,0,Y,Asc(Mid$(a$,Y,1)) 'Write address & byte Next Y I2C write &B1010000,0,3,0,Y+1,13 'Send final CR byte, and STOP 'I2C write &B1010000,0,2,0,0 'Reset address, and send a STOP A$="" For Y=1 To 25 I2C write &B1010000,0,2,0,0 'Reset address I2C read &B1010000,0,3,0,Y,B 'Suck a byte out of FRAM Print Chr$(B); A$=A$+Chr$(B) Next Y Print Len(A$) End For everything Micromite visit micromite.org Direct Email: whitewizzard@micromite.o |
||||
Grogster Admin Group Joined: 31/12/2012 Location: New ZealandPosts: 9066 |
Read command rejected that syntax - won't allow you to receive multipule bytes seperately, looks like you must use a string if more then one byte. Anyhoo, here is my latest attempt: [code] TEST3: I2C open 100,100 Input A$ For Y=1 To Len(A$) MSB=Y\256:LSB=Y Mod 256 'Figure out bytes for address word I2C write &B1010000,0,3,MSB,LSB,Asc(Mid$(a$,Y,1)) 'Write address & byte Next Y I2C write &B1010000,0,2,0,0 'Reset address, and send a STOP B$="" For Y=1 To Len(A$)+1 MSB=Y\256:LSB=Y Mod 256 I2C read &B1010000,1,1,B 'Suck a byte out of FRAM & hold bus B$=B$+Chr$(B) Next Y I2C Close Print B$,Len(B$) End > goto test3 ? Hello *Hello 6 > [/code] Progress - I am getting results now, but still have the rouge asterisk character. Tinkering continues... EDIT: I know where the * is coming from - address zero. If I change the line that resets the FRAM address to I2C WRITE &B1010000,0,2,0,1, that should fix that issue, as the FOR/NEXT loops will then jive with the preset address of the FRAM. Smoke makes things work. When the smoke gets out, it stops! |
||||
WhiteWizzard Guru Joined: 05/04/2013 Location: United KingdomPosts: 2794 |
I just cant get 'sequential' data-byte writes to work - I have to write the address and data byte as one command For everything Micromite visit micromite.org Direct Email: whitewizzard@micromite.o |
||||
Grogster Admin Group Joined: 31/12/2012 Location: New ZealandPosts: 9066 |
Do you think that is the FRAM being difficult, or something in the way that MMBASIC is doing it's I2C? EDIT: I have other EEPROM chips, so I will set one of them up on the breadboard, now that I have the basic commands working OK. I will stick to sequential writes inside any one page, starting at the top of page 1, just to find out if sequential writing is working OK on EEPROM chips - it might be the FRAM that is being difficult.... [code] TEST3: I2C open 100,100 Input A$ For Y=1 To Len(A$) MSB=Y\256:LSB=Y Mod 256 'Figure out bytes for address word I2C write &B1010000,0,3,MSB,LSB,Asc(Mid$(a$,Y,1)) 'Write address & byte Next Y I2C write &B1010000,0,2,0,1 'Reset address, and send a STOP B$="" For Y=1 To Len(A$) MSB=Y\256:LSB=Y Mod 256 I2C read &B1010000,1,1,B 'Suck a byte out of FRAM & hold bus B$=B$+Chr$(B) Next Y I2C Close Print B$,Len(B$) End > goto test3 ? Hello Backshed People! Hello Backshed People! 22 > [/code] Smoke makes things work. When the smoke gets out, it stops! |
||||
Grogster Admin Group Joined: 31/12/2012 Location: New ZealandPosts: 9066 |
Smoke makes things work. When the smoke gets out, it stops! |
||||
Page 1 of 4 |
Print this page |