PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : UART beeinflusst Variablen???



chris0983
08.03.2009, 16:20
Hallo,
ich beschäftige mich erst seit ein paar Wochen mit Microcontrollern und habe daher noch nicht allzu viel Erfahrung. Ich habe folgendes Programm für einen Datenlogger geschrieben:


$regfile = "m8def.dat"
$crystal = 1000000
$hwstack = 65
$swstack = 40
$framesize = 100
$baud = 4800


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



Declare Sub Serial0charmatch
Declare Sub Wertlesen(kanal As Word)
Declare Sub Speichern(daten As Word)
Declare Sub Lesen
Declare Sub Intervall(intervall_neu As String)
Declare Sub Datenausgabe(bereich As String)
Declare Sub Online


Dim Schreiben As Word At $250
Dim Schreiben1 As Byte At $250 Overlay
Dim Schreiben2 As Byte At $251 Overlay
Dim Addresse As Word At $260
Dim Addresse1 As Byte At $260 Overlay
Dim Addresse2 As Byte At $261 Overlay
Dim Lesen As Word At $270
Dim Lesen1 As Byte At $270 Overlay
Dim Lesen2 As Byte At $271 Overlay
Dim Befehl As String * 12
Dim Befehlarray(2) As String * 7
Dim Intervall As Word
Dim Zeit As Word
Dim A As Byte
Dim N As Word
Dim Ende As Word
Dim Zaehler As Word
Dim Temp As Word
Dim Druck As Word


Config Adc = Single , Prescaler = Auto
Start Adc
Config Timer1 = Timer , Prescale = 64
Timer1 = 49910
On Timer1 Isr_timer1
Config Serialin = Buffered , Size = 15 , Bytematch = 13
Config Pinb.2 = Input
Config Portb.1 = Output
'Config Portb.3 = Output
Portb.2 = 1
Zeit = 0
Zaehler = 1


Readeeprom Lesen1 , 10 'Intervallzeit lesen
Readeeprom Lesen2 , 11
If Lesen >= 1 Then
Intervall = Lesen
Else
Intervall = 1
End If

Enable Interrupts 'Programm Anfang
Enable Timer1
Do
Addresse = Zaehler * 2
Decr Addresse 'Hauptschleife
If Zeit >= Intervall Then
N = 0
Call Wertlesen(n)

Call Speichern(temp)
Addresse = 5000
Call Speichern(zaehler)
Incr Zaehler
End If

Loop
End


Isr_timer1: 'Timer zählt im Sekundentakt
Timer1 = 49910
If Pinb.2 = 0 Then
Incr Zeit
End If
Return


Sub Serial0charmatch() 'Daten über UART empfangen
Input Befehl Noecho
If Befehl <> "" Then
A = Split(befehl , Befehlarray(1) , " ")
Select Case Befehlarray(1)
Case "interv" : Call Intervall(befehlarray(2))
Case "lesen" : Call Datenausgabe(befehlarray(2))
Case "online" : Call Online
End Select
End If
End Sub

Sub Wertlesen(kanal As Word)
Toggle Portb.1 'AD-Wandler auslesen
Temp = Getadc(kanal)
Zeit = 0

End Sub

Sub Speichern(daten As Word)
Disable Interrupts
Schreiben = Daten
I2cstart 'Start
I2cwbyte &HA0 'Sende Slavadresse
I2cwbyte Addresse2 'Sende Speicheradresse High
I2cwbyte Addresse1 'Sende Speicheradresse LOW
I2cwbyte Schreiben2 'Sende Wert
I2cstop 'stop
Waitms 5 'warte 10ms
Incr Addresse
I2cstart 'Start
I2cwbyte &HA0 'Sende Slavadresse
I2cwbyte Addresse2 'Sende Speicheradresse High
I2cwbyte Addresse1 'Sende Speicheradresse LOW
I2cwbyte Schreiben1 'Sende Wert
I2cstop 'stop
Waitms 5 'warte 10ms
Enable Interrupts
End Sub

Sub Lesen
Disable Interrupts
I2cstart 'Start
I2cwbyte &HA0 'Sende Slavadresse +1 für Schreiben
I2cwbyte Addresse2 'Sende Speicheradresse High
I2cwbyte Addresse1 'Sende Speicheradresse Low
I2cstart 'Start
I2cwbyte &HA1 'Sende Slavadresse +1 für Lesen
I2crbyte Lesen2 , Nack 'Lese Adresse vom EEprom
I2cstop
Waitms 5 'Stop
Incr Addresse

I2cstart 'Start
I2cwbyte &HA0 'Sende Slavadresse +1 für Schreiben
I2cwbyte Addresse2 'Sende Speicheradresse High
I2cwbyte Addresse1 'Sende Speicheradresse Low
I2cstart 'Start
I2cwbyte &HA1 'Sende Slavadresse +1 für Lesen
I2crbyte Lesen1 , Nack 'Lese Adresse vom EEprom
I2cstop 'Stop
Waitms 5
Enable Interrupts
End Sub


Sub Intervall(intervall_neu As String)
Disable Interrupts
Schreiben = Val(intervall_neu)
Writeeeprom Schreiben1 , 10
Writeeeprom Schreiben2 , 11
Intervall = Val(intervall_neu)
Enable Interrupts
Print "Neuer Intervall: " ; Intervall_neu ' Intervallzeit ändern
End Sub

Sub Datenausgabe(bereich As String)
Select Case Bereich
Case "z"
Addresse = 5000
Call Lesen
Print Str(lesen)
Case "iv"
Print Str(intervall)
Case Else
Addresse = Val(bereich)
Ende = Val(bereich) + 19
Do
Call Lesen
Print Str(lesen)
Incr Addresse
Loop Until Addresse > Ende
End Select
End Sub


Sub Online
N = 0
Call Wertlesen(n)
Print Str(temp)
End Sub

Der Timer zählt im Sekundentakt die Variable Zeit hoch. Wenn Variable Zeit = Variable Intervall ist, wird der aktuelle Wert vom AD-Wandler gelesen, der Wert und der neue Zählerstand in einem externen EEPROM gespeichert und die Variable Zeit zurückgesetzt. Anschließend können die Daten über UART wieder ausgelesen werden.

Das funktioniert auch soweit, jedoch veränder sich der Zählerstand manchmal beim auslesen. Habe ich vielleicht bei der Variablendeklaration etwas falsch gemacht?
Vielen Dank im Voraus für eure Antworten

for_ro
08.03.2009, 18:21
Ich schätze das liegt daran, dass du High und Low Byte vertauschst. Musst du mal überprüfen. Wenn du sowas deklarierst

Dim Schreiben As Word At $250
Dim Schreiben1 As Byte At $250 Overlay
Dim Schreiben2 As Byte At $251 Overlay
Dim Addresse As Word At $260
Dim Addresse1 As Byte At $260 Overlay
Dim Addresse2 As Byte At $261 Overlay
Dim Lesen As Word At $270
Dim Lesen1 As Byte At $270 Overlay
Dim Lesen2 As Byte At $271 Overlay

dann liegt bei 250 das Low-Byte und bei 251 das High-byte der Variable Schreiben. Mit festen Adressen würde ich das Normalerweise sowieso nicht machen. Lieber so:

Dim Schreiben As Word
Dim Schreiben_low As Byte At Schreiben Overlay
Dim Schreiben_high As Byte At $Schreiben+1 Overlay
Dim Addresse As Word
Dim Addresse_low As Byte At Addresse Overlay
Dim Addresse_high As Byte At $Addresse+1 Overlay
Dim Lesen As Word
Dim Lesen_low As Byte At Lesen Overlay
Dim Lesen_high As Byte At Lesen+1 Overlay

So ist dein Code auch auf einen anderen µC portierbar, ohne dass du die Adressen ändern musst.

Außerdem würde ich eine Sub nicht genauso nennen wie eine Variable (Intervall). Bascom kommt zwar damit zurecht, es liest sich aber schwerer.

Gruß

Rolf

chris0983
08.03.2009, 19:29
Hallo Rolf,
danke für deine Tipps. Leider war das aber nicht der Fehler. Die Messwerte die ich auslese sind ok. Nur wenn ich mehrmals hintereinander den Zähler auslese (also lesen z sende), erhöht sich der Zähler um 1 und es wird ein neuer Messwert aufgenommen (obwohl PB2 1 ist). Als würde die Variable Zeit beeinflusst...

for_ro
08.03.2009, 21:40
Das war wohl eh Quatsch, was ich da bzgl. Low und High losgelassen habe. Bei dir im Programm ist es richtig rum. Sorry.
Ich kann deinen Code wegen der I2C Befehle nicht wirklich ausprobieren.
Wenn du vermutest, dass die Zeit erhöht wird, dann mach doch mal ein Print Zeit in die ISR, damit du sofort siehst, wann da was passiert.

Gruß

Rolf

chris0983
09.03.2009, 09:14
Die Variablen ändern sich wohl doch nicht. Aber obwohl Zeit = 0 und Intervall = 5 ist, wird die Bedingung if Zeit >= Intervall manchmal ausgeführt. Sehr komisch....

for_ro
09.03.2009, 10:55
Läuft da vielleicht eine der Variable über?
Versuch mal durch Prints oder Anzeigen auf dem Display einzugrenzen, unter welchen Bedingungen der Fehler auftritt.
Schau auch mal, ob die String Variablen, die vor Intervall deklariert sind, evtl. längere Strings bekommen können. Bascom überprüft und verhindert dies nicht. Ein Zeichen zu lang und schon hast du im Low-Byte von Intervall das Stringende-Zeichen stehen, eine 0.

Gruß

Rolf

chris0983
09.03.2009, 17:25
Ich denke nicht. Habe die String-Variablen und den UART-Puffer mal deutlich vergrößert, aber der fehler bleibt trotzdem. Und eigentlich werden nie mehr als 8 Byte empfangen.

Der Fehler tritt immer nur auf wenn ich den zähler (mit "lesen z") oder den aktuellen Wert ( mit "online") mehrmals hintereinander auslese. Beim auslesen der Datensätze ( z.B. "lesen 1") ist der Fehler noch nicht aufgetreten.