Hallo zusammen,
mir raucht der Kopf und ich weiss nimmer weiter.
Ich verwende ein STK 500 mit dem internen Clock von 3,686 MHz, undmöchte
gerne die Uart Libary von Peter Fleury verwenden.
ich habe mal das Beispiel hergenommen und versucht es zum Laufen zu
bewegen.
Es tut, aber ich bekomme nur Murks Ausgaben zurück: Kästchen,
Sonderzeichen, und so weiter.
Als Baudraten hab ich jetzt schon mehreres Versucht, wobei 9600 aber
stimmen sollte. Auch 115200 und 14400 hb ich schon versucht.
hier mein Code
* now enable interrupt, since UART library is interrupt controlled
50
*/
51
sei();
52
53
/*
54
* Transmit string to UART
55
* The string is buffered by the uart library in a circular buffer
56
* and one character at a time is transmitted to the UART using interrupts.
57
* uart_puts() blocks if it can not write the whole string to the circular
58
* buffer
59
*/
60
uart_puts("String stored in SRAM\n");
61
62
/*
63
* Transmit string from program memory to UART
64
*/
65
uart_puts_P("String stored in FLASH\n");
66
67
68
/*
69
* Use standard avr-libc functions to convert numbers into string
70
* before transmitting via UART
71
*/
72
itoa(num,buffer,10);// convert interger into string (decimal format)
73
uart_puts(buffer);// and transmit string to UART
74
75
76
/*
77
* Transmit single character to UART
78
*/
79
uart_putc('\r');
80
81
for(;;)
82
{
83
/*
84
* Get received character from ringbuffer
85
* uart_getc() returns in the lower byte the received character and
86
* in the higher byte (bitmask) the last receive error
87
* UART_NO_DATA is returned when no data is available.
88
*
89
*/
90
c=uart_getc();
91
if(c&UART_NO_DATA)
92
{
93
/*
94
* no data available from UART
95
*/
96
}
97
else
98
{
99
/*
100
* new data available from UART
101
* check for Frame or Overrun error
102
*/
103
if(c&UART_FRAME_ERROR)
104
{
105
/* Framing Error detected, i.e no stop bit detected */
106
uart_puts_P("UART Frame Error: ");
107
}
108
if(c&UART_OVERRUN_ERROR)
109
{
110
/*
111
* Overrun, a character already present in the UART UDR register was
112
* not read by the interrupt handler before the next character arrived,
113
* one or more received characters have been dropped
114
*/
115
uart_puts_P("UART Overrun Error: ");
116
}
117
if(c&UART_BUFFER_OVERFLOW)
118
{
119
/*
120
* We are not reading the receive buffer fast enough,
121
* one or more received character have been dropped
122
*/
123
uart_puts_P("Buffer overflow error: ");
124
}
125
/*
126
* send received character back
127
*/
128
uart_putc((unsignedchar)c);
129
}
130
}
131
132
}
Hoffentlich kann mir einer helfen. Was kann ich noch tun, bzw wo soll
ich schauen ?
Als Terminal habe ich 4 verschiedene versucht. Bei allen das Gleiche.
Erscheinen im Terminalprogramm kryptische Zeichen anstatt ordentlichen
Buchstaben (z. B. ü statt A), liegt das zu 99,9% an einer falsch
eingestellten/erzeugten Baudrate im Mikrocontroller.
Jop soweit war ich schon in der Checkliste.
Der Rest kann es fast nicht sein. Die Baudraten stimmen überein.
Ich verwende aktuell Hterm und Br@yTerminal
AVRTerminal hab ich heute mittag versucht...
mcnanuk schrieb:> Erscheinen im Terminalprogramm kryptische Zeichen anstatt ordentlichen> Buchstaben (z. B. ü statt A), liegt das zu 99,9% an einer falsch> eingestellten/erzeugten Baudrate im Mikrocontroller.>> Jop soweit war ich schon in der Checkliste.
Die Betonung liegt auf 'erzeugt'
Und damit die richtig erzeugt wird muss die Taktfrequenz des Controllers
stimmen.
Das hier
> mit dem internen Clock von 3,686 MHz
bestärkt mich im meiner Vermutung, dass dein µC eben nicht mit 3.686 Mhz
sondern mit den fabrikmässigen 1.0Mhz arbeitet.
einen internen Clock mit dieser Frequenz gibt es nicht. Wenn überhaupt,
dann hast du einen Quarz mit dieser Frequenz am µC hängen. Die Frage ist
allerdings: Ist der aktiv? Hast du das kontrolliert?
ich kenn die Library nicht aber hier steht:
> /* define CPU frequency in Mhz here if not defined in Makefile */>> #define F_CPU 3686000UL
du gibts die Frequenz aber in Hertz und nicht MHz an...
Reading fuses address 0 to 2.. 0xC2, 0xDD, 0xFF .. OK!
CLK_div8 ist nicht gesetzt
Int. RC Osc.; Start-up time: 6 CK + 65 ms habe ich gewählt bei den Fuses
ich dachte damit und der richtigen Jumper Setzung "On-Board software
clock signal connected" läuft das Board mit Standardmässigen 3,686 Mhz
Allerdings verwirrt mich das thema Fuses noch ein wenig
fa
mcnanuk schrieb:> Das heisst ich brauche unbedingt einen Quarz ?
ne, wenn du mit 1MHz auskommt, die der interne Oszilator zu Verfügung
stellt, dann nicht. Allerdings ist dieser nicht sonderlich stabil und
besonders temperaturabhängig...
>Das heisst ich brauche unbedingt einen Quarz ?
Du hast doch oben geschrieben, dass du einen 3,686 Mhz Takt hast. Ob der
von einem angeschlossenen Quarz oder einem externen oszillator kommt,
weiß ich nicht. Ich kenne ja deinen Aufbau nicht.
Das ist jedenfalls das entscheidende, was man mit den Fuses auswählt:
* Externer oszillator oder
* Externes Quartz oder
* Interner RC-Oszillator (ungenau)
Testweise kannst du die Fuseeinstellungen ja mal so lassen wie oben und
im Code 1 MHz als Takt angeben. Mal sehen, was dann passiert...
Grüße,
Peter
Also vielleicht um ein Wort was ich vorhabe:
ich will nur ein Int übergeben über das Uart...
ich habe keine Ahnung, ob der Interne Clock ausreichend ist. Ich dachte
bisher dass mein interner Clock 3,686 MHz ... wiso der jetzt nur 1 MHz
ist, versteh ich nicht.
Peter Diener schrieb:> Testweise kannst du die Fuseeinstellungen ja mal so lassen wie oben und> im Code 1 MHz als Takt angeben. Mal sehen, was dann passiert...
Habs getestet, aber es ändert sich nicht viel, ausser dass andere
Zeichen geplottet werden
So, ich hab das mal eben im Handbuch nachgelesen.
Das STK500 hat eine programmierbare Takterzeugung, bei der
Taktfrequenzen zwischen 0 und 3,68 MHz eingestellt werden können.
Per Jumperkonfiguration kann man diesen Takt auf den Zielprozessor
routen.
Die Fuses müssen dann für "external Clock" konfiguriert sein.
Hier gibt's ein Handbuch als Übersetzung:
http://www.mikrocontroller.net/attachment/42741/STK500-HW-Beschreibung.pdf
Das Wichtige steht auf Seite 28.
Grüße,
Peter
Wenn der XTAL1-Jumper gesetzt ist, liefert die STK500-interne
Takt-quelle den Takt für den AVR. Die interne Taktquelle kann entweder
durch einen Quarz oder durch einen Software-Taktgenerator vom
Bord-Controller betrieben werden. Der Software-Taktgenerator kann von 0
bis 3,68 MHz eingestellt werden. 3,68 MHz ist die Standardeinstellung.
Kapi-tel xy auf Seite xy erklärt wie die Taktfrequenz mit AVR Studio
eingestellt wird.
Wenn das vom Bord-Controller generierte Taktsignal genutzt wird, müs-sen
die Fuse-Bits des AVR auf „external clock“ als Taktquelle konfiguriert
werden.
Das ist mal ein Auzug aus dem STK 500 Handbuch.... Besonders der letzte
Satz ...
Args... das hat mich jetzt einen Tag gekostet :) Aber jetzt tut es...
ich danke für die vielen hilfreichen Hinweise nochmals auf bestimmte
Dinge zu schauen. Ich hab den Fehler woanders vermutet.
Returns in the lower byte the received character and in the higher byte the last receive error.
5
UART_NO_DATA is returned when no data is available.
6
7
Parameters:
8
void
9
10
Returns:
11
lower byte: received byte from ringbuffer
12
13
higher byte: last receive status
Das ist der Auszug aus dem Manual. Meine Frage ist nun, wie ich mittels
C-Code nun an das lower byte rankomme. Soweit ich es verstanden habe,
ist das die Information die geschickt worden ist.
Wie schon geschrieben, möchte ich eine Zahl vom PC empfangen und diese
dann in mein µC Programm einbinden. Da ich eigentlich nur Java wirklich
gut kann, stehe ich jetzt hier etwas auf dem Schlauch. Ich speichere das
ergebnis von uart_getc in einem unsigned int c.
Das sollte doch die 16 bit haben, die man benötigt um die 2 Byte zu
speichern.
Ich hoffe mir kann einer helfen :)
mcnanuk schrieb:> Das ist der Auszug aus dem Manual. Meine Frage ist nun, wie ich mittels> C-Code nun an das lower byte rankomme. Soweit ich es verstanden habe,> ist das die Information die geschickt worden ist.
Ähm.
Peter Fleury hat dir ein wunderschönes Demo-Beispiel gebaut.
Dort kannst du dir das alles ansehen.
Beitrag "Atmega644 UART - Komische Ausgabe"> Da ich eigentlich nur Java wirklich> gut kann, stehe ich jetzt hier etwas auf dem Schlauch.
Das sioll dich aber nicht daran hindern, mit einer Library mitgelieferte
Demos zu studieren.
Dieser Code funktioriert aber nicht so wie ich das erwarte: Unter der
IfElse Abfrage habe ich ich ein lcd_putc auskommentiert. Wenn nur dieses
dort steht, ohne die Schleife, dann wird genau das wiedergeben, was ich
gesendet habe. Allerdings innerhalb der Schleife, wird nur eine
einstellige Zahl wiedergegeben, genauer die letzte Stelle der Eingabe.
Was also mache ich falsch ? Und warum verhällt sich die Methode
innerhalb der Abfrage anders ?
eine Frage, warum benutzt du die Library überhaupt? Der Uart ist im
Grunde sehr einfach zu konfigurieren, in dieser Zeit hättest du das
locker selbst geschafft.
außerdem wärs sicherlich hilfreich, wenn du mal den kompletten Code
posten würdest...
* now enable interrupt, since UART library is interrupt controlled
38
*/
39
sei();
40
41
/*
42
* Transmit string to UART
43
* The string is buffered by the uart library in a circular buffer
44
* and one character at a time is transmitted to the UART using interrupts.
45
* uart_puts() blocks if it can not write the whole string to the circular
46
* buffer
47
*/
48
uart_puts("String stored in SRAM\n");
49
50
/*
51
* Transmit string from program memory to UART
52
*/
53
uart_puts_P("String stored in FLASH\n");
54
55
56
/*
57
* Use standard avr-libc functions to convert numbers into string
58
* before transmitting via UART
59
*/
60
itoa(num,buffer,10);// convert interger into string (decimal format)
61
uart_puts(buffer);// and transmit string to UART
62
63
64
/*
65
* Transmit single character to UART
66
*/
67
uart_putc('\r');
68
69
for(;;)
70
{
71
/*
72
* Get received character from ringbuffer
73
* uart_getc() returns in the lower byte the received character and
74
* in the higher byte (bitmask) the last receive error
75
* UART_NO_DATA is returned when no data is available.
76
*
77
*/
78
c=uart_getc();
79
if(c&UART_NO_DATA)
80
{
81
/*
82
* no data available from UART
83
*/
84
}
85
else
86
{
87
/*
88
* new data available from UART
89
* check for Frame or Overrun error
90
*/
91
if(c&UART_FRAME_ERROR)
92
{
93
/* Framing Error detected, i.e no stop bit detected */
94
uart_puts_P("UART Frame Error: ");
95
}
96
if(c&UART_OVERRUN_ERROR)
97
{
98
/*
99
* Overrun, a character already present in the UART UDR register was
100
* not read by the interrupt handler before the next character arrived,
101
* one or more received characters have been dropped
102
*/
103
uart_puts_P("UART Overrun Error: ");
104
}
105
if(c&UART_BUFFER_OVERFLOW)
106
{
107
/*
108
* We are not reading the receive buffer fast enough,
109
* one or more received character have been dropped
110
*/
111
uart_puts_P("Buffer overflow error: ");
112
}
113
/*
114
* send received character back
115
*/
116
117
/*
118
119
120
121
switch (c) {
122
123
case '1':
124
lcd_clrscr();
125
lcd_puts("Ha \n");
126
break;
127
128
case '2':
129
lcd_clrscr();
130
lcd_puts("Hu \n");
131
break;
132
} */
133
134
135
if(c<100)
136
{
137
lcd_clrscr();
138
lcd_puts("Kleiner 100 \n");
139
lcd_putc((unsignedchar)c);
140
}else{
141
lcd_clrscr();
142
lcd_puts("Größer 100 \n");
143
lcd_putc((unsignedchar)c);
144
}
145
146
lcd_putc((unsignedchar)c);
147
uart_putc((unsignedchar)c);
148
}
149
}
150
151
}
Mein Ziel ist es den vom PC empfangenen Wert in meinem Programm später
weiterzuverwenden. Ich versuche nun mit den Datentypen klar zu kommen.
Und eben hier verwirrt mich das Verhalten von meinem Code. Lasse ich den
IfElse Teil weg, dann wird der korrekte Wert am LCD ausgegeben. Schalte
ich ihn dazwischen, wird bloß die letzte Ziffer ausgegeben. Ich verstehe
einfach nicht warum.
Das c ist ist ein unsigned int.
Wenn ich das richtig verstehe, wird mit (unsigned char)c der LCD Routine
dieses int als Chararray übergeben, und char für char auf dem LCD
ausgegeben.
Aber hier verwirrt es mich nun völlig.
>Das c ist ist ein unsigned int.>Wenn ich das richtig verstehe, wird mit (unsigned char)c der LCD Routine>dieses int als Chararray übergeben, und char für char auf dem LCD>ausgegeben.
So einfach ist das nun auch nicht;)
Lies mal was zu itoa();
Und kauf dir ein C-Buch.
Das ist verkehrt, genauso wie alle nachfolgenden Aufrufe von
uart_puts_P. Denn es reicht nicht aus, dass der String behauptet, im
Flash zu sein, sondern er muss auch dorthin gebracht werden. Schau Dir
mal in der Dokumentation zu <avr/pgmspace.h> an, was z.B. der Macro
PSTR() tut.
Hallo Holger, itoa hilft mir doch nicht wirklich weiter oder? Diese
Methode wandelt mir doch ein Integer in einen String um. In der
variablen c steckt doch mehr als nur der Wert der gesendet wurde.
@ Hc Zimmerer: Der Code ist nicht von mir, es ist das Beispiel aus der
Fleury Libary. Ich könnte diese Zeilen auch löschen, da sie ja nur beim
Einschalten ausgeführt werden, und keine Funktion für mich haben. Ob es
nun richtig ist oder nicht kann ich nicht beurteilen, aber ich vertraue
mal darauf, dass Herr Fleury mehr davon versteht als ich im Moment noch.
>In der variablen c steckt doch mehr als nur der Wert der gesendet wurde.
Ja, das obere Byte ist der Fehlercode und das untere sind die Nutzdaten.
Nutzdaten = c & 0x00ff;
Fehlercode = c & 0xff00;
Korrekt müsste es also heißen:
1
if((c&0x00ff)<100)// ist das Zeichen ein ASCII-Code kleiner 100?
mcnanuk schrieb:> Wenn der XTAL1-Jumper gesetzt ist, liefert die STK500-interne> Takt-quelle den Takt für den AVR.
Wenn du für die Taktquelle des STK500 den Begriff "intern" vermeidest
und durch "STK500-eigenen Takt" ersetzt, reduzierst du die
perspektivische Verwirrung. Um zu vermeiden, dass der interne Takt des
Einen der externe Takt des Anderen ist.
Danke Peter,
leider bringt das auch keine Besserung...
1
if((c&0x00ff)<100)
2
{
3
lcd_clrscr();
4
lcd_puts("Kleiner 100 \n");
5
uart_puts(itoa((c&0x00ff),buffer,10));
6
lcd_puts(itoa((c&0x00ff),buffer,10));
7
}else{
8
lcd_clrscr();
9
lcd_puts("Größer 100 \n");
10
uart_puts(itoa((c&0x00ff),buffer,10));
11
lcd_puts(itoa((c&0x00ff),buffer,10));
12
}
Das terminal empfängt jetzt bei einer Eingabe von 255: 505353
Im LCD lese ich immer Kleiner als 100 und die letzten 2 Stellen der
Terminal Rückgabe hier als 53 werden zurückgegeben.
Hätte nicht gedacht, dass das so ne Nuss wird. Ich habe schon einen
manuellen versuch unternommen, aber auch dort passieren Dinge die sich
mir nicht erschliessen.
Ich häng den Code mal an: Vielleicht will es ja mal jemand checken, ich
finde den Fehler nicht.
Wenn ich 222 Transmitte, bekomme ich 20202000 wieder zurück. Es
schleicht sich irgendwo eine 0 dazwischen.
Hc Zimmerer schrieb:> Das ist verkehrt, genauso wie alle nachfolgenden Aufrufe von> uart_puts_P. Denn es reicht nicht aus, dass der String behauptet, im> Flash zu sein, sondern er muss auch dorthin gebracht werden.
Nö, das passt schon so. Das uart_puts_P der Fleury-Lib ist ein Makro,
das den String selber ins Flash packt.
hat noch irgendjemand einen Tipp für mich. Irgendwie kann es nicht so
schwer sein, aber ich bekomms einfach nicht hin.
1
charBuffer[16];
2
unsignedcharLastCharInBuffer;
3
4
voidAdd(charNeu)
5
{
6
Buffer[LastCharInBuffer++]=Neu;
7
Buffer[LastCharInBuffer]='\0';
8
}
1
lcd_clrscr();
2
uart_putc((c&0x00ff));
3
4
Add((c&0x00ff));
5
lcd_puts(Buffer);
6
lcd_puts("\n");
7
8
9
10
if(atoi(Buffer)<100)
11
{
12
lcd_clrscr();
13
lcd_puts("Kleiner 100");
14
}else{
15
lcd_clrscr();
16
lcd_puts("Bigger 100");
17
}
Sowohl im Terminal als auch auf dem LCD hab ich die gewünschten
Anzeigen, aber für meine IfElse Abfrage... da klappts nicht
Also wenn noch irgendwer nen Tipp hat, oder mir sagen kann, dass ich
völlig auf dem Holzweg bin, dann würde ich mich arg freuen.
Ich bin einen Schritt weiter: Das Problem jetzt, ich schreibe in meinen
Buffer die Zahlen. Allerdings würde ich gerne mit einem Enterdruck im
Terminal den Buffer danach wieder zurücksetzen, da sonst ja die weiteren
Einträge immer weiter in den Buffer geschrieben werden, bis dieser voll
ist.
Am liebsten würde ich den Buffer von Hinten befüllen. Das heisst alles
mit 0 besetzen, und dann meine terminaleingaben rechtbündig eintragen.
Somit hätte ich immer den ganzen Buffer voll, und beim Cast ins int
würden die führenden Nullen nicht stören.
oder eben irgendanders den Buffer resetten. Aber keinen Plan wie.
Buffer[0] = '\0'; klappt nicht
mcnanuk schrieb:> leider bringt das auch keine Besserung...
Kein Wunder.
Du hast ein massives Verständnisproblem.
Übertragen werden Zeichen. Genauer gesagt: Die ASCII Codes der Zeichen!
> Das terminal empfängt jetzt bei einer Eingabe von 255: 505353
Du tippst auf deiner Tatstatur: 255
Über die SChnittstelle wird übertragen:
Der ASCII Code für '2'
der ASCII Code für '5'
der ASCII Code für '5'
Und jetzt holst du dir aus dem Web eine ASCII Tabelle und siehst nach,
welche Codes das sind.
'2' hat den ASCII Code 0x32 oder dezimal 50
'5' hat den ASCII Code 0x35 oder dezimal 53
Hier
1
if((c&0x00ff)<100)
2
{
3
lcd_clrscr();
4
lcd_puts("Kleiner 100 \n");
5
uart_puts(itoa((c&0x00ff),buffer,10));
machst du nichts anderes als den ASCII Code des empfangenen Zeichens
auszugeben. Schlauerweise in dezimal und schlauerweise ohne Leerzeichen
dazwischen, damit man nicht weiß wo ein Code aufhört und der nächste
anfängt :-)
Du musst die einzelnen Zeichen, die du empfängst zuerst einmal zu einem
String zusammensetzen, ehe du dann atoi auf diesen String loslassen
kannst, der dir aus dem String "255" die Zahl 255 generiert.
Und noch was:
Leg dir eine char Variable zurecht. Wenn du von der UART ein gültigfes
Nutzbyte bekommst (erkennbar daran, dass dir die Fleury Lib im HighByte
keinen Fehlercode oder kein 'No Data' mitteilt), dann extrahierst du dir
das Zeichen in diese char Variable. Das ist doch Unsinn in weiterer
Folge ständig mit diesem & 0x00FF weiter zu operieren.
mcnanuk schrieb:> oder eben irgendanders den Buffer resetten. Aber keinen Plan wie.>> Buffer[0] = '\0'; klappt nicht
Logisch.
Deiner Add Funktion ist es sowas von egal, wo das '\0' Zeichen ist. Die
interessiert sich ausschliesslich dafür, welchen Inhalt LastCharInBuffer
hat. Dort kommt das nächste Zeichen hin.
> Am liebsten würde ich den Buffer von Hinten befüllen. Das heisst> alles mit 0 besetzen, und dann meine terminaleingaben rechtbündig> eintragen.
Das willst du mit einiger Sicherheit nicht.
Denn das verkompliziert alles nur ohne das es dir etwas bringt.