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
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