Forum: Mikrocontroller und Digitale Elektronik Programm mit mehrdimensionalem Array


von Andi (Gast)


Lesenswert?

Hallo,
ich bin gerade dabei ein Programm zuschreiben, welches Tastereingaben, 
welche ich auf dem STK500 tätige in eine Art Wertetabelle schreibt und 
anschließend alle Elemente nacheinander auf einem LCD ausgibt. Hier ist 
mein vorläufiges Programm:
1
#include <avr/io.h>
2
#include <util/delay.h>  
3
#include "lcd-routines.h"
4
#include <stdbool.h>
5
#include <avr/interrupt.h>
6
#include <stdio.h>        //nötig zur Benutzung von sprintf-Funktion
7
8
9
10
11
12
char buffer[20];
13
14
uint8_t lauf;
15
uint8_t array[2][10]= { {0,1,2,3,4,5,6,7,8,9}, {} };    //array mit zwei Spalten und 10 Zeilen
16
17
    
18
19
20
21
22
23
24
void delay_ms(uint16_t ms)
25
{
26
  while(ms>0)
27
  {
28
    _delay_ms(1);
29
    ms--;
30
  }
31
}
32
33
34
35
void befuellen(void)
36
{
37
  uint8_t eingabe, einlesen=0;
38
  
39
  for(lauf=0; lauf <10; lauf++)
40
  {
41
  
42
    PORTB &= ~(1<<PB7);    //LED7 an
43
    delay_ms(1000);
44
    array[1][lauf]= PIND;    //Derzeitiges Eingangsregister jeweiligem Array-Element zuordnen
45
46
    delay_ms(100);
47
    PORTB |= (1<<PB7);    //LED7 aus
48
    delay_ms(1000);
49
    
50
  }
51
  
52
  ausgabe();
53
}
54
55
56
void ausgabe(void)
57
{
58
  uint8_t i, ausgeben;
59
60
  for(i=0; i<10; i++)
61
  {
62
    ausgeben= array[1][i];    //Array-Elemente nacheinander ausgeben
63
    PORTB = ausgeben;      //Eingangsregister zur Kontrolle auf LEDs ausgeben
64
    lcd_setcursor(0,1);
65
    itoa(ausgeben, buffer, 2);  //duale Ausgabe des Eingangsregister auf dem LCD
66
    lcd_string(buffer);
67
    delay_ms(1000);
68
  }
69
}  
70
71
  
72
  
73
int main(void)
74
{
75
76
  lcd_init();
77
  DDRB |= 0xFF;  //alle Pins als Ausgang
78
  DDRD = 0x00;  //Alle Pins als Eingang
79
  PORTB |= 0xFF;  //alle LEDs aus
80
81
  
82
  
83
  
84
  
85
86
            
87
  while(1)
88
  {
89
    if(!(PIND & (1<<PD7)))
90
    {              //Wenn Taster eine Sekunde lang gedrückt
91
      delay_ms(1000);
92
      befuellen();
93
      
94
    }
95
96
    
97
  }
98
99
100
101
}

Das Programm funktioniert eigentlich so weit. Nur eine Kleinigkeit geht 
noch nicht so wie gewünscht. Und zwar wird das Drücken des Tasters an 
PD7 nicht richtig auf dem LCD ausgegeben. Auf dem LCD wird immer eine 1, 
also nicht gedrückter Taster ausgegeben. Im Array wird das drücken aber 
als eine 0, also richtig abgespeichert. Das erkenne ich am richtigen 
Blinken der LEDs. Der Fehler liegt also nicht am Array, sondern an der 
Ausgabe auf dem LCD.

Wer kann mir sagen warum das so ist?

Gruß

von Karl H. (kbuchegg)


Lesenswert?

Ich denke, da spielen mehrere Komponenten zusammen.
Einer davon ist
1
    itoa(ausgeben, buffer, 2);  //duale Ausgabe des Eingangsregister auf dem LCD

das "Problem" mit itoa ist, dass es keine führenden 0-en ausgibt. d.h. 
unter Umständen springt auf deiner Anzeige die Ausgabe hin und her, je 
nachdem welchen Taster du tatsächlich drückst. Und du verwechselst das 
mit falschen Werten, weil die nächste Ausgabe die vorhergehende nicht 
komplett überschreibt.

Sorg dafür, dass du immer eine Umwandlung des uint8_t auf 8 Bit 
bekommst, also inklusive führenden 0-en und teste dann nochmal.
1
void toBin( uint8_t zahl, char *Buffer )
2
{
3
  uint8_t i;
4
5
  for( i = 0; i < 8; i++ ) {
6
    Buffer[7-i] = zahl % 2;
7
    zahl = zahl / 2;
8
  }
9
  Buffer[8] = '\0';
10
}

und diese Funktion benutzt du anstelle von itoa
1
    ...
2
    lcd_setcursor(0,1);
3
    toBin(ausgeben, buffer);
4
    lcd_string(buffer);
5
    ...

damit solltest du erst mal alle 8 Bit von ausgeben sehen und das müsste 
dann mit deiner LED-Anzeige an PORTB übereinstimmen. Nicht ins Boxhorn 
jagen lassen. Je nachdem wie deine LED angeschlossen sind, bedeutet eine 
1 am LCD nicht zwangsläufig, dass die LED leuchten muss. Es kann auch 
umgekehrt sein. Aber es muss auf jeden Fall eine 1:1 Korrelation 
zwischen der Anzeige und dem Leuchten bzw. Nichtleuchten der LED geben.

von Andi (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> das "Problem" mit itoa ist, dass es keine führenden 0-en ausgibt

Diese Aussage leuchtet mir ein.

Karl Heinz Buchegger schrieb:
> void toBin( uint8_t zahl, char *Buffer )
> {
>   uint8_t i;
>
>   for( i = 0; i < 8; i++ ) {
>     Buffer[7-i] = zahl % 2;
>     zahl = zahl / 2;
>   }
>   Buffer[8] = '\0';
> }

Ich verstehe diesen Programmausschnitt nicht ganz bzw. habe wohl noch 
nie so eine Programmierschreibweise gesehen. Man übergibt ja beim 
Funktionsaufruf von toBin die Anfangsadresse des ersten Elements von 
buffer an den Pointer *Buffer. Soweit steig ich noch mit. Aber in der 
Funktion toBin tust du jetzt so, als ob Buffer kein Pointer sondern ein 
Array ist. Vielleicht kann mich ja da jemand genauer aufklären...

Aus meiner Sicht müsste die Funktion to Bin so aussehen:
1
void toBin( uint8_t zahl, char *Buffer )
2
{
3
  uint8_t i;
4
5
  for( i = 0; i < 8; i++ ) {
6
    *(Buffer+7-i) = zahl % 2;
7
    zahl = zahl / 2;
8
  }
9
   *(Buffer+8)= '\0';
10
}

Trotz allem habe ich das Programm nun nach deinen Vorschlägen abgeändert 
und dabei die Funktion toBin einmal nach deiner und einmal nach meiner 
Schreibweise eingefügt. Das Ergebnis ist beides mal das selbe. Und zwar 
erscheint auf der LCD-Anzeige die Zeichenkette "|| || || || || || || || 
||". Ich habe jetzt mal nach dem genauen ASCII-Code des Zeichens "||" in 
der ASCII-Tabelle gesucht um diesem Problem auf den Grund zu gehen, aber 
irgendwie kann ich kein so ein Zeichen finden.

Hier mein vorläufiges Programm:
1
#include <avr/io.h>
2
#include <util/delay.h>  
3
#include "lcd-routines.h"
4
#include <stdbool.h>
5
#include <avr/interrupt.h>
6
#include <stdio.h>        //nötig zur Benutzung von sprintf-Funktion
7
8
9
10
11
12
char buffer[20];
13
14
uint8_t lauf;
15
uint8_t array[2][10]= { {0,1,2,3,4,5,6,7,8,9}, {} };    //array mit zwei Spalten und 10 Zeilen
16
17
    
18
19
20
21
22
23
24
void delay_ms(uint16_t ms)
25
{
26
  while(ms>0)
27
  {
28
    _delay_ms(1);
29
    ms--;
30
  }
31
}
32
33
34
35
36
void toBin( uint8_t zahl, char *Buffer )
37
{
38
  uint8_t i;
39
40
  for( i = 0; i < 8; i++ ) {
41
    *(Buffer+7-i) = zahl % 2;
42
    zahl = zahl / 2;
43
  }
44
   *(Buffer+8)= '\0';
45
}
46
47
48
49
50
void befuellen(void)
51
{
52
  
53
  
54
  for(lauf=0; lauf <10; lauf++)
55
  {
56
  
57
    PORTB &= ~(1<<PB7);    //LED7 an
58
    delay_ms(1000);
59
    array[1][lauf]= PIND;    //Derzeitiges Eingangsregister jeweiligem Array-Element zuordnen
60
61
    delay_ms(100);
62
    PORTB |= (1<<PB7);    //LED7 aus
63
    delay_ms(1000);
64
    
65
  }
66
  
67
  ausgabe();
68
}
69
70
71
void ausgabe(void)
72
{
73
  uint8_t i, ausgeben;
74
75
  for(i=0; i<10; i++)
76
  {
77
    ausgeben= array[1][i];    //Array-Elemente nacheinander ausgeben
78
    PORTB = ausgeben;      //Eingangsregister auf LEDs ausgeben
79
    lcd_setcursor(0,1);
80
       toBin(ausgeben, buffer);
81
      lcd_string(buffer);
82
    delay_ms(1000);
83
  }
84
}  
85
86
  
87
  
88
int main(void)
89
{
90
91
  lcd_init();
92
  DDRB |= 0xFF;  //alle Pins als Ausgang
93
  DDRD = 0x00;  //Alle Pins als Eingang
94
  PORTB |= 0xFF;  //alle LEDs aus
95
96
  
97
  
98
  
99
  
100
101
            
102
  while(1)
103
  {
104
    if(!(PIND & (1<<PD7)))
105
    {              //Wenn Taster eine Sekunde lang gedrückt
106
      delay_ms(1000);
107
      befuellen();
108
      
109
    }
110
111
    
112
  }
113
114
115
116
}

Gruß

von Karl H. (kbuchegg)


Lesenswert?

Andi schrieb:

> Ich verstehe diesen Programmausschnitt nicht ganz bzw. habe wohl noch
> nie so eine Programmierschreibweise gesehen. Man übergibt ja beim
> Funktionsaufruf von toBin die Anfangsadresse des ersten Elements von
> buffer an den Pointer *Buffer. Soweit steig ich noch mit. Aber in der
> Funktion toBin tust du jetzt so, als ob Buffer kein Pointer sondern ein
> Array ist. Vielleicht kann mich ja da jemand genauer aufklären...

C:

Ein Array wird an eine Funktion übergeben, indem die Startadresse des 
Arrays übergeben wird. Also ein Pointer.


> Aus meiner Sicht müsste die Funktion to Bin so aussehen:
>
> void toBin( uint8_t zahl, char *Buffer )
> {
>   uint8_t i;
>
>   for( i = 0; i < 8; i++ ) {
>     *(Buffer+7-i) = zahl % 2;

Ist völlig identisch zu
    Buffer[7-i]

da ich aber weiß, dass mir der Aufrufer ein Array übergeben hat 
(übergeben muss) verwende ich hier lieber die Array-Syntax, da ich sie 
an dieser Stelle klarer halte.

Eine Funktion kann grundsätzlich nicht unterscheiden, ob der Pointer den 
sie bekommt zu einem einzelnen Speicherzelle verweist oder zu einem 
Array. Daher muss eine Funktion grundsätzlich immer darauf vertrauen, 
dass ihr Aufrufer das schon richtig macht.

Wenn du willst, kannst du den Funktionskopf auch so schreiben
1
void toBin( uint8_t zahl, char Buffer[] )
2
{
3
  ...
4
}

Ändert aber nichts daran, dass Buffer innerhalb der Funktion ein Pointer 
ist. Ist nur eine andere Schreibweise.


> erscheint auf der LCD-Anzeige die Zeichenkette "|| || || || || || || ||
> ||".

Autsch.
Mein Fehler. Da hab ich nicht mitgedacht
1
void toBin( uint8_t zahl, char *Buffer )
2
{
3
  uint8_t i;
4
5
  for( i = 0; i < 8; i++ ) {
6
    Buffer[7-i] = ( zahl % 2 ) + '0';
7
    zahl = zahl / 2;
8
  }
9
  Buffer[8] = '\0';
10
}

von Andi (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Mein Fehler. Da hab ich nicht mitgedacht
> void toBin( uint8_t zahl, char *Buffer )
> {
>   uint8_t i;
>
>   for( i = 0; i < 8; i++ ) {
>     Buffer[7-i] = ( zahl % 2 ) + '0';
>     zahl = zahl / 2;
>   }
>   Buffer[8] = '\0';
> }

Respekt. Jetzt funktioniert es. Kannst du mir vielleicht noch kurz 
erklären, was deine Änderung mit dem + '0' bewirkt? Kann es sein, dass 
dadurch der Inhalt in Buffer nicht als Zahl, sondern als Zeichen 
abspeichert?

Gruß

von Karl H. (kbuchegg)


Lesenswert?

Andi schrieb:

> Respekt. Jetzt funktioniert es. Kannst du mir vielleicht noch kurz
> erklären, was deine Änderung mit dem + '0' bewirkt? Kann es sein, dass
> dadurch der Inhalt in Buffer nicht als Zahl, sondern als Zeichen
> abspeichert?

Ein Zeichen ist im Grunde auch nichts anderes als eine Zahl in einer 
Variablen. Aber nicht einfach irgendeine Zahl.

Die Funktion lcd_string geht davon aus, dass der 'Text' den man ihr 
übergibt so aufgebaut ist, dass sich da drin ASCII Codes befinden. Also 
muss man, wenn man den Text zusammenbaut auch ASCII Codes 
hineinschreiben.

http://www.torsten-horn.de/techdocs/ascii.htm

Wenn ich in der Funktion toBin aber rumrechne, bekomme ich an dieser 
Stelle ja die Zahlen 0 oder 1 raus. Nur kann ich mit denen so erst mal 
nichts anfangen. Denn was ich brauche ist ja der ASCII Code von '0' bzw. 
'1'

Ich könnte jetzt natürlich schreiben

   if( zahl % 2 == 0 )
     Buffer[7-i] = '0';
   else
     Buffer[7-i] = '1';

wäre eine Möglichkeit.
Ich kann aber auch ausnutzen, dass die ASCII Codes der Ziffern alle 
aufsteigend sind. Wenn ich also zum ASCII Code von 0 (denn nichts 
anderes gebe ich ja mit '0' an) einfach das Rechenergebnis dazuzähle, 
dann ändert sich nichts wenn das Rechenergebnis 0 war. Und wenn das 
Rechenergebnis 1 war, dann erhalte ich damit automatisch den ASCII Code 
von '1'.

Und das ist genau das, was ich ja im String haben will.

Du magst dich vielleicht wundern, wie man mit Zeichen rechnen kann. Die 
Lösung besteht eben darin, dass es in Wirklichkeit keine Zeichen in dem 
Sinne gibt. Wenn du schreibst

    char c = 'A';

dann wird da der ASCII Code von 'A' in c gespeichert. Das ist daher 
völlig gleichwertig zu

    char c = 65;

(schau in die ASCII Tabelle. Der Code für 'A' ist 65)

oder auch

    char c = 0x41;

in allen 3 Fällen enthält die Variable c danach das Bitmuster 01000001. 
Und wenn ein Ausgabegerät, welches ASCII versteht (wie zb dein LCD) 
dieses Bitmuster zur Ausgabe präsentiert bekommt, dann malt es eben ein 
A hin.

Das heißt aber auch: Zeichen und Zahlen sind im Programm eigentlich 
dasselbe. Jedes Zeichen wird durch eine bestimmte Zahl repräsentiert. 
Erst bei der Ausgabe entscheidet sich, welche Version ich sehen will: 
Will ich die Zahl selber sehen oder will ich das Zeichen sehen, für das 
diese Zahl steht. Aber innerhalb des µC sind das einfach nur Zahlen in 
einem Byte. Und: daher kann man auch mit denen rechnen.

von Andi (Gast)


Lesenswert?

Jetzt hätte ich auch noch eine andere Frage.
Mit:
1
while(1)
2
  {
3
    if(!(PIND & (1<<PD7)))
4
    {              //Wenn Taster eine Sekunde lang gedrückt
5
      delay_ms(1000);
6
      befuellen();
7
      
8
    }    
9
  }

starte ich ja die Funktion befuellen(). Eigentlich habe ich das ja so 
gedacht, dass ich die Taste an PD7 eine Sekunde lang drücken muss, also 
PD7 eine Sekunde lang auf low ist, damit die Funktion befuellen() 
gestartet wird.

Jetzt hab ich aber gerade festgestellt, dass die Funktion befuellen() 
auch dann schon aufgerufen wird, wenn PD7 nur ganz kurz (im ms-Bereich) 
auf low ist.

Irgendwie verstehe ich dieses Verhalten nicht, denn nachdem PD7 low ist, 
wird ja sofort die delay-Funktion aufgerufen, welche nach einer Sekunde 
wieder verlassen wird. Aber dann hätte ich gedacht, dass die Funktion 
befuellen() nur dann aufgerufen wird, wenn PD7 immer noch low ist.

Gruß

von werghfgjh (Gast)


Lesenswert?

Andi schrieb:
> Aber dann hätte ich gedacht, dass die Funktion
> befuellen() nur dann aufgerufen wird, wenn PD7 immer noch low ist.
Wenn du das willst musst du es auch schreiben...
1
while(1)
2
{
3
  if(!(PIND & (1<<PD7)))
4
  { 
5
    delay_ms(1000);
6
    if(!(PIND & (1<<PD7)))
7
      befuellen();
8
  }
9
}

von Karl H. (kbuchegg)


Lesenswert?

Andi schrieb:
>
1
while(1)
2
>   {
3
>     if(!(PIND & (1<<PD7)))
4
>     {              //Wenn Taster eine Sekunde lang gedrückt
5
>       delay_ms(1000);
6
>       befuellen();
7
> 
8
>     }
9
>   }
10
>
>
> starte ich ja die Funktion befuellen(). Eigentlich habe ich das ja so
> gedacht, dass ich die Taste an PD7 eine Sekunde lang drücken muss, also
> PD7 eine Sekunde lang auf low ist, damit die Funktion befuellen()
> gestartet wird.

Das ist aber nicht das, was du programmiert hast.
Was du programmiert hast ist:

   wenn eine Taste gedrückt ist
      warte 1 Sekunde
      rufe die Funktion auf

Steht genau so da. Davon, dass die Taste 1 Sekunde lang gedrückt sein 
muss, kommt in deinem Code nichts vor.

Wenn ich dir Tür aufmache, dann eine halbe Stunde warte und erst dann 
das Licht einschalte, bedeutet das ja nicht, dass die Tür eine halbe 
Stunde auf war. Es bedeutet lediglich, dass eine halbe Stunde vor dem 
Licht einschalten die Tür aufgemacht wurde. Was in der Zwischenzeit mit 
der Tür passierte, ist damit nicht gesagt.

> Irgendwie verstehe ich dieses Verhalten nicht, denn nachdem PD7 low ist,
> wird ja sofort die delay-Funktion aufgerufen, welche nach einer Sekunde
> wieder verlassen wird. Aber dann hätte ich gedacht, dass die Funktion
> befuellen() nur dann aufgerufen wird, wenn PD7 immer noch low ist.

Warum sollte es?
Eine derartige Abfrage hast du nicht programmiert.

von STK500-Besitzer (Gast)


Lesenswert?

Du solltest nach dem Delay nachgucke, ob die Taste noch gedrückt ist, 
und daraufhin erst befuellen aufrufen.

von werghfgjh (Gast)


Lesenswert?

Eigentlich ist diese Methode allerdings nicht ganz sauber, denn: Es 
reicht wenn der Taster in dem Moment gedrückt ist wo die beiden ifs 
durchlaufen, dazwischen (während delay_ms) läuft ist der Zustand egal.

von werghfgjh (Gast)


Lesenswert?

Ups, mein zweiter Beitrag bezieht sich auf den ersten. Da sind ein paar 
andere dazwischen gekommen.

von Andi (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Ich kann aber auch ausnutzen, dass die ASCII Codes der Ziffern alle
> aufsteigend sind. Wenn ich also zum ASCII Code von 0 (denn nichts
> anderes gebe ich ja mit '0' an) einfach das Rechenergebnis dazuzähle,
> dann ändert sich nichts wenn das Rechenergebnis 0 war. Und wenn das
> Rechenergebnis 1 war, dann erhalte ich damit automatisch den ASCII Code
> von '1'.

Danke für diese tolle Erklärung. Dann wird also zum Beispiel

char variable= 1 + '0'

als variable= 0b00000001 + 0b00110000= 0b00110001

abgespeichert, was wiederum dem ASCII-Wert von 1 entspricht.
Eigentlich nutzt man dabei ja den Umstand aus, dass die ASCII-Zeichen 
von 0 und 1 im ASCII-Code auch nur um die Zahl 1 verschieden sind.

Allgemein kann man also sagen, dass von einer Zahl nur dann der 
ASCII-Wert in einer Variablen (bzw. in einem Array) abgespeichert 
werden, wenn man die Zahl innerhalb der '...' Zeichen schreibt.

Danke, das hab ich jetzt echt gut verstanden.

Gruß

von Andi (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> wenn eine Taste gedrückt ist
>       warte 1 Sekunde
>       rufe die Funktion auf

Also ist das was man sich bei sowas immer merken muss die Tatsache, dass 
das Programm innerhalb eines Blocks streng von oben nach unten arbeitet, 
egal ob die vorherige Bedingung für das Springen in den Block (hier 
PD7==low) während der Blockabarbeitung immer noch aktiv ist.

Gruß

von Karl H. (kbuchegg)


Lesenswert?

Andi schrieb:

> Also ist das was man sich bei sowas immer merken muss die Tatsache, dass
> das Programm innerhalb eines Blocks streng von oben nach unten arbeitet,
> egal ob die vorherige Bedingung für das Springen in den Block (hier
> PD7==low) während der Blockabarbeitung immer noch aktiv ist.

Ja

  if( Bedingung )
  {
    mach was
    mach noch was
  }

hat ein anderes Verhalten als

  if( Bedingung )
    mach was
  if( Bedingung )
    mach noch was

und das musst du dir auch nicht merken, das ergibt sich ganz automatisch 
aus dem Lesefluss von oben nach unten. Der Compiler erfindet nichts 
dazu. Wenn du den Block davon abhängig machst, dass er nur dann 
ausgeführt wird, wenn eine Bedingung erfüllt ist, dann gilt diese 
Bedingungserfüllung auch nur für das Betreten des Blocks. Drum steht sie 
ja auch vor dem Block.

von Andi (Gast)


Lesenswert?

So, jetzt hab ich noch ne kleine Frage. Und zwar hab ich das Programm 
jetzt noch um eine Ausgabe der Wertetabelle erweitert. Die jeweiligen 
Tabellenpaare sollen dabei immer gleichzeitig auf dem LCD ausgegeben 
werden.

Dafür hab ich das Programm jetzt so geändert:
1
#include <avr/io.h>
2
#include <util/delay.h>  
3
#include "lcd-routines.h"
4
#include <stdbool.h>
5
#include <avr/interrupt.h>
6
#include <stdio.h>        //nötig zur Benutzung von sprintf-Funktion
7
8
9
char buffer[20], buffer1[20];
10
11
uint8_t lauf;
12
uint8_t array[2][10]= { {0,1,2,3,4,5,6,7,8,9}, {} };    //array mit zwei Spalten und 10 Zeilen
13
14
15
void delay_ms(uint16_t ms)
16
{
17
  while(ms>0)
18
  {
19
    _delay_ms(1);
20
    ms--;
21
  }
22
}
23
24
25
void toBin( uint8_t zahl, char *ptr )    /*Umrechnung des jeweiligen Eingabewertes in Dualzahl, welche als ASCII-Wert abgespeichert wird
26
                      nötig, da bei itoa() Funktion immer das höchstwertigste Bit eine führende 1 ist*/
27
{                      
28
  uint8_t i;
29
30
  for( i = 0; i < 8; i++ ) 
31
  {
32
    *(ptr+7-i) = (zahl % 2)+ '0';    //1 bzw. 0 + '0'= 1 bzw. 0 + ASCII-WERT(0)= ASCII-WERT(0) bzw. ASCII-WERT(1)
33
    zahl = zahl / 2;
34
  }
35
  *(ptr+8)= '\0';
36
}
37
38
39
void befuellen(void)
40
{
41
  
42
  
43
  for(lauf=0; lauf <10; lauf++)    //Array befüllen
44
  {
45
  
46
    PORTB &= ~(1<<PB7);    //LED7 an
47
    delay_ms(1000);
48
    array[1][lauf]= PIND;    //Derzeitiges Eingangsregister jeweiligem Array-Element zuordnen
49
50
    delay_ms(100);
51
    PORTB |= (1<<PB7);    //LED7 aus
52
    delay_ms(1000);
53
    
54
  }
55
  
56
  ausgabe();
57
}
58
59
60
void ausgabe(void)      //Array auf LCD ausgeben
61
{
62
  uint8_t i, ausgeben;
63
64
  for(i=0; i<10; i++)
65
  {
66
    ausgeben= array[1][i];    //Array-Elemente nacheinander ausgeben
67
    
68
69
    lcd_setcursor(0,1);
70
       toBin(ausgeben, buffer);
71
      lcd_string(buffer);
72
    
73
    delay_ms(1000);
74
  }
75
76
  wertetabelle_ausgabe();
77
78
}  
79
80
81
void wertetabelle_ausgabe(void)
82
{
83
  uint8_t element_spalte1, element_spalte2;
84
  
85
  lcd_clear();
86
87
  for(lauf=0; lauf<8; lauf++)
88
  {  
89
    PORTB = lauf;            //Zur Kontrolle den Wert von lauf als Ausgabe auf den LEDs
90
    element_spalte1= array[0][lauf];
91
    element_spalte2= array[1][lauf];
92
93
    lcd_setcursor(0,1);
94
    itoa(element_spalte1, buffer1,10);  //dezimale Ausgabe der Elemente der ersten Spalte
95
    lcd_string(buffer1);
96
97
    lcd_setcursor(0,2);
98
    toBin(element_spalte2, buffer);    //duale Ausgabe der Elemente der zweiten Spalte
99
    lcd_string(buffer);
100
    delay_ms(1000);
101
  }
102
}
103
104
  
105
  
106
int main(void)
107
{
108
109
  lcd_init();
110
  DDRB |= 0xFF;  //alle Pins als Ausgang
111
  DDRD = 0x00;  //Alle Pins als Eingang
112
  PORTB |= 0xFF;  //alle LEDs aus
113
            
114
  while(1)
115
  {
116
    if(!(PIND & (1<<PD7)))
117
    {              //Nachdem Taster gedrückt ist eine Sekunde lang warten
118
      delay_ms(1000);
119
      befuellen();
120
      
121
    }    
122
  }
123
}

Eigentlich sollte diese Erweiterung ja kein Problem darstellen.  Jetzt 
ist es aber so, dass die neu hinzugefügte for-Schleife in der Funktion 
wertetabelle_ausgabe() nur einmal und nicht wie gewünscht achtmal 
ausgeführt wird. Über die LEDs kontrolliere ich den Inhalt von lauf. 
Dieser ist ständig auf 0.

Wer kann sich dieses Fehlverhalten erklären?

Gruß

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.