mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik STK 500 LED'S über UART


Autor: Bastler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich habe ein STK500 Board und kann inzwischen auf Tastendruck per UART 
einen String an mein Terminalprogramm senden.
Jetzt möchte ich die LED's des STK500 ansteuern und zwar in der Weise, 
das wenn ich eine 2 am Terminalprogramm eingebe, die zweite LED 
angeschaltet wird, bei einer 4 die vierte usw.
Außerdem wäre es schön, wenn das Controller das empfangene Zeichen 
wieder an das Programm zurücksenden würde.
Wie müsste eine solche Funktion aussehen?
Ich verwende einen AT90CAN128 Controller. Der UART ist sende und 
empfangsbereit geschaltet.
Wäre euch sehr dankbar für einen Code oder oder etwas Hilfe.

Gruß

Autor: Patrick (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hast Du hier schon mal nachgesehen? Mir hats geholfen.

http://www.mikrocontroller.net/articles/AVR-GCC-Tu...

Autor: Bastler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja hab ich schon gemacht, komm aber leider nicht wirklich weiter mit der 
einen kleinen Funktion....
Hast Du schon mal sowas ähnliches gemacht, wie ich machen will?

Autor: Bastler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jetzt hab ich es hinbekommen, das ich Strings einlesen kann. Wie muss 
die if nun aussehen, das ich bsp. wenn eine 4 Dez vom Terminalprogramm 
eingelesen wird die vierte LED angeht?
Wäre sehr dankbar für eine Hilfe!

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

Bewertung
0 lesenswert
nicht lesenswert
Ist das jetzt eine Fangfrage?

   if( empfangenes_Zeichen == '4' )
     tu was immer du tun musst um LED Nr 4 einzuschalten


etwas trickreicher ist allerdings diese Variante
Allerdings sollte sichergestellt sein, dass
in empfangenes Zeichen wirklich nur eine Ziffer
von '0' bis '7' steht

  uint8_t NrLed;
  NrLed = empfangenes_Zeichen - '0';
  PORTx = 0x00;      // alle anderen LED aus
  PORTx |= ( 1 << NrLed );

Das geht dann für alle LED Nummern von 0 bis 7.

Autor: Patrick (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was Du auch noch beachten solltest, ist dass die Zahl wirklich Dezimal 
daher kommt und nicht etwa im ASCII-Code.

Autor: Andreas K. (oldcoolman)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie sendest du denn die 2?

tippst du 2 und RETURN ?

dann sendest du den ascii wert des "Buchstabens" 2 !!

somit müßtest du nach den ascii wert abfragen (50)
0=48
1=49
2=50
3=51....

Gruß
andi

Autor: Jörg B. (manos)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Patrick wrote:
> Was Du auch noch beachten solltest, ist dass die Zahl wirklich Dezimal
> daher kommt und nicht etwa im ASCII-Code.
Warum?
Ob ich jetzt auf ==0 oder =='0' abfrage ist doch eigentlich egal...

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

Bewertung
0 lesenswert
nicht lesenswert
Andreas Krieger wrote:
> Wie sendest du denn die 2?
>
> tippst du 2 und RETURN ?

Das macht er mit Sicherheit.

>
> dann sendest du den ascii wert des "Buchstabens" 2 !!
>
> somit müßtest du nach den ascii wert abfragen (50)

Nicht so.
Es ist nicht falsch

  if( Zeichen == '2' )

zu schreiben. Das ist wesentlich selbstdokumentierender als

  if( Zeichen == 50 )  // war das eine ASCII '2'

zu schreiben

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

Bewertung
0 lesenswert
nicht lesenswert
Jörg B. wrote:
> Patrick wrote:
>> Was Du auch noch beachten solltest, ist dass die Zahl wirklich Dezimal
>> daher kommt und nicht etwa im ASCII-Code.
> Warum?
> Ob ich jetzt auf ==0 oder =='0' abfrage ist doch eigentlich egal...

Äh. Nein. Das ist nicht egal.
Das eine mal wird gegen den Zahlenwert 0 geprüft,
das andere mal wird gegen den ASCII Code von '0'
geprüft.


Autor: Bastler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
danke schon mal für die viele Hilfe,
ich habe euch mal den Code gepostet, den ich geschrieben habe.
Leider funktioniert das ganze noch nicht mit der LED.
Ich nutze die funktion atoi() ist das falsch oder frage ich an der 
falschen Stelle ab?

Hier der Code:

#include <stdint.h>
#include <avr/io.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>

#ifndef F_CPU
#define F_CPU 3686400UL     /* Quarz mit 3.6864 Mhz */
#endif
#define length 100  //Textlänge ab welcher Empfangen beendet wird


void uart_putc(unsigned char c)
{
    while (!(UCSR1A & (1<<UDRE1))) {}  // warten bis Senden möglich
    UDR1 = c;                         // Zeichen senden
}

void uart_puts (char *s)
{

  while (*s)          //Sende solange *s ungleich dem Sting Endezeichen 
ist
  {
    uart_putc(*s);
    s++;
  }
}

unsigned char uart_getc(void)
{
    while (!(UCSR1A & (1<<RXC1))) {} // warten bis Zeichen verfügbar
    return UDR1;                    // Zeichen aus UDR zurueckgeben
}



int main (void)
{

DDRB= 0xff;    //Ganzen Port B als Ausgang setzten
PORTB= 0xff;  //LED'S ausschalten

UBRR1L  = 11;                           // Lowbyte ist 11 ( dezimal ) 
ergibt 19,2k bei 3,7Mhz Clocktakt
UCSR1B |=  (1 << TXEN1)|(1 <<RXEN1);  // UART TX und RX einschalten 
(Sendebereit und Empfangsbereit machen)
UCSR1C |= (( 1<<UCSZ11 )|(1<<UCSZ10));  // Asynchron modus Character 
Size 8-bit,2 Stopbit, kein Parity
UBRR1H  = 0;               //Highbite sicher auf 0 setzten damit 
Übertragungsrate stimmt

  uint8_t i;
  int zahl;
 // int test=5;
  char c;
  char* s;
  char string[length+1];


while(1)
{
 zahl=atoi (string);

  if (zahl==4)
{
  PORTB &= ~(1<<PB4);
}
  s=string;
  i=0;

  do
  {
    c=uart_getc();
    if (c!='\r')
     {
      *s=c;
      uart_putc( c );
    s++;
    i++;
     }
  }
  while( i!=length && c!='\r');
  *s=0;

  uart_puts( "\r\n" );
  uart_puts( "eingegebender Text: " );
  uart_puts( string );
  while (!(UCSR1A & (1<<UDRE1))) {}
    uart_puts( "\r\n" );





}

return 0;
}

Autor: Bastler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab jetzt mal folgendes versucht:

zahl = uart_getc();

if (zahl=='4')
{
  PORTB &= ~(1<<PB4);

}


Somit kann ich die 4. LED zwar einschlalten, leider aber nur, wenn das 
erste übertragene Zeichen eine 4 gewesen ist. Wenn ich vorher bsp. eine 
6 oder Hallo übertragen habe, dann geht es nicht mehr?!?! Wie bekomm ich 
das in den Griff? Sicher nur ein paar Zeilen oder?

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du musst erst mal überprüfen, ob das empfangene Zeichen eine Ziffer 
zwischen 0 und 7 ist.
if((zahl >= '0') && (zahl <= '7'))
{
    //Code
}
Nur wenn die Bedingung erfüllt ist, darf die entsprechende LED 
eingeschaltet werden. Und dann kommt das erste Codebeispiel von Karl 
Heinz zum tragen (wobei ich mich frage, ob Du das überhaupt zur Kenntnis 
genommen hast...).

Autor: Bastler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist mir klar, allerdings ändert das nichts daran, das immer nur das 
erste Zeichen eine Zahl sein muss, jedes weitere Zeichen wird nicht mehr 
beachtet, da der Sting nicht durchgezählt wird, wie ich eben schon oben 
beschrieben habe.
Geb ich ne 5 ein, so reagiert zwar jetzt die fünfte LED, jedoch geb ich 
als nächstes eine 3 ein, so passiert nix mehr, geschweigedenn wenn ich 
vor der 5 noch ein Hallo eingegeben habe, dann bekommt man keine LED zum 
leuchten!
Das ist das Problem!

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

Bewertung
0 lesenswert
nicht lesenswert
Mal ne blöde Zwischenfrage: Wozu sammelst du
die Zeichen in einem String?

Warum nicht einfach so
  while( 1 ) {

    c = uart_getc();

    if( c >= '0' && c <= '7' ) {
      c = c - '0';    // aus dem ASCII Code die Ziffer machen
      PORTB = 0xFF;      // alle anderen LED aus
      PORTB &= ~( 1 << c );
    }
  }

Ist doch viel simpler als der ganze Klimbim, den du da
mit String zusammensuchen und atoi treibst.

Autor: Bastler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Karl Heinz, genauso mach ich es inzwischen auch schon, 
funktioniert aber leider eben nicht genau so wie ich es gerne hätte.
Ich kann zwar eine LED einschalten, aber das wars auch schon , eine 
Zweite geht nicht mehr und wenn vor einer Zahl ein anderes Zeichen 
gesendet wurde, bekomme ich keine zum einschalten.
Ich muss irgendwie die Variable zahl nach jedem Return löschen und neu 
bschreiben lassen sonst bekomme ich das nicht in den Griff oder? Wie 
mach ich das?
Hier is mein Code:

zahl = uart_getc();

if ((zahl >= '0') && (zahl<= '7'))            //Wir deine Zahl zwischen 
0 und 7 eingegeben?
{
  uint8_t NrLed;                    //Hilfsvariable int
  NrLed = zahl - '0';
  PORTB = 0xff;                        // alle anderen LED aus
  PORTB &= ~(1 << NrLed);                //Entsprechende LED einschalten
}

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

Bewertung
0 lesenswert
nicht lesenswert
Aber zurück zu deinem Problem.
Ich denke der Fehler liegt hier
  do
  {
    c=uart_getc();
    if (c!='\r')
     {
      *s=c;
      uart_putc( c );
    s++;
    i++;
     }
  }
  while( i!=length && c!='\r');
  *s=0;

Abhängig von deinem Terminal schickt das am Zeilenende
nicht nur \r, sondern auch einen \n. Und ich vermute
mal die Reihenfolge ist: Zuerst der \r und dann der \n.

Da du den \n aber nicht ausfilterst, landet der im String
und damit beginnt der String mit einem \n woraufhin
atoi mit diesem String nichts mehr anfangen kann, da
der ja nicht mit einer Ziffer (oder Vorzeichen) beginnt
sondern mit \n

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

Bewertung
0 lesenswert
nicht lesenswert
Bastler wrote:

> Ich kann zwar eine LED einschalten, aber das wars auch schon , eine
> Zweite geht nicht mehr und wenn vor einer Zahl ein anderes Zeichen
> gesendet wurde, bekomme ich keine zum einschalten.
> Hier is mein Code:
>
> zahl = uart_getc();
>
> if ((zahl >= '0') && (zahl<= '7'))            //Wir deine Zahl zwischen
> 0 und 7 eingegeben?
> {
>   uint8_t NrLed;                    //Hilfsvariable int
>   NrLed = zahl - '0';
>   PORTB = 0xff;                        // alle anderen LED aus
>   PORTB &= ~(1 << NrLed);                //Entsprechende LED einschalten
> }

Das ist nicht der komplette Code.
Zeig mal die vollständige main()


Autor: Bastler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aber gerne, hier ist sie:

int main (void)
{

DDRB= 0xff;    //Ganzen Port B als Ausgang setzten
PORTB= 0xff;  //LED'S ausschalten

UBRR1L  = 11;                           // Lowbyte ist 11 ( dezimal ) 
ergibt 19,2k bei 3,7Mhz Clocktakt
UCSR1B |=  (1 << TXEN1)|(1 <<RXEN1);  // UART TX und RX einschalten 
(Sendebereit und Empfangsbereit machen)
UCSR1C |= (( 1<<UCSZ11 )|(1<<UCSZ10));  // Asynchron modus Character 
Size 8-bit,2 Stopbit, kein Parity
UBRR1H  = 0;               //Highbite sicher auf 0 setzten damit 
Übertragungsrate stimmt

  uint8_t i;
  int zahl;
 // int test=5;
  char c;
  char* s;
  char string[length+1];


while(1)
{

  s=string;
  i=0;

zahl = uart_getc();

if ((zahl >= '0') && (zahl<= '7'))            //Wir deine Zahl zwischen 
0 und 7 eingegeben?
{
  uint8_t NrLed;                    //Hilfsvariable int
  NrLed = zahl - '0';
  PORTB = 0xff;                        // alle anderen LED aus
  PORTB &= ~(1 << NrLed);                //Entsprechende LED einschalten
}



  do
  {
    c=uart_getc();
    if (c!='\r')
     {
      *s=c;
      uart_putc( c );
    s++;
    i++;
     }
  }
  while( i!=length && c!='\r');
  *s=0;

  uart_puts( "\r\n" );
  uart_puts( "eingegebender Text: " );
  uart_puts( string );
  while (!(UCSR1A & (1<<UDRE1))) {}
    uart_puts( "\r\n" );





}

return 0;
}


Ihr armen müsst echt eine Engelsgedult mit mit haben sry....

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

Bewertung
0 lesenswert
nicht lesenswert
Bastler wrote:

Welchen Teil von
  while( 1 ) {

    c = uart_getc();

    if( c >= '0' && c <= '7' ) {
      c = c - '0';    // aus dem ASCII Code die Ziffer machen
      PORTB = 0xFF;      // alle anderen LED aus
      PORTB &= ~( 1 << c );
    }
  }

hast du nicht verstanden?
Das ist bereits die komplette main-Hauptschleife, schmeiss
den ganzen Klimbim mit String-Zusammenwarten raus.
Da ist irgendwo ein Wurm drinn.

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

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger wrote:
> Da ist irgendwo ein Wurm drinn.

Bzw. da läuft schon wieder das \r \n Problem auf.
Du wartest zwar schön, bis der String komplett ist,
dann kommt irgendwann der \r und du stellst den String
fertig, und gibst ihn aus.
Aber dann: Vom Terminal kommt als nächstes der \n
Der wird dann aber erst hier

> while(1)
> {
>
>   s=string;
>   i=0;
>
>   zahl = uart_getc();

von der Schnittstelle abgeholt und da das keine Ziffer ist,
passiert auch nichts mehr.

Wie gesagt: Schmeiss die komplette String Verarbeitung raus.
Du brauchst sie für diese Aufgabenstellung nicht. Oder aber
alternativ sorge dafür, dass dir ein \n nicht in die Quere
kommt.






Autor: Bastler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Sting Verarbeitung würde ich gerne lassen, so gibt mir der 
Controller wenigstens immer die eingegebenen Zeichen an das Terminal 
zurück.
Naja dann werde ich mal schauen wie ich das trotzdem in den Griff 
bekommen.
Vielen Dank trotzem euch allen.

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

Bewertung
0 lesenswert
nicht lesenswert
Bastler wrote:
> Die Sting Verarbeitung würde ich gerne lassen, so gibt mir der
> Controller wenigstens immer die eingegebenen Zeichen an das Terminal
> zurück.

Das tut er so auch:
  while( 1 ) {

    c = uart_getc();
    uart_putc( c );

    if( c >= '0' && c <= '7' ) {
      c = c - '0';    // aus dem ASCII Code die Ziffer machen
      PORTB = 0xFF;      // alle anderen LED aus
      PORTB &= ~( 1 << c );
    }
  }

Aber ok, wenn du das zeilenweise verarbeiten willst (weil
du ev. irgendwann zu einer Art Commandline kommen willst),
dann wirst du nicht umhin kommen, dich um das \n zu
kümmern.

Tip: Wenn du mit Sicherheit weist, dass dein Terminal
immer die Sequenz \r\n bei einem Return schickt, dann
ist das relativ einfach zu brücksichtigen: Die Funktion
uart_getc() ignoriert ganz einfach den \n
unsigned char uart_getc(void)
{
  char c;

  do {
    while (!(UCSR1A & (1<<RXC1))) {} // warten bis Zeichen verfügbar
    c = UDR1;                    // Zeichen aus UDR zurueckgeben
  } while( c == '\n' );

  return c;
}

aber wehe, du gerätst dann mal an ein Terminal, welches gar keinen
\r und nur \n schickt :-)

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

Bewertung
0 lesenswert
nicht lesenswert
Noch ein Tipp:
lagere wenigstens den ganzen 'Warte auf eine komplette Zeile-Teil'
in eine eigene Funktion aus.

a) braucht man das sowieso häufig
b) wird dadurch die Hauptschleife kürzer und übersichtlicher
c) kannst du dich dann mal fragen, wie es eigentlich sein
   kann, dass du in deiner Hauptschleife schon einen Befehl
   auswertest, noch bevor du ihn empfangen hast :-)

Autor: Bastler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ob mein Terminalprogramm das immer so macht, weiß ich leider nicht das 
Programm heißt Terminal v1.9b by bray
Das Programm ist eigentlich ganz gut, allerdings wie es genau sendet, 
keinen Plan.
Danke Für deine Tips, Du bist echt voll der Checker, vielleicht kann ich 
irgendwann in 100 fernen Jahren auch mal so gut programmieren wie Du :-)

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

Bewertung
0 lesenswert
nicht lesenswert
Bastler wrote:
> Ob mein Terminalprogramm das immer so macht, weiß ich leider nicht das
> Programm heißt Terminal v1.9b by bray

Das Problem besteht darin, dass Terminals (und auch Terminal-
simulationen) normalerweise konfigurierbar sind, wie sie
Return behandeln sollen.

> Das Programm ist eigentlich ganz gut, allerdings wie es genau sendet,
> keinen Plan.

Für solche Zwecke ist es immer gut, wenn man ein kleines
Testprogramm in petto hat, welches exakt jedes Zeichen,
aber auch wirklich jedes Zeichen, in lesbarer Form mit-
protokolliert. Das heist dann auch: anstelle von \n muss
die Ausgabe dann '\\' 'n' lauten, anstelle von \r kommt '\\' 'r'
und anstelle von \t kommt '\\' 't'.
So dass man exakt mitlesen kann welche Zeichen nun wirklich über
die Schnittstelle in welcher Reihenfolge kommen.
int main()
{
  ....

  while( 1 ) {

    c = uart_getc();

    if( c == '\n' )
      uart_puts( "\\n" );
 
    else if( c == '\r' )
      uart_puts( "\\r" );

    else if( c == '\t' )
      uart_puts( "\\t" );

    else
      uart_putc( c );
  }
}

Damit kannst du dann ganz leicht untersuchen, was denn nun
wirklich gesendet wird (die restlichen Sonderzeichen kleiner
als Leerzeichen im ASCII Code muesste man noch behandeln)
und mal überlegen, wie dein Programm darauf reagiert.

Ja: manchmal muss man sich Debug-Hilfsmittel selbst bauen
um dahinter zu kommen, was da eigentlich passiert.

Autor: Bastler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hey Karl Heinz,

kann das wirklich sein, das mein Terminal garkein \n und \r schickt?
Hab gerade mal dein Testprogramm ausprobiert. Ich bekomme immer genau 
das zurück geliefert, was ich eingebe, aber nie ein \\r oder \\n obwohl 
ich Strings eingebe und auch Return drücke... Kann das sein?

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

Bewertung
0 lesenswert
nicht lesenswert
Bastler wrote:
> Hey Karl Heinz,
>
> kann das wirklich sein, das mein Terminal garkein \n und \r schickt?
> Hab gerade mal dein Testprogramm ausprobiert. Ich bekomme immer genau
> das zurück geliefert, was ich eingebe, aber nie ein \\r oder \\n obwohl
> ich Strings eingebe und auch Return drücke... Kann das sein?

Glaub ich nicht.
Eines von beiden (oder alle beide) müssten kommen.


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.