Forum: Compiler & IDEs STK500-Taster abfragen


von EinSteigÄr (Gast)


Lesenswert?

Hallo nochmal!

Wieder habe ich ein Problem mit dem Abfragen von Tastern. und zwar soll 
einfach beim Druck auf einen Taster am STk500 die darüberligende LED 
leuchten. Nur irgendwie habe ich es auch noch nicht ganz mit den 
Pullup-Widerständen verstanden....
Was ist falsch?


#include <avr/io.h>

int main(void)
{
DDRA=0xFF;    //Ausgang = PortA
PORTB=0x00;    //Pullup-Widerstände ausschalten
DDRB=0x00;    //PortB als Eingang

  for(;;)
    {
     if (PORTB=0x01) //wenn erster Taster1 gedrückt ist, dann...
     {
      PORTA=0x01;   //leuchte LED1
     }
    }

     .
     .
     .
     .

}



Danke!

von johnny.m (Gast)


Lesenswert?

Die Taster sind Low-Side angeschlossen! Wenn ein Taster gedrückt wird, 
liegt eine Null (Low-Pegel) am Pin und keine 1.

von Biff (Gast)


Lesenswert?

Fragt man für die Eingänge nicht eher PINB (anstelle von PortB) ab? Also 
folgendermaßen:

if (PINB == 0x01)
{
...
}

Gruß

Biff

von Michael U. (Gast)


Lesenswert?

Hallo,

PORTB=0x00;    //Pullup-Widerstände ausschalten
DDRB=0x00;    //PortB als Eingang

und sollte man die PullUps nicht eher EINschalten, damit es überhaupt 
einen Hig-Pegel am Pin geben kann, wenn nichts gedrückt ist?

PS: die PullUps liegen zwischen Eingangspin und +Ub, wenn sie 
eingeschaltet sind und sorgen so dafür, daß es überhaupt definierte 
Verhältnisse in dieser Beschaltung gibt. Ohne hängt der Pin einfach nur 
in der Luft, wenn die Taste nicht gedrückt ist...

Gruß aus Berlin
Michael

von EinSteigÄr (Gast)


Lesenswert?

ok vielen Dank!

ich habe meinen fehler selbst gefunden...es war die If-Abfrage mit == 
und =. Programmiere nebenher noch Visual Basic und da gibts kein "==" 
sondern NUR "=", drum war ich bissl verwirrt ;)

nun noch eine Frage:

Ich habe selbst ein Board aufgebaut und bei dem muss ich nicht wie beim 
STK500 beispielsweise den Taster1 mit "0x7F" sondern einfach mit "0x01" 
abfragen. Woran liegt das? Gibt es so eine Art "invertierung" in C, 
damit ich anstelle von 0x7F für das STK500 auch 0x01 schreiben kann?

danke!

von Karl H. (kbuchegg)


Lesenswert?

EinSteigÄr wrote:
> ok vielen Dank!
>
> ich habe meinen fehler selbst gefunden...es war die If-Abfrage mit ==
> und =. Programmiere nebenher noch Visual Basic und da gibts kein "=="
> sondern NUR "=", drum war ich bissl verwirrt ;)

Das war aber nicht dein einziges Problem :-)
>
> nun noch eine Frage:
>
> Ich habe selbst ein Board aufgebaut und bei dem muss ich nicht wie beim
> STK500 beispielsweise den Taster1 mit "0x7F" sondern einfach mit "0x01"
> abfragen. Woran liegt das?

Das liegt daran, dass du deine Taster anders angeschlossen
hast, als sie im STK500 angeschlossen sind.

Im STK500 sind sie so angeschlossen:


   PIN ---o----------+
                     |
                       /
                      /
                     |
                     |
       GND ----------+

Du hast deine so angeschlossen

    Vcc -------------+
                     |
                       /
                      /
                     |
                     |
   PIN ---o----------+
                     |
                    +-+
                    | |
                    +-+
                     |
      GND -----------+

Wenn also in der STK Variante der Taster geschlossen wird, so
stellt er eine Verbindung zu Masse her. Das hat den Vorteil, dass
dann die AVR internen Pullup Widerstände zugeschaltet werden
können und keine externen benötigt werden wie bei deiner Lösung.
(Du hast doch Pulldown Widerstände eingebaut, oder?)



> Gibt es so eine Art "invertierung" in C,
> damit ich anstelle von 0x7F für das STK500 auch 0x01 schreiben kann?

Sicher gibt es das: Die Tilde ~

    ~0x01  == 0x7F

    ~0x7F  == 0x01

Die Tilde dreht alle Bits um. Sollte sich aber auch in deinem
C Buch finden.

von EinSteigÄr (Gast)


Lesenswert?

ok vielen Dank!

Habe es jetzt gecheckt...

Nun noch eine Frage lieber Karl heinz, und zwar bin ich nun fast mit 
meinem Projekt fertig. (Außer dass ich noch die Schaltung löten muss -> 
kann ja nicht das STK500 abgeben ;) und noch paar Verbesserungen am 
Programm vornehmen muss)...

Hier mal der Quellcode. Ich hoffe du weißt noch um was es ging. Es ist 
das Projekt mit den Lichtschranken, die nacheinander Durchfahren werden. 
Sobald eine Lichtschranke durchfahren wird, wird der momentane 
TimerRegister in eine variable (reg1...8) gespeichert und der bis dahin 
stattgefundene Überlauf dieses Timer-Registers (ubergabe1...8). Der 8. 
Taster ist zum Senden der Variablen (ubergabe1...8 und reg1...8) über 
den UART gedacht.
Nun mein Problem: Wenn ich im Terminal die werte ansehe (also nachdem 
ich den schalter8: 0x7F gedrückt habe), kommen da schon mal nicht alle 
werte an, obwohl ich nacheinander die 8 Taster drücke. Somit müssten ja 
14 Werte (8 "reg"-variablen und 8 "ubergabe"-variablen plus jeweils ein 
x dazwischen) erscheinen. Es kommen aber immer nur 5 (plus Trenn"x"). 
Die x haben nur die Aufgabe, dass das von mir geschrieben VisualBasic 
Programm weiß, wann es die werte in die nächste Textbox/Variable 
schreiben soll. Nächstes Problem ist, dass MINUS-Zahlen kommen??!!

Hier der Code:
1
_________________________________________________________________________
2
#include <inttypes.h>
3
#include <avr/io.h>
4
5
//Für 8 Lichtschranken programmiert
6
//---------------------------------------------------------------------------
7
int uart_putc(unsigned char c)
8
{
9
  while (!(UCSRA & (1<<UDRE)))  /* warten bis Senden moeglich */
10
  {
11
  }
12
 
13
  UDR = c;                      /* sende Zeichen */
14
  return 0;
15
}
16
17
//---------------------------------------------------------------------------
18
int sendx(void)
19
{
20
  while (!(UCSRA & (1<<UDRE)))  /* warten bis Senden moeglich */
21
  {
22
  }
23
 
24
  UDR = 'x';                      /* sende Zeichen */
25
}
26
//---------------------------------------------------------------------------
27
28
void uart_puts (char *s)
29
{
30
  while (*s)
31
  {   /* so lange *s != '\0' also ungleich dem "String-Endezeichen" */
32
    uart_putc(*s);
33
    s++;
34
  }
35
}
36
//-------------------------------------------------------------------------------
37
int wandle(int y)
38
{
39
char Buffer[20];
40
  int i = y;
41
42
  sprintf( Buffer, "%d", i );
43
44
  uart_puts( Buffer );
45
46
}
47
48
49
//-------------------------------------------------------------------------------------------------------------------
50
51
int main (void)
52
{
53
int ubergabe=0,ubergabe1=0,ubergabe2=0,ubergabe3=0, ubergabe4=0,ubergabe5=0,ubergabe6=0,ubergabe7=0,ubergabe8=0;
54
int reg1=0,reg2=0,reg3=0,reg4=0,reg5=0,reg6=0,reg7=0,reg8=0, kontrol=0;
55
DDRD =0xFF;
56
DDRB =0x00;
57
TCCR0 |=  (1<<CS00);          
58
59
for(;;)
60
{
61
  if (TIFR &(1<<TOV0)) //wenn generell Überlauf, erhöhe Variable "ubergabe" um eins
62
  {
63
  ubergabe++;
64
  TIFR = 1<<TOV0;
65
  }
66
67
  if (PINB==0xFE)    //wenn Taste1 gedrückt wird, dann schreibe in Var "reg1" den Zählerstand (TCNT0)
68
  {                     //und den momentanen Wert von Var "uberlauf" in "uberlauf1"
69
    reg1=TCNT0;
70
    ubergabe1=ubergabe;
71
  }
72
  if (PINB==0xFD)
73
  {
74
    reg2=TCNT0;
75
  ubergabe2=ubergabe;
76
  }
77
  if (PINB==0xFB)
78
  {
79
    reg3=TCNT0;
80
  ubergabe3=ubergabe;
81
          
82
  }
83
     if (PINB==0xF7)
84
  {
85
    reg4=TCNT0;
86
  ubergabe4=ubergabe;
87
  }
88
  if (PINB==0xEF)
89
  {
90
    reg5=TCNT0;
91
  ubergabe5=ubergabe;
92
  }
93
  if (PINB==0xDF)
94
  {
95
    reg6=TCNT0;
96
  ubergabe6=ubergabe;
97
  }
98
  if (PINB==0xBF)
99
  {
100
    reg7=TCNT0;
101
  ubergabe7=ubergabe;
102
  }
103
  if (PINB==0x7F)
104
  { 
105
    reg8=TCNT0;                    //sobald der letzte Taster(taster8) gedrückt wird, dann wird der Timer gestoppt und über kontrol=1 das senden der Daten über den UART verursacht
106
  ubergabe8=ubergabe;
107
  TCCR0=0;
108
  kontrol=1;
109
  }
110
111
 if (kontrol==1)
112
 {
113
  UCSRB |= (1<<TXEN);              //Senden aktivieren
114
  UCSRC |= (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1);  // 
115
116
  UBRRH = 00;                      //Baudrate einstellen 9600 bei 8 MHz
117
  UBRRL = 51;
118
119
  sendx();
120
  wandle(reg1);
121
  sendx();
122
  wandle(ubergabe1);
123
  sendx();
124
  wandle(reg2);
125
  sendx();
126
  wandle(ubergabe2);
127
  sendx();
128
  wandle(reg3);
129
  sendx();
130
  wandle(ubergabe3);
131
  sendx();
132
  wandle(reg4);
133
  sendx();
134
  wandle(ubergabe4);
135
  sendx();
136
  wandle(reg5);
137
  sendx();
138
  wandle(ubergabe5);
139
  sendx();
140
  wandle(reg6);
141
  sendx();
142
  wandle(ubergabe6);
143
  sendx();
144
  wandle(reg7);
145
  sendx();
146
  wandle(ubergabe7);
147
  sendx();
148
  wandle(reg8);
149
  sendx();
150
  wandle(ubergabe8);
151
    TCCR0=0;
152
  kontrol=0;
153
  }
154
155
}
156
}



Viiiielen Dank! :)

von EinSteigÄr (Gast)


Lesenswert?

edit: natürlich nicht 14 sondern bei 2mal 8 werten 16 ;)

von Karl H. (kbuchegg)


Lesenswert?

EinSteigÄr wrote:
> Nun mein Problem: Wenn ich im Terminal die werte ansehe (also nachdem
> ich den schalter8: 0x7F gedrückt habe), kommen da schon mal nicht alle
> werte an, obwohl ich nacheinander die 8 Taster drücke. Somit müssten ja
> 14 Werte (8 "reg"-variablen und 8 "ubergabe"-variablen plus jeweils ein
> x dazwischen) erscheinen. Es kommen aber immer nur 5 (plus Trenn"x").

Wie hast du das kontrolliert?

Häng doch mal ein Terminalprogramm (Hyperterminal) an die
Leitung und schau nach was da ankommt.
So wie es aussieht, gibt es 2 Fehlermöglichkeiten:
Entweder schickt der Sender (also der AVR) nicht das was er soll
oder der Empfänger wertet das empfangene nicht korrekt aus.
Da das empfangende Programm ebenfalls von dir ist, kann der Fehler
in beiden stecken. Und um rauszukriegen in welchem, ersetzt man
halt mal eine Seite durch ein Programm, von dem man weiss das
es funktioniert. In deinem Fall ist das einfachste, da mal
ein Termialprogramm ala Hyperterminal dranzuhängen.

> Die x haben nur die Aufgabe, dass das von mir geschrieben VisualBasic
> Programm weiß, wann es die werte in die nächste Textbox/Variable
> schreiben soll. Nächstes Problem ist, dass MINUS-Zahlen kommen??!!

Auch das ist klar.
Bei dir ist alles ein int. Und ein int kann nun mal auch negativ
werden. Insbesondere wird eine Addition von 1 zur größtmöglichen
positiven Zahl einen 'Überlauf' zur kleinstmöglichen Zahl bewirken.
Genau aus dem Grund gibt es den Datentyp 'unsigned int'. Dann
musst du dir aber raussuchen welches Formatierzeichen der sprintf
für unsigned int haben will.

>
> Hier der Code:

Du solltest dir wirklich ein C Buch zulegen.
Ist dir das ewige Code-Duplizieren nicht auf den Wecker
gefallen? Sowas macht man doch mit Arrays.

von EinSteigÄr (Gast)


Lesenswert?

also ich habe es vorhin ja mit einem TerminalProgramm (Hyperterminal von 
Microsoft) aber da kommen eben nicht alle werte an und außerdem manchmal 
"minus"-zahlen.

das ist eben der fehler. Genauso kommt es aber auch in meinem 
VB-Programm an, also kanns schon mal nicht am visualbasic-programm von 
mir liegen, da ja hyperterminal das gleiche anzeigt.

von Karl H. (kbuchegg)


Lesenswert?

schmeiss doch mal die sendx() Funktion raus. Die braucht keiner.

Und dann veränderst du dein Hauptprogramm so:

  UCSRB |= (1<<TXEN);              //Senden aktivieren
  UCSRC |= (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1);  //

  UBRRH = 00;                      //Baudrate einstellen 9600 bei 8 MHz
  UBRRL = 51;

  uart_putc( 'a' );
  wandle(reg1);
  uart_putc( 'b' );
  wandle(ubergabe1);

  uart_putc( 'c' );
  wandle(reg2);
  uart_putc( 'd' );
  wandle(ubergabe2);

  uart_putc( 'e' );
  wandle(reg3);
  uart_putc( 'f' );
  wandle(ubergabe3);

  uart_putc( 'g' );
  wandle(reg4);
  uart_putc( 'h' );
  wandle(ubergabe4);

  uart_putc( 'i' );
  wandle(reg5);
  uart_putc( 'j' );
  wandle(ubergabe5);

  uart_putc( 'k' );
  wandle(reg6);
  uart_putc( 'l' );
  wandle(ubergabe6);

  uart_putc( 'm' );
  wandle(reg7);
  uart_putc( 'n' );
  wandle(ubergabe7);

  uart_putc( 'o' );
  wandle(reg8);
  uart_putc( 'p' );
  wandle(ubergabe8);

    TCCR0=0;
  kontrol=0;
}

und siehst mal nach, welche Werte denn kommen und welche
nicht.

> und außerdem manchmal
> "minus"-zahlen.

Ja. Sagte ich doch schon warum das so ist.

PS: Und zieh die UART Initialisierung vor die Schleife.
Es reicht völlig, wenn der UART einmal bei Programmstart
initialisiert wird. Es gibt keinen Grund das jedesmal zu machen.

von EinSteigÄr (Gast)


Lesenswert?

habe mal deine veränderung am code so reingeschrieben und geflasht. 
folgendes kommt am Terminal nun an:

a0b0c0d0e0f0g0h0i0j0k0l0m0n0o142p-10330a0b0

nachdem ich die taste 0x7F gedrückt habe.

danke

von EinSteigÄr (Gast)


Lesenswert?

sorry! habe was falsches kopiert. Das ist angekommen:

a0b0c0d0e0f0g0h0i0j0k0l0m0n0o142p-10330

von Karl H. (kbuchegg)


Lesenswert?

Na ja. Sind doch alle da! Von 'a' bis 'p'!

Die negative kriegst du weg, indem du jetzt endlich mal
die Umstellung von 'int' zu 'unsigned int' machst.
Und dann musst du dich mal damit beschäftigen, warum ein
Teil der Werte 0 ist.


von EinSteigÄr (Gast)


Lesenswert?

naja, weil eben die variablen noch nicht gefüllt sind bis zu dem 
zeitpunkt, wo ich den 0x7f drücke

von EinSteigÄr (Gast)


Lesenswert?

ok, also ich werde heute mal die "int" variablentypen mit "unsigned int" 
ersetzen. Dann müsste das Problem mit dem vorzeichen vor den Zahlen 
behoben sein :-)

danke!

von Karl H. (kbuchegg)


Lesenswert?

Denk aber dran, dass das Formatierzeichen im sprintf
ebenfalls ersetzt werden muss.

von EinSteigÄr (Gast)


Lesenswert?

Also. habe heute mal aus den "int" Datentypen "unsigned int" gemacht, 
aber anscheinend erfolglos. Wenn ich mein Programm nun so laufen lasse, 
wie Karl-Heinz mir vorgeschlagen hat, bringt er wieder die zeichen von 
a-p im Terminal, jedoch immer noch die "-" -> vorzeichen.

Hier der Terminal-Ausdruck, nachdem alle Taster nacheinander gedrückt 
wurden:

a213b30121c128d-12895e63f11358g12h30918i49j-11897k166l19707m233n-18894o1 
42p3595a213b30121c128d-12895e63f11358g12h30918i49j-11
897k166l19707m233n-18894o158p3595

Hier nochmal der gesamte Code:

[ c ]
int main (void)
{
unsigned int ubergabe=0,ubergabe1=0,ubergabe2=0,ubergabe3=0, 
ubergabe4=0,ubergabe5=0,ubergabe6=0,ubergabe7=0,ubergabe8=0;
unsigned int reg1=0,reg2=0,reg3=0,reg4=0,reg5=0,reg6=0,reg7=0,reg8=0, 
kontrol=0;
DDRD =0xFF;
DDRB =0x00;

TCCR0 |=  (1<<CS00);      //Prescaler für Timer

UCSRB |= (1<<TXEN);              //Senden aktivieren
UCSRC |= (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1);

  UBRRH = 00;                      //Baudrate einstellen 9600 bei 8 MHz
  UBRRL = 51;

for(;;)
{
  if (TIFR &(1<<TOV0)) //wenn generell Überlauf, erhöhe Variable 
"uberlauf" um eins
  {
  ubergabe++;
  TIFR = 1<<TOV0;
  }

  if (PINB==0xFE)    //wenn Taste1 gedrückt wird, dann schreibe in Var 
"reg1" den Zählerstand (TCNT0)
  {                     //und den momentanen Wert von Var "uberlauf" in 
"uberlauf1"
    reg1=TCNT0;
    ubergabe1=ubergabe;
  }
  if (PINB==0xFD)
  {
    reg2=TCNT0;
  ubergabe2=ubergabe;
  }
  if (PINB==0xFB)
  {
    reg3=TCNT0;
  ubergabe3=ubergabe;
          //bei Druck auf Taste3, Timer beenden (TCCR0=0)
  }
   //Speichert bis hierher bei verschiedenen Tastendrücken die 
momentanen Überläufe (ubergabe1-3)
    //sowie die momentanen Registerwerte (reg1-3)
  if (PINB==0xF7)
  {
    reg4=TCNT0;
  ubergabe4=ubergabe;
  }
  if (PINB==0xEF)
  {
    reg5=TCNT0;
  ubergabe5=ubergabe;
  }
  if (PINB==0xDF)
  {
    reg6=TCNT0;
  ubergabe6=ubergabe;
  }
  if (PINB==0xBF)
  {
    reg7=TCNT0;
  ubergabe7=ubergabe;
  }
  if (PINB==0x7F)
  {
    reg8=TCNT0;
  ubergabe8=ubergabe;
  TCCR0=0;
  kontrol=1;
  }

 if (kontrol==1)
 {

/*
  sendx();
  wandle(reg1);
  sendx();
  wandle(ubergabe1);
  sendx();
  wandle(reg2);
  sendx();
  wandle(ubergabe2);
  sendx();
  wandle(reg3);
  sendx();
  wandle(ubergabe3);
  sendx();
  wandle(reg4);
  sendx();
  wandle(ubergabe4);
  sendx();
  wandle(reg5);
  sendx();
  wandle(ubergabe5);
  sendx();
  wandle(reg6);
  sendx();
  wandle(ubergabe6);
  sendx();
  wandle(reg7);
  sendx();
  wandle(ubergabe7);
  sendx();
  wandle(reg8);
  sendx();
  wandle(ubergabe8);
    TCCR0=0;
  kontrol=0;*/

uart_putc( 'a' );
  wandle(reg1);
  uart_putc( 'b' );
  wandle(ubergabe1);

  uart_putc( 'c' );
  wandle(reg2);
  uart_putc( 'd' );
  wandle(ubergabe2);

  uart_putc( 'e' );
  wandle(reg3);
  uart_putc( 'f' );
  wandle(ubergabe3);

  uart_putc( 'g' );
  wandle(reg4);
  uart_putc( 'h' );
  wandle(ubergabe4);

  uart_putc( 'i' );
  wandle(reg5);
  uart_putc( 'j' );
  wandle(ubergabe5);

  uart_putc( 'k' );
  wandle(reg6);
  uart_putc( 'l' );
  wandle(ubergabe6);

  uart_putc( 'm' );
  wandle(reg7);
  uart_putc( 'n' );
  wandle(ubergabe7);

  uart_putc( 'o' );
  wandle(reg8);
  uart_putc( 'p' );
  wandle(ubergabe8);

  kontrol=0;
  }

}
}


[ /c ]

Außerdem: Wenn man nicht sofort den Taster 0x7F "zum Senden" loslässt, 
kommt der String - logischerweise - sooft, bis man den Schalter 
loslässt. Wie kann ich nur Einmal den String senden??

Vielen dank!

von Karl H. (kbuchegg)


Lesenswert?

> Hier nochmal der gesamte Code:

Das ist nicht der geamte Code. Wo ist die Funktion wandle?

Nochmal: Deine Funktion wandle() kriegt jetzt einen
unsigned int! Das heist du musst das Formatierzeichen
im sprintf austauschen! %d ist für int, %u ist für
unsigned int.

> Wie kann ich nur Einmal den String senden??

Indem du eine Variable benutzt, in der du dir merkst,
dass die ganze Litanei schon gesendet wurde.

Ist die Variable auf 0 und kommt der Zustand 0x7F
dann sendest du die Daten und setzt die Variable auf 1
Wenn du das nächste mal 0x7F antriffst und diese Variable
ist auf 1, dann weist du, dass die Daten schon gesendet
wurden und brauchst nichts tun.
Jetzt musst du dir nur noch ein schönes Plätzchen suchen,
wo die Variable wieder auf 0 gesetzt wird.


Nachtrag:
Mit deiner kontrol Variablen hast du schon den Grundstock dafür.
Daraus kannst du diese Steuerung aufbauen.

von Karl H. (kbuchegg)


Lesenswert?

Dann studier mal das hier.
Deine Kopier-Orgien sind ja grauenhaft. Sowas macht
man mit Arrays und ein paar Schleifen.
1
void SendeWerte( unsigned int Overflows[], unsigned int Values[] )
2
{
3
  unsigned char i;
4
  unsigned char Filler = 'a';
5
6
  for( i = 0; i < 8; ++i ) {
7
    uart_putc( Filler++ );
8
    wandle( Values[i] );
9
10
    uart_putc( Filler++ );
11
    wandle( Overflows[i] );
12
  }
13
}
14
15
int main (void)
16
{
17
  unsigned int Ueberlauf = 0;
18
  unsigned int Ueberlaeufe[8] = { 0 };
19
  unsigned int Zaehler[8] = { 0 };
20
  unsigned char Tasten[8] = { 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F };
21
  unsigned char i;
22
  unsigned char Gesendet = 0;
23
24
  DDRD = 0xFF;
25
  DDRB = 0x00;
26
27
  TCCR0 |=  (1<<CS00);      //Prescaler für Timer
28
29
  UCSRB |= (1<<TXEN);              //Senden aktivieren
30
  UCSRC |= (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1);
31
32
  UBRRH = 00;                      //Baudrate einstellen 9600 bei 8 MHz
33
  UBRRL = 51;
34
35
  for(;;)
36
  {
37
    if (TIFR &(1<<TOV0))          //wenn generell Überlauf, erhöhe Variable "uberlauf" um eins
38
    {
39
      Ueberlauf++;
40
      TIFR = 1<<TOV0;
41
    }
42
43
    for( i = 0; i < 8; ++i ) {    // alle Tasten abfragen
44
      if( PINB == Tasten[i] )     // war die Taste i gedrueckt ?
45
      {
46
        Zaehler[i] = TCNT0;       // Werte merken
47
        Ueberlaeufe[i] = Ueberlauf;
48
49
        if( i == 7 ) {            // War das die letzte Taste ?
50
          if( !Gesendet ) {       // Wurden die Werte schon gesendet ?
51
            SendeWerte( Ueberlaeufe, Zaehler);  // Nein: Werte senden
52
            Gesendet = 1;                       // und merken dass schon gesendet wurde
53
          }
54
        }
55
        else
56
          Gesendet = 0;          // Taste gedrückt, aber es war nicht die letzte Taste
57
                                 // Wenn das nächste mal die letzte Taste gedrueckt wird
58
                                 // gibt es wieder was zum Senden
59
      }
60
    }
61
  }
62
}

von EinSteigÄr (Gast)


Lesenswert?

Danke für die Code-Lösung, werde diese wohl auch so anwenden, ist mit 
arrays wirklich viel einfacher. Trotzdem zeige ich nochmal meinen Code. 
Die Vorzeichen habe ich nun wegbekommen. Jetzt geht es um ein 
Verständnis-Problem:

Ich schicke ja nacheinander immer "reg", dann x und dann "ubergabe". Wie 
kann es sein, dass die Zahlen im terminal so aussehen?

                  23x3998x239x1999x.....
                   |   |
                 reg,  uberlauf
Wie kann es mit meinem Code vorkommen, dass die Überläufe nicht 
aufsteigend größer werden, da die "uberlauf"-variable ja eigentlich 
hochzählen sollte und immer der momentane Wert in die "uberlauf1-8" 
reingeschrieben werden sollen, die dann am terminal ausgegeben werden? 
Es müsste doch ein aufsteigendes "uberlauf"-muster im terminal geben? 
Macht es aber nicht


danke

von EinSteigÄr (Gast)


Lesenswert?

Hier der gesamte Code:

#include <inttypes.h>
#include <avr/io.h>

//Für 8 Lichtschranken gemacht
//---------------------------------------------------------------------- 
-----
unsigned int uart_putc(unsigned char c)
{
  while (!(UCSRA & (1<<UDRE)))  /* warten bis Senden moeglich */
  {
  }

  UDR = c;                      /* sende Zeichen */
  return 0;
}

//---------------------------------------------------------------------- 
-----
int sendx(void)
{
  while (!(UCSRA & (1<<UDRE)))  /* warten bis Senden moeglich */
  {
  }

  UDR = 'x';                      /* sende Zeichen */
}
int senda(void)
{
  while (!(UCSRA & (1<<UDRE)))  /* warten bis Senden moeglich */
  {
  }

  UDR = 'a';                      /* sende Zeichen */
}

//---------------------------------------------------------------------- 
-----

void uart_puts (unsigned char *s)
{
  while (*s)
  {   /* so lange *s != '\0' also ungleich dem "String-Endezeichen" */
    uart_putc(*s);
    s++;
  }
}
//---------------------------------------------------------------------- 
---------
unsigned int wandle(unsigned int y)
{
unsigned char Buffer[20];
  unsigned int i = y;

  sprintf( Buffer, "%u", i );

  uart_puts( Buffer );

}


//---------------------------------------------------------------------- 
---------------------------------------------

int main (void)
{
unsigned int ubergabe=0,ubergabe1=0,ubergabe2=0,ubergabe3=0, 
ubergabe4=0,ubergabe5=0,ubergabe6=0,ubergabe7=0,ubergabe8=0;
unsigned int reg1=0,reg2=0,reg3=0,reg4=0,reg5=0,reg6=0,reg7=0,reg8=0, 
kontrol=0;
DDRD =0xFF;
DDRB =0x00;

TCCR0 |=  (1<<CS00);      //Prescaler für Timer

UCSRB |= (1<<TXEN);              //Senden aktivieren
UCSRC |= (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1);

  UBRRH = 00;                      //Baudrate einstellen 9600 bei 8 MHz
  UBRRL = 51;

for(;;)
{
  if (TIFR &(1<<TOV0)) //wenn generell Überlauf, erhöhe Variable 
"uberlauf" um eins
  {
  ubergabe++;
  TIFR = 1<<TOV0;
  }

  if (PINB==0xFE)    //wenn Taste1 gedrückt wird, dann schreibe in Var 
"reg1" den Zählerstand (TCNT0)
  {                     //und den momentanen Wert von Var "uberlauf" in 
"uberlauf1"
    reg1=TCNT0;
    ubergabe1=ubergabe;
  }
  if (PINB==0xFD)
  {
    reg2=TCNT0;
  ubergabe2=ubergabe;
  }
  if (PINB==0xFB)
  {
    reg3=TCNT0;
  ubergabe3=ubergabe;
          //bei Druck auf Taste3, Timer beenden (TCCR0=0)
  }
   //Speichert bis hierher bei verschiedenen Tastendrücken die 
momentanen Überläufe (ubergabe1-3)
    //sowie die momentanen Registerwerte (reg1-3)
  if (PINB==0xF7)
  {
    reg4=TCNT0;
  ubergabe4=ubergabe;
  }
  if (PINB==0xEF)
  {
    reg5=TCNT0;
  ubergabe5=ubergabe;
  }
  if (PINB==0xDF)
  {
    reg6=TCNT0;
  ubergabe6=ubergabe;
  }
  if (PINB==0xBF)
  {
    reg7=TCNT0;
  ubergabe7=ubergabe;
  }
  if (PINB==0x7F)
  {
    reg8=TCNT0;
  ubergabe8=ubergabe;
  TCCR0=0;
  kontrol=1;
  }

 if (kontrol==1)
 {


  senda();
  wandle(reg1);
  sendx();
  wandle(ubergabe1);
  sendx();
  wandle(reg2);
  sendx();
  wandle(ubergabe2);
  sendx();
  wandle(reg3);
  sendx();
  wandle(ubergabe3);
  sendx();
  wandle(reg4);
  sendx();
  wandle(ubergabe4);
  sendx();
  wandle(reg5);
  sendx();
  wandle(ubergabe5);
  sendx();
  wandle(reg6);
  sendx();
  wandle(ubergabe6);
  sendx();
  wandle(reg7);
  sendx();
  wandle(ubergabe7);
  sendx();
  wandle(reg8);
  sendx();
  wandle(ubergabe8);
    sendx();
  TCCR0=0;
  kontrol=0;

/*uart_putc( 'a' );
  wandle(reg1);
  uart_putc( 'b' );
  wandle(ubergabe1);

  uart_putc( 'c' );
  wandle(reg2);
  uart_putc( 'd' );
  wandle(ubergabe2);

  uart_putc( 'e' );
  wandle(reg3);
  uart_putc( 'f' );
  wandle(ubergabe3);

  uart_putc( 'g' );
  wandle(reg4);
  uart_putc( 'h' );
  wandle(ubergabe4);

  uart_putc( 'i' );
  wandle(reg5);
  uart_putc( 'j' );
  wandle(ubergabe5);

  uart_putc( 'k' );
  wandle(reg6);
  uart_putc( 'l' );
  wandle(ubergabe6);

  uart_putc( 'm' );
  wandle(reg7);
  uart_putc( 'n' );
  wandle(ubergabe7);

  uart_putc( 'o' );
  wandle(reg8);
  uart_putc( 'p' );
  wandle(ubergabe8);

  kontrol=0;*/
  }
//---------------------------------------------------------------------- 
--------------------------------------------
}
}





von Karl H. (kbuchegg)


Lesenswert?

EinSteigÄr wrote:
>
> Ich schicke ja nacheinander immer "reg", dann x und dann "ubergabe". Wie
> kann es sein, dass die Zahlen im terminal so aussehen?
>
>                   23x3998x239x1999x.....
>                    |   |
>                  reg,  uberlauf
> Wie kann es mit meinem Code vorkommen, dass die Überläufe nicht
> aufsteigend größer werden, da die "uberlauf"-variable ja eigentlich
> hochzählen sollte und immer der momentane Wert in die "uberlauf1-8"
> reingeschrieben werden sollen, die dann am terminal ausgegeben werden?
> Es müsste doch ein aufsteigendes "uberlauf"-muster im terminal geben?
> Macht es aber nicht

Wie schnell taktest du deinen µC und wie schnell drückst du
die Tasten?

Ich geh mal von 4 Mhz aus.

d.h. der Timer zählt mit 4 Mhz, da der Prescaler 1 ist.
Bis zum Überlauf muss er bis 256 zählen. Das passiert
in 1 Sekunde 4000000 / 256 = 15625 mal

Ein unsigned int kann bis 65535 zählen. Da deine
ueberlauf Variable 15625 mal in der Sekunde erhöht wird,
ist dieser Zahlenbereich in knapp 4 Sekunden einmal durch,
dann beginnt ueberlauf wieder bei 0

Oder anders ausgedrückt, wenn du nicht innerhalb von 4
Sekunden (bei 4 Mhz Takt), alle Tasten der Reihe nach
drückst, siehst du einen Sprung. Wenn dein µC mit 16 Mhz
läuft, hast du entsprechend wendiger Zeit. Dann bist du in
knapp 1 Sekunde einmal rum.

Und dann hast du natuerlich noch das Problem, dass du
die ganzen Zaehler nie auf 0 zurücksetzt. Da du zwischen den
Zahlen aber immer nur x ausgibst, weist du in deiner Zahlenreihe
nie, wo denn ein neuer Messzyklus beginnt.


von EinSteigÄr (Gast)


Lesenswert?

ich muss doch die zähler auch nicht auf null zurücksetzen, wenn ich in 
meinem VB-Programm die Differenz (zeit-uberlaufe1,2 = 
uberlauf2-uberlauf1)

oder?

von Karl H. (kbuchegg)


Lesenswert?

EinSteigÄr wrote:
> ich muss doch die zähler auch nicht auf null zurücksetzen, wenn ich in
> meinem VB-Programm die Differenz (zeit-uberlaufe1,2 =
> uberlauf2-uberlauf1)
>
> oder?

Setz einfach mal ein paar Zahlenwerte ein und du wirst sehen
was dann raus kommt.

von EinSteigÄr (Gast)


Lesenswert?

also es funktioniert :) habe mal gaaanz schnell die taster nacheinander 
gedrückt und habe gesehen, dass es aufsteigend funktioniert. Werde dann 
entweder - wie karlheinz geschrieben hat - immer die werte auf 0 
zurücksetzen oder einfach größere Datentypen für die Variablen 
verwenden.


Danke!

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.