PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Problem Portabfrage alle 25ms



Enterprise
09.06.2007, 14:15
Hallo Forum,

Ich möchte über einen Atmega8 3,686 Mhz getaktet.
Den Portd.3 alle 25ms abfragen ob dieser Port auf Masse liegt.
Dieses soll genau 10 Sekunden dauern.
Dann müsste ich ja 400 Werte bekommen, das ist nicht der Fall.
Ich bekomme mal 307,317,323,... Werte heraus nie die 400.


$regfile = "m8def.dat"
$crystal = 3686400
$baud = 9600 'Baudrate der UART: 9600 Baud

Config Timer1 = Timer , Prescale = 64
On Timer1 Timer_irq
Const Timervorgabe = 7936 ' Const 7936


Ddrd = &B00000000
Ddrc = &B11111111
Portd = &B11111111


Dim Sekunden As Byte
Dim P3 As Byte
Dim P4 As Byte
Dim A As Byte
Dim T0 As Long
Dim T1 As Long
Dim E1 As Long
Declare Sub Ledon
Declare Sub Main
Declare Sub Abfragen
Declare Sub Ende
Declare Sub Zler1

Enable Timer1
Enable Interrupts


Main:
'----------------------------------------------------------
'######## einschalten Portd.2 ####################
'----------------------------------------------------------
Do
Debounce Pind.2 , 0 , Abfragen , Sub 'Entprellt
Loop


'----------------------------------------------------------
'######## Abfrage des Portd.3 ###################
'----------------------------------------------------------
Abfragen:

Portc.3 = 1

A = 0

Do

Zler1:

Waitms 25

P3 = Pind.3

If P3 = 0 Then
Portc.1 = 1 'Led An
' Portc.2 = 1 ' Summer an Portc.2 an
A = A + 1
Print " A " ; A
If A = 8 Then
Goto Ledon
End If
Goto Zler1
Else
Portc.1 = 0 'Led Aus
' Portc.2 = 0 ' Summer an Portc.2 aus
A = 0
End If


Loop

'----------------------------------------------------------
'############ Led und Summer #############################
'----------------------------------------------------------

Ledon:

T0 = 0
T1 = 0

Print "S" 'Senden ein S über RS232
Sekunden = 0 ' Sek auf 0 stellen dass die 10 S

Do
If Sekunden < 1 Then
Portc.0 = 1 'Led zeigt 10 Sek.an
' Print " " ; Sekunden ' Kontrolle der Skunden
Else
Portc.0 = 0 'Led wird aus geschaltet
' Sekunden = 0 'Sekunden werden auf 0 gestzt
Goto Ende
End If

'Print Pind.4 ; " " ' Kontrolle des Portsd.4
P4 = Pind.3
If P4 = 1 Then
' Print "0" 'Senden ein 0 über RS232
Portc.1 = 0 ' Led aus Portc.1
Portc.2 = 0 ' Summer an Portc.2 aus
T0 = T0 + 1
Print "0" ; " " ; T0
Else
' Print "1" 'Senden ein 1 über RS232
Portc.1 = 1 ' Led ein Portc.1
Portc.2 = 1 ' Summer an Portc.2 ein
T1 = T1 + 1
Print "1" ; " " ; T1
End If

Waitms 25 ' Abfrage alle 25 ms


Loop

'------------------------------------------------------------
'####### Ende ###############
'------------------------------------------------------------

Ende:

E1 = T0 + T1
Print "E" 'Senden ein E über RS232
Print " "
Print " "
Print " Treffer = " ; T1
Print " N.Treffer = " ; T0
Print " "
Print " Gesammt = " ; E1
Print " "
Print " Sekunde = " ; Sekunden
Print " "
Print " "

T0 = 0
T1 = 0
Sekunden = 0

Portc.1 = 0 ' Led an Portc.1 aus
Portc.2 = 0 ' Summer aus Portc.2
Portc.3 = 0 ' Laser einschalten

Goto Main

'-------------------------------------------------------------
'########## Timer Skundenbasis #############################
'-------------------------------------------------------------

Timer_irq:
Timer1 = Timervorgabe
Incr Sekunden
Return

End




Kann mir jemand helfen welche Werte falsch sind.

mfg
Enterprise

robodriver
09.06.2007, 19:03
Das ist ganz einfach:
dein Controller wartet 25ms, danach überprüft er den Portstatus, vergleicht ihn und reagiert drauf. Das alles braucht auch nochmal Zeit.
schon alleine das senden von " A " (3 Bytes) benötigt bei 9600 Baud etwa 3ms.
und wenn der Pin das 8. mal in folge auf Null ist, dann macht der Controller ja noch mehr...
Desshalb nimmt er effektiv nicht alle 25ms den Portstatus auf, sondern immer in unterschiedlichen Abständen.
Je nach dem ob der Pin 0 oder 1 ist und wie oft der Pin auf 0 ist, dauert es immer länger als 25 ms bis der nächste Wert abgefragt wird.
Und desshalb hast du auch immer unterschiedlich viele Werte. Die Anzahl hängt halt davon ab wie oft der Pin auf 0 war.

peterfido
09.06.2007, 22:12
Du solltest die 400 Werte erstmal zwischenspeichern und sie dann anschließend auswerten.

uwegw
09.06.2007, 22:22
Oder den 25ms-Abfragetakt über einen Timer erzeugen...

Enterprise
10.06.2007, 00:39
Danke für die Infos.

Kann das funktionieren mit 25ms und über die RS232 zu übertragen.

Es soll in Echtzeit über die RS232 übertragen werden, also mit

zwischen speichern ist nicht.

UWEGW Wie könnte ich das mit dem Timer einrichten ?


mfg
Enterprise

peterfido
10.06.2007, 10:36
Ich habe mir das noch mal genauer angesehen. Du könntest Zeit sparen, indem du nicht in jeder Schleife p3=pind.3 zuweist, sondern ganz oben ein p3 alias pind.3. Dann könntest du den Timer auf 25 ms einstellen. Alle 40 Durchläufe setzt du dann sekunden eins hoch. So hast du deine 25ms. Dann natürlich die wait25ms rausnehmen und aus der do loop Schleife ein sub machen, welches vom Timer alle 25ms angesprungen wird.

Config Timer1 = Timer , Prescale = 8
On Timer1 Timer_irq
Const Timervorgabe = 54016 ' Const 7936

Enterprise
10.06.2007, 15:25
Hallo,

Habe versucht deine Aussage um zu setzen.
Habe warscheinlich etwas nicht richtig verstanden.
Das Hauptprogramm fängt erst bei Ledon: an.
Die Definition P3 habe ich jetzt nur einmal.
Habe eine FOR Next Schleife eingebaut das war glaube ich nicht richtig.
Den Zusammenhang vom Interupt ins Programmspringen habe ich noch nicht richtig verstanden wo ?
Kannst du mir vielleicht zeigen wo ich die Änderungen machen soll.




$regfile = "m8def.dat"
$crystal = 3686400
$baud = 9600 'Baudrate der UART: 9600 Baud

'Config Timer1 = Timer , Prescale = 64
'On Timer1 Timer_irq
'Const Timervorgabe = 7936 ' Const 7936

Config Timer1 = Timer , Prescale = 8
On Timer1 Timer_irq
Const Timervorgabe = 54016

Ddrd = &B00000000
Ddrc = &B11111111
Portd = &B11111111


Dim Sekunden As Byte
Dim P3 As Byte
Dim P4 As Byte
Dim A As Byte
Dim T0 As Long
Dim T1 As Long
Dim E1 As Long
Dim Durchl40 As Long
Declare Sub Durchlauf10s
Declare Sub Ledon
Declare Sub Main
Declare Sub Abfragen
Declare Sub Ende
Declare Sub Zler1

Enable Timer1
Enable Interrupts


Main:

P3 = Pind.3

'----------------------------------------------------------
'######## einschalten Portd.2 ####################
'----------------------------------------------------------
Do
Debounce Pind.2 , 0 , Abfragen , Sub 'Entprellt
Loop


'----------------------------------------------------------
'######## Abfrage des Portd.3 ###################
'----------------------------------------------------------
Abfragen:

Portc.3 = 1

A = 0

Do

Zler1:

Waitms 25

'P3 = Pind.3

If P3 = 0 Then
Portc.1 = 1 'Led An
' Portc.2 = 1 ' Summer an Portc.2 an
A = A + 1
Print " A " ; A
If A = 8 Then
Goto Ledon
End If
Goto Zler1
Else
Portc.1 = 0 'Led Aus
' Portc.2 = 0 ' Summer an Portc.2 aus
A = 0
End If


Loop

'----------------------------------------------------------
'############ Led und Summer #############################
'----------------------------------------------------------

Ledon:

T0 = 0
T1 = 0

Print "S" 'Senden ein S über RS232
Sekunden = 0 ' Sek auf 0 stellen dass die 10 S

'Do
For I = 1 to 40

If Sekunden < 10 Then
Portc.0 = 1 'Led zeigt 10 Sek.an
' Print " " ; Sekunden ' Kontrolle der Skunden
Else
Portc.0 = 0 'Led wird aus geschaltet
' Sekunden = 0 'Sekunden werden auf 0 gestzt
Goto Ende
End If

'Print Pind.4 ; " " ' Kontrolle des Portsd.4
P4 = Pind.3
If P4 = 1 Then
' Print "0" 'Senden ein 0 über RS232
Portc.1 = 0 ' Led aus Portc.1
Portc.2 = 0 ' Summer an Portc.2 aus
T0 = T0 + 1
Print "0" ; " " ; T0
Else
' Print "1" 'Senden ein 1 über RS232
Portc.1 = 1 ' Led ein Portc.1
Portc.2 = 1 ' Summer an Portc.2 ein
T1 = T1 + 1
Print "1" ; " " ; T1
End If

'Waitms 25 ' Abfrage alle 25 ms
'Loop

Next I

'------------------------------------------------------------
'####### Ende ###############
'------------------------------------------------------------

Ende:

E1 = T0 + T1
Print "E" 'Senden ein E über RS232
Print " "
Print " "
Print " Treffer = " ; T1
Print " N.Treffer = " ; T0
Print " "
Print " Gesammt = " ; E1
Print " "
Print " Sekunde = " ; Sekunden
Print " "
Print " "

T0 = 0
T1 = 0
Sekunden = 0

Portc.1 = 0 ' Led an Portc.1 aus
Portc.2 = 0 ' Summer aus Portc.2
Portc.3 = 0 ' Laser einschalten

Goto Main

'-------------------------------------------------------------
'########## Timer Skundenbasis #############################
'-------------------------------------------------------------

Timer_irq:
Timer1 = Timervorgabe
Incr Sekunden
Return

End



mfg
Enterprise

peterfido
10.06.2007, 20:47
So, mein erster Entwurf. Musst evtl noch Fehler ausmerzen, habe gerade keine Zeit zum testen.

Du könntest mehr Reserve rausholen, wenn du nen schnelleren Quarz nimmst, die Baudrate erhöhst, den Code optimierst...



$regfile = "m8def.dat"
$crystal = 3686400
$baud = 9600 'Baudrate der UART: 9600 Baud

'Config Timer1 = Timer , Prescale = 64
'On Timer1 Timer_irq
'Const Timervorgabe = 7936 ' Const 7936

Config Timer1 = Timer , Prescale = 8
On Timer1 Timer_irq
Const Timervorgabe = 54016

Ddrd = &B00000000
Ddrc = &B11111111
Portd = &B11111111


Dim Sek As Byte
Dim Sekunden As Byte
Dim P3 As Byte
Dim P4 As Byte
Dim A As Byte
Dim T0 As Long
Dim T1 As Long
Dim E1 As Long
Dim Durchl40 As Long
Declare Sub Durchlauf10s
Declare Sub Ledon
Declare Sub Main
Declare Sub Abfragen
Declare Sub Ende
Declare Sub Zler1

Config Portc.1 = Output
Config Portc.2 = Output
Config Portc.3 = Output
Config Portd.2 = Input



Enable Timer1
Enable Interrupts


'Main:

Led1 Alias Portc.1
Summer Alias Portc.2
Laser Alias Portc.3

P3 Alias Pind.3
Eingang Alias Pind.2

'P4 Alias Pind.3

Main:
Sek = 0



'----------------------------------------------------------
'######## einschalten Portd.2 ####################
'----------------------------------------------------------
'Do
' Debounce Pind.2 , 0 , Abfragen , Sub 'Entprellt
'Loop


'----------------------------------------------------------
'######## Abfrage des Portd.3 ###################
'----------------------------------------------------------
Sub Abfragen()

Set Laser 'Portc.3 = 1

'A = 0

'Do

Zler1:

'Waitms 25

'P3 = Pind.3

If P3 = 0 Then
Set Led1 'Led An
' set summer ' Summer an Portc.2 an
A = A + 1
Print " A " ; A
If A = 8 Then
Gosub Ledon
End If
'Goto Zler1
Else
Reset Led1 'Led Aus
' reset summer ' Summer an Portc.2 aus
A = 0
End If


End Sub
'loop

'----------------------------------------------------------
'############ Led und Summer #############################
'----------------------------------------------------------

Ledon:
A = 0
T0 = 0
T1 = 0

Print "S" 'Senden ein S über RS232
Sekunden = 0 ' Sek auf 0 stellen dass die 10 S

'Do
'For I = 1 to 40

If Sekunden < 10 Then
Portc.0 = 1 'Led zeigt 10 Sek.an
' Print " " ; Sekunden ' Kontrolle der Skunden
Else
Portc.0 = 0 'Led wird aus geschaltet
' Sekunden = 0 'Sekunden werden auf 0 gestzt
Goto Ende
End If

'Print Pind.4 ; " " ' Kontrolle des Portsd.4
If P4 = 1 Then
' Print "0" 'Senden ein 0 über RS232
Portc.1 = 0 ' Led aus Portc.1
Portc.2 = 0 ' Summer an Portc.2 aus
T0 = T0 + 1
Print "0" ; " " ; T0
Else
' Print "1" 'Senden ein 1 über RS232
Portc.1 = 1 ' Led ein Portc.1
Portc.2 = 1 ' Summer an Portc.2 ein
T1 = T1 + 1
Print "1" ; " " ; T1
End If
Return
'Waitms 25 ' Abfrage alle 25 ms
'Loop

'Next I

'------------------------------------------------------------
'####### Ende ###############
'------------------------------------------------------------

Ende:

E1 = T0 + T1
Print "E" 'Senden ein E über RS232
Print " "
Print " "
Print " Treffer = " ; T1
Print " N.Treffer = " ; T0
Print " "
Print " Gesammt = " ; E1
Print " "
Print " Sekunde = " ; Sekunden
Print " "
Print " "

T0 = 0
T1 = 0
Sekunden = 0

Reset Led1 ' Led an Portc.1 aus
Reset Summer ' Summer aus Portc.2
Reset Summer ' Laser einschalten
Goto Main

'-------------------------------------------------------------
'########## Timer Skundenbasis #############################
'-------------------------------------------------------------

Timer_irq:
Timer1 = Timervorgabe
Sek = Sek + 1
If Sek = 40 Then
Incr Sekunden
Sek = 0
End If
Call Abfragen
If Sekunden = 10 Then
Sekunden = 0
Goto Ende
End If

return

End

Enterprise
11.06.2007, 00:05
Danke peterfido,

Habe deine Verbesserungen in mein Script eingebaut.
Nun funktioniert es.


Diese Anweißung hat bei mir nicht funktioniert.

Config Portc.1 = Output
Config Portc.2 = Output
Config Portc.3 = Output
Config Portd.2 = Input

Habe es dann so geändert.

Config Portc = Output
Config Portd = Input


Wie kann man den Timer1 Ausschalten ?
So dass, er nicht den Interrupt alle 25ms startet.


mfg
Enterprise

peterfido
11.06.2007, 19:00
DAfür gibt es disable timer1

Enterprise
11.06.2007, 22:28
Danke peterfido,

Diesen Befehl habe ich nicht in meinem Buch gefunden.


mfg
Enterprise