mikrocontroller.net

Forum: Compiler & IDEs STK500-Taster abfragen


Autor: EinSteigÄr (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: johnny.m (Gast)
Datum:

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

Autor: Biff (Gast)
Datum:

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

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

Gruß

Biff

Autor: Michael U. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: EinSteigÄr (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: EinSteigÄr (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
_________________________________________________________________________
#include <inttypes.h>
#include <avr/io.h>

//Für 8 Lichtschranken programmiert
//---------------------------------------------------------------------------
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 */
}
//---------------------------------------------------------------------------

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

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

  uart_puts( Buffer );

}


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

int main (void)
{
int ubergabe=0,ubergabe1=0,ubergabe2=0,ubergabe3=0, ubergabe4=0,ubergabe5=0,ubergabe6=0,ubergabe7=0,ubergabe8=0;
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);          

for(;;)
{
  if (TIFR &(1<<TOV0)) //wenn generell Überlauf, erhöhe Variable "ubergabe" 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;
          
  }
     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;                    //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
  ubergabe8=ubergabe;
  TCCR0=0;
  kontrol=1;
  }

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

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

  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;
  }

}
}




Viiiielen Dank! :)

Autor: EinSteigÄr (Gast)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: EinSteigÄr (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: EinSteigÄr (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: EinSteigÄr (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
sorry! habe was falsches kopiert. Das ist angekommen:

a0b0c0d0e0f0g0h0i0j0k0l0m0n0o142p-10330

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.


Autor: EinSteigÄr (Gast)
Datum:

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

Autor: EinSteigÄr (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Denk aber dran, dass das Formatierzeichen im sprintf
ebenfalls ersetzt werden muss.

Autor: EinSteigÄr (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dann studier mal das hier.
Deine Kopier-Orgien sind ja grauenhaft. Sowas macht
man mit Arrays und ein paar Schleifen.
void SendeWerte( unsigned int Overflows[], unsigned int Values[] )
{
  unsigned char i;
  unsigned char Filler = 'a';

  for( i = 0; i < 8; ++i ) {
    uart_putc( Filler++ );
    wandle( Values[i] );

    uart_putc( Filler++ );
    wandle( Overflows[i] );
  }
}

int main (void)
{
  unsigned int Ueberlauf = 0;
  unsigned int Ueberlaeufe[8] = { 0 };
  unsigned int Zaehler[8] = { 0 };
  unsigned char Tasten[8] = { 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F };
  unsigned char i;
  unsigned char Gesendet = 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
    {
      Ueberlauf++;
      TIFR = 1<<TOV0;
    }

    for( i = 0; i < 8; ++i ) {    // alle Tasten abfragen
      if( PINB == Tasten[i] )     // war die Taste i gedrueckt ?
      {
        Zaehler[i] = TCNT0;       // Werte merken
        Ueberlaeufe[i] = Ueberlauf;

        if( i == 7 ) {            // War das die letzte Taste ?
          if( !Gesendet ) {       // Wurden die Werte schon gesendet ?
            SendeWerte( Ueberlaeufe, Zaehler);  // Nein: Werte senden
            Gesendet = 1;                       // und merken dass schon gesendet wurde
          }
        }
        else
          Gesendet = 0;          // Taste gedrückt, aber es war nicht die letzte Taste
                                 // Wenn das nächste mal die letzte Taste gedrueckt wird
                                 // gibt es wieder was zum Senden
      }
    }
  }
}

Autor: EinSteigÄr (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: EinSteigÄr (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;*/
  }
//---------------------------------------------------------------------- 
--------------------------------------------
}
}





Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.


Autor: EinSteigÄr (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: EinSteigÄr (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.