PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Wait durch Timer ersetzen?



TobiasBlome
02.02.2009, 21:44
Hallo,
ich habe mir einen Datenlogger gebaut. Analogwerte werden eingelesen und seriell an den USB Stick (FTDI Chip) gesendet.

Um die Daten zb. alle 10 sekunden an den Chip zu senden benutze ich den Waitbefehl. Das Programm funktioniert soweit.

Da nun aber noch die Controlerzeit zum Programm abarbeiten hinzu kommt werden die Daten alle 10sekunden + Controllerzeit geschrieben.

Nun möchte ich den Waitbefehl durch Timer1 ersetzen. Leider bekomme ich nun aber Probleme beim initialisieren des USB Sticks...

Das 1. Programm ist mit Waitbefehl und funktioniert ;-)


'THE BOX 2008
'Datenlogger
'_________________________________________________ ______________________________
'INFO´s

'Eingang abfragen: PINX.X = X
'Ausgang setzen: PORTX.X = X
'Timer2 wird von der Date/Time Funktion belegt und ist nicht weiter konfigurierbar
'Sectic wird jede Sekunde von der Time/Date Funktion aufgerufen
'_________________________________________________ ______________________________
'_________________________________________________ ______________________________
'VERSION:

'Version: 0.0:
' -LCD über Date / Time Funktion mit 2tem externen Quarz
' -Analogwert von PA0 anzeigen
' Funktion i.O.!!!12.07.2008

'Version: 0.1:
' -USB-Stick über VINCULUM-Chip von FTDI angeschlossen
' -
'Version: 0.5:
' -bei Antwort "No Disk" wieder neu starten
' -nach jedem Durchlauf speichern
'
'Version: 0.6:
' -Wert Messung wird hochgezählt und in der txt gespeichert
' -Wert Messung wird bei Neustart auf 0 gesetzt
'
'
'-------------------------------------------------------------------------------
'Konfiguration µC:
$regfile = "m32def.dat" 'AT-Mega32
$crystal = 14745600 'Quarz: 14,7456 MHz
$baud = 9600 'Baudrate definieren

'-------------------------------------------------------------------------------
'Ein- Ausgänge:

Ddra = &B00000000 '1 Ausgang, 0 Eingang = Pin PA7-0
Ddrb = &B11111111 '1 Ausgang, 0 Eingang = Pin PB7-0
Ddrc = &B11111111 '1 Ausgang, 0 Eingang = Pin PC7-0
Ddrd = &B01111111 '1 Ausgang, 0 Eingang = Pin PD7-0

Porta = &B00000000 '1 = Pullup
Portb = &B00000000 '1 = Pullup
Portc = &B11111111 '1 = Pullup
Portd = &B00000000 '1 = Pullup



'-------------------------------------------------------------------------------
'Analogmessung:
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc 'Starte analog Messung

'-------------------------------------------------------------------------------
'Vor Programmstart:

'Enable Interrupts

Start Adc 'Analogmessung starten

'-------------------------------------------------------------------------------
'USB Confi!!!!

Echo Off '///für USB-Stick
Open "com1:" For Binary As #1 '///für USB-Stick

'Dim Samples As Word 'Anzahl der Messungen
Dim Delayms As Long 'Messintervall in ms (Long bis 2.147.483.647)
Dim Channels As Word 'Anzahl der Messkanäle (8Kanäle -> 0-7)(Word bis 65535)
Dim N As Integer
Dim I As Integer
Dim L As Integer
Dim S As String * 40
Dim Ad As Integer
Dim Messung As Long 'Anzahl der gemessenen Werte (Long bis 2.147.483.647)


'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'Hauptprogramm Do...Loop
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------


Usbloop:
Do
Input S
Loop Until S = "D:\>" 'USB Controller abfragen, bis D:\> gesendet wird

Waitms 1000

Print "rd todo.txt" + Chr(13); 'todo.txt Datei LESEN

Input Delayms 'Wartezeit zwischen den Messungen aus Datei übernehmen
Get #1 , L
Input Channels 'Anzahl der Messkanäle aus Datei übernehmen
Get #1 , L
Input S

Do
Print "OPW Log.txt" + Chr(13); 'Datei Log.txt öffnen
Input S
Toggle Portb.0
Incr Messung
S = Str(messung) + Chr(9)
For I = 0 To Channels 'Kanäle 0-7 MAX
Ad = Getadc(i) 'hole Analogwert von Kanal = (Variable "I")
S = S + Str(ad) 'S + aktuellen Analogkanal
If I < Channels Then S = S + Chr(9) 'wenn noch nicht alle Kanäle abgefragt wurden kommt ein Chr(9) = Tab drann!!!
Next I
S = S + Chr(13) + Chr(10) 'zum Schluss noch Zeichen 13+10 Carriage Return + Line Feed
L = Len(s) 'gibt die Länge von String "S" wieder
Print "WRF "; 'Befehl um in die geöffnete Datei zu schreiben
Put #1 , 0
Put #1 , 0
Put #1 , 0
Put #1 , L 'L ist die Länge vom String S
Put #1 , 13
Print S ;
Input S
Waitms Delayms 'Wartezeit zwischen den Messungen

Print "CLF log.txt" + Chr(13); 'Datei log.txt schließen
Input S


Loop Until Pind.7 = 0

Portb.0 = 0 'LED abschalten
Messung = 0 'Zähler für Messungen zurücksetzen
Goto Usbloop 'Programm neu starten
End


'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'ENDE - Hauptprogramm Do...Loop
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------

End




Der 2. Code ist mit Timer1, der 4 mal pro Sekunde einen Interrupt auslöst. Wenn zb. der 8. Interrupt kommt (also nach 2 sek.) sollen die Daten gespeichert werden.




'-------------------------------------------------------------------------------
'Konfiguration µC:
$regfile = "m32def.dat" 'AT-Mega32
$crystal = 14745600 'Quarz: 14,7456 MHz
$baud = 9600 'Baudrate definieren

'-------------------------------------------------------------------------------
'Ein- Ausgänge:

Ddra = &B00000000 '1 Ausgang, 0 Eingang = Pin PA7-0
Ddrb = &B11111111 '1 Ausgang, 0 Eingang = Pin PB7-0
Ddrc = &B11111111 '1 Ausgang, 0 Eingang = Pin PC7-0
Ddrd = &B01111111 '1 Ausgang, 0 Eingang = Pin PD7-0

Porta = &B00000000 '1 = Pullup
Portb = &B00000000 '1 = Pullup
Portc = &B11111111 '1 = Pullup
Portd = &B00000000 '1 = Pullup

'-------------------------------------------------------------------------------
'Timer1 = 16 Bit
Config Timer1 = Timer , Prescale = 64 'Teiler 1/8/64/256/1024
Enable Timer1 'timer einschalten
Const Timer1vorgabe = 7936 '7936 = 4 mal pro Sekunde
Timer1 = Timer1vorgabe
On Timer1 Ontimer1overflow 'Unteprogramm aufrufen


'-------------------------------------------------------------------------------
'Analogmessung:
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc 'Starte analog Messung

'-------------------------------------------------------------------------------
'Vor Programmstart:


Enable Interrupts
Start Adc 'Analogmessung starten

'-------------------------------------------------------------------------------
'USB Confi!!!!

Echo Off '///für USB-Stick
Open "com1:" For Binary As #1 '///für USB-Stick

'Dim Samples As Word 'Anzahl der Messungen
Dim Delayms As Long 'Messintervall in ms (Long bis 2.147.483.647)
Dim Channels As Word 'Anzahl der Messkanäle (8Kanäle -> 0-7)(Word bis 65535)
Dim N As Integer
Dim I As Integer
Dim L As Integer
Dim S As String * 40
Dim Ad As Integer
Dim Messung As Long 'Anzahl der gemessenen Werte (Long bis 2.147.483.647)

Dim Wartezeit As Long 'Wartezeit über Timer

Dim Logging As Bit '1 = Daten werden aufgezeichnet



Logging = 0
Wartezeit = 0

'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'Hauptprogramm Do...Loop
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------

Do

If Logging = 0 Then
Gosub Usb_auslesen
End If


Loop

'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'ENDE - Hauptprogramm Do...Loop
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------

Usb_auslesen:
Stop Timer1
Do
Input S
Loop Until S = "D:\>" 'USB Controller abfragen, bis D:\> gesendet wird

Waitms 1000

Print "rd todo.txt" + Chr(13); 'todo.txt Datei LESEN

Input Delayms 'Wartezeit zwischen den Messungen aus Datei übernehmen
Get #1 , L
Input Channels 'Anzahl der Messkanäle aus Datei übernehmen
Get #1 , L
Input S

Logging = 1 'Daten werden aufgezeichnet


Start Timer1
End
Return



Usb_schreiben:

Print "OPW Log.txt" + Chr(13); 'Datei Log.txt öffnen
Input S
Portb.0 = 1 'schreib LED an
Incr Messung
S = Str(messung) + Chr(9)
For I = 0 To Channels 'Kanäle 0-7 MAX
Ad = Getadc(i) 'hole Analogwert von Kanal = (Variable "I")
S = S + Str(ad) 'S + aktuellen Analogkanal
If I < Channels Then S = S + Chr(9) 'wenn noch nicht alle Kanäle abgefragt wurden kommt ein Chr(9) = Tab drann!!!
Next I
S = S + Chr(13) + Chr(10) 'zum Schluss noch Zeichen 13+10 Carriage Return + Line Feed
L = Len(s) 'gibt die Länge von String "S" wieder
Print "WRF "; 'Befehl um in die geöffnete Datei zu schreiben
Put #1 , 0
Put #1 , 0
Put #1 , 0
Put #1 , L 'L ist die Länge vom String S
Put #1 , 13
Print S ;
Input S


Print "CLF log.txt" + Chr(13); 'Datei log.txt schließen
Input S
Portb.0 = 0 'schreib LED aus
End
Return


'-------------------------------------------------------------------------------
'TIMER SPRUNGMARKEN:

Ontimer1overflow:
Timer1 = Timer1vorgabe
Incr Wartezeit
Print Delayms
Print Channels
If Wartezeit = Delayms And Logging = 1 Then 'Wartezeit zwischen den Messungen
Wartezeit = 0 'Wartezeit zurücksetzen
Gosub Usb_schreiben

End If

If Pind.7 = 0 Then 'RESET
Logging = 0
Messung = 0 'Zähler für Messungen zurücksetzen
Portb.0 = 0 'schreib LED aus
Gosub Usb_auslesen
End If



Return


Hat jemand eine Idee?
Tobias

MelMan
04.02.2009, 10:13
Könnte es theoretisch passieren dass Wartezeit größer als Delayms ist?


If Wartezeit = Delayms And Logging = 1 Then 'Wartezeit zwischen den Messungen
Wartezeit = 0 'Wartezeit zurücksetzen
Gosub Usb_schreiben

Hatte öfter solche Probleme und hab deshalb immer auf >= abgefragt.

stefan_Z
04.02.2009, 15:54
Jau, der verpasst irgendwie die richtige Zahl nehme ich an.
Mach das > rein, dann sollte es besser gehen

TobiasBlome
04.02.2009, 17:05
Hallo,
das ist nicht (allein?) das Problem...
Hab es geändert aber der µC bleib an einer Stelle stehen.
wollte über Timer1 eine LED blinken lassen um zu sehen ob der Timer arbeitet. Kann er aber nicht, weil der Timer1 erst aktiv ist, wenn die Routine: "Usb_auslesen" durchlaufen wurde - und das passiert nicht. Da die Daten seriell zwischen µC und USB Controller ausgetauscht werden habe ich die Daten mal mitgeschrieben(kannman gut sehen das er in dieser Routine stehen bleibt - aber warum....das Programm im ersten Post sieht ähnlich aus un funktioniert....):

Hier die Daten von der Seriellenschnittstelle vom USB Controller zum µC:
Ver 03.66VDAPF On-Line: -------- egal
Device Detected P2 -------- egal
No Upgrade --------egal
D:\> -------- start für µC um Anfrage zu senden
8 --------USB sendet Wert 1 zurück
0 --------USB sendet Wert 2 zurück
D:\> -------- egal


Auf der Seriellenschnittstelle sehe ich vom µC nur den gesendeten Befehl: rd todo.txt -------- also USB Stick auslesen! die 2 Werte werden vom USB Controller gesendet aber dann geht es nicht weiter...



Also mal zum Ablauf über die RS232 Schnittstelle:

- der µC wartet bis der USB-Controller "D:\>" sendet

- der µC sendet "rd todo.txt" um die Daten von USB zu lesen

-USB sendet 2 Zahlen zurück die der µC in die Variablen Delayms und Channels schreibt.

-dann beginnt die sich wiederholende Routine zum schreiben der Analogwerte in eine Datei. Diese Routine wird vom Timer1 gestartet:

-der µC sendet "OPW Log.txt" um die Datei von USB zu öffnen

-(Werte werden analog eingelesen)

-der µC sendet "WRF " um in die geöffnete Datei zu schreiben

-µC sendet die Werte

-µC sendet "CLF log.txt" um Datei zu schließen

-Routine beginnt neu wenn Timer1 kommt


hat jemand eine Idee?
Tobias

stefan_Z
04.02.2009, 17:12
Definier mal ausreichend große Stacks, dann könnte es schon gehen!

TobiasBlome
04.02.2009, 17:21
äh - was wäre denn (aufjedenfall) ausreichend?

Tobias

stefan_Z
04.02.2009, 17:42
Der M32 hat ja genügend Reserven...
Mach mal je 80 oder so.. das schadet nie.
Alzuviel verbraucht das Progi selber ja nicht.

TobiasBlome
04.02.2009, 17:44
;-) das Prog liegt bei 5%

stefan_Z
04.02.2009, 17:48
Ich meinte allerdings den RAM...
Den bekommt man mit einem Programm um 1% schon voll:
Dim Array(128) as Long

TobiasBlome
04.02.2009, 17:50
so:

$hwstack = 80
$swstack = 80
$framesize = 80

bleibt an der selben Stelle stehen...
wobei es ja im anderen Programm ohne "deklaration" funktioniert.

Was könnte es den noch sein?

Tobias

stefan_Z
04.02.2009, 18:00
Also nach dem Senden von rd todo.txt wartet er ja auf Input vom PC.
Wenn der nicht kommt, oder nicht verstanden wird, dann ist Essig.

TobiasBlome
04.02.2009, 18:01
wie schreibt man das?

$xramstart = &H1000
$xramsize = &H1000

???

stefan_Z
04.02.2009, 18:04
XRAM?
Hast du externen Speicher dran? Nee oder?

Ich helfe mir immer mit "Markierungen" die der µC sendet.
Also ein fröhliches "***BREAKPOINT***" printen - wenns kommt, weiter nach unten verschieben bis es nicht mehr kommt. Dann haste deinen Hänger.

Ich tippe auf falschen Input vom PC aus. Schreib mal ne ganz einfache 4-zeilige Input-Routine an den Anfang und schau ob's geht.

Vielleicht kommt da einfach nur kein Zeilenende an.

TobiasBlome
04.02.2009, 18:12
hmmm,
also den PC lassen wir mal raus, weil der nur zum abhören ist....

Fakt ist, dass der USB Controller sendet. Als erstes sendet er: D:\>

Der µC reagiert auf die "Fertigmeldung" mit dem Print: rd todo.txt

Und darauf reagiert der USB Controller mit den 2 Werten aus der Datei vom USB Stick: "8" und "0" und danach wieder "D:\>".

Daraus schließe ich das die Kommunikation zwischen µC <-> USB Controller funktioniert.

Tobias

stefan_Z
04.02.2009, 18:18
Ah OK, ich verstehe...
Dann mach das doch mal mit dem PRINT "XYZ" zwischen den Zeilen und schau wo er hängt.

TobiasBlome
04.02.2009, 18:19
ok Breakpoint war gut ;-)

anscheinend wird der Timer1 nicht gestartet....

Warum?

Ent19
04.02.2009, 18:32
Hi, also ich würde schon empfehlen ein paar Sachen anderes zu machen, man fängt damit an das man nicht im Timer die Information sendet. Im Timer solltest du nur ein Variable setzen und im Hauptprogramm prüfen ob die Variable gesetzt ist.


If Usb_schreiben_ok = 1 then
Usb_schreiben_ok = 1
Gosub Usb_schreiben
End If


---


Timer1:
If Wartezeit = Delayms And Logging = 1 Then 'Wartezeit zwischen den Messungen
Wartezeit = 0 'Wartezeit zurücksetzen
Usb_schreiben_ok = 1
End If
return

-----------------------------------------------

so kann es nicht passieren das du:
A: Den Timer durcheinander bringst (Es können keine weitere interrupts ausgeführt werden während du diesen Timer noch Aktiv hast, erst wieder beim return).

B: Verhinderst das die Funktion aufgerufen wird bevor du das Hauptprogramm erreicht hast (Ich habe jetzt nicht ausführlich geguckt ob dieses der Fall ist, da du ja nicht wirklich viel machst zwischen Enable Interrupts und dem Maincode (Do loop)).



Musste man auch nicht Com1 vorher definieren 8 bit, No Parity, 1 Stop oder so bevor man den Benutzt als Binary? oder sind das Defaults?

Kannst ja mal ein paar Tests machen:
1. versuche mal den Timer 1 erst direkt vor dem DO zu enabeln.
2. Das oben beschrieben mit den Bit setzen und dann in Main ausführen.
3. Buffer mal die ausgabe: Config Serialout = Buffered , Size = 250

StevieL
04.02.2009, 18:36
Hallo Tobias,

der Timer wird vielleicht schon gestartet. Ich könnte mir vorstellen, dass das Problem in deiner ISR Ontimer1overflow liegt. Die ist recht umfangreich und du hast da zudem zwei Gosub drin. Ich glaube, das funktioniert so nicht. Soweit ich das in Erinnerung habe, wird das bis zum Return abgearbeitet. Allerdings dann nicht das Return der ISR sondern das des Unterprogramms. In der ISR solltest du nur ein Flag setzen und den Rest in die Hauptschleife abarbeiten.

TobiasBlome
04.02.2009, 18:44
ok - ich überarbeite mal das Programm - vielen Dank erst mal.

Tobias

TobiasBlome
04.02.2009, 19:59
Läuft ;-)

bitte Schönheitsfehler bemängeln!



'-------------------------------------------------------------------------------
'Konfiguration µC:
$regfile = "m32def.dat" 'AT-Mega32
$crystal = 14745600 'Quarz: 14,7456 MHz
$baud = 9600 'Baudrate definieren

$hwstack = 80 ' default use 32 for the hardware stack
$swstack = 80 ' default use 10 for the SW stack
$framesize = 80 ' default use 40 for the frame space


'-------------------------------------------------------------------------------
'Ein- Ausgänge:

Ddra = &B00000000 '1 Ausgang, 0 Eingang = Pin PA7-0
Ddrb = &B11111111 '1 Ausgang, 0 Eingang = Pin PB7-0
Ddrc = &B11111111 '1 Ausgang, 0 Eingang = Pin PC7-0
Ddrd = &B01111111 '1 Ausgang, 0 Eingang = Pin PD7-0

Porta = &B00000000 '1 = Pullup
Portb = &B00000000 '1 = Pullup
Portc = &B11111111 '1 = Pullup
Portd = &B00000000 '1 = Pullup

'-------------------------------------------------------------------------------
'Timer1 = 16 Bit
Config Timer1 = Timer , Prescale = 64 'Teiler 1/8/64/256/1024
Enable Timer1 'timer einschalten
Const Timer1vorgabe = 7936 '7936 = 4 mal pro Sekunde
Timer1 = Timer1vorgabe
On Timer1 Ontimer1overflow 'Unteprogramm aufrufen


'-------------------------------------------------------------------------------
'Analogmessung:
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc 'Starte analog Messung


'-------------------------------------------------------------------------------
'USB Confi!!!!

Echo Off '///für USB-Stick
Open "com1:" For Binary As #1 '///für USB-Stick

'Dim Samples As Word 'Anzahl der Messungen
Dim Delayms As Long 'Messintervall in ms (Long bis 2.147.483.647)
Dim Channels As Word 'Anzahl der Messkanäle (8Kanäle -> 0-7)(Word bis 65535)
Dim N As Integer
Dim I As Integer
Dim L As Integer
Dim S As String * 40
Dim Ad As Integer
Dim Messung As Long 'Anzahl der gemessenen Werte (Long bis 2.147.483.647)

Dim Wartezeit As Long 'Wartezeit über Timer

Dim Auslesen_ok As Bit 'ausleseroutine erfolgreich
Dim Logging As Bit '1 = Daten werden aufgezeichnet

'-------------------------------------------------------------------------------
'Vor Programmstart:

Auslesen_ok = 0
Logging = 0
Wartezeit = 999
Delayms = 0


Enable Interrupts
Start Adc 'Analogmessung starten


Usb_auslesen:

Stop Timer1

Do
Input S
Loop Until S = "D:\>" 'USB Controller abfragen, bis D:\> gesendet wird

Waitms 1000

Print "rd todo.txt" + Chr(13); 'todo.txt Datei LESEN

Input Delayms 'Wartezeit zwischen den Messungen aus Datei übernehmen
Get #1 , L
Input Channels 'Anzahl der Messkanäle aus Datei übernehmen
Get #1 , L
Input S

Auslesen_ok = 1
Start Timer1

'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'Hauptprogramm Do...Loop
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------

Do
'_________________________________________________ ______________________________
'Reset
If Pind.7 = 0 Then 'RESET
Logging = 0
Messung = 0 'Zähler für Messungen zurücksetzen
Portb.0 = 0 'schreib LED aus
Gosub Usb_auslesen
End If

'_________________________________________________ ______________________________
'speichern
If Logging = 1 Then
Logging = 0
Gosub Usb_schreiben
End If


Loop

'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'ENDE - Hauptprogramm Do...Loop
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------



Usb_schreiben:

Print "OPW Log.txt" + Chr(13); 'Datei Log.txt öffnen
Input S
Portb.0 = 1 'schreib LED an
Incr Messung
S = Str(messung) + Chr(9)
For I = 0 To Channels 'Kanäle 0-7 MAX
Ad = Getadc(i) 'hole Analogwert von Kanal = (Variable "I")
S = S + Str(ad) 'S + aktuellen Analogkanal
If I < Channels Then S = S + Chr(9) 'wenn noch nicht alle Kanäle abgefragt wurden kommt ein Chr(9) = Tab drann!!!
Next I
S = S + Chr(13) + Chr(10) 'zum Schluss noch Zeichen 13+10 Carriage Return + Line Feed
L = Len(s) 'gibt die Länge von String "S" wieder
Print "WRF "; 'Befehl um in die geöffnete Datei zu schreiben
Put #1 , 0
Put #1 , 0
Put #1 , 0
Put #1 , L 'L ist die Länge vom String S
Put #1 , 13
Print S ;
Input S


Print "CLF log.txt" + Chr(13); 'Datei log.txt schließen
Input S
Portb.0 = 0 'schreib LED aus

Return


'-------------------------------------------------------------------------------
'TIMER SPRUNGMARKEN:

Ontimer1overflow:
Timer1 = Timer1vorgabe
Incr Wartezeit
'Toggle Portb.0 'nur zum testen ob timer1 läuft

If Wartezeit => Delayms And Auslesen_ok = 1 Then 'Wartezeit zwischen den Messungen
Wartezeit = 0 'Wartezeit zurücksetzen
Logging = 1 'Daten werden aufgezeichnet
End If

Return


Tobias

PS. ich habe den Fehler im alten Programm gefunden:

irgendwie ist mir den End Befehl 2 mal ins Programm geschlichen.... :-b



Usb_auslesen:
Stop Timer1
...
Start Timer1
End
Return


-------
Usb_schreiben:
...
End
Return

TobiasBlome
04.02.2009, 21:13
gibt es eine Möglichkeit um zu testen, wie ausgelastet der µC ist? Also nicht von der Speicherkapazität, sondern von der Zykluszeit?

Tobias

for_ro
04.02.2009, 21:26
Enable Interrupts
Start Adc 'Analogmessung starten


Usb_auslesen:

Stop Timer1

Do
Input S
Loop Until S = "D:\>" 'USB Controller abfragen, bis D:\> gesendet wird

Waitms 1000

Print "rd todo.txt" + Chr(13); 'todo.txt Datei LESEN

Input Delayms 'Wartezeit zwischen den Messungen aus Datei übernehmen
Get #1 , L
Input Channels 'Anzahl der Messkanäle aus Datei übernehmen
Get #1 , L
Input S

Auslesen_ok = 1
Start Timer1

'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'Hauptprogramm Do...Loop
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------

Do
'_________________________________________________ ______________________________
'Reset
If Pind.7 = 0 Then 'RESET
Logging = 0
Messung = 0 'Zähler für Messungen zurücksetzen
Portb.0 = 0 'schreib LED aus
Gosub Usb_auslesen
End If



Hallo Tobias,
da ist aber mehr falsch als nur ein Schönheitsfehler.
Usb_auslesen ist eine Subroutine, in die das Programm gleich zu Anfang rein läuft. Ohne auf ein Return zu kommen - was hier auch fatal wäre - geht es in die main loop. Dort kann dann wieder usb_auslesen aufgerufen werden. Dies wird relativ schnell zu einem Stack Overflow führen.
Setze deine Subs alle hinter das End und schließe sie immer mit einem Return ab.
Mehr habe ich mir noch nicht angesehen.

Gruß

Rolf

TobiasBlome
04.02.2009, 22:20
hab das Programm geändert - aber es lief vorher auch schon: hab es aber immer nur ein paar Minuten getestet...

Aber ich möchte es natürlich nicht riskieren das der µC sich "aufhängt"



'-------------------------------------------------------------------------------
'Konfiguration µC:
$regfile = "m32def.dat" 'AT-Mega32
$crystal = 14745600 'Quarz: 14,7456 MHz
$baud = 9600 'Baudrate definieren

$hwstack = 80 ' default use 32 for the hardware stack
$swstack = 80 ' default use 10 for the SW stack
$framesize = 80 ' default use 40 for the frame space


'-------------------------------------------------------------------------------
'Ein- Ausgänge:

Ddra = &B00000000 '1 Ausgang, 0 Eingang = Pin PA7-0
Ddrb = &B11111111 '1 Ausgang, 0 Eingang = Pin PB7-0
Ddrc = &B11111111 '1 Ausgang, 0 Eingang = Pin PC7-0
Ddrd = &B01111111 '1 Ausgang, 0 Eingang = Pin PD7-0

Porta = &B00000000 '1 = Pullup
Portb = &B00000000 '1 = Pullup
Portc = &B11111111 '1 = Pullup
Portd = &B00000000 '1 = Pullup

'-------------------------------------------------------------------------------
'Timer1 = 16 Bit
Config Timer1 = Timer , Prescale = 64 'Teiler 1/8/64/256/1024
Enable Timer1 'timer einschalten
Const Timer1vorgabe = 7936 '7936 = 4 mal pro Sekunde
Timer1 = Timer1vorgabe
On Timer1 Ontimer1overflow 'Unteprogramm aufrufen


'-------------------------------------------------------------------------------
'Analogmessung:
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc 'Starte analog Messung


'-------------------------------------------------------------------------------
'USB Confi!!!!

Echo Off '///für USB-Stick
Open "com1:" For Binary As #1 '///für USB-Stick

'Dim Samples As Word 'Anzahl der Messungen
Dim Delayms As Long 'Messintervall in ms (Long bis 2.147.483.647)
Dim Channels As Word 'Anzahl der Messkanäle (8Kanäle -> 0-7)(Word bis 65535)
Dim N As Integer
Dim I As Integer
Dim L As Integer
Dim S As String * 40
Dim Ad As Integer
Dim Messung As Long 'Anzahl der gemessenen Werte (Long bis 2.147.483.647)

Dim Wartezeit As Long 'Wartezeit über Timer

Dim Auslesen_ok As Bit 'ausleseroutine erfolgreich
Dim Logging As Bit '1 = Daten werden aufgezeichnet

'-------------------------------------------------------------------------------
'Vor Programmstart:

Auslesen_ok = 0
Logging = 0
Wartezeit = 999
Delayms = 0



Start Adc 'Analogmessung starten
Stop Timer1



'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'Hauptprogramm Do...Loop
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------

Do
'_________________________________________________ ______________________________
'Reset
If Pind.7 = 0 Then 'RESET
Auslesen_ok = 0 'Speicher zurücksetzen
End If

'_________________________________________________ ______________________________
'Auslesen
If Auslesen_ok = 0 Then
Logging = 0
Messung = 0 'Zähler für Messungen zurücksetzen
Portb.0 = 0 'schreib LED aus
Auslesen_ok = 0 'Speicher zurücksetzen
Gosub Usb_auslesen
End If

'_________________________________________________ ______________________________
'speichern
If Logging = 1 Then
Logging = 0
Gosub Usb_schreiben
End If


Loop

'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'ENDE - Hauptprogramm Do...Loop
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------

Usb_auslesen:

Stop Timer1

Do
Input S
Loop Until S = "D:\>" 'USB Controller abfragen, bis D:\> gesendet wird

Waitms 1000

Print "rd todo.txt" + Chr(13); 'todo.txt Datei LESEN

Input Delayms 'Wartezeit zwischen den Messungen aus Datei übernehmen
Get #1 , L
Input Channels 'Anzahl der Messkanäle aus Datei übernehmen
Get #1 , L
Input S

Auslesen_ok = 1
Enable Interrupts
Start Timer1

Return

'-------------------------------------------------------------------------------

Usb_schreiben:

Print "OPW Log.txt" + Chr(13); 'Datei Log.txt öffnen
Input S
Portb.0 = 1 'schreib LED an
Incr Messung
S = Str(messung) + Chr(9)
For I = 0 To Channels 'Kanäle 0-7 MAX
Ad = Getadc(i) 'hole Analogwert von Kanal = (Variable "I")
S = S + Str(ad) 'S + aktuellen Analogkanal
If I < Channels Then S = S + Chr(9) 'wenn noch nicht alle Kanäle abgefragt wurden kommt ein Chr(9) = Tab drann!!!
Next I
S = S + Chr(13) + Chr(10) 'zum Schluss noch Zeichen 13+10 Carriage Return + Line Feed
L = Len(s) 'gibt die Länge von String "S" wieder
Print "WRF "; 'Befehl um in die geöffnete Datei zu schreiben
Put #1 , 0
Put #1 , 0
Put #1 , 0
Put #1 , L 'L ist die Länge vom String S
Put #1 , 13
Print S ;
Input S


Print "CLF log.txt" + Chr(13); 'Datei log.txt schließen
Input S
Portb.0 = 0 'schreib LED aus

Return


'-------------------------------------------------------------------------------
'TIMER SPRUNGMARKEN:

Ontimer1overflow:
Timer1 = Timer1vorgabe
Incr Wartezeit
'Toggle Portb.0 'nur zum testen ob timer1 läuft

If Wartezeit => Delayms And Auslesen_ok = 1 Then 'Wartezeit zwischen den Messungen
Wartezeit = 0 'Wartezeit zurücksetzen
Logging = 1 'Daten werden aufgezeichnet
End If


Return




@for_ro
Dies wird relativ schnell zu einem Stack Overflow führen.

warum führt das zu einem Stack Overflow? Allgemein oder bei Programmierfehlern?

vielen Dank,
Tobias

for_ro
04.02.2009, 22:40
Allgemein oder bei Programmierfehlern?


Was meinst du damit?

Nachdem eine Sub ausgeführt worden ist, wird das Programm mit dem Befehl nach dem Gosub fortgesetzt. Die Speicherstelle des Befehls wird dazu im Stack abgelegt. Dann werden die Befehle in der Sub ausgeführt. Kommt jetzt das nächste Gosub, wird wieder die Rücksprungadresse in den Stack gelegt und zwar in die nächste Zelle. Wird dann ein Return Befehl ausgeführt, springt das Programm an die letzte gespeicherte Stelle zurück und löscht diese vom Stack. Wenn also zu einem Gosub kein Return gefunden wird, bleibt die entsprechende Rücksprungadresse im Stack liegen. Da der Stack nur eine begrenzte Größe hat, läuft er irgendwann voll. Die nächste Adresse wird dann in einen Bereich geschrieben, der nicht dafür reserviert ist und es passieren meistens vollkommen ungewollte und nicht nachvollziehbare Aktionen.

Gruß

Rolf

TobiasBlome
05.02.2009, 17:06
Ach so,
dann habe ich ja "Glück gehabt" weil ich diese Sub nur max 2-3 mal benutze. Nämlich jedesmal wenn ich den Taster an Pind.7 betätige um eine neue Aufzeichnung zu starten. Meisten zeichnet man ja nur 1 mal auf ;-) - nach einem Neustart ist der Stack ja dann sowieso leer.

Danke,
Tobias

hardware.bas
05.02.2009, 19:24
TobiasBlome: Das Projekt interessiert nich sehr, da ich schon lange
nach einer Möglichkeit suche. Daten von AVR auf einen USB-Stick
ohne Umwege zu loggen. Gibts dazu ne Schaltungg? Vielen Dank und
Viele Grüße Micha

TobiasBlome
05.02.2009, 22:03
@hardware.bas

ich benutze den "Vinculum" der Firma FTDI. In der Elektor(11/2008 S.42) ist ein ausführlicher Artikel. Ausserdem kann man das IC(smd 48pin) als fertig Modul mit USB-Buchse auf einer Platine bei Elektor im shop kaufen.
Angesteuert wird das IC über die serielle Schnittstelle - also relativ bequem vom µC ansteuerbar.

Tobias