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ß
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?
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!
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.
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
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...
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
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.
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;
}
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?
Du musst erst mal überprüfen, ob das empfangene Zeichen eine Ziffer
zwischen 0 und 7 ist.
1
if((zahl>='0')&&(zahl<='7'))
2
{
3
//Code
4
}
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...).
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!
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
}
Aber zurück zu deinem Problem.
Ich denke der Fehler liegt hier
1
do
2
{
3
c=uart_getc();
4
if(c!='\r')
5
{
6
*s=c;
7
uart_putc(c);
8
s++;
9
i++;
10
}
11
}
12
while(i!=length&&c!='\r');
13
*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
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()
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....
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.
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.
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.
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:
1
while(1){
2
3
c=uart_getc();
4
uart_putc(c);
5
6
if(c>='0'&&c<='7'){
7
c=c-'0';// aus dem ASCII Code die Ziffer machen
8
PORTB=0xFF;// alle anderen LED aus
9
PORTB&=~(1<<c);
10
}
11
}
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
1
unsignedcharuart_getc(void)
2
{
3
charc;
4
5
do{
6
while(!(UCSR1A&(1<<RXC1))){}// warten bis Zeichen verfügbar
7
c=UDR1;// Zeichen aus UDR zurueckgeben
8
}while(c=='\n');
9
10
returnc;
11
}
aber wehe, du gerätst dann mal an ein Terminal, welches gar keinen
\r und nur \n schickt :-)
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 :-)
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 :-)
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.
1
intmain()
2
{
3
....
4
5
while(1){
6
7
c=uart_getc();
8
9
if(c=='\n')
10
uart_puts("\\n");
11
12
elseif(c=='\r')
13
uart_puts("\\r");
14
15
elseif(c=='\t')
16
uart_puts("\\t");
17
18
else
19
uart_putc(c);
20
}
21
}
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.
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?
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.