PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : ERAM Problem mit Mega8



KL7000F
03.06.2010, 12:22
Hallo,
kurz zu mir: Ich bin neu hier und Anfänger! Bislang "spielte" ich nur auf einem Testboard mit Mega8 und LCD.

Ich hab mich nun dran gemacht ein Projekt nachzubauen. Die Hardware läuft prima und auch die Software (Bascom) funktioniert überraschend gut.
Im Programm sollen knapp 30 Datensätze im ERAM des Mega8 gespeichert werden. Ein Datensatz besteht aus einer 13-stelligen Zahl welche einen fünfstelligen Code (Folge), Datum und Uhrzeit beinhaltet.

Schreiben funktioniert absolut ohne Probleme, lesen mach nach ein paar Minuten Laufzeit Probleme. Dort werden die Zahlen eines Datensatzes quer durchgemischt ausgelesen, aber nur bei einigen Datensätzen. Sprich der Großteil bleibt OK.

Definition:


Dim Eepointer As Eram Byte
Dim Pointer As Byte
Dim Codestring As String * 13
Dim Ecodestring(30) As Eram String * 13
Dim Zeitlcd As String * 11
Dim Folgelcd As String * 16
Dim Codedat As String * 4
Dim Codetime As String * 4
Dim Codeuhr As String * 8


Schreiben:


Pointer = Eepointer
If Pointer = 50 Then Pointer = 0
Incr Pointer
Eepointer = Pointer
Codestring = Folge + Bcd(day) + Bcd(month) + Bcd(h) + Bcd(m)
Ecodestring(pointer) = Codestring


Lesen:


If Richtung = 0 Then Incr Position
If Richtung = 1 Then Decr Position
If Position = 31 Then Position = 1
If Position = 0 Then Position = 30
If Position = 255 Then Position = 30
Pointer = Eepointer
Sprung = Pointer - Position
Sprung = Sprung + 1
If Sprung >= 0 Then
Stelle = Pointer
Stelle = Stelle - Position
Stelle = Stelle + 1
Else
Stelle = Pointer
Stelle = Stelle - Position
Stelle = Stelle + 31
End If
Codestring = Ecodestring(stelle)
Codeuhr = Right(codestring , 8)
Codedat = Left(codeuhr , 4)
Codetime = Right(codeuhr , 4)
Zeitlcd = Left(codedat , 2) + "/" + Right(codedat , 2) + " " + Left(codetime , 2) + ":" + Right(codetime , 2)
Folge = Left(codestring , 5)


Im Hintergrund läuft ein PCF8583P welcher Datum und Uhrzeit über I2C bereitstellt.

Kann man anhand dieser Codeschnipsel einen Fehler feststellen oder braucht ihr mehr? Kann gerne auch den gesamten Code reinstellen.

Gruß
Andy

for_ro
03.06.2010, 14:09
Hallo Andy,


Dim Ecodestring(30) As Eram String * 13
If Pointer = 50 Then Pointer = 0

Du deklarierst dir 30 Strings, benutzt aber 50.




If Richtung = 0 Then Incr Position
If Richtung = 1 Then Decr Position
If Position = 31 Then Position = 1
If Position = 0 Then Position = 30
If Position = 255 Then Position = 30
Pointer = Eepointer
Sprung = Pointer - Position
Sprung = Sprung + 1
If Sprung >= 0 Then
Stelle = Pointer
Stelle = Stelle - Position
Stelle = Stelle + 1
Else
Stelle = Pointer
Stelle = Stelle - Position
Stelle = Stelle + 31
End If


Mit dieser Berechnung der Stelle zum Lesen komme ich nicht klar. Wenn in EEPointer die aktuelle Position steht, dann brauchst du doch eigentlich nur
Stelle = EEPointer * 14 'Stringlänge 13 + Ende 0

KL7000F
03.06.2010, 15:00
Hallo,
mit der Berechnung der Stelle ist folgendes bewirkt:
Am Gerät sind drei Taster verbaut. Mit zweien kann ich durch die Datensätze switchen. Der dritte Taster ist sozusagen "Set" (für Menü). Da die Datensätze nach Eingang sortiert werden (sprich der zuletzt eingegebene Eintrag an der Nr. 1, somit werden diese immer um eine Stelle nach hinten geschoben. Bei 31 sind sie somit weg).

Die Anzahl der Strings werde ich mal reduzieren. Warum das so ist kann ich mir gerade nicht erklären :)

for_ro
03.06.2010, 15:37
Wenn du wirklich immer den letzten Eintrag auf der Stelle 1 stehen hast, dann musst du alle anderen verschieben. Das ist im EEPROM sicher ganz besonders schlecht, da ja nur beschränkt oft geschrieben werden kann.
Ich hätte jetzt gedacht, dass du das Array als Ring-Puffer benutzt und EEPointer auf die aktuelle Stelle zeigt.
Dabei brauchst du gar nichst umzukopieren es läuft alles über den Schreib-Zeiger auf die letzte Stelle. Dein Lese-Zeiger kann dann beliebig gesetzt werden. Kommt einer der Zeiger oben oder unten ans Ende, wird er entsprechend auf das andere Ende gesetzt. Da keine Einträge verschoben werden, geht das auch viel schneller.
Schwierig wird es nur, wenn die Elemente unterschiedlich lang sind, was bei dir aber ja nicht der Fall ist.

KL7000F
03.06.2010, 17:07
Hi,
zumindest wird das Programm die einzelnen Strings nicht durcheinander. Aber einige Zuordnungen werden entweder garnicht gespeichert bzw. in der Reihenfolge durcheinander gebracht. Meist nur einer oder zwei.



$regfile = "m8def.dat"
$crystal = 10000000

$lib "i2c.lib"


Ddrb = &B111
Ddrd = &B00000001
Portd.1 = 1
Portd.2 = 1
Portd.3 = 1
Portb.0 = 1

Config Lcd = 16 * 2
Config Lcdbus = 4
Config Lcdpin = Pin , Db4 = Portc.0 , Db5 = Portc.1 , Db6 = Portc.2 , Db7 = Portc.3 , E = Portb.1 , Rs = Portb.2
Cursor Off

Config Timer1 = Timer , Prescale = 1 , Capture Edge = Rising , Noise Cancel = 1
Config Aci = On , Compare = On , Trigger = Rising

On Timer0 Ontimer0
Config Timer0 = Counter , Edge = Falling
Enable Timer0


On Icp1 Oncapture
Enable Icp1

On Int0 Taster1
Config Int0 = Falling


On Int1 Taster2
Config Int1 = Falling

Enable Interrupts

Config Sda = Portc.4
Config Scl = Portc.5
I2cinit

Dim Zaehler As Word
Dim Icr_neu As Word
Dim Icr_alt As Word
Dim Frequlong As Long
Dim Frequenz As Word
Dim A(10) As Word
Dim Frequsumme As Word
Dim Adizaehler As Integer
Dim Durchschnitt As Word
Dim Grenzeo As Word
Dim Grenzeu As Word
Dim Ton As String * 1
Dim Tonalt As String * 1
Dim Tonalt2 As String * 1
Dim Folge As String * 5
Dim Timeout As Word
Dim Folgeto As Word

Dim Ausgabe As String * 16
Dim Folgealt As String * 16

Dim Eepointer As Eram Byte
Dim Pointer As Byte
Dim Codestring As String * 13
Dim Ecodestring(30) As Eram String * 13
Dim Zeitlcd As String * 11
Dim Folgelcd As String * 16
Dim Codedat As String * 4
Dim Codetime As String * 4
Dim Codeuhr As String * 8

Dim Richtung As Bit
Dim Position As Byte
Dim Stelle As Integer
Dim Sprung As Integer

'Variablen f�r RTC
Dim S As Byte , M As Byte , H As Byte , Day As Byte , Month As Byte
Dim Wm As Byte , Yd As Byte

Dim Zeit As Byte
Dim Zeitstring As String * 8
Dim Rtcstellen As Bit
Dim Zeitstellen As Byte


Declare Sub Zuordnung
Declare Sub Anzeige
Declare Sub Settime
Declare Sub Gettime
Declare Sub Zeitanzeigen

Timer0 = 196
Cls
Lcd " 5Ton-Decoder "
Lowerline
Lcd " Bitte warten.. "
Wait 1
Cls
Call Zeitanzeigen
Lowerline
Lcd "Uhr einstellen?"
For Zeitstellen = 1 To 50
If Pind.1 = 0 Then
Zeitstellen = 51
Call Settime
End If
Waitms 100
Next
Cls
Call Zeitanzeigen
Enable Int0
Enable Int1

Main:

Waitms 1


If Pind.1 = 0 Then
Enable Timer0
Cls
Call Zeitanzeigen
Waitms 100
End If
Frequlong = 10000000 / Icr_neu
Icr_neu = 1
Frequenz = Frequlong

Incr Timeout
If Timeout > 80 Then
Folge = ""
Tonalt = ""
Timeout = 0
End If

Incr Folgeto
If Folgeto > 6000 Then
Folgealt = ""
Folgeto = 0
End If

A(10) = A(9)
A(9) = A(8)
A(8) = A(7)
A(7) = A(6)
A(6) = A(5)
A(5) = A(4)
A(4) = A(3)
A(3) = A(2)
A(2) = A(1)
A(1) = Frequenz

Frequsumme = 0
For Adizaehler = 1 To 10
Frequsumme = Frequsumme + A(adizaehler)
Next

Durchschnitt = Frequsumme / 10
Grenzeo = A(1) + 10
Grenzeu = A(1) - 10

If Durchschnitt > Grenzeu And Durchschnitt < Grenzeo Then

Select Case Durchschnitt
Case 1050 To 1070 : Ton = "1"
Case 1150 To 1170 : Ton = "2"
Case 1260 To 1280 : Ton = "3"
Case 1390 To 1410 : Ton = "4"
Case 1520 To 1540 : Ton = "5"
Case 1660 To 1680 : Ton = "6"
Case 1820 To 1840 : Ton = "7"
Case 1990 To 2010 : Ton = "8"
Case 2190 To 2210 : Ton = "9"
Case 2390 To 2410 : Ton = "0"
Case 2590 To 2610 : Ton = "w"
Case Else : Goto Main
End Select

Else : Goto Main
End If

If Ton = Tonalt Then Goto Main
Tonalt = Ton
If Ton = "w" Then Ton = Tonalt2
Tonalt2 = Ton

Folge = Folge + Ton
Timeout = 0
If Len(folge) = 5 Then
If Folge = Folgealt Then
Folgealt = ""
Goto Main
Else
Folgealt = Folge
Folgeto = 0
Goto Folgeerkannt
End If
Folge = ""
End If

Goto Main



Folgeerkannt:

Disable Timer0


Pointer = Eepointer

If Pointer = 31 Then Pointer = 0
Incr Pointer
Eepointer = Pointer
Call Gettime
Codestring = Folge + Bcd(day) + Bcd(month) + Bcd(h) + Bcd(m)
Ecodestring(pointer) = Codestring

Call Zeitanzeigen
Call Zuordnung
Locate 2 , 1
Lcd " "
Locate 2 , 1
Lcd Folgelcd

If Folge = "12345" Then
Portd.0 = 1
Waitms 500
Portd.0 = 0
End If

Enable Timer0

Goto Main


Sub Anzeige


If Richtung = 0 Then Incr Position
If Richtung = 1 Then Decr Position
If Position = 31 Then Position = 1
If Position = 0 Then Position = 30
If Position = 255 Then Position = 30
Pointer = Eepointer
Sprung = Pointer - Position
Sprung = Sprung + 1
If Sprung >= 0 Then
Stelle = Pointer
Stelle = Stelle - Position
Stelle = Stelle + 1
Else
Stelle = Pointer
Stelle = Stelle - Position
Stelle = Stelle + 31
End If
Codestring = Ecodestring(stelle)
Codeuhr = Right(codestring , 8)
Codedat = Left(codeuhr , 4)
Codetime = Right(codeuhr , 4)
Zeitlcd = Left(codedat , 2) + "/" + Right(codedat , 2) + " " + Left(codetime , 2) + ":" + Right(codetime , 2)
Folge = Left(codestring , 5)
Call Zuordnung
Cls
Upperline
Lcd Position
Lcd " "
Lcd Zeitlcd
Lowerline
Lcd Folgelcd
'Lcd Codestring


End Sub



Sub Zuordnung
Select Case Folge

Case "12345" : Ausgabe = "Eins"
Case "54321" : Ausgabe = "Zwei"

Case Else : Ausgabe = Folge


End Select

Folgelcd = ""
Folgelcd = Folge + " " + Ausgabe
End Sub


Taster1:
If Rtcstellen = 1 Then
Decr Zeit
Lowerline
Locate 2 , 1
Lcd " "
Locate 2 , 1
Lcd Zeit
Else
Disable Timer0
Richtung = 1
Call Anzeige
End If
Waitms 100
Return

Taster2:
If Rtcstellen = 1 Then
Incr Zeit
Lowerline
Locate 2 , 1
Lcd " "
Locate 2 , 1
Lcd Zeit
Else
Disable Timer0
Richtung = 0
Call Anzeige
End If
Waitms 100
Return

Ontimer0:
Timer0 = 196
Locate 1 , 1
Call Zeitanzeigen
Return


Oncapture:
Zaehler = Timer1
Icr_neu = Zaehler - Icr_alt
Icr_alt = Zaehler
Return


Sub Settime
Rtcstellen = 1
Enable Int0
Enable Int1
Call Gettime
Waitms 200
Cls
Lcd "Monat:"
Zeit = Makedec(month)
Lowerline
Lcd Zeit
Do
Loop Until Pind.1 = 0
Waitms 200
Month = Zeit
Cls
Lcd "Tag:"
Zeit = Makedec(day)
Lowerline
Lcd Zeit
Do
Loop Until Pind.1 = 0
Waitms 200
Day = Zeit
Cls
Lcd "Stunden:"
Zeit = Makedec(h)
Lowerline
Lcd Zeit
Do
Loop Until Pind.1 = 0
Waitms 200
H = Zeit
Cls
Lcd "Minuten:"
Zeit = Makedec(m)
Lowerline
Lcd Zeit
Do
Loop Until Pind.1 = 0
Waitms 200
M = Zeit
'values are stored as BCD values so convert the values first
S = Makebcd(s) 'seconds
M = Makebcd(m) 'minuts
H = Makebcd(h) 'hours
Day = Makebcd(day) 'days
Month = Makebcd(month) 'months

I2cstart 'generate start
I2cwbyte &HA0 'write address
I2cwbyte 0 'select control register
I2cwbyte 8 'set year and day bit for masking
I2cstop 'generate stop


I2cstart 'generate start
I2cwbyte &HA0 'write mode
I2cwbyte 2 'select seconds Register
I2cwbyte S 'write seconds
I2cwbyte M 'write minuts
I2cwbyte H 'write hours
I2cwbyte Day 'write days
I2cwbyte Month 'write months
I2cstop
Rtcstellen = 0
End Sub

Sub Gettime
Dim Dum As Byte
I2cstart 'generate start
I2cwbyte &HA0 'write addres of PCF8583
I2cwbyte 2 'select second register
I2cstart 'generate repeated start
I2cwbyte &HA1 'write address for reading info
I2crbyte S , Ack 'read seconds
I2crbyte M , Ack 'read minuts
I2crbyte H , Ack 'read hours
I2crbyte Day , Ack 'read year and days
I2crbyte Month , Nack 'read weekday and month
I2cstop 'generate stop

Rem You Could Also Use The Lcd Statement For Displaying The
Rem Time On The Lcd Display
End Sub

Sub Zeitanzeigen
Call Gettime
Locate 1 , 1
Lcd " "
Locate 1 , 1
Lcd Bcd(day) ; "/" ; Bcd(month)
Lcd " " ; Bcd(h) ; ":" ; Bcd(m) ;
End Sub


Mich verwirren gerade total die Zurordnungen der einzelnen Einträge im ERAM und die ganze Pointergeschichte. Hilfe!

Dein Eintrag "Stelle = EEPointer * 14 'Stringlänge 13 + Ende 0" funktioniert bei mir gar nicht, sondern erzeugt eine Fehlermeldung: "Source variable does not match the target variable"

for_ro
03.06.2010, 18:23
If Pointer = 31 Then Pointer = 0
Incr Pointer
Eepointer = Pointer
Call Gettime
Codestring = Folge + Bcd(day) + Bcd(month) + Bcd(h) + Bcd(m)
Ecodestring(pointer) = Codestring

Hiermit wird ganz sicher nicht auf Position 1 der neueste Eintrag abgespeichert, sondern an der Stelle Pointer. Das ganze ist ein Ringspeicher, genauso wie ich den gemacht hätte.
Schreiben scheint also klar zu sein. Lesen geht wohl so:

If Richtung = 0 Then Incr Position 'Position ist die aktuelle Lese position (z.B. 17)
If Richtung = 1 Then Decr Position
If Position = 31 Then Position = 1 'max 30, darüber wieder bei 1
If Position = 0 Then Position = 30 'min 1, darunter wieder 30
If Position = 255 Then Position = 30 'Sinn ist mir nicht klar
Pointer = Eepointer 'EEPointer ist die letzte SchreibPosition (z.B. 25)
Sprung = Pointer - Position 'Sprung = 25 - 17 = 8
Sprung = Sprung + 1 'Sprung = 9
If Sprung >= 0 Then
Stelle = Pointer 'Stelle = 25
Stelle = Stelle - Position 'Stelle = 25 - 17 = 8
Stelle = Stelle + 1 'Stelle = 9
Else
Stelle = Pointer 'angenommen Pointer war 5
Stelle = Stelle - Position 'Stelle = 5 - 17 = -12
Stelle = Stelle + 31 'Stelle = -12 + 31 = 19
End If
Codestring = Ecodestring(stelle) 'in einem Fall liest er bei 9, im anderen bei 19

Warum an diesen Stellen gelesen wird, verstehe ich nicht. Hast du das programmiert? Weißt du, warum dies so ist?

KL7000F
03.06.2010, 18:47
Nein, wurde nicht von mir geschrieben. Somit kann ich das jetzt auch nicht wirklich erkläen. Aber so wie von dir dargestellt macht das ganze erstmal wenig Sinn. Ich werde morgen mal die ganze Lesestelle rausschmeißen und wie du geschrieben hast "einfacher" über einen simplen LesePointer machen. Daran kann es wohl auch liegen das einige Einträge komplett verschwinden bzw. von falscher Stelle aufgerufen werden.

Danke schonmal für deine Mühe!!

KL7000F
04.06.2010, 12:42
@for_ro: Wie würdest du den Bereich "Lesen" machen? Ich hab verschiedene Ansätze probiert, aber alles führte zu noch mehr Datenchaos.

Zu dem original Code: Soweit ich das verstanden habe liest er damit immer die aktuelle Position des Schreibpointers aus und weiß dadurch wo sich die Nr. 1 befindet. Zum großteil funktioniert es auch, warum auch immer.

for_ro
04.06.2010, 14:36
@for_ro: Wie würdest du den Bereich "Lesen" machen?
Hängt davon ab, welche Funktionalität du beim Lesen haben möchtest. Z.B. was die Taster für Hoch und Runter bewirken sollen.
Generell denke ich an so etwas ganz simples:
If Richtung = 0 Then Incr Position
If Richtung = 1 Then Decr Position
If Position = 31 Then Position = 1
If Position = 0 Then Position = 30
Codestring = Ecodestring(Position)
Codeuhr = Right(codestring , 8)
Codedat = Left(codeuhr , 4)
Codetime = Right(codeuhr , 4)
Zeitlcd = Left(codedat , 2) + "/" + Right(codedat , 2) + " " + Left(codetime , 2) + ":" + Right(codetime , 2)
usw.

KL7000F
04.06.2010, 17:16
Hi,
soweit funktioniert es. Über diesen Weg ist halt die Sortierung (letzter Durchlauf/Eintrag steht unter Position 1) weg. Aber das ist erstmal egal. Vieleicht fällt mir irgendwann noch eine Lösung ein.

Großes Danke an Dich!

Gruß
Andy

for_ro
04.06.2010, 19:20
Über diesen Weg ist halt die Sortierung (letzter Durchlauf/Eintrag steht unter Position 1) weg.

Hallo Andy,
das ist der Punkt, den ich noch nicht verstanden habe. Kannst du da mal genauer erklären, wie du es haben möchtest.

KL7000F
04.06.2010, 19:41
Hi,
ist bissl "blöd" zu erklären. Aber ich versuche es.
Die Hardware wertet aus einem Audiosignal Frequenzen welche in schlichte Ziffern angegeben wird (z.B. 1060 Hz entspricht der Ziffer 1). Gesamt besteht eine sogenannte 5-Ton-Folge aus 5 Ziffern (z.B. 12345).
Es werden in der Regel mehrere dieser 5-Ton-Folgen hintereinander gesendet. Diese Reihenfolge sollte somit in umgekehrter Reihenfolge abrufbar sein. D.h. an Position 1 ist die zuletzt erkannte Folge, die Vorletzte dann an Position 2 usw.
Somit "rutscht" bei jedem neuen Eintrag im EEPROM die Reihenfolge um eines nach hinten.
Der Author des Programms hat über diesen verwirrenden Code versucht neben den Einträgen im Speicher die Position mit dieser Berechnung zu verwirklichen. Aber da steckt ja der Wurm drin, sonst hätte ich hier nicht nach Hilfe geschriehen ;)

Ich hoffe ich konnte es bissl deutlicher machen!

Gruß
Andy

for_ro
04.06.2010, 20:08
Aha, ich glaube jetzt habe ich das verstanden.
Ich hatte auch übersehen, dass die Variable Position mit ausgegeben wird. Die ist dann wohl diese Nummer.
Du könntest jetzt einfach eine Variable benutzen, die dir die aktuelle Lese-Position hält und dann jeweils rauf und runter zählt. Wenn aber während des Lesens neue Daten kommen und im EEPROM um eine Stelle weiter geschrieben wird, dann stimmt die Positionsnummer nicht mehr. Ich glaube, dass der Autor das ausgleichen wollte.
Kann das passieren und wie soll sich die Anzeige dann verhalten?

KL7000F
04.06.2010, 20:26
Exakt. Ich habs jetzt so gelöst dass ich einfach die Position zum Lesen von der letzten geschriebenen Position (Pointer) übernehme und mit 1 addiere. Somit kann ich per Taster (Zurück) direkt zum letzten Eintrag springen. Die Positionsnummer ist zwar dann nicht 1, aber das ist Nebensache...