Hallo,
ich wuede gerne im uC prufen ob ich mehrere einsen oder nullen anliegen
habe (8bit). kenn mir jemand einen tip geben.
Machs mir glaub irgendwie bisschen umstaendlich.
Ich wuerde alle zusammenzaehlen und entweder:
>4 mehr einsen
<4 mehr nullen
==4 anzahl gleich
gehts irgendwie einfacher mit maskieren oder spezielle befehle. ich
programmiere in.
gruss
Du hast vergessen die Programmiersprache zu nennen ;P Und dann wäre die Info welche ControllerFamilie auch nett. :)
1 | char count_ones( char val ) |
2 | {
|
3 | char i; |
4 | for( i = 0; val; val <<= 1 ) |
5 | if( val & 0x80 ) |
6 | i++; |
7 | return i; |
8 | }
|
:
Bearbeitet durch User
Hallo, Einem Byte kann man die Werte nach folgneder Tabelle zuordnen:
1 | 0000 0000 < |
2 | 0000 0001 < |
3 | 0000 0010 < |
4 | 0000 0011 < |
5 | 0000 0100 < |
6 | 0000 0101 < |
7 | 0000 0110 < |
8 | 0000 0111 < |
9 | 0000 1000 < |
10 | 0000 1001 < |
11 | ... |
12 | 0000 1110 < |
13 | 0000 1111 = |
14 | 0001 0000 < |
15 | ... |
16 | 0001 1110 = |
17 | 0001 1111 > |
18 | 0010 0000 < |
19 | .... |
Also stell eine Tabelle (array, 256 Bytes) auf mit den korrekten Einträgen <,=,>, lies das Portbyte ein und verwende es als Index für den Zugriff auf die Tabelle. Geht maximal schnell, verbraucht dafür 256 Byte. Georg
Vielen Dank, funktioniert super. Könntest du mir noch erklären was da genau passiert?
Also hier: char count_ones( char val ) { char i; for( i = 0; val; val <<= 1 ) if( val & 0x80 ) i++; return i; }
hallo, habs jetzt nochmal auf dem bard probiert. become nicht dass richtige ergebnis. mache ich was falsch?
1 | int tmp = 0x00; // Global variable cnt with starting values |
2 | |
3 | void External_ISR()org 0x0003 ilevel 0 { // Interrupt rutine |
4 | EA_bit = 0; // Disable all Interrupts |
5 | tmp = 1; // Set variable tmp |
6 | EA_bit = 1; // Enable all Interrupts |
7 | }
|
8 | |
9 | int count_ones(int val) |
10 | {
|
11 | int i; |
12 | for( i = 0; val; val <<= 1 ) |
13 | if( val & 0x80 ) |
14 | i++; |
15 | return i; |
16 | }
|
17 | |
18 | void main() { // Main program |
19 | |
20 | int val = 0x00; // Variable for value of the port |
21 | int result = 0x00; |
22 | |
23 | |
24 | P0 = 0xFF; // Set P0 as high impedance input |
25 | P1 = 0xFF; // Set P1 as input |
26 | P2 = 0xFF; // Set P2 as input |
27 | P3 = 0xFF; // Set P3 as input |
28 | |
29 | IE = 0x81; // Setting the Interrupts: EA=1, EX0=1 --> just external interrupt enabled |
30 | |
31 | |
32 | while (1) |
33 | {
|
34 | |
35 | while (tmp == 1) |
36 | {
|
37 | val = P0; |
38 | result = count_ones(val); |
39 | |
40 | P1 = result; |
41 | |
42 | tmp = 0; |
43 | }
|
44 | }
|
45 | }
|
:
Bearbeitet durch User
Kannst du mir verraten, warum du mit dem externen Interrupt die Dinge schon wieder komplizierter machen musst, als unbedingt notwendig? Warum nicht beim ersten Versuch alles so einfach wie möglich, so dass man möglichst wenig Chancen auf Fehler hat? Hauptschleife { P0 einlesen - Anzahl Bits bestimmen - auf P1 ausgeben }. Fertig. Mehr braucht es für den ersten Versuch nicht. Alles darüber hinausgehende birgt nur wieder neue Möglichkeiten für Fehler, die mit dem eigentlich zu Testenden nichts zu tun haben.
1 | int tmp = 0x00; |
da fehlt ein volatile. FAQ: Was hat es mit volatile auf sich
:
Bearbeitet durch User
Abgesehen davon solltest du dir mal über Datentypen Gedanken machen. Einfach für alles "int" zu verwenden ist nicht nett dem µC gegenüber. Du treibst ihn damit in 16 Bit Verarbeitung rein, die nicht sein müsste. Dein Programm handelt im wesentlichen von Bytes. Dafür ist 'unsigned char' der Datentyp der Wahl, oder wenn du hast 'uint8_t'.
Tag, weil ich den Interrupt vorher getestet hatte. Interrupt raus gemacht, volatile rein gemacht. Keine Veraenderung...
marten schrieb: > Interrupt raus gemacht, volatile rein gemacht. Keine Veraenderung... ... die jetzige Version erneut zeigen. Aus eigener Erfahrung: Es gibt kein Programm, das einfach genug wäre als das man nicht blöde Fehler machen kann, die man dann auch selbst nicht sieht.
:
Bearbeitet durch User
Ich weiss ja nicht, wei die 8051 das sehen. Aber ...
1 | P1 = 0xFF; // Set P1 as input |
2 | |
3 | ...
|
4 | |
5 | P1 = result; |
ich würde das zumindest soweit korrigieren, dass ich P1 auf Ausgang setze, wenn ich was ausgeben will.
Karl Heinz schrieb: > ich würde das zumindest soweit korrigieren, dass ich P1 auf Ausgang > setze, wenn ich was ausgeben will. no passt schon, so macht man das bei 8051ern. Beitrag "Re: Ports AT89S8253" @Marten: was legst du denn an P0 an und was kommt an P1 raus? Hast du die Pegel mal nachgemessen?
Karl Heinz schrieb: > dass ich P1 auf Ausgang > setze Das gibt es bei den OC-Pins eines 8051 garnicht. Georg
1 | unsigned char count_ones(unsigned char val) |
2 | {
|
3 | unsigned char i; |
4 | for( i = 0; val; val <<= 1 ) |
5 | if( val & 0x80 ) |
6 | i++; |
7 | return i; |
8 | }
|
9 | |
10 | void main() { // Main program |
11 | |
12 | unsigned char val = 0x00; // Variable for value of the port |
13 | unsigned char result = 0x00; |
14 | |
15 | |
16 | P0 = 0xFF; // Set P0 as high impedance input |
17 | P1 = 0xFF; // Set P1 as input |
18 | P3 = 0xFF; // Set P3 as input |
19 | |
20 | |
21 | while (1) |
22 | {
|
23 | |
24 | if (P3.B2 == 0) |
25 | {
|
26 | while (P3.B2 == 0) |
27 | val = P0; |
28 | result = count_ones(val); |
29 | P2 = result; |
30 | }
|
31 | }
|
32 | }
|
:
Bearbeitet durch User
Wir arbeiten an einem Experimentierboard Easy8051B. An P0 sind Pushbuttons angeschlossen. Wir wollen die einsen, die an Port0 anliegen zaehlen und den wert dan an P1 ausgeben. Wenn ich z.B. zwei buttons druecke, habe ich zwei nullen und 6 einsen anliegen. dass heist ich will die binaere 2 an port1 ausgeben.
marten schrieb:
1 | P0 = 0xFF; // Set P0 as high impedance input |
Das kann 1. der Compiler nicht und 2. der Controller nicht 1. weil der Compiler Kommentare ignoriert 2. weil der 8051 einen Pullup eingebaut hat und nur nach GND treiben kann Es könnte natürlich bei den vielen 8051 Derivaten durchaus auch eines mit Richtingsregister geben. Das wäre aber ungeschickt... BTW: Welche Pegel hast du tatsächlich am P0?
was du willst, ist klar. Was du konkret als Fehler beobachtest ist unklar. Also nochmal: welches konkretes Bitmuster liegt an Port0 (mit Multimeter nachmessen) welches konkrete Bitmuster wird an Port2 ausgegeben? Dir ist auch klar, dass du B2 von Port 3 toggeln musst, damit was passiert?
marten schrieb: > Wenn ich z.B. zwei buttons druecke, habe ich zwei nullen und 6 einsen > anliegen. dass heist ich will die binaere 2 an port1 ausgeben. Wäre es dann nicht sinnvoll, die Nullen zu zählen? Wozu das Rumgehampel mit dem P3? Ich würde da einfach mal das hier vorschlagen:
1 | while (1) |
2 | {
|
3 | val = P0; |
4 | result = count_ones(val); |
5 | P2 = 8-result; // Anzahl der Nullen(!) berechnen... |
6 | }
|
:
Bearbeitet durch Moderator
marten schrieb: Ich gebs auf > while (1) > { > > if (P3.B2 == 0) > { > while (P3.B2 == 0) > val = P0; > result = count_ones(val); > P2 = result; > } > } > } da hast du doch schon wieder Nebenbedingungen! Was ist so schwer an
1 | while (1) |
2 | {
|
3 | val = P0; |
4 | result = count_ones(val); |
5 | P2 = result; |
6 | }
|
und wenn DAS funktioniert, dann wird ausgebaut! Aber nicht vorher. Ich meine das absolut und 100%-ig Ernst mit: so einfach wie nur irgendwie möglich! Im Grunde wäre ein
1 | while (1) |
2 | {
|
3 | P2 = count_ones( P0 ); |
4 | }
|
noch einfacher. Aber - geschenkt.
:
Bearbeitet durch User
Hallo marten, die Ports sind beim 89S8253 nach Reset automatisch auf 0xFF (Eingang), sie nochmal damit zu überschreiben schadet aber nicht. Ich weiß nicht welchen Compiler du verwendest, beim Keil werden die Portbit nicht P3.B2, sondern P3_2 beeichnet (in AT89S8253.h festgelegt). Habe dein Programm mal mit Keil ausprobiert. In der "if --- while" Kombination frißt es sich fest. Ohne das "while" läuft es wie gewollt. if (P3_2 == 0) {// while (P3_2 == 0) ;ausklammern oder löschen val = P0; result = count_ones(val); P2 = result; oder: P2 = count_ones(P0); } Ich hoffe es hilft dir weiter. Gruß. Tom
Ok. Habs geschnallt. unsigned char count_ones(unsigned char val) { unsigned char i; for( i = 0; val; val <<= 1 ) if( val & 0x80 ) i++; return i; } void main() { // Main program P0 = 0xFF; // Set P0 as high impedance input P2 = 0xFF; // Set P2 as input while (1) { P2 = count_ones( P0 ); } } Das funktioniert nicht.
Nullen zeahlen aber wohl :). Vielen viel dank fuer eure hilfe. Ich habe glaube einen Denkfehler mit der umgekehrten logic... unsigned char count_ones(unsigned char val) { unsigned char i; for( i = 0; val; val <<= 1 ) if( val & 0x80 ) i++; return i; } void main() { // Main program P0 = 0xFF; // Set P0 as high impedance input P2 = 0xFF; // Set P2 as input while (1) { P2 = (8 - count_ones( P0 )); } } Das geht. P0 high Pegel 3,1 V Taster nicht gedrueckt P0 low Pegel 0,1 V Taster gedrueckt P2 high Pegel 4,7 V Taster nicht gedrueckt P2 low Pegel 0,1 V Taster gedrueckt
Hallo marten, du hast weiter oben mal geschrieben "ich will die binaere 2 an port1 ausgeben". Dann mußt du P1 anstatt P2 schreiben: P1 = count_ones( P0 ); Das 8 - ... brauchst du nicht, die Routine von Peter gibt direkt die Anzahl der "1" zurück. Gruß. Tom
Mann es tut mir leid!!! Es funktioniert alles einwandfrei!!! Sorry, ich hab mich einfach von leuchten und nichtleuchten verwirren lassen!
TomA schrieb: > ausgeben". Dann mußt du P1 anstatt P2 schreiben: Das P1 anstelle von P2 ist optional. Anscheinend hat er zwischendurch seine Meinung geändert, an welchem Port ausgegeben werden soll. > Das 8 - ... brauchst du nicht, die Routine von Peter gibt direkt die > Anzahl der "1" zurück. Allerdings will er eigentlich die Anzahl an 0-en zählen. Denn er will gedrückte Tasten feststellen und die liefern ihm eine 0 am Portpin. Daher die Subtraktion von 8.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.