Hallo,
ich als erfahrener Programmierer und uC-Anfänger habe mir ein
eHajoEtaval-Board und ein Atmega8-16PU besorgt, um über kleine
Beispielprojekte in die Mikrocontroller-Welt einzusteigen. Die erste
Aufgabe besteht für mich nun Daten vom uC auf den PC zu bekommen, um so
printf-Debugging betreiben zu können und damit nicht ganz blind zu sein.
Leider habe ich keinen Debugger (eventuell kann mir da jemand einen Tipp
geben wie ich das kostenkünstig dann doch hinbekomme mit meinem Board)
und da erschient mir UART als Möglichkeit zum Debuggen sinnvoll zu sein.
Daraufhin habe ich mir einen USB-TTL-Adapter gekauft und
losprogrammiert. Mithilfe der Doku war es auch nicht schwer eine
funktionsfähige Verbindung hinzubekommen. Jedoch habe ich ein wenig
gegooogelt weil ich gedacht habe, dass ich nicht der einzige sein kann
der dieses Problem gelöst hat und so eine Bibliothek gesucht habe, die
mir ein wenig unter die Arme greift. Jetzt habe ich 2 Libs ausprobiert
(u.a. AVR-UART-lib) und diese nicht richtig zum laufen gebraucht. Die
Zeichenketten, die auf meinen PC ankommen sind immer falsch. Kann mir
jemand eventuell einen Tipp geben was ich falsch gemacht habe.
1
#include<avr/io.h>
2
#include<util/delay.h>
3
#include<avr/interrupt.h>
4
5
// Defines:
6
#define LED1 (1<<PD5)
7
#define LED2 (1<<PD6)
8
9
extern"C"
10
{
11
#include"AVR-UART-lib/usart.h"
12
}
13
14
boolbUseLib=false;
15
#define BAUD 9600UL
16
#include<util/setbaud.h>;
17
18
voiduart_init(void)
19
{
20
UBRRH=UBRRH_VALUE;
21
UBRRL=UBRRL_VALUE;
22
#if USE_2X
23
UCSRA|=(1<<U2X);
24
#else
25
UCSRA&=~(1<<U2X);
26
#endif
27
28
// Enable Receiver and Transmitter
29
UCSRB|=(1<<TXEN)|(1<<RXEN);
30
// Set frame format: 8data, 2stop (USBS=1) bit, asychon (umsel=0)
//stdin = &uart0_io; // uart0_in and uart0_out are only available if NO_USART_RX or NO_USART_TX is defined
42
}
43
else
44
{
45
uart_init();
46
}
47
48
// Globales Interruptflag einschalten:
49
sei();
50
51
// LED-Pins als Ausgang definieren
52
DDRD|=LED1|LED2;
53
54
// LED1 einschalten
55
PORTD|=LED1;
56
57
while(1)
58
{
59
PORTD^=LED1|LED2;
60
_delay_ms(1000);
61
62
char*pstr="Hallo\0";
63
if(bUseLib)
64
{
65
uart0_putstr(pstr);
66
}
67
else
68
{
69
for(constchar*pP=pstr;*pP!='\0';++pP)
70
{
71
while(!(UCSRA&(1<<UDRE))){}
72
UDR=*pP;
73
}
74
}
75
}
76
77
return0;
78
}
Der Code ist nicht sehr schwer. Ich schalte zusätzlich 2 Leds, um zu
sehen, ob das Programm auch wirklich läuft. Wenn ich nun bUSeLib=true
setze, dann kommt nichts richtiges mehr auf der anderen Seite an.
Eigentlich kann das doch nicht so schwer sein, weil ich es mit dem
Handbuch doch auch leicht hinbekommen habe. Habe ich eventuell eine
fehlerhaft Lib verwendet? Wo holt ihr euch die Libs? Gibt es eine gute
Anlaufstelle für verschiedene Probleme?
Danke im Voraus
Als "erfahrener Programmierer" ist es mir unmöglich, aus den gemachten
Angaben und dem Programmschnipsel etwas Brauchbares herauszulesen; mir
fehlt alles Wesentliche. Also: versetzen Sie sich in unsere Lage und
überlegen Sie, was alles an Angaben fehlen könnte.
Übrigens:
> Mithilfe der Doku war es auch nicht schwer eine> funktionsfähige Verbindung hinzubekommen.
Ist doch prima, so hatte ich auch mal angefangen, und mir dann meine
Bibliotheken selbst geschrieben (in Assembler, nur am Rande).
Was ist das denn für ein merkwürdiges Konstrukt?
Und warum wird der UART offenbar mit 2 Stoppbits initialisiert und
weiter unten in den Kommentaren steht 8n1? Und zwei
uart_init-Funktionen, einmal mit, einmal ohne Parameter?
Christoph W. schrieb:> ich als erfahrener Programmierer und uC-Anfänger habe mir ein> eHajoEtaval-Board und ein Atmega8-16PU besorgt, um über kleine> Beispielprojekte in die Mikrocontroller-Welt einzusteigen.
[...]
> und so eine Bibliothek gesucht habe, die> mir ein wenig unter die Arme greift.
Falscher Ansatz. Wenn du wirklich µC beherrschen lernen willst, ist die
Verwendung irgendwelcher Libs genau der falsche Weg.
Kann man ja schon sehr schön sehen: du hast keinen Plan, wie du das
Debugging (der Lib bzw. deiner Verwendung selbiger) angehen willst. Und
das, obwohl du immerhin schon LEDs zur Debugausgabe verfügbar hast...
Das spricht übrigens definitiv nicht für einen wirklich "erfahrenen"
Programmierer, als den du dich darstellst... Alles, was du wohl bist,
ist ein Lib-Zusammenleimer, aber auch da nicht sonderlich erfahren,
sonst hättest du schon Debugstrategien für dein Problem...
FS schrieb:> Was ist das
Das ist C++, auch wenn man es dem Code sonst nicht ansieht.
Komische Zeichen aus der Usart kommen eigentlich immer durch eine
falsche Baudrate. Falscher CPU-Takt, falsche Initialisierung, oder
prinzipbedingt ungenauer Takt können Ursachen sein.
Oliver
Der Atmega8 hat keine Debugging Schnittstelle.
Was die Library angeht, darfst du gerne mal meine versuchen:
http://stefanfrings.de/avr_hello_world/index.html
Sie verwendet nur für den Empfang einen Puffer. Gesendet wird direkt
blockierend.
Ich stimme allerdings c-hater zu, dass selber machen lehrreicher ist und
letztendlich auch mit Sicherheit mehr Erfolg verspricht.
Hast du dich mit den Fuses zur Takt-konfiguration und F_CPU beschäftigt?
Ist da alles richtig? Wenn du eine LED blinken lässt (abwechselnd 1s an
und aus) stimmt dann das Timing? Verwendest du den Quarz? Ist die GND
Leitung mit dem PC verbunden?
Hi,
Ui dann habe ich es hier ja mit richtigen Männer zu tun, die ihren Code
selber schreiben und dann am besten in assembler. Leider muss ich auch
feststellen, dass einige nicht nur vom programmieren her vor 30 Jahren
stehengeblieben sind, sondern auch als Persönlichkeit, schade. Alle die
mir Konstruktiv helfen wollen schon mal Dank im Voraus.
Ja das ist C++ (Bitte keine Grundsatzdisskusstion wieso ich C++
verwende). Und ja, wenn ich keine Debuschnittstelle habe, dann lege ich
mir eben eine zurecht und für mich als Laie schien UART das richtige zu
sein (wegen der HW-Kosten um es anzuschließen und weil es einfach
umzusetzen ist) oder könnte ihr mir da Tipps geben? Und ja, bevor ich
programmiere lege ich mir eine Debugstrategie zurecht und das ist genau
diese. Ich finde es wichtig und richtig von der Pieke auf alles zu
programmieren, um viel über das zu lernen was man da macht. Deswegen
habe ich es auch zuerst selber implementiert, aber ich will bewußt eine
Lib nehmen. Der Grund dafür ist, dass ich für mein Projekt eventuell auf
einen anderen Atmel uC gehen möchte (geringer Kosten, kleiner,
Stromsparender, ...) und für mich ist der Große eine Art Spielwiese wo
ich vieles ausprobieren kann. Und die Libs bieten mir genau die
Möglichkeit, ohne das ich später den Applikationscode ändern und ein
neues Datasheet lesen muss.
Es kann nicht Grundlegend falsch sein was ich mit der Lib eingestellt
habe. Meine Beobachtung ist, dass ich 5 Bytes verschicke und auch 5
Bytes ankommen, aber leider die falschen. Wenn ich bewußt etwas falsch
einstelle kommen immer mehr oder weniger Bytes an. Wie gesagt die
Variante mit bUseLib==false (also ohne Lib) geht auch, also gehe ich
davon aus, dass ich alles richtig verdrahtet habe.
Hier die Ausgabe mal richtig mal falsch.
Für mich sieht es so aus, dass bei den falschen Bits das 5te Bit einfach
nach vorne wandern müsste und es würde alles richtig sein. Es kommt mir
also nicht ganz falsch vor und davon würde ich ausgehen, wenn ich die
Baudrate falsch einstelle.
Übrigens die Fuse-Bits habe ich nicht angefaßt und läuft damit mit 1Mhz
takt. Ich habe extra die Leds benutzt um zu schauen ob der Takte (1hz)
stimmt, den ich angegeben habe. F_CPU habe ich als Präprozessor-Variable
angegeben, deswegen taucht das nicht auf.
Grüße
Christoph W. schrieb:> Ui dann habe ich es hier ja mit richtigen Männer zu tun, die ihren Code> selber schreiben und dann am besten in assembler.
Ich kann das auch in C oder notfalls auch in C++ und auch noch in
etlichen anderen Sprachen. Im Tiefschlaf und eventuell sogar mit 3.8‰
auf'm Turm.
Du allerdings offensichtlich nicht. Und deswegen solltest du vor allem
eins lernen: deinen Fähigkeiten angemessenene Bescheidenheit.
> Und ja, wenn ich keine Debuschnittstelle habe, dann lege ich> mir eben eine zurecht
Du hast die LEDs. Die SIND eine Debugschnittstelle. Bei der
µC-Entwicklung sogar sehr oft die einzig mögliche!
Nutze sie also erstmal zum Debugging bezüglich der gewünschten
UART-Funktionalität. Das würde jeder erfahrene Programmierer so machen.
Nur Vollidioten suchen statt dessen nach der nächste UART-Lib, bis sie
eine gefunden haben, die mehr oder weniger zufällig in genau dieser
einen konket vorliegenden Konfiguration der Zielhardware funktioniert...
Nein, das machen nur (Ardu)Idioten so...
Moeglicherweise hast du keinen Quarz sondern den internen RC Oszillator
verwendet. Der waere dann zu ungenau. und macht solche Fehler, von
Bitverschieben.
Zweitens war der Mega8 die falsche Wahl. Der hat nichts, der kann
nichts. Ich wuerde eher etwas in Richtung Mega 644 gehen. Auch im 44pin
gehause, dafuer 2 Uarts und 64k Flasch
Ich verwende auch keine Libs, sondern hab etwas was fuer meine
Anwendugne optimiert ist. Ich hab Master-Slave betrieb, bedeutet
Senden-Empfangen nicht gleichzeitig. Und verwende einen linearen Buffer,
keinen Ringbuffer.
Christoph W. schrieb:> Für mich sieht es so aus, dass bei den falschen Bits das 5te Bit einfach> nach vorne wandern müsste und es würde alles richtig sein. Es kommt mir> also nicht ganz falsch vor und davon würde ich ausgehen, wenn ich die> Baudrate falsch einstelle.
Vielleicht bist du ein erfahrener Programmierer, aber du bist ganz gewiß
kein erfahrener Mikrocontroller-Anwender.
Also versuchen wir es mal mit ein wenig Denken:
1. Ansatzpunkt: Was passiert, wenn die Baudrate bei Sender und Empfänger
absolut gleich ist? Klar: man kann senden, was man will und es kommt
niemals aus dem Tritt.
2. Ansatzpunkt: Was passiert, wenn die Baudrate bei Sender und Empfänger
eben NICHT gleich ist, sondern nur so etwa gleich? Dann läuft das Ganze
für ein paar Bits durchaus synchron, aber irgendwann eben nicht mehr.
Der Ausweg: man stellt den Sender auf 2 Stopbits ein. Dann hat die
Übertragung ein ganzes Bit, um sich am Beginn des nächsten Zeichens
wieder auf dessen Startbit zu synchronisieren.
Nach meiner Erfahrung haben einige der üblichen USB-seriell-Adapter
genau das Problem, was du beschrieben hast, wenn man am µC nur mit einem
Stopbit sendet und die Baudrate (von beiden Teilen) nicht sehr exakt
übereinstimmt.
Also stelle mal auf deinem µC zwei Stopbits ein und versuche es damit.
W.S.
Christoph W. schrieb:> Wenn ich nun bUSeLib=true> setze, dann kommt nichts richtiges mehr auf der anderen Seite an.> Eigentlich kann das doch nicht so schwer sein, weil ich es mit dem> Handbuch doch auch leicht hinbekommen habe. Habe ich eventuell eine> fehlerhaft Lib verwendet? Wo holt ihr euch die Libs?
Hey Christoph,
ich habe das grad mal aus Spaß getestet und ja, irgendwas passt da
nicht.
Aber das gute daran ist doch, das was du selbst geschrieben hast,
funktioniert!
Ich würde mir nicht die Mühe machen und den Grund für ein Fehlverhalten
in einer Lib suchen, wenn man es eben selbst schreiben kann.
Dafür das du nur eine Debug-Ausgabe auf deinem ATmega8 haben möchtest,
ist die AVR-UART-LIB viel zu überladen.
Hi
Nun, hier wird anscheinend ein Mega8 mit der internen Takterzeugung von
1 MHz
betrieben. Nicht so gut für serielle Datenübertragung. Es gibt hier auf
der Website sehr gute Tutorials. In Assembler, vermutlich aber auch in
C.
@Christoph
Du schreibst von dir, das du erfahrener Programmierer bist, warum? Uns
beeindruckt das nicht. Im Gegenteil, denn dein Auftreten lässt dich n
einem anderen Licht erscheinen. Ich habe viele Jahre Maschinen
programmiert, mich mit Pascal, Basic und Assembler befaßt und auch
einiges durchaus brauchbares produziert, bin aber weit davon entfernt,
mich hier als erfahrenen Programmierer vorzustellen.
Das nur mal so nebenbei. Arbeiten mit Controllern setzt außer der
Fähigkeit Programme zu schreiben ein wenig Kenntnisse der Controller und
der Hardware voraus und Programmiersprache hin und her, auch in C nimmst
du nicht einfach einen x-beliebigen Controller und haust da C drauf und
es läuft völlig ohne ein paar Anpassungen. Wie bereits gesagt, mit dem
1MHz internen Takt kann man zwar Mal probieren, aber nix stabiles
erwarten.
An diejenigen, das ein Mega8 nicht zu debuggen sei, völlig falsch, das
geht auch mit einer LED oder mit dem, was bei Makerconnect unter FAQ in
meinem Buch beschrieben ist. Da dürft ihr gerne drin blättern, auch wenn
es nicht ganz fehlerfrei ist. Aber schwere Fehler hab ich auch schon in
Büchern gefunden, die weit über 50 € lagen.
In dem Sinne, bleibt gesund.
Gruß oldmax
Adam P. schrieb:> Grund für ein Fehlverhalten
Noch eine kurze Anmerkung:
Die Lib funktioniert, jedoch nicht mit deinen 1MHz.
Mit einem 11.0592Mhz ext. Quarz läuft alles problemlos.
Christoph W. schrieb:> Leider muss ich auch> feststellen, dass einige nicht nur vom programmieren her vor 30 Jahren> stehengeblieben sind, sondern auch als Persönlichkeit, schade. Alle die> mir Konstruktiv helfen wollen schon mal Dank im Voraus.
Sowohl c-hater als auch ich programmieren durchaus auch in modernen
Programmiersprachen. Wenn du dir mal meine Homepage anschaust, siehst
du, dass Assembler dort nur eine winzig kleine Ecke belegt. Und der
c-hater hat mit einen tiefgründigen Kenntnissen hier schon einigen C++
programmierern detailliert erklärt, warum etwas nicht so funktionierte,
wie es erwartet wurde.
Insofern kannst du dich solche frechen Sprüche bitte sparen.
Ein bisschen mehr Dankbarkeit für meinen schlanken funktionierenden
Lösungsvorschlag in C wäre auch angebracht. Wenn du das gelesen hättest,
wüsstest du auch über die Tauglichkeit des R/C Oszillators und der 1MHz
Taktfrequenz bescheid.
Die wenigen Zeilen Code kannst du gerne in eine C++ Klasse verpacken,
wenn du magst und darin mehr Sinn erkennst, als ich. Aber heule dann
nicht, dass puts(), printf(), scanf(), etc. alle nicht funktionieren.
Christoph W. schrieb:> Habe ich eventuell eine> fehlerhaft Lib verwendet?
Welche Lib, ich kann nicht hellsehen. Typisch postet man den Link auf
die verwendeten Sourcen oder man packt das komplette Projekt in ein Zip.
Hi,
danke für den Tipp mit dem Mega644. Ich werde ihn mir anschauen.
Der Tipp das 1Mhz nicht gut sein soll bzw. generell irgendetwas mit dem
internen Oszi nicht stimmt und das die Fehler verursacht ist genau
richtig gewesen. Ich habe die Fuse-Bits so angepaßt das der interne Takt
bei 8Mhz läuft und siehe da es geht nun auch mit der Lib.
Auch auf die Gefahr hin mich weiter als Lib-Schupser zu outen, werde ich
an der Lib erst einmal festhalten. Damit bleibt es mir erspart mich
genau mit den Feinheiten von Atmel8-UART zu beschäftigen mit dem FIFO
und speziellen Registern. Ich möchte das wirklich nur benutzen, um nicht
blind bei der Programmierung zu sein. Für mich wird das was ich noch vor
habe genügend herausfordernd und ich widme mich lieber diesen Details.
Ich verstehe nicht wieso ihr auf diesem "erfahrenen Programmierer"
rumreitet. Wieso stört euch so ein Aussage? Doch nur wenn ihr euch
irgendwie mit mir vergleicht. Wieso solltet ihr das? Ich habe es einfach
hingeschreiben um damit auszudrücken, dass ihr mit mir als Programmierer
reden könnt (ich also die Begrifft recht gut verstehe) und ihr mir
Code-Beispiele geben könnt. Und mit dem µC-Anfänger will ich genau das
Geneteil ausdrücken. Auch das µC-Anfänger ist relativ, wie das mit dem
erfahrenen Programmierer. Darüber regt sich aber keiner auf. Im
Gegensatz zu meiner Oma würde ich mich aber schon als erfahrener
Programmierer bezeichnen, aber auch als erfahrener µC-Programmierer :-)
Nochmals danke für euch Hilfe. Spannend mit euch zu reden.
Grüße
> Tipp mit dem Mega644. Ich werde ihn mir anschauen
Dann möchte ich Joggel E. ein wenig korrigieren (ich wurde nicht umsonst
an anderer Stelle als Pedant bezeichnet): es fehlt ein "P", also
ATmega644P, der ATmega644 hat nur einen USART. Übrigens könnte man dann
gleich auf den ATmega1284P umsteigen, mit seinen 16 KiB RAM und Timer3.
Oder, warum nicht, falls es räumlich kleiner sein soll, der AVR128DA28.
Nur der ATmega8, der ist "vor 30 Jahren stehengeblieben" - na ja,
nicht ganz.
> Der Tipp das 1Mhz nicht gut sein soll ... ist genau richtig gewesen.
So ganz klar ist mir das nicht: gleich zu Beginn hieß es
> Mithilfe der Doku war es auch nicht schwer eine> funktionsfähige Verbindung hinzubekommen.
Da muss also ganz bewusst, nach Studium des Datenblattes, das UCSRA.U2X
eingeschaltet worden sein, sonst hätten 9600 Bd bei 1 MHz nie&nimmer
funktioniert, bei einem Fehler von 7 %. Wenn also in der Dokumentation
dieser Library nicht explizit auf die Eigenheiten des Schalters USE_2X
hingewiesen wurde, so hätten Sie doch spätestens an dieser Ihrer
Programmstelle
stammt aus util/setbaud.h von der mitgelieferten avr-lib, die dabei ist.
Intern wird über eine Formel überprüft wie der eingestellte Takt und die
Baudrate im Verhältnis stehen und im Fall von 1Mhz und 9600bps wurde
USE_2X=1 gesetzt.
Schönen Abend euch