config port b zeugs komt bei dir doch doppelt vor? hat das einen tieferen grund?
Hallo
Ich habe jetzt versucht es mit der Methode mit String umzusetzen doch ich habe ein paar Probleme damit.
Und zwar muss ich die Variable Ergebnis als Double deklarieren damit keine Fehler angezeigt werden.
Zudem zeigt mir Bascom an dass 29% Speicher benutzt werden. Das heißt ich kann das Ganze nicht mehr kompilieren weil ich nur die Demo habe.
Wenn ich den Befehl Lcd Ergebnis weglasse nimmt das Programm nur 20% in Anspruch.
Ich war mir bei der Deklaration von Rechnung auch nicht ganz sicher ob das stimmt.
Hier der Quellcode
Code:$regfile = "M16def.dat" ' use the Mega16 $crystal = 1000000 Config Lcdpin = Pin , Db4 = Porta.3 , Db5 = Porta.2 , Db6 = Porta.1 , Db7 = Porta.0 , E = Porta.4 , Rs = Porta.5 Config Lcd = 16 * 2 Initlcd Config Pinb.0 = Input 'Zahl 0 Config Pinb.1 = Input 'Zahl 1 Config Pinb.2 = Input 'Zahl 2 Config Pinb.3 = Input 'Zahl 3 Config Pinb.4 = Input 'Zahl 4 Config Pind.0 = Input 'Zahl 5 Config Pind.1 = Input 'Zahl 6 Config Pind.2 = Input 'Zahl 7 Config Pind.3 = Input 'Zahl 8 Config Pind.4 = Input 'Zahl 9 Config Pind.5 = Input 'Plus Config Pind.7 = Input 'Minus Config Pina.6 = Input 'Mal Config Pina.7 = Input 'Geteilt Config Pinc.7 = Input 'DELETE Config Pinc.6 = Input 'AC Config Pinc.5 = Input '= Config Pinc.4 = Input 'Komma Config Pinc.3 = Input 'Shift Config Pinc.2 = Input 'x Hoch y Config Pinc.0 = Output ' Beleuchtung Portb.0 = 1 'Zahl 0 Portb.1 = 1 'Zahl 1 Portb.2 = 1 'Zahl 2 Portb.3 = 1 'Zahl 3 Portb.4 = 1 'Zahl 4 Portd.0 = 1 'Zahl 5 Portd.1 = 1 'Zahl 6 Portd.2 = 1 'Zahl 7 Portd.3 = 1 'Zahl 8 Portd.4 = 1 'Zahl 9 Portd.5 = 1 'Plus Portd.7 = 1 'Minus Porta.6 = 1 'Mal Porta.7 = 1 'Geteilt Portc.7 = 1 'Beleuchtung Portc.6 = 1 'AC Portc.5 = 1 '= Portc.4 = 1 'Komma Portc.3 = 1 'Shift Portc.2 = 1 'x Hoch y Dim Positionzeile As Integer Dim Positionspalte As Integer Dim Stelle As Integer Dim Ergebnis As Double Dim X As Integer Positionzeile = 1 Positionspalte = 1 Dim Rechnung$ As String * 15 Rechnung$ = String(15 , 65) Do If Positionspalte > 16 Then Positionzeile = 2 Waitms 50 End If If Positionzeile > 2 Then Positionzeile = 1 Waitms 50 End If If Pinb.0 = 0 Then Cursor Off Locate Positionzeile , Positionspalte ' Zahl 0 schreiben Lcd "0" Positionspalte = Positionspalte + 1 Rechnung$ = Rechnung$ + "0" Waitms 300 End If If Pinb.1 = 0 Then 'Zahl 1 schreiben Cursor Off Locate Positionzeile , Positionspalte Lcd "1" Positionspalte = Positionspalte + 1 Rechnung$ = Rechnung$ + "1" Waitms 300 End If If Pinb.2 = 0 Then Cursor Off Locate Positionzeile , Positionspalte Lcd "2" Positionspalte = Positionspalte + 1 Rechnung$ = Rechnung$ + "2" Waitms 300 End If If Pinb.3 = 0 Then Cursor Off Locate Positionzeile , Positionspalte Lcd "3" Positionspalte = Positionspalte + 1 Rechnung$ = Rechnung$ + "3" Waitms 300 End If If Pinb.4 = 0 Then Cursor Off Locate Positionzeile , Positionspalte Lcd "4" Positionspalte = Positionspalte + 1 Rechnung$ = Rechnung$ + "4" Waitms 300 End If If Pind.0 = 0 Then Cursor Off Locate Positionzeile , Positionspalte Lcd "5" Positionspalte = Positionspalte + 1 Rechnung$ = Rechnung$ + "5" Waitms 300 End If If Pind.1 = 0 Then Cursor Off Locate Positionzeile , Positionspalte Lcd "6" Positionspalte = Positionspalte + 1 Rechnung$ = Rechnung$ + "6" Waitms 300 End If If Pind.2 = 0 Then Cursor Off Locate Positionzeile , Positionspalte Lcd "7" Positionspalte = Positionspalte + 1 Rechnung$ = Rechnung$ + "7" Waitms 300 End If If Pind.3 = 0 Then Cursor Off Locate Positionzeile , Positionspalte Lcd "8" Positionspalte = Positionspalte + 1 Rechnung$ = Rechnung$ + "8" Waitms 300 End If If Pind.4 = 0 Then Cursor Off Locate Positionzeile , Positionspalte Lcd "9" Positionspalte = Positionspalte + 1 Rechnung$ = Rechnung$ + "9" Waitms 300 End If If Pind.5 = 0 Then Cursor Off Locate Positionzeile , Positionspalte Lcd "+" Positionspalte = Positionspalte + 1 Rechnung$ = Rechnung$ + "+" Waitms 300 End If If Pind.7 = 0 Then Cursor Off Locate Positionzeile , Positionspalte Lcd "-" Positionspalte = Positionspalte + 1 Rechnung$ = Rechnung$ + "-" Waitms 300 End If If Pina.6 = 0 Then Cursor Off Locate Positionzeile , Positionspalte Lcd "x" Positionspalte = Positionspalte + 1 Rechnung$ = Rechnung$ + "x" Waitms 300 End If If Pina.7 = 0 Then Cursor Off Locate Positionzeile , Positionspalte Lcd "/" Positionspalte = Positionspalte + 1 Rechnung$ = Rechnung$ + "/" Waitms 300 End If If Pinc.6 = 0 Then Cls Cursor Off Positionspalte = 1 Positionzeile = 1 Waitms 300 End If If Pinc.7 = 0 Then Portc.0 = 1 Wait 7 Portc.0 = 0 Wait 4 End If If Pinc.5 = 0 Then Rechnung$ = Rechnung$ + "=" Waitms 300 Lcd Ergebnis End If For Stelle = 1 To Len(rechnung$) If Mid(rechnung$ , Stelle , 1) = "+" Then Ergebnis = Val(mid(rechnung$ , 1 , Stelle)) + Val(mid(rechnung$ , Stelle + 1 , Len(rechnung$))) End If Next Stelle Loop
Kann man den Code noch irgendwie ändern dass ich wenigstens die vier Grundrechenarten in Bascom schaffe zu flashen ?
Mfg
David
config port b zeugs komt bei dir doch doppelt vor? hat das einen tieferen grund?
@Thomas$,
Dein Verfahren ist nicht umständlich - nur aufwendig. Man braucht dazu einen Formel-Interpreter, der aus dem String eine Datenstruktur macht. So wie hier vorgeführt:
http://www.delphipraxis.net/topic156836,0,asc,0.html
Dein Vorschlag belohnt den viel höheren Programmieraufwand mit dem Vorteil, auch kompliziertere Ausdrücke, auch mit Klammern usw., berechnen zu können.
@Dave,
für den Anfang würde ich nicht den aufwendigen Weg gehen, sondern einen ganz einfachen Rechner simulieren. Welche Tasten, hast Du Dir vorgestellt, soll das Teil haben?
Ciao,
mare_crisium
Hallo mare_crisium
Mir würde es schon reichen wenn ich die Zahlen von 0 bis 9 eingeben könnte.
Es wäre nicht schlecht wenn das ganze auch mit Kommazahlen und nicht nur ganzzahligen Zahlen funktionieren würde.
Bei den Rechenoperationen wäre plus,minus,geteilt,mal und wurzel nicht schlecht.
@Thomas
Ich denke ich habe die Portbs nur einmal konfiguriert.
Mfg
David
sorry hab mich irgendwie getäuscht
Hi,
ich hatte so ein ähnliches Projekt auch mal am Laufen und bin dort zu dem
Ergebniss gekommen, dass das Programm mit größeren Zahlen einfach
nicht umgehen kann/ ungenau wurde und viel zu viel Speicher verbraucht.
Ich meine auch, dass es iwie ein kleines Problem mit dieser E^-6
Darstellung gab. Ich bin mir deshalb nicht ganz sicher ob es so sinnvoll ist
den Taschenrechner in Bascom zu programmieren.
Grüße Furtion
Dave,
wenn ich so meinen Taschenrechner und Deine Vorstellungen angucke, dann brauchst Du folgende Tasten:
10 Stck für die Ziffern 0 bis 9,
1 für das Komma,
4 für die Rechenoperationen (Wurzel lassen wir erstmal weg),
1 für den Vorzeichenwechsel ("+/-")
1 für Reset /Clear ("C", löscht alles),
1 für Clear Eingabe ("CE", löscht nur die Eingabe) und
1 für "Lösche letztes Zeichen" ("CL" löscht nur das zuletzt eingebene Zeichen).
macht insgesamt 19. Es ist wichtig, das vorher festzulegen, weil es die Bedienung des Teils festlegt. Du wirst bald merken: Die Bedienerführung verursacht nachher im Programm mehr als doppelt soviel Aufwand, wie das eigentliche Rechnen.
Weil die Rechenoperationen (bis auf den Vorzeichenwechsel) immer zwei Zahlen mit einander verknüpfen, brauchst Du dafür zwei Speicher. Es ist praktisch, es so wie Du zu machen, und die beiden Zahlen als Strings zu speichern. Daneben brauchst Du auch einen Speicher für die Rechenoperation und einen Kommazähler. Die Rechenoperation kannst Du als ASCII-Zeichen oder als Nummer (0 = "+", 1 = "-" usw.) speichern. Der Kommazähler braucht nur von 0 bis 1 zu gehen. Er wird gebraucht, um zu merken, wenn der Bediener mehr als ein Komma pro Zahl eingeben will.
Wie man einen Zahlen-String in eine real-Variable umwandelt, habe ich in der angehängten .pdf-Datei aufgeschrieben. Wie immer: Es geht auch anders, aber damit kannst Du mal anfangen. Es ist praktisch, diesen Teil in eine Subroutine zu verpacken.
Wenn das Umwandeln klappt, musst Du Dich als nächstes um die Bedienerführung kümmern. Dabei geht's darum, auf jeden möglichen Tastendruck des Bedieners eine passende Reaktion einzubauen.
@Furtion,
gerade an der sauberen Programmierung der Benutzerführung beim Taschenrechner kann man viel über Ablaufsteuerungen lernen. Vor allem, dass man auf alles eine Reaktion vorgesehen haben muss, weil man das Verhalten eines Bedieners nie voraussehen kann. Insofern ist es doch nützlich, den Milliarden Taschenrechnern noch einen dazuzufügen.
Ciao,
mare_crisium
Dave,
wenn ich mir Deine Code so angucke, kann ich mir vorstellen, mit welchem Enthusiasmus Du Dich ans Programmieren gemacht hast. Darunter hat die Systematik etwas gelitten. Zuerst ist das nicht weiter schlimm, aber es wird später lästig, wenn's ans Fehlersuchen geht.
Deshalb habe ich 'mal aufgeschrieben, was man sich, bevor man zu Programmieren beginnt, zur Struktur des Programms so ausdenken kann, damit es schön übersichtlich und entwicklungsfähig wird.
Wenn Du damit was anfangen kannst, können wir's ja noch weiter verfeinern.
Ciao,
mare_crisium
Edit: Das pdf-Dokument noch mal neu erzeugt und dabei die Grafik des Programmablaufs entwirrt.
Edit: Anhang gelöscht wg. Upload-Limit.
Ich fand die Idee ganz witzig und habe mal Davids Programm etwas erweitert.
Funktionsumfang sollte ungefähr so sein wie von mare_crisium im PDF beschrieben.
Es können beim Compilieren über die SchalterCode:Const Ok = 1 Const Not_ok = 0 Const Yes = 1 Const No = 0 Const Op = 2 Const Minus = 3 $regfile = "m16def.dat" $crystal = 16000000 Const Print_ausgabe = No 'hier Yes/No um die Prints zu aktivieren Const Use_double = No 'hier Yes/No um mit Double/Single zu rechnen Const Enable_power = No 'hier Yes/No um den Power-Operator zu aktivieren 'Power und Double funktioniert nicht richtig, keine Ahnung warum #if Print_ausgabe = Yes $baud = 38400 #endif $hwstack = 32 $swstack = 32 $framesize = 64 Config Lcd = 20 * 4 Config Lcdpin = Pin , Db4 = Porta.3 , Db5 = Porta.2 , Db6 = Porta.1 , Db7 = Porta.0 , E = Porta.5 , Rs = Porta.4 ', Rw = Portc. 5 Dim Positionzeile As Byte Dim Positionspalte As Byte #if Use_double = Yes Dim Ergebnis As Double , Operand1 As Double , Operand2 As Double 'auskommentieren um nur Single zu rechnen #else Dim Ergebnis As Single , Operand1 As Single , Operand2 As Single 'auskommentieren, um Double zu rechnen #endif Dim Prta As Byte , Prtb As Byte , Prtd As Byte , Prtc As Byte 'die Masken der Ports, 1=wird verwendet, 0=wird nicht verwendet Dim Port_masken As Long At Prta Overlay 'Long liegt über allen 4 Masken Dim Alte_taste As Long Dim Tastea As Byte , Tasteb As Byte , Tasted As Byte , Tastec As Byte 'Reihenfolge nicht ändern, sonst passt das Overlay nicht mehr Dim Taste As Long At Tastea Overlay 'Long liegt über allen 4 Tasten-Ports Dim Taste_string As String * 32 'definiert, welche Funktion auf welchem Pin liegt Dim Taste_array(1) As Byte At Taste_string Overlay 'darüber ein Byte Array, damit man leichter eine Schleife drüber machen kann Dim Taste_index As Byte Dim Operator As String * 1 'das gefundene Operator Zeichen Dim Operator_pos As Byte 'Position des Operators in Rechnung$ Dim Rechnung$ As String * 33 'die gesamte Eingabe Dim String_length As Byte 'die Länge von Rechnung$ Dim Operand$(2) As String * 16 'die beiden Operanden Dim Check As Byte 'gültige Eingabe Dim Found As Byte 'alle Flags Operation Alias 0 'es wurde schon ein Operator eingegeben Comma_op1 Alias 1 'Komma in Operator 1 gefunden Comma_op2 Alias 2 'Komma in Operator 2 gefunden Minus_op1 Alias 3 'Operand 1 ist negativ Minus_op2 Alias 4 'Operand 2 ist negativ Prta = &B11000000 Prtb = &B00011111 Prtc = &B11110111 Prtd = &B10111100 Porta = Prta Portb = Prtb Portc = Prtc Portd = Prtd Initlcd Cls Cursor Off Locate 2 , 1 Lcd "Taschenrechner" Positionzeile = 1 Positionspalte = 1 ' 123456789 123456789 123456789 12 Position in Taste_string = Taste_index ' AAAAAAAABBBBBBBBDDDDDDDDCCCCCCCC Dies ist meine Tastenbelegung ' 01234567012345670123456701234567 geringfügig anders als die ursprüngliche #if Enable_power = Yes Taste_string = " */01234 789+ -56^ .=CD" 'C=Clear all, D=Delete ein Zeichen Prtc = &B11110111 ' 11101111 #else Taste_string = " */01234 789+ -56 .=CD" 'C=Clear all, D=Delete ein Zeichen Prtc = &B11110111 ' 11001111 #endif Prtd = &B10111100 ' 00111101 Prtb = &B00011111 ' 11111000 Prta = &B11000000 '00000011 'weiteres Zeichen hinzufügen: ' 123456789 123456789 123456789 12 'Taste_string = " */01234 789+ -56^ .=CD" neues Zeichen an eine Leerstelle setzen 'Prtc = &B11110111 ' 11001111 im zugehörigen Port eine 1 setzen 'Prtd = &B10111100 ' 00111101 'Prtb = &B00011111 ' 11111000 'Prta = &B11000000 '00000011 'im Select case taste_index für die Position im String ein case schreiben Porta = Prta 'setzen der PullUps Portb = Prtb 's.o. Portc = Prtc 's.o. Portd = Prtd 's.o. String_length = 0 Do Tastea = Pina And Prta Tasteb = Pinb And Prtb Tastec = Pinc And Prtc ' c d b a Tasted = Pind And Prtd '11110100 10111110 00011111 11000000 If Taste <> Port_masken Then If Taste <> Alte_taste Then Alte_taste = Taste Taste_index = 0 Check = Not_ok If Rechnung$ = "" Then Lcd Spc(20) Do If Port_masken.taste_index = 1 Then If Taste.taste_index = 0 Then Incr Taste_index Select Case Taste_index Case 9 To 13 : '01234 die Zahlen Check = Ok Case 19 To 21 : '789 Check = Ok Case 25 To 26 : '56 Check = Ok #if Enable_power = Yes Case 7 To 8 Or Taste_index = 22 Or Taste_index = 27: '*****/////+++++^^^^^ #else Case 7 To 8 Or Taste_index = 22: '*****/////+++++ #endif If Found.operation = No Then 'die Operatoren, außer '-' wegen Vorzeichen-Sonderbehandlung Check = Op Found.operation = Yes Operator_pos = String_length + 1 Operator = Chr(taste_array(taste_index)) End If Case 29 : '..... If Found.operation = No Then 'wenn noch kein Operator eingegeben wurde, ist das Komma im 1. Operanden If Found.comma_op1 = No Then Check = Ok Found.comma_op1 = Yes End If Else If Found.comma_op2 = No Then 'ansonsten im 2. Operanden Check = Ok Found.comma_op2 = Yes End If End If Case 24: '----- If String_length = 0 Then 'Fortsetzung der Berechnung mit letztem Ergebnis als Operand 1 If Found.operation = No Then 'dann muss der Operator als erstes Zeichen kommen, also kein Vorzeichen Check = Op Found.operation = Yes Operator_pos = String_length + 1 Operator = "-" End If Elseif Found.operation = Yes Then 'wenn schon ein Operator eingegeben wurde, ist das '-' ein Vorzeichen des 2. Operanden Found.minus_op2 = Yes Check = Minus Else Found.minus_op1 = Yes 'dann muss das Vorzeichen des 1. Operanden sein Check = Minus End If Case 32: 'D = Delete: ein zeichen löschen Positionspalte = Positionspalte - 1 Locate Positionzeile , Positionspalte : Lcd " " If Right(rechnung$ , 1) = "." Then If Found.operation = Yes Then Found.comma_op2 = No Else Found.comma_op1 = No End If Elseif Operator_pos = String_length Then Found.operation = No End If Decr String_length Rechnung$ = Left(rechnung$ , String_length) Check = Not_ok Case 31: 'C = Clear: alles löschen Cls 'alles zurücksetzen Positionspalte = 1 Positionzeile = 1 Rechnung$ = "" Found = 0 Operator_pos = 0 Check = Not_ok String_length = 0 Case 30: '===== If Operator_pos > 1 Then Decr Operator_pos 'Operand 1 endet links vom Operator Operand$(1) = Left(rechnung$ , Operator_pos) Operand1 = Val(operand$(1)) Operator_pos = Operator_pos + 1 'Operand 2 beginnt rechts vom Operator Else 'Fortsetzung einer Berechnung Operand1 = Ergebnis Operand$(1) = Str(operand1) Incr Operator_pos End If Operator_pos = String_length - Operator_pos Operand$(2) = Right(rechnung$ , Operator_pos) #if Print_ausgabe = Yes Print Operand$(1) ; Operand$(2) #endif Operand2 = Val(operand$(2)) Select Case Operator Case "+" : Ergebnis = Operand1 + Operand2 Case "-" : Ergebnis = Operand1 - Operand2 Case "*" : Ergebnis = Operand1 * Operand2 Case "/" : Ergebnis = Operand1 / Operand2 #if Enable_power = Yes Case "^" : Ergebnis = Power(operand1 , Operand2) #endif End Select Locate 2 , 1 : Lcd Spc(20) Locate 2 , 1 : Lcd Ergebnis : Locate 1 , 1 #if Print_ausgabe = Yes Print "ergebnis=" ; Ergebnis #endif Ergebnis = Operand1 ^ Operand2 Locate 2 , 20 : Lcd Ergebnis : Locate 1 , 1 Print "ergebnis=" ; Ergebnis Positionspalte = 1 'alles zurücksetzen, nur Ergebnis bleibt auf dem alten Wert Positionzeile = 1 Rechnung$ = "" Found = 0 'alle Flags auf 0 Operator_pos = 0 Check = Not_ok String_length = 0 End Select If Check <> Not_ok Then 'wenn die Eingabe erlaubt war, wird das Zeichen ausgegeben und an Rechnung$ angehangen Locate Positionzeile , Positionspalte ' Zahl 0 schreiben Lcd Chr(taste_array(taste_index)) Positionspalte = Positionspalte + 1 Rechnung$ = Rechnung$ + Chr(taste_array(taste_index)) Incr String_length #if Print_ausgabe = Yes Print "Rechnung=" ; Rechnung$ #endif End If Exit Do Decr Taste_index End If End If Incr Taste_index Loop Until Taste_index = 32 Waitms 200 'zum Tasten entprellen End If Else Alte_taste = Port_masken 'wenn keine taste mehr gedrückt ist (dann ist Taste = Port_Masken) wird Alte_Taste auch zurückgesetzt End If Loop End
Const Print_ausgabe = No 'hier Yes/No um die Prints zu aktivieren
Const Use_double = No 'hier Yes/No um mit Double/Single zu rechnen
Const Enable_power = No 'hier Yes/No um den Power-Operator zu aktivieren
verschiedene zusätzliche Funktionen aktiviert werden.
Wenn alles auf No steht, compiliert er bei mir knapp unter 4KB, sollte also auch in der Demo laufen.
Mit allem auf Yes braucht es schon 8KB.
Vielleicht schaut es sich mal einer an.
Gruß
Rolf
Hallo
Ich bin sehr dankbar für eure Antworten vor allem die von mare_crisium sind sehr hilfreich.
Leider werde ich in nächste Zeit eher weniger Zeit finden um das Projekt weiterzuführen.
Also werde ich mich erst ein bisschen später wieder melden.
Mfg
David
Lesezeichen