Hallo Ich bin gerade dabei ein I2C EEPROM (24LC128) anzusteuern. Wenn ich das EEPROM mit Daten beschreiben will, muss ich ja die Pagegröße beachten. Außerdem muss ich beachten ab welcher Adresse ich anfange mit schreiben. Wollte jetzt mal nachfragen ob ich beim Auslesen (Sequential read) auch die Pagegröße beachten muss. Also ob ich maximal 64bytes auf einmal auslesen kann. So wie ich das Datenblatt lese, bin ich der Meinung ich kann so lange auslesen bis der Master "kein ACK" sendet. Könnt ihr mir da weiter helfen? Grüße Bean
@ Mr Bean (Gast) >Wollte jetzt mal nachfragen ob ich beim Auslesen (Sequential read) auch >die Pagegröße beachten muss. Nein, man kann ohne Begrenzung auslesen. >kann so lange auslesen bis der Master "kein ACK" sendet. Ja. MFG Falk
Hm, sehr gut. Das lesen aus dem EEPROM scheint jetzt auch zu funktionieren. Nur das Schreiben über Pagegrenzen hinweg macht mir noch etwas Probleme. (Schreiben einzelner Bytes funktioniert) Habt ihr mir hier vielleicht noch irgend einen Tipp? Grüße Bean
@Mr Bean (Gast) >funktionieren. Nur das Schreiben über Pagegrenzen hinweg macht mir noch >etwas Probleme. Das muss man aufteilen. Man kann immer nur innerhalb einer Page schreiben. Mfg Falk
> Habt ihr mir hier vielleicht noch irgend einen Tipp?
Berechnen, ob ne Page überschritten wird. Entsprechend Schreibvorgang
für die aktuelle Page beenden und für die neue Page starten.
Ralf
Ja, das hab ich mir auch schon überlegt, aber dazu muss ich ja erstmal berechnen wieviel bytes ich in die angefangene Page (wenn ich mitten im Speicher anfange mit schreiben) noch schreiben kann. Dann muss ich noch berechnen wie viele Pages ich überschreib und dann dementsprechend die Adressen setzen und die Pages voll schreiben oder sehe ich das falsch? Vielleicht denke ich auch zu kompliziert. Habt ihr mir speziell hierzu vielleicht noch BSP Code. Habe bis jetzt immer nur das Schreiben einzelner Bytes... gefunden. Kein "Streams". Grüße Bean Und danke schonmal!
@ Mr Bean (Gast) >Ja, das hab ich mir auch schon überlegt, aber dazu muss ich ja erstmal >berechnen wieviel bytes ich in die angefangene Page (wenn ich mitten im >Speicher anfange mit schreiben) noch schreiben kann. Dann muss ich noch >berechnen wie viele Pages ich überschreib und dann dementsprechend die >Adressen setzen und die Pages voll schreiben oder sehe ich das falsch? Das siehst du richtig. Iast aber nicht so kompliziert. Der Modulo Operator ist dein Freund. Adresse MOD Pagesize = Page_Position Pagesize - Page_position = Anzahl Bytes in der 1. Page MfG Falk
Ja, soetwas hab ich mir schon gedacht. Scheitere aber gerade daran wie ich weiter mache wenn ich die erste Page voll geschrieben hab. Hier mal mein derzeitiger Code:
1 | int EEPROM_BUF_Write(unsigned int address, unsigned char buf[], unsigned int count) |
2 | {
|
3 | unsigned char retval; |
4 | unsigned char I2Cstat; |
5 | unsigned char sendbuf[PAGESIZE]; |
6 | unsigned char i=0; |
7 | unsigned int pos = 0; |
8 | unsigned char bytenum = 0; |
9 | |
10 | sendbuf[1] = address & 0xFF; |
11 | sendbuf[0] = (address >> 8) & 0xFF; |
12 | |
13 | if(count > PAGESIZE) |
14 | {
|
15 | pos = address % PAGESIZE; |
16 | bytenum = PAGESIZE - pos; |
17 | |
18 | SMB_Write(EEPROM_ADDR, sendbuf, 2); |
19 | |
20 | while(i <= bytenum) |
21 | {
|
22 | SMB_Write(EEPROM_ADDR, buf, bytenum); |
23 | count--; |
24 | address++; |
25 | i++; |
26 | }
|
27 | sendbuf[1] = address & 0xFF; |
28 | sendbuf[0] = (address >> 8) & 0xFF; |
29 | SMB_Write(EEPROM_ADDR, sendbuf, 2); |
30 | |
31 | }
|
32 | |
33 | else
|
34 | {
|
35 | SMB_Write(EEPROM_ADDR, sendbuf, 2); |
36 | I2Cstat = SMB_Write(EEPROM_ADDR, buf, count); |
37 | if(I2Cstat) |
38 | {
|
39 | retval = EEPROMWRITEFAIL; |
40 | }
|
41 | retval = EEPROMWRITESUCCESS; |
42 | }
|
43 | return retval; |
44 | }
|
Ist aber wie gesagt noch nicht fertig. Ich meiner SMB_Write funktion sagen soll dass Sie wenn ich die nächste Page beschreiben will bei meinem Datenbuffer (buf[]) wieder an Stelle null anfängt... :-( Grüße Bean
Denke auch daran, dass Du nach dem schreiben einer Page einige Millisekunden warten musst (siehe Datenblatt), bis Du wieder auf's EEPROM zugreifen kannst...
ACK polling ist hier auch besser als delay_ms ^^ ack polling bis wieder frei ist dann weiterschreiben
eine variable kannst du noch einsparen statt unsigned int pos = 0; unsigned char bytenum = 0; pos = address % PAGESIZE; bytenum = PAGESIZE - pos; gehts auch gleich unsigned char bytenum = 0; bytenum = PAGESIZE - (address % PAGESIZE); das pos is umsonst
Ja stimmt, dachte ich brauche "pos" später noch... Ich hatte mir soetwas mit dem ACK schon gedacht. Bin mir aber nicht sicher ob das bei meinem Baustein funktioniert, im Datenblatt steht: "The 24XX128 does not generate any Acknowledge bits if an internal programming cycle is in progress." Ich hab jetzt mal 5ms warten eingebaut. Grüße
>ACK polling ist hier auch besser als delay_ms ^^ >ack polling bis wieder frei ist dann weiterschreiben Stimmt nicht in jedem Fall! Statt zu warten und solange nichts tun, könnten andere Tasks was sinvolles erledigen...
Naja, im Moment komme ich ja nicht über das Schreiben der ersten Page hinaus... Wenn ich die Adresse dann neu Setze (nächste Page) und dann meiner Write funktion aufrufe, fängt diese an wieder die gleichen Daten wie auf der ersten Page zu schreiben... Grüße Bean
"The 24XX128 does not generate any Acknowledge bits if an internal programming cycle is in progress." genau das nutzt man da man schreibt den eeprom so lange an bis dieser ein ACK liefert und das war bei meinen eeprom bisher immer unter 5ms !! je nach tagesform ^^ da is glaueb noch fehler drin .... while( length ) { page_cnt = PAGE_SIZE - (adress%PAGE_SIZE); startcondition eepromadresse + schreibbefehl datenadresse while( page_cnt ) { daten senden length--; if(length == 0) break; } // neue adresse = anfang der nächsten seite // alte seite +1 adress = ((adress/PAGE_SIZE)+1) * PAGE_SIZE; page_cnt = length; Stopkonition senden ack_polling oder delay_ms(5) }
du must ziwschen den pages eine stopkondition senden und warten man kann nicht gleich weiterschreiben also adresse ausrechnen , stop senden , warten und dann weiterschreiben das if(length == 0) break; is für den fall das nicht über eine seite geschrieben wird ^^
Hab das Ganze jetzt nochmal umgeschrieben. Funktioniert aber leider immer noch nicht wie gewollt. So langsam wird die ganze Funktion auf recht groß finde ich...
1 | int EEPROM_BUF_Write(unsigned int address, unsigned char buf[], unsigned int count) |
2 | {
|
3 | unsigned char retval; |
4 | unsigned char ret; |
5 | unsigned char sendbuf[PAGESIZE+2]; |
6 | unsigned char i, index; |
7 | unsigned char bytenum = 0; |
8 | |
9 | bytenum = PAGESIZE - (address % PAGESIZE); |
10 | |
11 | if(count > PAGESIZE || count > bytenum) |
12 | {
|
13 | LED = !LED; |
14 | |
15 | sendbuf[1] = address & 0xFF; |
16 | sendbuf[0] = (address >> 8) & 0xFF; |
17 | |
18 | for(i = 0; i <= bytenum; i++) |
19 | {
|
20 | sendbuf[i+2] = buf[i]; |
21 | address++; |
22 | count--; |
23 | }
|
24 | SMB_Write(EEPROM_ADDR, sendbuf, bytenum + 2); |
25 | T2_Waitms(5); |
26 | index = i; |
27 | |
28 | while((count / PAGESIZE) == 0) |
29 | {
|
30 | |
31 | sendbuf[1] = address & 0xFF; |
32 | sendbuf[0] = (address >> 8) & 0xFF; |
33 | |
34 | for(i = 0; i <= PAGESIZE; i++) |
35 | {
|
36 | sendbuf[i+2] = buf[index]; |
37 | index++; |
38 | count--; |
39 | address++; |
40 | }
|
41 | SMB_Write(EEPROM_ADDR, sendbuf, PAGESIZE+2); |
42 | T2_Waitms(5); |
43 | }
|
44 | |
45 | if(count > 0) |
46 | {
|
47 | sendbuf[1] = address & 0xFF; |
48 | sendbuf[0] = (address >> 8) & 0xFF; |
49 | LED = !LED; |
50 | for(i = 0; i <= count; i++) |
51 | {
|
52 | sendbuf[i+2] = buf[index]; |
53 | index++; |
54 | address++; |
55 | }
|
56 | SMB_Write(EEPROM_ADDR, sendbuf, count+2); |
57 | }
|
58 | }
|
59 | |
60 | else
|
61 | {
|
62 | sendbuf[1] = address & 0xFF; |
63 | sendbuf[0] = (address >> 8) & 0xFF; |
64 | |
65 | for(i = 0; i <= count; i++) |
66 | {
|
67 | sendbuf[i+2] = buf[i]; |
68 | address++; |
69 | }
|
70 | |
71 | ret = SMB_Write(EEPROM_ADDR, sendbuf, count+2); |
72 | |
73 | if(ret) |
74 | {
|
75 | retval = EEPROMWRITEFAIL; |
76 | }
|
77 | retval = EEPROMWRITESUCCESS; |
78 | }
|
79 | return retval; |
80 | }
|
Wenn ich mehr als eine Page schreiben möchte, wird nur die Adresse übertragen.... :-( Grüße
frag ist warum buf ? mach ein *char draus und fertig damit kannst du auch array schreiben .. is ja kein ding ein unsigned char buf[] als übergabe is schon kompliziert wenn man mal kein [] hat sondern ein struct ins eeprom schieben will besser wäre hier vlt ein void *data und das da oben vin mir .. while( length ) { page_cnt = PAGE_SIZE - (adress%PAGE_SIZE); startcondition eepromadresse + schreibbefehl datenadresse while( page_cnt ) { daten senden length--; if(length == 0) break; } // neue adresse = anfang der nächsten seite // alte seite +1 adress = ((adress/PAGE_SIZE)+1) * PAGE_SIZE; page_cnt = length; Stopkondition senden ack_polling oder delay_ms(5) } ist so ziemlich das einzisgte in meiner funktion ... ich weiß nich was deine SMB_Write(..) macht .. sie darf aber in keinem fall ein STOP senden page write : start eepromadresse datenadresse daten daten daten . . .. daten stop bei überschreiten einer page : start eepromadresse datenadresse daten daten daten . pageende erreicht STOP 5ms warten start eepromadresse neue datenadresse daten daten daten . .. daten stop
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.