Forum: Mikrocontroller und Digitale Elektronik Pin-Code Abfrage


von Ti B. (duriel)


Angehängte Dateien:

Lesenswert?

Ich verzweifel gerade an einer einfachen Aufgabe..
Ich möchte  einen Code über mein Tastenfeld einlesen und diesen dann auf 
meinem Display ausgeben...
Weiß gar nicht wie viele for- und while-Schleifen ich in den letzten 
Stunden programmiert habe, vielleicht sehe ich es auch einfach nicht 
mehr..

Das LCD wird mit der Lib aus dem Mikrocontroller Tutorial betrieben, als 
Code lese ich BCD ein, die Funktion "Einlesen();" wandelt mit das dann 
in ein char Element um. Allerdings schaffe ich es nicht, den Code in ein 
int-Array zu packen ...
Die Zahlen zeigt es richtig an, nur das Umwandeln harpert. Ich habe den 
Code schon so einfach runtergehandelt wie es mir möglich war.

Bin neu im Bereich Mikrocontroller, bezweifle aber, dass ich bei einem 
"normalen" C-Programm mal derartige Schwierigkeiten hatte, so eine 
simple Aufgabe zu lösen...

Ich muss das Problem leider weiter geben und vielleicht auch ins Bett^^ 
Hoffe es kann sich jemand die Sache mal anschauen.

Vielen Dank

von Basti B. (basti195) Benutzerseite


Lesenswert?

So wie ich das verstehe möchtest du über X knöpfe die dazu entsprechende 
Zahl am Display anzeigen lassen?

möchtest du zb. eine 4bit zahl einlesen kannst du per Bitmanipulation 
einfach für jeden einzeln Button jeweils eine 1<<X verschieben.
so kannst du einfach eine zahl "zusammen basteln" ohne Größen Rechen und 
Speicher Aufwand.
zusätzlich könntest du über einen weiteren Button die zahl wieder 
zurücksetzten.

Beispiel
WHile(1){
if(PINA&(1<<1))
{
zahl = 1<<0; // 0 bit
}
if(PINA&(1<<2))
{
zahl = 1<<1;   // 1 bit
}
if(PINA&(1<<3))
{
zahl = 1<<2;   // 2 bit
}
if(PINA&(1<<4))
{
zahl = 1<<3;   // 3 bit
}



if(PINA&(1<<5))
{
zahl = 0;   REset
}

}

damit kannst du eine 4 bit zahl zusammen bauen. und zurücksenden.
evl noch einen 6 Button, um die zahl aufs Display zu senden.

edit:
Link für bitmanipulation
http://www.mikrocontroller.net/articles/Bitmanipulation

: Bearbeitet durch User
von Chris (Gast)


Lesenswert?

Hi,

ich finde den Code etwas umständlich. Du musst wissen, dass 
Zeichen(char) auch nur Zahlen sind. Das Stichwort ist hier 
ASCII-Tabelle. In Einlesen() bekommst du einen acht Bit Integer und 
machst daraus ein Zeichen.

Das geht kürzer:
1
uint8_t key = ....;
2
char zeichen = '0' + key;

Somit müsste auch klar sein, wie man aus einem Zeichen z.B. der Eins 
wieder die Zahl 1 machen kann.
1
uint8_t digit = zeichen - '0';

'0' steht hier für die Zahl 48. (Siehe ASCII-Tabelle)

von Schönschrift (Gast)


Lesenswert?

Für 1 << 3 schreibt man besser BIT_3. Vorher hat man einmalig das Ding 
#define BIT_3 0x08 gebaut. Das ist für die Lesbarkeit das Gleiche wie 
bei unsigned int und uint16_t auf dem 8bitter.

von Basti B. (basti195) Benutzerseite


Lesenswert?

Schönschrift schrieb:
> Für 1 << 3 schreibt man besser BIT_3

aber über <<3 kann man es einfacher verstehen, was hinter dem Befehl 
liegt.

von Schönschrift (Gast)


Lesenswert?

??? Bit3 ist Bit3,  wie soll das mit einem Shift einfacher zu verstehen 
sein? Der Portpin heißt auch nicht PINA<<3, oder?

Pack mal ein paar der Konstrukte in eine if Abfrage mit mehreren 
Bedingungen. Dann kommst du auch noch drauf. ;-)

von Karl H. (kbuchegg)


Lesenswert?

Ti Bo schrieb:

> Bin neu im Bereich Mikrocontroller, bezweifle aber, dass ich bei einem
> "normalen" C-Programm mal derartige Schwierigkeiten hatte, so eine
> simple Aufgabe zu lösen...

Wenn du 4 Zeichen speichern willst, dann solltest du
1
        uint8_t pin_code[3];
das Array auch mit einer Länge von 4 allokieren.

Genau aus dem Grund benutzt man zb Makros um derartige magische 
Konstanten nicht quer durch den Programmtext zu verstreuen, wo man sie 
nur schwer wiederfindet.

Mach dir ein
1
#define KEY_STROKES  4
und benutz dann KEY_STROKES überall an den Stellen, die von der Länge 
deines Codes abhängen. Und benutze for-Schleifen, wenn deine 
while-Schleife sich vernünftig in eine umformulieren lässt.
1
...
2
      lcd_string("Enter zum ");
3
      lcd_setcursor(0,4);
4
      lcd_string("Bestaetigen:");
5
      lcd_setcursor(0,2);
6
7
      uint8_t pin_code[KEY_STROKES];
8
      uint8_t i = 0;
9
      char pin;
10
11
      for( i = 0; i < KEY_STROKES; i++ ) {
12
        pin =  Einlesen();
13
        if(pin >= '0' && pin <= '9' ) {
14
          pin_code[i] = pin - '0';
15
          lcd_data(pin);
16
        }
17
      }
18
19
      lcd_clear();
20
      lcd_setcursor(0,1);
21
      lcd_string("Neuer Code:");
22
      lcd_setcursor(0,2);
23
24
      for( i = 0; i < KEY_STROKES; i++ ) {
25
        lcd_data (pin_code[0] + '0 ');
26
      }
27
    }
28
...

änderst du mal deine Meinung und willst 3 oder 5-stellige Codes anstatt 
der 4-stelligen, dann änderst du einfach das #define auf den Wert und 
den Rest des Programms passt der Compiler für dich an.

von Ti B. (duriel)


Lesenswert?

Muss man nicht Platz lassen für das Terminierungszeichen '\0' wie bei 
C??? also eine Arraylänge von 5?

Mit dem einlesen des Ascii, bzw BCD-Codes hatte ich keine Probleme, for 
schleifen hatte ich jede Menge ausprobiert, find ich auch am Besten, 
erst als es nicht funktioniert hatte hatte ich einen so umständlichen 
Text schreiben müssen...

Allerdings... Ich hab das Problem gelöst, aber erst, als ich für meine 
Schleifen (egal ob for oder while), static integer benutzt habe... 
Sobald ich static weglasse zählt der uC nicht mehr nach oben, warum auch 
immer. In meinem Programm macht sich das bemerkbar, dass er vom Pin-Code 
immer die erste Zahl überschreibt...

Wenn ich den Pin-Code jetzt zurücksetzen will hab ich Probleme damit, 
ich kann den Code einlesen, speichern und durch mit einer Bestätigung 
vergleichen. Wenn ich ihn aber zurücksetzten will schaff ich es nicht 
das Array zu leeren oder sonst was..

von Karl H. (kbuchegg)


Lesenswert?

Ti Bo schrieb:
> Muss man nicht Platz lassen für das Terminierungszeichen '\0' wie bei
> C??? also eine Arraylänge von 5?

Kommt drauf an.
Wenn du das Ergebnis der EInleserei als String auffassen willst, dann 
ja.
Wenn du aber sagst, das ist einfach nur ein Datenfeld, bei dem jeder 
Character einer Eingabe entspricht, dann brauchst du kein \0. Nicht 
jedes char Array ist auch automatisch ein String bzw. muss als String 
angesehen werden.

Ganz abgesehen davon, sind ja im char Array wegen
1
          pin_code[i] = pin - '0';
ja auch gar keine ASCII Zeichen gespeichert. Das ist einfach nur ein 
Array, in dem die einzelnen Ziffern des Codes gespeichert sind. Man 
hätte dort natürllich auch direkt die Digits in Form ihres ASCII Codes 
speichern können.


Hängt halt eben alles davon ab, wie du als Programmierer die Dinge sehen 
willst.

: Bearbeitet durch User
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
Noch kein Account? Hier anmelden.