Ich bin im Moment an einem Schulprojekt. Ziel ist es ein einfaches
Oszilloskop zu erstellen. Die Anwendung schlussendlich ist eigentlich
nicht wichtig, es geht nur ums Prinzip. Nun habe ich aber ein komischs
Problem.
Ich benutze einen 80C537-N als Controller, die Ausgabe erfolgt über ein
T6963C-Display.
Das Speichermodell ist small, einige Variabeln sind als data andere als
idata und ein grosses Array ist als xdata definiert. Um Variabeln auch
im Interrupt zu gebrauchen habe ich globale Variabeln verwendet. Habe
ich dies üerhaupt richtig gelöst?
IN MAIN.C:
1
charxdataScopeMem[220];// Speicherung der ADC-Daten in externem Speicher
2
charMemFlag=0;// Flag für Timer0-Überlauf
3
unsignedcharMemPos=0;// Position in ScopeMem
IN INTERRUPT.C:
1
externcharxdataScopeMem[220];// Speicherung der ADC-Daten in externem Speicher
2
externcharMemFlag;// Flag für Timer0-Überlauf
3
externunsignedcharMemPos;// Position in ScopeMem
Im main() sollte eigentlich gar nicht viel gemacht werden, dieses wurde
um den Fehler zu suchen stark vereinfacht.
Das Problem ist, dass auf dem Display in Abhängigkeit des Interrupts
eine andere Ausgabe erfolgt. Eigentlich sollte das Display nur
intialisiert werden und auf ihm ein Raster gezeichnet werden. Ist im
Interrupt aber folgende Zeile aktiv, so wird noch eine weitere Funktion
ausgeführt.
Besagte Zeile, welche auskommentiert wird oder nicht (befindet sich in
interrupt.c):
Funktion, die fälschlicherweise aufgerufen wird, wenn obere Zeile
ausgefürt wird (befindet sich in T6963C.c):
1
voidT6963cPutADCline(intidatadelay,intidatazoom)
Ich glaube, dass diese Funktion nur einmal am Anfang aufgerufen wird.
Nun, ich sehe nicht ganz wo das Problem liegt, allerdings kenne ich mich
mit Memorybereichen etc. auch nicht sonderlich gut aus. Im Anhang habe
ich noch das MemoryMap des Projektes angehängt.
Dieses sieht zwar je nach Code-Optimierungslevel (welches im Moment auf
Level 0 'constant folding' eingestellt ist) ein bisschen anders aus, der
Fehler wirkt sich aber gleich aus.
Es wird wohl irgendwas in der Speicherzuordnung (Stack, Adressierung der
Funktionen, o.ä.) nicht stimmen.
Wäre sehr dankbar wenn mir jemand helfen könnte. Bin am verzweifeln!
[Anhängend in einer Datei:]
- main.c
- interrupt.c
Hier ein mögliches Problem:
ScopeMem[220];
reserviert 220 Werte, aber von 0...219
if(MemPos>219) MemPos = 0;
MemPos wird bei Dir aber 220, das darf es nicht, also auf >218 testen
sonst überschreibst Du irgendwas im Speicher.
Matthias wrote:
> MemPos wird bei Dir aber 220, das darf es nicht, also auf >218 testen> sonst überschreibst Du irgendwas im Speicher.
Es wird zwar 220, in dem Fall wird es aber gleich darauf wieder
gelöscht. Es kommt nie zum Aufruf ScopeMem[220]. Die Reihefolge ist ja:
inkrementieren, prüfen, schreiben.
MemPos++;// Position f�r n�chstes mal inkrementieren
5
6
if(MemPos>219)// Falls Array voll ist, wieder bei erster Position beginnen
7
MemPos=0;
Ich habe aber noch etwas herausgefunden: Bestimme ich die Position in
ScopeMem nicht mit einer Variabeln, sondern mit einer Konstante (sei es
0, 50, 219, oder was auch immer) so tritt der Fehler nicht auf.
Wenn ich es aber doch mit einer Variable mache, dann funktioniert es
nur, wenn ich diese nicht inkrementiere. Ich kann die Variable aber mit
anderen Werten laden (0...219).
Beispiele die funktionieren:
Mit einer Konstante:
Also, noch eine Erkenntniss...
Hab das ganze mal ausserhalb des Interrupts realisiert, der Fehler blieb
gleich.
Die Übergabe von MemPos an ScopeMem[] scheint wirklich das Problem zu
sein.
Ist MemPos als data definiert funktioniert es nicht. Bei idata oder
xdata jedoch schon:
funktioniert nicht:
1
unsignedcharMemPos=0;// Position in ScopeMem
2
oder
3
unsignedchardataMemPos=0;// Position in ScopeMem
funktioniert:
1
unsignedcharidataMemPos=0;// Position in ScopeMem
2
oder
3
unsignedcharxdataMemPos=0;// Position in ScopeMem
Könnt ihr euch vorstellen, woran das liegt? Kann man mit einer
'data'-Variable kein kein Feld eines 'xdata'-Arrays bestimmen?
Kanns ja nicht sein. Und die Variable nun als idata oder xdata zu
definieren will ich eigentlich nicht, da diese rel. oft gebraucht wird.
Es gibt mehrere Unbekannte:
Wo wird das Programm abgelegt?
Wird es vielleciht im RAM abgelget, der glechzeitig als Codespeicehr
dient?
Dann überschreibst Du Dir die ersten 220Byte Deines Programms.
Wo ist das Displayprogramm, wie ist das Display angeschlossen (memory
mapped)?
Vielleicht schreibst Du ja statt in den SRAM, ins Display.
Schau Dir mal die Board-Doku an, wie welche Speicherbereiche
angeschlossen sind.
Peter
@Helmi
Hab ich probiert, allerdings leider ohne Erfolg.
@Peter Dannegger
Keil sollte das eigentlich intern selbst regeln. Ich muss gestehen, dass
ich in diesem Bereich leider nicht gereade viel Erfahrung habe.
Aber der 8051 sollte ja eigentlich verschiedene Speicherbereiche haben,
für code, data, xdata, etc.
Solange ich nicht selbst etwas mit dem Memory-Typ 'code' überschreibe
sollte eigentlich nichts passieren. Ganz sicher bin ich mir aber nicht.
Das Display ist Parallel an Port4 und Port5 angehängt. Dass ich direkt
in das RAM des Displays schreibe habe ich auch schon gedacht, aber das
kann ich mir nicht wirklich vorstellen.
memory mapped habe ich zwar schon gehört, habe damit aber noch nie was
gemacht. Und so ausversehen das Display so anzusteuern ist wohl nicht
möglich, oder schon?
Habe meine Funktion denen von Simon Küppers angepasst, und in diesem
Thread steht, dass es nicht memory mapped ist.
Beitrag ""Bessere" T6963c Library"
Doku hab ich vom uC schon gelesen, aber nichts spezielles gefunden :|
@Matthias
Auszug aus ScopeMeter.lnp:
Da in Deiner .lnp die Angabe zum XDATA-Bereich fehlt, wird der Linker
XDATA bei Adresse 0x0000 beginnen. Liegt Dein XDATA wirklich ab Adresse
0000H?
Auch gibt es keine Angabe zu der XDATA Größe.
In der .lnp sollte noch dies stehen:
XDATA(0X0000-0X3FFF)
nur als Bsp., hier Xdata ab 0000H und 16kB Lang
Diese Einstellung musst Du bei Keil (Device-Optionen) machen und wird
dann automatisch in die .lnp übernommen.