Forum: Mikrocontroller und Digitale Elektronik LCD Ausgabe (Erhöhen einer Variable durch Signal am Eingang)


von Laura (Gast)


Lesenswert?

Hallo Freunde=),

ich sitze gerade an einem Projekt, mit dem ich über den ATMega8 einen 
LCD (HD44780)ansteuern möchte. Die Ausgabe klappt soweit, leider schaffe 
ich es nicht ein anliegendes Signal (Taster) am PORTC durch den ATMega 
zum LCD zu schicken.

PortB wird hierbei als Eingang definiert, Pin 1 besitzt die Wertigkeit 
1, Pin 2 Wertigkeit 2 usw. usf. Somit ergibt sich bei aktivierten Pin1 
und Pin2 eine 3. (Binär zu Dezimal). Problem hierbei ist, das wir eine 
Variable haben, welche direkt um die Wertigkeit erhöht werden soll.

Sprich;

i = 0;

Wenn An Pin1 nun ein high Signal anliegt, so wird i um 1 inkrementiert, 
bei Pin2 um 2, Pin3 um 4, Pin4 um 8.


Der Code sieht folgendermaßen aus:
1
int i;
2
3
DDRC = 0x00 // Port C als Eingang definieren
4
5
If (PC1==1)
6
{
7
 i = i+1
8
}
9
10
If (PC2==1)
11
{
12
 i = i+2
13
}
14
If (PC3==1)
15
{
16
 i = i+4
17
}
18
...


Auch die Ausgabe von der Variablen I stellt kein Problem dar, bei dem 
eben genannte code jedoch wird die Zahl unabhängig von dem 
Eingangssignal leider nicht erhöht.


Wäre für jede Anregung dankbar.


bussi Laura

von Karl H. (kbuchegg)


Lesenswert?

Laura schrieb:

> Der Code sieht folgendermaßen aus:

Bitte poste ihn vollständig.

>
>
1
> 
2
> int i;
3
> 
4
> DDRC = 0x00 // Port C als Eingang definieren
5
> 
6
> If (PC1==1)
7
> {
8
>  i = i+1
9
> }
10
> 
11
> If (PC2==1)
12
> {
13
>  i = i+2
14
> }
15
> If (PC3==1)
16
> {
17
>  i = i+4
18
> }
19
> ...
20
>
>
>
> Auch die Ausgabe von der Variablen I stellt kein Problem dar, bei dem
> eben genannte code jedoch wird die Zahl unabhängig von dem
> Eingangssignal leider nicht erhöht.

Hast du deine ganze Programlogik in eine Schleife gepackt?
Wenn nicht: Du hast nach starten des Programms ein paar Nanosekunden 
Zeit die Taste zu drücken (oder du drückst sie bereits bevor das 
Programm startet). Bist du wirklich so schnell?

(Aber auch in einer Schleife wird das nicht gehen. Der µC arbeitet die 
Schleife viele Tausend male in der Sekunde ab. So schnell bist du nicht, 
dass du den Taster nur für einen Schleifendurchlauf gedrückt halten 
kannst)

Aber zeig jetzt erst mal dein komplettes Programm.

von Karl H. (kbuchegg)


Lesenswert?

> If (PC1==1)

Seit wann fragt man den ein Portpin so ab?

if( PINC & ( 1 << PC1 ) )

aber das ist noch nicht alles, du brauchst eine Schleife.

von MagIO (Gast)


Lesenswert?

i = i + (portc & 7) ist auch ne Idee. Wenn der Code auch noch 
sicherstellen muss, dass nur eine Taste gedrückt wird, dann muss man eh 
beide Ansätze nochmal überdenken.

von Volker S. (volkerschulz)


Lesenswert?

...und, je nachdem wie die Taster angeschlossen sind, muss man 
vielleicht gar auf ein LOW checken... ;)

Volker

von Laura (Gast)


Lesenswert?

Guten Abend :)

vielen Dank für die zahlreichen Antworten, haben mir sehr 
weitergeholfen. Nun muss ich doch etwas ausschwenken.

Durch PortD bekomme ich ein codiertes Signal, welches zuerst decodiert 
wird und über die ersten 4 Pins an PortB ausgegeben wird. Die 4 Bits 
ergeben einen dem Binärcode entsprechenden Zahlenwert wie z.b.  (Binär) 
1 0 1 1 = 11 (Dezimal). Diese verbinde ich parallel mit den letzten 4 
Pins von PortB, welche als Eingang defniniert werden müssen.

Nun das Problem :-(, will den Zustand an allen Pins(Pin4 - Pin7) 
einlesen (einmalig, bis sich etwas ändert), bearbeiten und als 
Dezimalzahl auf dem LCD-Display ausgeben. Alternativ könnte die Abfrage 
auch zyklisch? laufen, also alle 2 Sekunden wird der Wert eingelesen und 
ausgegeben. Wichtig hierbei wäre mir, dass wenn möglich kein Interrupt 
verwendet wird, da diese in anderen Programmteilen schon verwendet 
werden.

Was bei dem versuchten Beispiel noch fehlt, ist zum Einen die 
Schleifenbedingung wie auch die Eingangs/Ausgangsdefinierung von PortB.

Danke nochmals für Eure investierte Zeit, freue mich auf neue Anregungen 
und Ansätze.
1
#include <avr/io.h>
2
#include "lcd-routines.h"
3
4
5
int main(void)
6
{
7
    lcd_init();
8
  int i;
9
  
10
  if( PINC & ( 1 << PC1 ) )
11
  {
12
     i=i++
13
  }
14
  
15
  if( PINC & ( 1 << PC2 ) )
16
  {
17
     i=i+2
18
  }
19
  
20
  if( PINC & ( 1 << PC3 ) )
21
  {
22
     i=i+4
23
  }
24
  
25
  if( PINC & ( 1 << PC4 ) )
26
  {
27
     i=i+8
28
  }
29
 
30
  char Buffer[20];
31
  
32
 
33
  toa( i, Buffer, 10 );
34
  lcd_string( Buffer ); 
35
 
36
  
37
 
38
    while(1)
39
    {
40
    }
41
 
42
    return 0;
43
}




bussi Laura

PS: Was mir sonst noch einfallen würde, wäre eine 
Case-Fallunterscheidung je nach String, da im späteren Stadium des 
Projekts nur 4-6 Fälle möglich sind.

von Laura (Gast)


Lesenswert?

Guten Morgen =)


hab nochmal eine Nacht darüber geschlafen, der jetzige Code (Vorerst nur 
mit einem PIN, anstatt 4) sieht wie folgt aus:
1
#include <avr/io.h>
2
#include <stdlib.h>
3
#include "lcd-routines.h"
4
#include <util/delay.h>
5
6
int i = 0;
7
 
8
int main(void)
9
{
10
   DDRC = 0x00;
11
  
12
 lcd_init();
13
 while(1)
14
    {
15
 if ( PINC & ( 1 << PC1 ) )
16
  {
17
     i=i++;
18
     _delay_ms(1000);
19
  
20
  
21
  char Buffer[20];
22
  
23
 
24
  itoa( i, Buffer, 10 );
25
  lcd_string( Buffer ); 
26
} 
27
28
29
 
30
    
31
    }
32
 
33
    return 0;
34
}

Leider reagiert der mega8 weder auf das Eingangssignal, noch 
aktualisiert er die Zahl am Display.

Sollte ja so aussehen:
Sequenz 1 : 0
Sequenz 2 : 1 (Wenn an dem Pin ein high Signal anliegt)
Sequenz 3 : 1 (Wenn Low)
Sequenz 4 : 2 (Wenn high)
usw usf.

So sieht es momentan aus:
Sequenz 1 : 1
Sequenz 2 : 12
Sequenz 3 : 123
(Unabhängig vom Eingangssignal)

Bin echt am Ende. vielleicht weiß jemand von Euch weiter.

bussi laura

von Karl H. (kbuchegg)


Lesenswert?

Laura schrieb:

> So sieht es momentan aus:
> Sequenz 1 : 1
> Sequenz 2 : 12
> Sequenz 3 : 123
> (Unabhängig vom Eingangssignal)

unabhängig kann nicht sein.
Da wird wohl der Pin ständig auf High liegen. Und jedesmal wenn die 
Abfrage

 if ( PINC & ( 1 << PC1 ) )

den Pin als High vorfindet, wird i um 1 erhöht.

Und da du die Zahlenwerte nicht übereinander schreibst, sondern 
hintereinander, taucht eben dieses Sequenz auf deinem LCD auf.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Bist du sicher, dass _delay_ms(1000) - hardwaremäßig - eine Sekunde lang 
Däumchen dreht? _delay_ms(1000) ist zunächst mal nur eine 
Programmanweisung. Die ist so nur wirksam, wenn 1. die Hardware passend 
beschaltet und eingestellt ist und 2. die Übersetzung entsprechend 
gemacht wurde. Näheres siehe 
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Warteschleifen_.28delay.h.29

Bist du sicher, dass du die Taste active high angeschlossen hast? Vom 
Programm oben her, braucht deine Schaltung einen externen 
Pull-Down-Widerstand. Ist der vorhanden? Näheres siehe 
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Tasten_und_Schalter

Bist du sicher, dass du die Taste in weniger als 1s wieder los lässt, 
damit keine Mehrfachzählung auftritt? Du könntest diesen Punkt mit einer 
Programmerweiterung entschärfen, indem du nach der Registrierung eines 
Tastendrucks wartest, bis die Taste wieder losgelassen wurde. Bzgl. 
Tasten schau dir auch das Thema Entprellung an.

von MagIO (Gast)


Lesenswert?

Ich nehme mal an, dass PC von 0 bis 7 geht, oder? Programmiere gerade 
nen anderen Controller ;o)


int main(void)
{
   DDRC = 0x00;

 lcd_init();
 while(1)
    {
 if ( PINC & ( 1 << PC1 ) )
 // if (PINC & 14) prüft alle 3 Pins gleichzeitig
 // kann man ggf auch in ein switch ( PINC & 14 ) umwandeln,
 // damit kann man dann nämlich das drücken mehrerer Tasten prüfen und
 // ggf. ignorieren
  {
     i=i++;
     // das wird zwar vom Compiler wegoptimiert, ist aber trotzdem 
Unsinn.
     // i++ schreibt das Ergebnis immer in i zurück, die Zuweisung 
bringt
     // also nix.
     // abgesehen davon, für alle 3 Pins dann
     i += ( PINC & 14 )>>1

     _delay_ms(1000);


  char Buffer[20];
  // sowas macht man in der Regel außerhalb der Schleife.

  itoa( i, Buffer, 10 );
  // wofür steht die 10?
  lcd_string( Buffer );
}




    }

    return 0;
    // kann man sich sparen, da es eh eine Endloss-Schleife ist.
    // Ggf int main in void main umwandeln.
}

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.