Astrein !!! Manchmal braucht es eben auch etwas Druck :lol: (Nebenbei bemerkt würd ich es jetzt auch etwas anders machen als bei meinem ersten Vorschlag. @Sauerbruch ;) )
Viel Spaß und Erfolg
Gruß
Searcher
Druckbare Version
Ich schon: Ich denke, dass mit Registerinhalten keine größeren Rechenoperationen durchgeführt werden können. Und erst recht nicht, wenn sich der Inhalt des Registers schnell mal ändern kann (wie PINA). Deshalb ist es im Zweifelsfall immer sicherer, den Registerinhalt in eine Variable zu übernehmen, und dann mit dieser Variablen weiterzuspielen. Vielleicht gibt es hier ja irgendwelche Freaks, die diese Vermutung bestätigen (und vielleicht sogar erklären!) können...Zitat:
Wirklich keine Ahnung, woran es lag,
Viel Spaß beim Weitermachen :-)
Hallöle Allerseits ^^.
Das eine Problem war nun gebannt und kam auch nicht wieder, dafür ein Anderes. Ich kann es aber auch nur beschreiben, und zwar wie folgt:
Zum Auf- und Abdimmen einer bzw. mehrerer LED habe ich den Timer0 mit einem Prescaler von 64 versehen (8MHz Systemtakt) und anschließend den Timer0 immer auf 249 vorgeladen. Es klingt vielleicht ein wenig umständlich, dass ich den Timer mit NUR 6 Takten betreibe, aber so ist das LED-Fading einfach viel besser einstellbar als mit einem Prescaler von 8 und Vorladen um die 170.
Wie dem auch sei - ihr seht im ersten Programmabschnitt den ersten Case, in welchem bei [alle Eingangsbits = 1] alle Ausgangsregister auf 1 gesetzt werden, also alle LED = Off.
In einer speziellen Sub (standardgemäß über den CASE selektiert) wurde nun der Timer aufgerufen und sollte die Ausgänge mit einer LED-PWM auf- und abdimmen.
Und was geschah? NICHTS!
Also habe ich ein Testprogramm auf einer neuen Seite geschrieben, in welchem der lediglich 2 Test-CASE vorkamen - die LED fadete so, wie sie sollte.
Also wieder zurück ins Hauptprogramm und - funktioniert noch immer nicht.
Also habe ich den Übetäter kurz deaktiviert (den ersten Case mit dem " ' " in Schrift gewandelt) und - fadet noch immer nicht.
Nach gut einer Stunde Suchen habe ich dann alle Case, bis auf den letzten (in dem der Timer genutzt wurde) deaktiviert. Und plötzlich - funktioniert.
Also nacheinander alle Step-by-step wieder reaktiviert. Als ich dann beim ersten CASE ankam, funktionierten die anderen wieder problemlos.
Habe diesen dann auch wieder reaktiviert und was soll ich sagen - keine Spur mehr von einem Problem. Die Ausgänge fadeten ohne Murren.
Mittlerweile läuft das Programm fehlerfrei und ich teste jede neue CASE ausgiebig, bevor ich diese endgültig abspeichere.
Beispielsweise hatte ich auch das Problem der Signalüberschneidung. Am Ende der ISR des Timer0 stehen ja die angesteuerten Ports mit entsprechenden Bedingungen drin. Da ich aber unter verschiedenen Bedingungen bestimmte Ports ansteuere, kam es beim Fading dazu, dass die LED nur halbhell aufleuchteten.
Wie ich das gelöst habe, seht ihr am Ende des Codes...
Code:$regfile = "m8515.dat"
$crystal = 8000000
$hwstack = 40
$swstack = 32
$framesize = 60
'-------------------------------------------------------------------------------
' *** Konfiguriere Ein- und Ausgangsports ***
Config Porta = Input
Config Portb = Output
Config Portc = Output
Config Portd = Output
Porta = &HFF ' Aktiviert die internen Pullup-Widerstände
Portb = &HFF ' schaltet alle Ausgänge 1, LED = 0
Portc = &HFF
Portd = &HFF
'-------------------------------------------------------------------------------
' *** Konfiguriere Timer ***
Config Timer0 = Timer , Prescale = 64
On Timer0 Timerroutine
Enable Timer0
Start Timer0
Enable Interrupts
'-------------------------------------------------------------------------------
' *** Deklarieren der Variablen ***
Dim Programm As Byte
Dim Zaehler As Word
Dim Timerzaehler As Word
Dim Led_rack0 As Word ' Abrufbar wenn nur ein Rack gefordert
Dim Led_rack1 As Word ' Acht LED-Racks - abrufbar, wenn mehr als ein Racks gefordert
Dim Led_rack2 As Word ' Jedes Rack steht dabei für ein Regalfach, egal ob horizontal oder vertikal
Dim Led_rack3 As Word
Dim Led_rack4 As Word
Dim Led_rack5 As Word
Dim Led_rack6 As Word
Dim Led_rack7 As Word
Dim Led_rack8 As Word
Dim Choose_rack As Byte ' Variable zum Weiterschalten eines Racks in einer Ablaufprozedur
Dim Folgesequenz As Byte ' Variable zum Weiterschalten einer Sequenz in die Folgende
Dim M1 As Bit ' Programmabbruch-Variable
'-------------------------------------------------------------------------------
' *** Deklarieren der Subroutinen ***
Declare Sub All_off
Declare Sub All_on
Declare Sub Horizontal_lines
Declare Sub Vertical_lines
Declare Sub Straight
Declare Sub Diagonal_falling
Declare Sub Diagonal_rising
Declare Sub Net
Declare Sub Net_invert
Declare Sub Arrow_up
Declare Sub Pulsing_rack
Declare Sub Left_to_right
'-------------------------------------------------------------------------------
' ===============================
' ***** Hauptprogramm *****
' ===================================
Do
Programm = Pina ' Variable übernimmt das Portregister von Port A
Programm = Programm And &B00011111 ' Die ersten 3 Bits von Port A werden deaktiviert, somit brauchen
' im folgenden Select nur noch die Folgebits stehen
Select Case Programm
Case &B11111 : Call All_off ' 00000
Case &B11110 : Call All_on ' 00001
Case &B11101 : Call Horizontal_lines ' 00010
Case &B11100 : Call Vertical_lines ' 00011
Case &B11011 : Call Straight ' 00100
Case &B11010 : Call Diagonal_falling ' 00101
Case &B11001 : Call Diagonal_rising ' 00110
Case &B11000 : Call Net ' 00111
Case &B10111 : Call Net_invert ' 01000
Case &B10110 : Call Arrow_up ' 01001
Case &B10101 : Call Pulsing_rack ' 01010
Case &B10100 : Call Left_to_right ' 01011
End Select
If Programm = &B11111 Then M1 = 1 Else M1 = 0 ' Programmabbruch-Bedingung
Loop
'-------------------------------------------------------------------------------
' ====================================
' **** Unterprogramme ****
' ================================
Sub All_off: ' 00000
Portd = &B11111111
Portc = &B11111111
Portb = &B11111111
Choose_rack = 0 ' Setzt bei Programmabbruch Variable zurück
Disable Timer0 ' Setzt bei Programmabbruch Timer0 Ausser Kraft
End Sub All_off
Sub All_on: ' 00001
Portd = &B00000000
Portc = &B00000000
Portb = &B00000000
End Sub All_on
Sub Horizontal_lines: ' 00010
Portd = &B10101010
Portb = &B10101010
Portc = &B10101010
End Sub Horizontal_lines
Sub Vertical_lines: ' 00011
Portd = &B00000000
Portc = &B11111111
Portb = &B00000000
End Sub Vertical_lines
Sub Straight: ' 00100
Portd = &B11111111
Portc = &B00000000
Portb = &B11111111
End Sub Straight
Sub Diagonal_falling : ' 00101
Portd = &B00100100
Portc = &B01001001
Portb = &B10010010
End Sub Diagonal_falling
Sub Diagonal_rising: ' 00110
Portd = &B10010010
Portc = &B01001001
Portb = &B00100100
End Sub Diagonal_rising
Sub Net: ' 00111
Portd = &B10101010
Portc = &B01010101
Portb = &B10101010
End Sub Net
Sub Net_invert: ' 01000
Portd = &B01010101
Portc = &B10101010
Portb = &B01010101
End Sub Net_invert
Sub Arrow_up: ' 01001
Portd = &B11011101
Portc = &B10111011
Portb = &B11011101
End Sub Arrow_up
Sub Pulsing_rack: ' 01010
Enable Timer0 ' Startet Timer0 (muss ja nicht immer laufen)
'----- Aufdimmen -----
For Zaehler = 0 To 300
Led_rack0 = Zaehler
Waitms 10
Next Zaehler
'----- Abdimmen -----
For Zaehler = 300 To 0 Step -1
Led_rack0 = Zaehler
Waitms 10
Next Zaehler
End Sub Pulsing_rack
Sub Left_to_right:
' Diese Sub dimmt jeweils 3 LED-Streifen (bestehend aus je 1 Port) nacheinander auf und in gleicher Reihenfolge wieder ab.
' Mit Hilfe der Variable "CHOOSE_RACK" war es möglich, jeweils um 1 LED-Rack (1 Port) weiterzuschalten, ohne eine neue
' FOR-Schleife aufbauen zu müssen.
Enable Timer0
Choose_rack = Choose_rack + 1 ' 01011
Aufdimmen:
For Zaehler = 0 To 300
If M1 = 1 Then Exit Sub ' Abbruchbedingung
If Choose_rack = 1 Then Led_rack1 = Zaehler
If Choose_rack = 2 Then Led_rack2 = Zaehler
If Choose_rack = 3 Then Led_rack3 = Zaehler
Waitms 3
Next Zaehler
If Choose_rack = 3 Then Gosub Abdimmen:
Abdimmen:
For Zaehler = 300 To 0 Step -1
If M1 = 1 Then Exit Sub
If Choose_rack = 4 Then Led_rack1 = Zaehler
If Choose_rack = 5 Then Led_rack2 = Zaehler
If Choose_rack = 6 Then Led_rack3 = Zaehler
Waitms 3
Next Zaehler
If Choose_rack = 6 Then Choose_rack = 0
End Sub Left_to_right
End
'-------------------------------------------------------------------------------
' *** ISR für Timer erzeugen - Overflow-Counter in Warteposition bringen ***
Timerroutine:
Timer0 = 249
Incr Timerzaehler
If Timerzaehler = 300 Then Timerzaehler = 0 ' Auflösung der LED's von 300Hz
' Die nachfolgenden Port-PWM-Ansteuerungen werden durch die Programm-Bedingung separiert.
' Ohne Trennung gäbe es eine Signalüberschneidung, welche die Helligkeit um 50% reduziert.
'---------- Sub Pulsing_Rack ----------
If Programm = &B10101 Then
If Timerzaehler < Led_rack0 Then Portb = &B00000000 Else Portb = &B11111111
End If
'---------- Sub Left_To_Right ----------
If Programm = &B10100 Then
If Timerzaehler < Led_rack1 Then Portb = &B00000000 Else Portb = &B11111111
If Timerzaehler < Led_rack2 Then Portc = &B00000000 Else Portc = &B11111111
If Timerzaehler < Led_rack3 Then Portd = &B00000000 Else Portd = &B11111111
End If
Return
Bin echt froh, dass ich an vielen Stellen selbst weiterkomme, aber ohne eure Hilfe würde der Code sicher um Einiges größer.
Wobei ich aber auch sagen muss, dass es keinen nennenswerten Unterschied zur Schreibweise "PinA = &B00011101" und "PinA = 11101" gibt. Habe es mehrfach geprüft - die Dateigröße bleibt gleich.
Der Code oben liegt derzeit übrigens bei ca. 1,7KB - und für meine Verhältnisse ist das echt verdammt wenig. Denke, dass das Deklarieren der Subs auch eine ganze Menge raus haut. Gosub-Sprungmarken ohne Deklaration der Sub ziehen doch schon ihren Speicherplatz...
LG - Maik
Also, bevor ich versuche zu verstehen ob es jetzt aktuell noch ein Problem gibt, muss ich Dich nochmal auf drei fundamentale Denkfehler hinweisen:Zitat:
Wobei ich aber auch sagen muss, dass es keinen nennenswerten Unterschied zur Schreibweise "PinA = &B00011101" und "PinA = 11101" gibt. Habe es mehrfach geprüft - die Dateigröße bleibt gleich.
Erstens:
Man kann das Register PINA (ebenso wie alle anderen PIN-Register) nicht beschreiben!!! D.h. man kann es schon, aber bereits mit dem nächsten Taktzyklus des Controllers übernimmt jedes der 8 Bits den Wert, der den logischen Pegeln auf den Anschlüssen PINX.7 bis PINX.0 anliegt. In PORT-Register kann man durchaus alle möglichen Werte reinschreiben - aber beim PIN-Register funktioniert es nicht und macht vor allem keinen Sinn. Es ist ein reines Auslese-Register!!!!
Zweitens:
Natürlich macht es einen Unterschied, ab man einer Byte-Variablen den Wert 11101 oder &b00011101 zuweist! Das kann man am Simulator sehr schön sehen - aber nicht am Speicherplatz, den der Programmcode benötigt!! Der benötigte Speicherplatz ist nur ein ganz, ganz grober Schätzer - aber wenn Du Dir mal vergegenwärtigst, dass die meisten Befehle 2 Byte Speicher benötigen wird klar, dass man ein Programm komplett umändern kann, ohne dass sich der Speicherplatz-Bedarf ändert.
Drittens:
Wenn Du einer Byte-Variablen eine Dezimal-Wert von 11101 zuweist, müsste Bascom eigentlich sofort die Fehlermeldung rausgeben "Hey Du Troll - Bytes können einen Wert von maximal 255 annehmen". Aber Bascom ist da etwas gnädiger. Was es macht, kannst Du verstehen, wenn mal die "Taschenrechner"-App auf Deinem PC aktivierst, dort die Dezimalzahl 11101 eingibst, und sie in einen Binärwert umwandelst. Das Ergebnis ist &b 0010 1011 0101 1101. Bascom ignoriert einfach die oberen 8 Bits und schreibt wenigstens die unteren 8 Bits (also &b 0101 1101) in das Byte. Wenn Du irgendeine LCD-Anzeige an Deinem Controller hast, kannst Du das ja mal ausprobieren:
Dim X as Byte
X = 11101
LCD X
Auf dem Display wird die Zahl 93 stehen (=&b 0101 1101)
Wenn diese Dinge nicht klar sind, wird´s wohl immer wieder Schwierigkeiten geben :-)
Hi Sauerbruch.
Danke nochmals.
Display ist vorhanden, momentan jedoch keine Zeit. Ich bin gestern so gut voran gekommen und habe auch viel Neues dazu gelernt, dass ich jetzt da weitermache, wo ich gestern aufgehört habe.
Für Display-Übungen steht aber auch noch eine Programmierwoche an, nämlich wenn ich den MASTER-Controller beschreibe. Der hat neben der PWM-Ausgabe und den Eingabe-Tastern auch noch ein Display. Wird das erste mal - bin selbst schon gespannt ^^.
LG - Maik
Hallo Freunde.
Das Arbeiten am Slave-Controller habe ich nun erst einmal beiseite gepackt und mich an den Master gesetzt, welcher neben dem Display und der Cursor-Steuerung auch Übertragungsbits bereit stellt.
Allerdings habe ich dabei ein kleines Problem, und es kann ja sogar auch sein, dass das Ganze so gar nicht funktioniert, wie ich mir das vorstelle:
Beim Einlesen eines ganzen Registers konnte ich ja das gesamte Register verwenden. Nun allerdings habe nur noch Teile 2er Ausgaberegister zur Verfügung, nämlich von PortB und PortD.
Mit den nun für mich relevanten Ports versuchte ich, eine neue Wahrheitstabelle aufzubauen, welche in einer "Select" zusätzlich zu einem ausgegebenen Display-Text angesprochen wird.
Hier der Codeausschnitt:
Die Ausgangsbits sind korrekt als Ausgänge konfiguriert, die zugewiesene Variable als Byte deklariert. Dieser kleine Bereich ist Teil eines 5,3KB großen Programms, weshalb ich nur diesen Ausschnitt poste. Bislang funktioniert auch alles tadellos, und mit dem Sprung in die Variable "Starr" wird auch der in der Select stehende Text für den entsprechenden Wert von "Starr" korrekt ausgegeben. Die Variable funktioniert also tadellos, nur werden die Ausgänge nicht gesetzt.Code:' Konfiguration der Ausgangsbits für Wahrheitstabelle
Ausgabebyte.0 = Portd.7
Ausgabebyte.1 = Portd.6
Ausgabebyte.2 = Portd.5
Ausgabebyte.3 = Portb.7
Ausgabebyte.4 = Portb.6
Ausgabebyte.7 = Portb.0
Locate 1 , 1 : Lcd "3.1 Stillstehend" : Locate 2 , 1 : Lcd Chr(1) : Locate 2 , 16 : Lcd Chr(2)
'- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
' Konfigurieren und Ausgabe der Musterbits für stehende Muster
Locate 2 , 2
Select Case Starr
Case 0 : Ausgabebyte = &B00000000 : Lcd " Bitte w hlen " : Locate 2 , 10 : Lcd Chr(3)
Case 1 : Ausgabebyte = &B11111111 : Lcd " Alle Cluster "
End Select
Setze ich hingegen testweise NUR einen einzelnen Port, indem ich ihn direkt anrufe, dann wird der Ausgang wie gewünscht gesetzt.
In etwa so:
Kann es also u.U. daran liegen, dass ich in einem Byte lediglich Ports eines einzelnen Registers anrufen kann oder geht das bei Ausgängen gar nicht?Code:
Locate 1 , 1 : Lcd "3.1 Stillstehend" : Locate 2 , 1 : Lcd Chr(1) : Locate 2 , 16 : Lcd Chr(2)
'- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
' Konfigurieren und Ausgabe der Musterbits für stehende Muster
Locate 2 , 2
Select Case Starr
Case 0 : Portb.0 = 0 : Lcd " Bitte w hlen " : Locate 2 , 10 : Lcd Chr(3)
Case 1 : portb.0 = 1 : Lcd " Alle Cluster "
End Select
LG - Maik
Ach menno - das hatten wir doch schon:
X = A bedeutet, dass der Variablen X der Wert von A zugewiesen wird. So rum - und nicht anders!!!
Das Gleichheitszeichen geht bei Bascom nur in eine Richtung: Der rechts vom Gleichheitszeichen stehende Wert wird der links davon stehenden Variablen zugewiesen. Die links stehende Variable macht NIEMALS etwas mit der rechts stehenden Variable. Das ist der fundamentale Unterschied zum Gleichheitszeichen im mathematischen Sinne.
Wenn Du also am Anfang schreibst X = A und dann im Verlauf mit X weiterrechnest, ändert sich A in keinster Weise! Der Befehl X = A liegt erstens schon lange zurück, und zweitens hat die links stehende Variable wie gesagt niemals einen Einfluss auf die rechts stehende Variable!
Was macht also diese Befehlssequenz:
Ausgabebyte.0 = Portd.7
Ausgabebyte.1 = Portd.6
Ausgabebyte.2 = Portd.5
Ausgabebyte.3 = Portb.7
Ausgabebyte.4 = Portb.6
Ausgabebyte.7 = Portb.0
?????
Riiiiiichtiiiig - nicht das Byte "Ausgangsbyte" bestimmt die Port-Pegel, sondern aus den Bits, die in den Registerzellen PORTD.7, D.6, D.5, B.7 B.6 und B.0 stehen, wird das Byte "Ausgangsbyte" zusammengebastelt.UND NICHT ANDERSHERUM!!!! Ich nehme an, dass an einer so frühen Stelle alle Bits in den PORT-Regsitern noch 0 sind, damit dürfte Ausgangsbyte in diesem Moment auch &b00000000 sein - aber das ist ja auch egal, denn später passiert ja anscheinend irgendwas mit diesem Byte, d.h. es wird ohnehin verändert.
Klingelt´s jetzt vielleicht so weit, dass Du auf die Lösung kommst?