Hallo,
Ich arbeite im Moment an folgendem Projekt:
Durch 8 Schalter wird eine 8bit Zahl an Port0 eingegeben.
Diese 8bit Zahl wird im nächsten Schritt durch Bitmasken in zwei 4bit
Zahlen geteilt.
Diese zwei "Tuppels" werden dann entweder (je nach Auswahl durch zweiten
Schalterblock) addiert, subtrahiert, multipliziert oder dividiert.
Anschließend wird die Zahl dezimal mithilfe der Division durch 10
(Zehner) und duch Division mit 10 und Rest (Einer) auf zwei 7-Segment
Anzeigen ausgegeben.
All das funktioniert auch super. Jedoch schaffe ich es nicht, beide
Stellen, also Zehner (4bit) und Einer (4bit) an einem einzelnen Port
auszugeben. Ich gebe im Moment die Zehner bei P3 und die Einer bei P1
raus. P3 benötige ich allerdings für etwas anderes.
Wie bekomme ich beide Zahlen auf einen Port, ohne dass sie sich
gegenseitig überschreiben?
Danke im voraus.
Edit: Im Bild mit dem Code sind Zehner und Einer vertauscht
> Diese 8bit Zahl wird im nächsten Schritt durch Bitmasken> in zwei 4bit Zahlen geteilt.
Das kann aber noch nicht alles gewesen sein.
Denn danach wirst du ja die oberen 4 Bits durch schieben erst mal
zurecht geschoben haben, damit du wieder schöne Zahlen hast, mit denen
du arbeiten kannst.
Und jetzt hast du eben das umgekehrte Problem.
Du hast 2 4-Bit Einheiten, die du zu 8 Bit zusammenführen musst, ehe du
sie am Port ausgibst.
Also die Zehner um 4 Bit 'nach oben' schieben, noch die Einer rein-Odern
und du hast 8 Bit, die du am Port ausgeben kannst.
PS: Was sollen diese _PNG Files sein?
Das ist das Bild von der Schaltung und dem Code falls notwendig.
Ich verstehe was du meinst. Da werde ich mich gleich einmal dransetzen
Edit: So klappts jetzt:
e = ((P0 & 0b11110000) >> 4) + (P0 & 0b00001111); // Addition der 4bits
P1 = (e % 10) | ((e / 10) << 4); // Dezimale Ausgabe in 8bit :)
Eine Frage hätte ich da noch.
Ich möchte, dass wenn jemand eine Zahl über 9 eingibt, also A - F (sind
ja Hexa Displays), dass dann nicht gerechnet wird. Die Zahl darf auf dem
Display stehen, jedoch soll nicht gerechnet werden. Dies funktioniert
auch, jedoch muss ich nach jeder if Abfrage erneut den Wert von Port0
berechnen, da er ja nicht wartet bis etwas gedrückt wurde, sondern dies
jederzeit geschehen kann. Ich finde das persönlich sehr unschön und
Verschwendung von Rechenleistung. Hat hier jemand eine bessere Idee?
Marcel Schwegler schrieb:> jederzeit geschehen kann. Ich finde das persönlich sehr unschön und> Verschwendung von Rechenleistung.
Kriegst du vom µC-Hersteller Geld zurück?
Wenn etwas jederzeit gerechnet wird, dann muss dieses jederzeit auch die
notwendigen Prüfungen enthalten.
Ich kann zwar dein Bild nicht sehen (poste doch bitte das nächste mal
Programmtext auch als Text. Du brauchst einfach nur dein C-File als
Attachment anhängen), aber wo ist da jetzt das Problem
1
...
2
while(1)
3
{
4
Zahl1=P0&0x0F;
5
Zahl2=(P0>>4)&0x0F;
6
7
if(Zahl1<10&&Zahl2<10)
8
{
9
Ergebnis=Zahl1+Zahl2;
10
....
11
}
12
else
13
Ergebnis=0;
14
15
P1=((Ergebnis/10)<<4)|(Ergebnis%10);
16
}
diese Bereichsprüfung sieht für mich jetzt nicht wirklich grossartig
problematisch aus. In Relation dazu sind die nachfolgenden DIvisionen
das viel größere 'Problem'.
// die beiden Zahlen sind gültig. Mach mit ihnen was es zu machen
11
// gibt
12
if(!P20&&!P21)
13
e=tup1+tup2;
14
15
elseif(P20&&!P21)
16
e=tup2-tup1;
17
18
elseif
19
....
20
}
21
else
22
e=0;
23
24
P1=......
du musst anfangen ein bischen zu schauen, wie du Dinge ineinander
schachteln kannst, welche Dinge du schon geprüft hast, welche WErte du
bereits wo berechnet hast, etc.
WEnn du nach einem Aufruf von berechne_tupel die Eingangslkeitungen
bereits in 2 Variablen aufgeteilt hast, dann willst du die auch weiter
verwenden und nicht erneut auf P0 direkt losgehen.
Genauso mit dem Ergebnis.
Du willst nicht an allen Ecken und Enden verstreut den Code haben, der
die Zehner und Einer auf den P1 rauspfriemelt. Das braucht es nur an
einer einzigen Stelle (bzw auch P3). Alles was du tun musst ist, in e
(deinem Ergebnis) einen entsprechenden Wert zu hinterlassen und diese
eine Codestelle gibt den dann aus.
solche Dinge sind zwar immer lieb gemeint, aber im Grunde recht sinnlos.
Du brauchst hier nicht prüfen, ob der Error eingeschaltet ist. Schalte
ihn einfach ab.
Wenn er schon abgeschaltet war, dann passiert nichts weiter. Mehr als
abschalten kannst du ihn nicht
1
P3=0x00;
Fass doch hier
1
elseif(P20&&P21)e=tup1/tup2;// Beide Tupples dividieren
elseP1=(e%10)|((e/10)<<4);// Dezimales Ergebnis an P1 ausgeben
die Dinge zusammen.
Du willst bei einer Subtraktion ein fehlerhaftes Ergebnis abfangen. Gut.
Aber das gehört zur Subtraktion dazu! Es ist nicht schlau derartige
Dinge ohne Grund auseinander zu reissen.
1
if(!P20&&!P21)
2
e=tup1+tup2;// Beide Tupples addieren
3
4
elseif(P20&&!P21){
5
e=tup1-tup2;// Beide Tupples subtrahieren
6
if(e>9)
7
e=0;
8
}
9
10
elseif(!P20&&P21)
11
e=tup1*tup2;// Beide Tupples multiplizieren
12
13
elseif(P20&&P21)
14
e=tup1/tup2;// Beide Tupples dividieren
15
16
P1=(e%10)|((e/10)<<4);// Dezimales Ergebnis an P1 ausgeben
Deine Kommentare:
1
e=tup1+tup2;// Beide Tupples addieren
ach echt? Das hätte ich mir nicht gedacht, dass hier die beiden Tupels
addiert werden, wenn ich mir den Code angesehen habe.
Erzähl mir nichts in einem Kommentar, was ich nicht auch im Code sehen
kann. Jeder Halbblinde kann anhand von
1
...tup1+tup2;
sehen, dass hier addiert wird. Das brauchst du nicht kommentieren. Denn:
Im besten Fall erzählt mir der Kommentar nichts neues (weil es eh schon
im Code steht), im schlimmsten Fall ist aber der Kommentar falsch (weil
er bei Codeänderungen nicht nachgezogen wurde!).
Als Faustregel: Im Code steht das WIE, im Kommentar steht das WARUM.
if(tup1<10&&tup2<10)// A - F sind keine zulaessigen Werte
15
{
16
P3=0x00;// Error abschalten, da zulaessige Werte
17
18
if(!P20&&!P21)e=tup1+tup2;// Addition
19
20
elseif(P20&&!P21){e=tup1-tup2;// Subtraktion
21
if(e>9){e=0;
22
P3=0x0E;}}// Error anzeigen, da falsches Ergebnis
23
24
elseif(!P20&&P21)e=tup1*tup2;// Multiplikation
25
26
elseif(P20&&P21)e=tup1/tup2;// Divison
27
28
P1=(e%10)|((e/10)<<4);// Dezimales Ergebnis an P1 ausgeben
29
}
30
else
31
{
32
P1=0x00;// Da Error, Ergebnis ausblenden
33
P3=0x0E;// Error anzeigen
34
}
35
}
36
}
Ein paar Kommentare hab ich für mich und die Allgemeinheit stehen
lassen, zur Orientierung. Den Rest hab ich jetzt mal versucht ein wenig
zu erklären.
Ich möchte auch noch gerne einen Error ausgeben, wenn die Subtraktion
"falsch" war. Das ist soweit auch im Code ersichtlich denke ich.
Allerdings flackert dann die Anzeige, da ich ja im gleichen Block auch
den Error jedesmal zurücksetze. Mir fällt da im Moment wirklich keine
schicke Lösung ein. Ansonsten ist das Programm erst einmal fertig. Ich
danke dir für die wirklich gute Hilfe und die Tipps
Marcel Schwegler schrieb:> Ich möchte auch noch gerne einen Error ausgeben, wenn die Subtraktion> "falsch" war. Das ist soweit auch im Code ersichtlich denke ich.> Allerdings flackert dann die Anzeige, da ich ja im gleichen Block auch> den Error jedesmal zurücksetze. Mir fällt da im Moment wirklich keine> schicke Lösung ein.
Dann darf das Abschalten eben nicht mehr generell passieren, sondern
nur, wenn du sicher bist, dass es keinen Fehler gab/gibt. Da gibt es
jetzt mehrere Möglichkeiten. Zb das hier
1
if(!P20&&!P21){
2
e=tup1+tup2;// Addition
3
P3=0x00;
4
}
5
6
elseif(P20&&!P21){
7
e=tup1-tup2;// Subtraktion
8
if(e>9){
9
e=0;
10
P3=0x0E;
11
}
12
else
13
P3=0x00;
14
}
15
16
elseif(!P20&&P21){
17
e=tup1*tup2;// Multiplikation
18
P3=0x00;
19
}
20
21
elseif(P20&&P21){
22
e=tup1/tup2;// Divison
23
P3=0x00;
24
}
ist eine Möglichkeit.
Aber man muss zugeben .. etwas langatmig.
Etwas kürzer wird es mit einer Hilfsvariablen
1
haveError=0;
2
3
if(!P20&&!P21)
4
e=tup1+tup2;// Addition
5
6
elseif(P20&&!P21){
7
e=tup1-tup2;// Subtraktion
8
if(e>9){
9
e=0;
10
haveError=1;
11
}
12
}
13
14
elseif(!P20&&P21)
15
e=tup1*tup2;// Multiplikation
16
17
18
elseif(P20&&P21)
19
e=tup1/tup2;// Divison
20
21
if(haveError)
22
P3=0x0E;
23
else
24
P3=0x00;
25
26
...
hat es eigentlich einen speziellen Grund, dass du laufend auf immer
wieder noch blödere Formatierungen verfällst, wie du die { - } bzw.
einzelne Statements anordnen kannst?
Gewöhn es dir an
1
if( Ausdruck )
2
abhängige Anweisung
das ist nicht einfacher oder änderungsfreundlicher, wenn du die
abhängige Anweisung in die selbe Zeile wie das if quetscht. Ein Programm
wartbar zu haben, hat sehr viel damit zu tun es optisch so zu gestalten,
dass man Dinge, Zusammenhänge auf einen Blick erfassen kann. Dazu gehört
auch, welche Anweisungen von welchen anderen Anweisungen abhängig sind.
Hier
1
elseif(P20&&!P21){e=tup1-tup2;// Subtraktion
2
if(e>9){e=0;
3
P3=0x0E;}}// Error anzeigen, da falsches Ergebnis
kann man überhaupt nichts auf einen Blick sehen. Das muss man erst mal
im Geiste umformatieren, um zu sehen, welche Anweisungen aufgrund
welcher anderen Anweisungen ausgeführt werden
1
elseif(P20&&!P21){
2
e=tup1-tup2;// Subtraktion
3
if(e>9){
4
e=0;
5
P3=0x0E;
6
}
7
}// Error anzeigen, da falsches Ergebnis
kann man das sehen. Jede Abhängigkeit ist eine weitere Einrückstufe. Ob
man die { jetzt am Zeilenede macht, oder ob man sie in eine eigene Zeile
macht, so wie hier
1
elseif(P20&&!P21)
2
{
3
e=tup1-tup2;// Subtraktion
4
if(e>9)
5
{
6
e=0;
7
P3=0x0E;
8
}
9
}// Error anzeigen, da falsches Ergebnis
ist Ansichtssache und wird einem in einer Softwarefirma meistens
vorgeschrieben. Letzteres hat den Vorteil, dass man die jeweils öffnende
{, die zu einer schliessenden } gehört, optisch leicht finden kann (und
umgekehrt). Aber auch die erste Variante ist nicht so schlecht, denn
anhand der Einrückung findet man auch so, wo die öffnende { sein muss
(sofern man sie nicht vergessen hat) und hat den Vorteil, dass der Code
nicht so in die Länge gezogen wird.
Aber in einem sind sich alle verbreiteten Stile einig. Das hier
1
elseif(P20&&!P21){e=tup1-tup2;// Subtraktion
2
if(e>9){e=0;
3
P3=0x0E;}}// Error anzeigen, da falsches Ergebnis
geht gar nicht. Denn da muss ich erst mal 30 Sekunden drauf starren, ehe
mir klar wird, wie da die Verschachtelungen sind. Das ist einfach nur
ein strukturloser Haufen Buchstaben.
Aber so flackert die Anzeige doch immernoch, oder hab ich jetzt einen
Denkfehler? Beim ausprobieren hat es jedenfalls geflackert..
Ich weiß bescheid mit der Formatierung. Mache ich auch normalerweise
nicht, jedoch wollte ich es unbedingt so schmal wie möglich halten. War
eine blöde Idee, ich gebs zu ;)
>> Aber so flackert die Anzeige doch immernoch, oder hab ich jetzt einen> Denkfehler? Beim ausprobieren hat es jedenfalls geflackert..
Wie soll da was flackern?
Edit:
Oder hast du etwa das Rücksetzen von P3 am Anfang der Schleife drinn
gelassen? Die muss natürlich raus! P3 wird am Ende der ganzen
Berechnungen abhängig von haveError entwedder gesetzt oder nicht
gesetzt. Aber es kann nicht vorkommen, dass es zwischendurch auf 0
gesetzt wird um gleich darauf wieder auf 0x0E zu gehen.
Ausserdem: das ganze läuft so schnell ab, ich bezweifle ernsthaft, dass
du da irgendwo ein Flackern sehen kannst. Du bist ja nicht Superman.
Marcel Schwegler schrieb:>> haveError = 0; <------ Wird hier nicht sofort beim naechsten> Durchlauf wieder der Error> ausgeschaltet?
Ja, und?
macht ja nix.
Das siehst du ja optisch nicht, dass die Variable einen Wert bekommen
hat.
> if( haveError )> P3 = 0x0E;> else> P3 = 0x00;
erst hier siehst du es! Wenn P3 entsprechend gestellt wird.
Und das wird immer gleich gestellt, wenn ein Error vorliegt.
Solange aber die Fehlersituation vorliegt, HAT haveError an dieser
Stelle immer den Wert 1. Das haveError zwischendurch auch mal 0 war, ist
uninteressant. Entscheidend ist der Wert an DIESER Stelle! Und der ist
1, wenn die Subtraktion einen Fehler festgestellt hat.
Ahhhhh ich glaub jetzt verstehe ich :D
Werds nochmal testen
Edit: Klappt jetzt!
Noch ein Problem...Mir fällt gerade auf, dass bei Multiplikationen, aber
nur dann, die Zehnerstelle manchmal um 2 Stellen verschoben ist.
Beispielsweise ergibt 4*8 = 52 statt 32. 8*8 ergibt aber wieder 64. Hä??
Marcel Schwegler schrieb:> Ahhhhh ich glaub jetzt verstehe ich :D> Werds nochmal testen>> Edit: Klappt jetzt!>> Noch ein Problem...Mir fällt gerade auf, dass bei Multiplikationen, aber> nur dann, die Zehnerstelle manchmal um 2 Stellen verschoben ist.> Beispielsweise ergibt 4*8 = 52 statt 32. 8*8 ergibt aber wieder 64. Hä??
Teste das mal systematisch.
Könnte es sein, dass beim Anschliessen der Dekoder ein Fehler passiert
ist und da 2 Leitungen (Bit 1 und Bit 2 von der Zehner-Anzeige)
irrtümlich vertauscht wurden?
> die Zehnerstelle manchmal um 2 Stellen verschoben ist
wie kommst du auf verschoben
1
Binär 5 0101
2
Binär 3 0011
3
^^
4
**
eine Vertauschung der beiden Spalten könnte das erklären.
Oh mein Gott du bist echt ein Held. Auf soetwas naheliegendes wäre ich
ewige Zeiten nicht gekommen. Ich habe den Fehler im Code vermutet. Aber
okay, es klappt jetzt wirklich alles. Für diese tatkräfitge
Unterstützung muss ich wirklich ein besonders großen Dank aussprechen.
Einige Tipps und ein paar Erfahrungswerte kann man daraus auf jedenfall
mitnehmen. Dankeschön!