PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : einige Fragen zu Grundlagen der C-Programmierung



jagdfalke
20.11.2005, 20:31
Hi,
ich mach gerade das mir empfohlene Tut durch und kapier einiges nicht:
1. Was ist ein Register?
2. ein Code-Beispiel aus dem Tut:


#include <avr/io.h>
#include <stdint.h>

uint8_t foo;

int main (void) {
foo = PINB;
}


Warum werden die Packete io.h aud stdint.h hinter # eingebunden? Ich dachte # markiert Kommentare !?

Warum gibt main ein int zurück? Ich komme von Java, und da gibt main nix zurück, warum auch !? Andereseites steht in Klammern "void", was bei Java heißt, dass eine Methode nix zurückgibt. (das versteh einer :S)

Was soll dieses PINB ? Ist das ne Variable, die in dem Codeausschnitt nicht definiert wurde, oder eine feste Variable aus einem der Packete? Hä?

Hmm, ich glaubt das wäre es bis jetzt. Mehr fällt mir im Moment nicht ein.
Ich hoffe ihr könnt meinem verwirrten Gehirn helfen.

mfg
jagdfalke

izaseba
20.11.2005, 20:41
ups,
sorry ich gebe Dir noch ein Link zu C allgemein : hier (http://www.pronix.de/pronix-4.htm) ist ein Openbook "C von A bis Z", und hier (http://wwwuser.gwdg.de/~kboehm/ebook/inhalt.html) ist noch
ein Tutorial zu C unter Linux.
Dort findest Du Antworten auf die meisten Fragen.

Gruß Sebastian

EDIT: Ich sehe gerade, der erste Link geht nicht direkt :-( einfach auf "Open Books" und dann "C von A bis Z" drücken

jagdfalke
20.11.2005, 20:44
also dein Link zu C allgemein funktioniert nicht. Aber der andere hilft mir bestimmt schon.
Danke!
mfg
jagdfalke

jagdfalke
20.11.2005, 21:40
Ich hab jetzt schon 4 Tage von dem Tut durch, aber meine Frage wurden noch nicht beantwortet.
btw: kann der avr Rekursion? (ist ja sehr ram-intensiv)

Was bedeuten immer diese "%d" ?? Das wurde auch noch nicht erklärt, aber ständig benutzt.

mfg
jagdfalke

maze2k
20.11.2005, 23:27
%d ist ein Platzhalter für einen Double-Wert.
PINB ist wohl irgendeine Registeroperation, bei der irgendein Byte rumgeschoben wird :)

Das ganze wird hinter # eingebunden, weil das in C so ist.

Die wichtigsten Dinge, die hinter einer # sind:
#include <package.h>
und
#define konstante wert

Ein Register ist ein Speicher für eine Zahl in deiner Hardware.

Zu deiner Frage mit der Rekursion: probier's aus. Normalerweise sollte es funktionieren. Ich weiss auch nicht ob der Compiler automatisch rekursionen auflöst...Aber ich denke, es geht. Probiers.

Ich komme auch aus der Java-Welt und tue mir mit C etwas schwer. Such dir doch ne Java VM für deinen µC...

izaseba
20.11.2005, 23:51
@maze2k,
ich will Dich ja nicht beleidigen, aber bevor Du sowas postest, poste lieber garnichts!

Gruß Sebastian

askazo
21.11.2005, 07:03
Ich versuche mal, Deine Fragen ausführlich zu beantworten:

1) Was ist ein Register?
Über Register wird ein µP eingestellt bzw. der µP stellt Informationen darüber zur Verfügung. Im Prinzip ist es nichts anderes als Speicherplatz auf bestimmten Adressen im internen RAM des Prozessors.
Es gibt z.B. ein Register DDRB (Data Direction Register B). In diesem Register kannst Du einstellen, welche Pins von Port B als Eingänge und welche als Ausgänge benutzt werden. Am besten schaust Du mal ins Datenblatt Deines AVRs, dort sind alle Register ausführlich beschrieben.

2) - In C beschreibt '#' eine Compiler-Anweisung. Ein Kommentar ist entweder // (einzeilig) oder /* kommentar */ (mehrzeilig).
- Manche C-Compiler wollen von der main-Funktion einen Rückgabewert haben. Keine Ahnung warum, ist einfach so. Stör Dich nicht weiter dran.
In den Klammern stehen ein oder mehrere Werte, die der Funktion als Parameter übergeben werden. Die main Funktion bekommt keine Parameter, also steht void drin.
- PINB ist ein Makro für Register. Die Definitionen der Register-Makros stehen in der io-Bibliothek Deines AVRs, die über die io.h eingebunden wird. PINB ist das Eingangsregister für Port B. Mit diesem Programm liest Du also den Zustand der Eingänge an Port B in die Variable foo ein.

Gruß,
askazo

jagdfalke
21.11.2005, 07:33
Danke askazo, das hat mir schon sehr geholfen.
Eine Frage noch:


Mit diesem Programm liest Du also den Zustand der Eingänge an Port B in die Variable foo ein.

Mich verwundert der Plural etwas: Wie kann man mehrerer Zustände in einer uint8_t-Variable speichern?

askazo
21.11.2005, 07:49
Der Typ uint8_t ist 8 Bit groß.
Der Port B hat 8 Eingänge, das Register PINB ist ebenfalls 8 Bit groß.
Jedes Bit steht für den Zustand eines Eingangs, also kannst Du alle 8 Eingangszustände in foo speichern.

askazo

SprinterSB
21.11.2005, 09:15
Warum werden die Packete io.h aud stdint.h hinter # eingebunden? Ich dachte # markiert Kommentare !?

Kommentare in C werden mit /* begonnen und mit */ wieder beendet. Es gibt auch die Kurzform // um bis zum Zeilenende auszukommentieren, aber das ist kein ANSI-C. Geht aber mit avr-gcc (ohne Option -ansi natürlich ;-))

# gehört eigentlich nicht zu C. Das kennzeichnet Präprozessor-Dirktiven wie

#include
#define
#undef
#if
#ifdef
#else
#endif
#error
#warning
#pragma

Bevor der eigentliche Compiler zum Zuge kommt rauscht ein Präprozessor über die Quelle und macht Textersatz.

Wenn du zB hinschreibst PINB (ein in avr/ioxxxx.h definiertes Makro), macht der Präprozessor so was draus:

(*(volatile uint8_t *)((0x16) + 0x20))

Für nen Compiler ist das verständlich, für Menschen weniger. Es bedeutet so viel wie "Inhalt der Speicherstelle an Adresse 0x36". An dieser Adresse liegt das ober werklärte PINB-Register -- zumindest beim ATMega8. Über das Makro PINB kann man besser leserlich auf dieses Register zugreifen.


Warum gibt main ein int zurück? Ich komme von Java, und da gibt main nix zurück, warum auch !? Andereseites steht in Klammern "void", was bei Java heißt, dass eine Methode nix zurückgibt. (das versteh einer :S)

In Java bedeutet das nicht, daß eine Funktion nix zurückgibt, sondern daß sie keine Parameter hat. In C ist das genauso. main() hat keine Eingabeparameter -- woher auch.
main() gibt allerdinge einen int zurück. Das ist Konvention in C, um Werte an eine shell zurück zu liefern. In Java müsste man das mit System.exit(xxx) machen. Auf einem embedded System läuft keine shell, daher ist das return int unnötig. Wenn man aber hinschreibt

void main()

bekommt man eine lästige Compiler-Warnung. Diese vermeidet man mit der gcc-Option -ffreestanding, die sagt, daß das Programm alleine läuft, also nicht in einer Umgebung mit shell.


btw: kann der avr Rekursion? (ist ja sehr ram-intensiv)
Der AVR kann alles, was ein Compiler ihm in der Lage ist zu verklickern :-)
Für avr-gcc heisst das: Rekursion geht.
Speicherverbrauch ist ein kritisches Thema auf nem Hänfling wie AVR. Da muss man schon ein Auge drauf haben...

jagdfalke
21.11.2005, 12:28
Ok, es reicht also aus, wenn ich "PINB" als eine Art System-Variable ansehe. Bei welchem Controller PINB welches Register ist, wird über diese Packages geklärt, nehm ich mal an.

Schreibt printf() eigentlich auf dem AVR dann auf RS232 ? Mit welchem Programm kann ich auf meinem PC darstellen, was vom Controller kommt?

Wo finde ich denn ne API für C? Ist C eigentlich oo? Bis jetzt hab ich nämlich noch keine Klassen gesehen. Wenn es Klassen gibt: Kann man dann Klassen auf dem AVR benutzen? (vieeele Fragennn...)

mfg
jagdfalke

askazo
21.11.2005, 12:56
-PINB ist ein Register das zum Port B gehört. Würdest Du Port A auslesen wollen, nimmst Du PINA. Welcher Port wo ist und welche Register dazu gehören, steht im Datenblatt.

- es gibt zwar die Funktion printf im gcc, aber ich habe sie noch nicht benutzt und kann auch nicht sagen, was sie macht. Aber auf die serielle Schnittstelle schreibt sie afaik nicht. Man kann sich aber relativ einfach eine Funktion bauen, die genau das macht. Um die Daten auf dem PC darzustellen, nimmst Du am Anfang am besten das HyperTerminal. (Wenn Du unter Windows arbeitest...)

- C ist nicht objektorientiert. Also gibt es auch keine Klassen...

askazo

jagdfalke
21.11.2005, 13:05
Kannst du mir sagen wie ich mir so eine Funktion schreiben kann, die auf RS232 schreibt bauen kann? Dann hätte ich wenigstens schon mal einen kleinen Erfolg auf dem ich aufbauen könnte.
mfg
jagdfalke

askazo
21.11.2005, 13:37
Sag doch bitte mal kurz, mit welchem Prozessor Du arbeitest. Dann könnte ich direkt ein paar Codeschnippsel liefern.
Zudem solltest Du einen externen Quarz verwenden, da der interne Clock-Generator für eine RS232-Übertragung zu ungenau ist.

jagdfalke
21.11.2005, 14:09
Mein Prozessor ist der Atmega32. So ein Quarz ist da schon drauf. Kenn mich nicht wirklich gut aus mit den Sachen, wäre also nett, wenn du die Codeschnipsel gut auskommentieren könntest.

Welches Programm kann ich unter Linux statt Hyperterminal benutzen? Geht telnet irgendwie?

Danke
jagdfalke

jagdfalke
21.11.2005, 15:36
Ich hab was in der Doku des RNBFRA gefunden:

die wichtigsten Board-Adressen:



RS232 TX: Port PD1
RS232 RX: Port PD0


Was ist nun wieder ein Port?
Wie das in C verwendet wird kann man nicht rauslesen, da die Codebeispiele in Bascom geschreiben sind (zum schreiben print, zum lesen input)

askazo
21.11.2005, 15:39
So, ich habe mal ein kleines Programm geschrieben, das einfach einen einzelnen Buchstaben (in diesem Fall ein x) endlos auf der UART ausgibt.
Hab leider gerade keine Zeit, da noch eine Funktion draus zu basteln, die einen ganzen String ausgibt, aber das sollte kein großes Problem mehr sein. Du musst noch Deine Taktfrequenz anpassen, ich habe jetzt einfach mal 8MHz angenommen.
Ich bin jetzt auch davon ausgegangen, dass Du WinAVR benutzt. Solltest Du einen anderen Compiler verwenden, wird's nicht laufen...


#include <avr/io.h>
#include <avr/sfr_defs.h>


//Einige Makros zur Berechnung des Baud-Raten Registers
#define F_CPU 8000000 // 8MHz Taktfrequenz
#define BAUD_RATE 9600 // gewünschte Baud-Rate für UART
#define BAUD_SELECT (F_CPU/(BAUD_RATE*16l)-1) //Berechnungsformel für das Baud-Raten Register

//Diese Funktion sendet ein einzelnes Zeichen an die UART
void uart_putchar(char c)
{
//warte, bis das Bit UDRE im Register UCSRA gesetzt ist.
//Dieses Bit wird vom Prozessor gesetzt, wenn das Senderegister leer ist
loop_until_bit_is_set(UCSRA, UDRE);
//Übergebenes Zeichen ins Senderegister UDR legen.
//Die Daten werden jetzt an die UART geschickt.
UDR = c;
}


int main (void)
{
//Zuerst muss die UART initialisiert werden

//Hier wird der Sender der UART aktiviert.
//Der Empfänger und die Interrupts bleiben in diesem Beispiel aus
UCSRB = 0x08;

//Jetzt muss noch die Baudrate eingestellt werden.
//Wir weisen dem Register einfach das Makro von oben zu.
UBRRL = BAUD_SELECT;

//Jetzt kommt die Hauptschleife
//Es wird immer das gleiche Zeichen (x) an die UART ausgegeben
while(1)
{
uart_putchar('x');
}
return 1;
}

Gruß,
askazo

jagdfalke
21.11.2005, 20:06
Also das kapier ich noch nicht ganz:
wo kommt die methode loop_until_bit_is_set her? Heißt das, dass Bits nicht immer gesetzt werden, wenn man dem Controller das sagt? Das würde ja allen Grundlagen der Logik widersprechen.

Woher weiß du, wie die ganzen Register heißen? z.B. UCSRB kommt in meine Doku nich einmal vor. (Wer sie sich anschaun möchte: http://www.robotikhardware.de/download/dokurnbfra1.2.pdf )

Und was bedeutet z.B. 0x03 ?? Im AVR-GCC Tut steh es das mit 0 und 1 auf 1 und den Rest auf 0. Hä? Wo soll man das denn aus 0x03 rauslesen?

Warum funktioniert der Code nur mit WinAVR?

mfg
jagdfalke

izaseba
21.11.2005, 20:30
Also das kapier ich noch nicht ganz:
wo kommt die methode loop_until_bit_is_set her? Heißt das, dass Bits nicht immer gesetzt werden, wenn man dem Controller das sagt? Das würde ja allen Grundlagen der Logik widersprechen

lese mal hier

//warte, bis das Bit UDRE im Register UCSRA gesetzt ist.
//Dieses Bit wird vom Prozessor gesetzt, wenn das Senderegister leer ist


Warum widerspricht das der Logik?

Wenn das Senderegister noch nicht leer ist, darf man wohl nichts reinschreiben, sondern man muß auf ein Signal,Flag warten, daß es weitergehen darf, ist das logisch?

Und damit hat das Register UCSRA was zu tun, Lese mal die Dattenblätter zu Deinem AVR.


Woher weiß du, wie die ganzen Register heißen?
Lese Dattenblätter


UCSRB kommt in meine Doku nich einmal vor
ATMega32.pdf, Seite 159



Und was bedeutet z.B. 0x03[/qoote]

0x03 Hex bedeutet 3 Dezi und "000000"11 Binär.
[quote]
Warum funktioniert der Code nur mit WinAVR?
???

Gruß Sebastian

jagdfalke
21.11.2005, 20:47
Ok, jetzt vestehe ich das einigermaßen. Danke !
Doku ungleich Doku, aha ! Aber woher hast du Atmega32.pdf ? Ich hab das gar nicht.


Ich bin jetzt auch davon ausgegangen, dass Du WinAVR benutzt. Solltest Du einen anderen Compiler verwenden, wird's nicht laufen...
Das war mit "Warum funktioniert der Code nur mit WinAVR?" gemeint.

Vielen Danke für deine / eure Geduld!

mfg
jagdfalke

izaseba
21.11.2005, 21:04
Achso,
Das habe ich überlesen :oops:
Also WinAVR ist eine Portierung von gcc-avr nach Windows, deswegen dieses Win, es wird also ohne Probleme bei Dir klappen.

Noch was zu der Funktion
loop_until_bit_is_set(UCSRA, UDRE);

Sie befindet sich in sfr_defs.h und macht nichts, bis das Bit mit dem Namen
vom 2. Parameter (Hier UDRE) im BYTE vom 1.Parameter (hier Register UCSRA) nicht gesetzt ist.
Man könnte das in diesem Fall auch so schreiben:

while (!(UCSRA & (1<<UDRE)));

Ich weiß, die schreibweise ist ja nicht gerade einfach, deswegen vielleicht
C allgemein was üben.
! -> nicht
& - UND Verknüpfung
<< Bits nach links schieben
das ist alles C allgemein.

Ich hoffe, daß es alles so stimmt



Aber woher hast du Atmega32.pdf

Ich habe es mir mal runtergeladen....
Schaue mal hier im Forum im Downloadbereich nach, oder füttere google damit :-)

Ich kann Dich gut verstehen, daß es nicht einfach ist vom Bascom zu C zu wechseln, aber ein Vorteil hast Du dadurch, Du arbeitest ziemlich Hardware nah, und lernst die µC richtig kennen.

Gruß Sebastian

jagdfalke
21.11.2005, 21:11
Ja das merkt man: Krank wie viel Code man brauch um was über UART auszugeben. In Bascom hat print() gereicht :D

askazo
21.11.2005, 21:27
Datenblätter findet man übrigens meistens auf der Seite des Chipherstellers: http://www.atmel.com/dyn/products/product_card.asp?part_id=2014

Krank ist's eigentlich nicht. Es kommt immer darauf an, welche Dinge schon in der Programmiersprache, im Compiler oder in Deinen eigenen Librarys implementiert sind. Wenn Du in C einmal eine Funktion geschrieben hast, die einen String auf die UART ausgibt, packst Du sie in eine Library und brauchst sie beim nächsten Mal nur noch einbinden und aufrufen. Und Sebastian hat Recht - so lernt man den µP recht gut kennen.

askazo

jagdfalke
21.11.2005, 21:45
Ich dachte schon das System der OOP zu lernen war schwierig, aber das setzt nochmal eins oben drauf. Allein aus dem Datenblatt rauszufinden was man wie setzen muss, damit das und das passiert ist ja die Hölle.

mfg
jagdfalke

PS: Mir fehlt immernoch ein brauchbares Programm um mir anzuschaun was da vom Controller über RS232 ankommt. (Linux) Kennt jemand eins?

izaseba
21.11.2005, 22:09
Ja Logo,
ich persönlich benutze minicom,
mag ich am liebsten, aber ich merke es schon, Du bist kein Konsolen Freak,
was hast du? KDE ? Gnome ?
Solltest Du Gnome haben oder die gtk libs, sowieso drauf, nimm gtkterm, ist auch gut, für KDE kenn ich keinen Terminal, gibt es sicher auch.

Gruß Sebastian

jagdfalke
22.11.2005, 07:22
Ich hab mir jetzt auch mal minicom installiert. Muss ich dann bei Serial Device /dev/ttyS0 angeben? Baudrate hab ich auf 9600 gestellt, wie in dem Code.

Pascal
22.11.2005, 12:39
Muss ich dann bei Serial Device /dev/ttyS0 angeben?

du musst bei Serial Device die serielle Schnittstelle angeben, die du auchverwendest

wenn du die erste verwendest, stimmt dein /dev/ttyS0, für die zweite wäre es dann /dev/ttyS1 usw.

jagdfalke
22.11.2005, 16:32
Ok, das hab ich getan: Baud auf 9600, serial port auf /dev/ttyS0. Kabel sollte richtig verbunden sein, da es das selbe ist, das ich unter Window schon erfolgreich benutzt haben. minicom hab ich einfach per "minicom" gestartet. Dann kam "initializing modem", dann wird aber nicht angezeigt, was vom seriellen Port kommt. Also entweder hab ich was mit minicom falsch gemacht oder der Code funktioniert nicht.
Kann jemand helfen?

askazo
22.11.2005, 16:50
Wenn minicom ähnlich funktioniert wie HyperTerminal unter Windows (Also Zeichen von der Tastatur gesendet und empfangene Daten im Terminal angezeigt werden) kannst Du zumindest die minicom-Funktion ganz leicht testen. Verbinde am SUB-D 9 (http://www.mikrocontroller.info/kabelsalat/subd9.html) Stecker Pin 2 und 3 miteinander (mit einem Jumper oder einem Stück Draht). Wenn Du nun Zeichen über die Tastatur eingibst, sollten sie auf dem Terminal angezeigt werden.

askazo

jagdfalke
22.11.2005, 16:57
Also minicom funktioniert einwandfrei. Ich hab in die 2 Stecker, die am Ende des Kabels an die Platine angeschlossen werden mit einem Draht überbrückt. Ich hab alle Zeichen wiederbekommen solange die Brücke da war.
Dh. es muss an dem Programm liegen oder der Platine selber... :(

askazo
22.11.2005, 17:05
Welche Platine benutzt Du denn?

jagdfalke
22.11.2005, 17:10
rnbfra 1.1 mit atmega 32 von robotikhardware.de.
Mir ist aber noch was komisches aufgefallen: Wie gesagt minicom funktioniert, wenn ich RX mit TX verbinde. Wenn ich den Stecker an meinen Controller anschließe kommen nur kryptische Zeichen zurück wenn ich was hinsende, dh. manchmal sind es komische Zeichen, manchmal aber auch das richtige Zeichen. Eigentlich sollte doch er doch auf das Senden von Zeichen überhaupt nicht reagieren oder? Das verstehe ich nicht!

izaseba
22.11.2005, 17:27
manchmal sind es komische Zeichen
Hast Du die Baudrate am µC auch richtig eingestellt ?
Komische Zeichen haben meistens was mit der falsch eingestellten Baudrate zutun.
Hast Du ein Quarz dran oder nur den internen Takt?
Beim internen Takt klappt es eventuell auch nicht immer...

Gruß Sebastian

jagdfalke
22.11.2005, 17:35
Also die Baudrate ist im Programm-Code festgelegt. Hier nochmal der Code zur Erinnerung:


#include <avr/io.h>
#include <avr/sfr_defs.h>


//Einige Makros zur Berechnung des Baud-Raten Registers
#define F_CPU 8000000 // 8MHz Taktfrequenz
#define BAUD_RATE 9600 // gewünschte Baud-Rate für UART
#define BAUD_SELECT (F_CPU/(BAUD_RATE*16l)-1) //Berechnungsformel für das Baud-Raten Register

//Diese Funktion sendet ein einzelnes Zeichen an die UART
void uart_putchar(char c)
{
//warte, bis das Bit UDRE im Register UCSRA gesetzt ist.
//Dieses Bit wird vom Prozessor gesetzt, wenn das Senderegister leer ist
loop_until_bit_is_set(UCSRA, UDRE);
//Übergebenes Zeichen ins Senderegister UDR legen.
//Die Daten werden jetzt an die UART geschickt.
UDR = c;
}


int main (void)
{
//Zuerst muss die UART initialisiert werden

//Hier wird der Sender der UART aktiviert.
//Der Empfänger und die Interrupts bleiben in diesem Beispiel aus
UCSRB = 0x08;

//Jetzt muss noch die Baudrate eingestellt werden.
//Wir weisen dem Register einfach das Makro von oben zu.
UBRRL = BAUD_SELECT;

//Jetzt kommt die Hauptschleife
//Es wird immer das gleiche Zeichen (x) an die UART ausgegeben
while(1)
{
uart_putchar('x');
}
return 1;
}


Mit Quarzen kenn ich mich überhaupt nicht aus. Ich nehm aber mal an, dass es dieses silberne kleine Kästchen direkt neben dem Prozessor ist, da neben dem CoController auch nochmal sowas ist. (kling logisch, ein Quarz für jeden Prozessor) Mal abgesehen davon steht auf dem neben dem MainController 8.000 Mhz, auf dem anderen 4.000 Mhz.

mfg
jagdfalke

askazo
22.11.2005, 17:39
Auf das Senden von Zeichen sollte er in der Tat nicht reagieren, das hört sich etwas seltsam an. Du hast nicht zufällig ein Oszilloskop zur Verfügung? :)

Ich tippe aber auch mal auf eine nicht richtig eingestellte Baudrate.
Hast Du die Fuses auf den externen Quarz eingestellt?

askazo

jagdfalke
22.11.2005, 17:44
Bitte was? Fuses? Ich war froh, dass ich in Bascom nie Fusebits einstellen musste. Keine Ahnung wie ich das mit Linux und C mache :S

Ich hab hier so ein script:


#!/bin/sh
prg="adude"
#
help()
{
echo "prg_fusebit_uc -- read and write fuse bits of the atmega8"
echo ""
echo "Usage: prg_fusebit_uc [-hu] -r|-w Freq"
echo ""
echo "OPTIONS: -h this help"
echo " -r read fuse bytes"
echo " -u use uisp instead of avrdude"
echo " avrdude can automatically detect dapa or avrusb500."
echo " uisp can only be used with the parallel port dapa."
echo " -w write fuse bytes such that a given Freq is used"
echo " a frequency of 0 means external crystal. Possible"
echo " values are 0,1,2,4,8"
echo ""
echo "EXAMPLE: program the fuses to 4MHz internal"
echo " prg_fusebit_uc -w 4"
echo ""
echo "Warning: you can not undo the setting \"external crystal\" unless"
echo " you have a crystal that works."
echo "This script can be easily adapted to different programmer types"
exit 0
}
while [ -n "$1" ]; do
case $1 in
-h) help;shift 1;;
-u) prg="uisp";shift 1;;
-r) opt_r="1";shift 1;;
-w) opt_w="1";freq="$2";shift 2;;
-*) echo "error: no such option $1. -h for help";exit 1;;
*) break;;
esac
done

if [ -z "$opt_r" -a -z "$opt_w" ];then
# one of those options is mandatory
help
fi

hf=0xd9
if [ "$opt_w" = "1" ]; then
case $freq in
0) lf=0xee;echo "Make sure you have a crystal otherwise you can not change this!";sleep 2;;
1) lf=0xe1;;
2) lf=0xe2;;
4) lf=0xe3;;
8) lf=0xe4;;
*) echo "error: no such frequency, -h for help";exit 1;;
esac
fi


if [ "$prg" = "uisp" ]; then
if [ "$opt_r" = "1" ];then
set -x
uisp -dlpt=/dev/parport0 -dprog=dapa --rd_fuses
set +x
echo "Explanation: Fuse Low Byte: 0xe1 (1MHz intern), 0xe3 (4MHz intern), "
echo " 0xe4 (8MHz intern)"
echo " Fuse High Byte should be 0xd9"
exit 0
fi
if [ "$opt_w" = "1" ]; then
set -x
uisp -dlpt=/dev/parport0 -dprog=dapa --wr_fuse_l=$lf
uisp -dlpt=/dev/parport0 -dprog=dapa --wr_fuse_h=$hf
set +x
exit 0
fi

fi
if [ "$prg" = "adude" ]; then
if grep "Vendor=0403 ProdID=6001" /proc/bus/usb/devices > /dev/null ; then
prg="avrusb500"
else
prg="dapa"
fi
if [ "$opt_r" = "1" ];then
set -x
avrdude -p m8 -c $prg -v -q
set +x
echo "Explanation: Fuse Low Byte: 0xe1 (1MHz intern), 0xe3 (4MHz intern), "
echo " 0xe4 (8MHz intern)"
echo " Fuse High Byte should be 0xd9"
exit 0
fi
if [ "$opt_w" = "1" ]; then
set -x
avrdude -p m8 -c $prg -u -v -U lfuse:w:$lf:m
avrdude -p m8 -c $prg -u -v -U hfuse:w:$hf:m
set +x
exit 0
fi
fi



hilft das irgendwie?

izaseba
22.11.2005, 17:56
So kommen wir nicht weiter.....

Unter Windows ist das Board richtig gelaufen?
Hast Du mit Bascom programmiert ?
Hast Du irgendwie eine hex Datei, die 100 % geht ?
Z.B. irgendwas, was Du mit Bascom erstellt hast ?
mach die mal rein und guck, ob es klappt,
wenn nicht kann ich Dir was posten, dann versuchst Du es damit.

naja und nochwas hast Du RX vom PC mit TX und TX vom PC mit RX vom µC verbunden, aber wenn es unter Windows geklappt hat, wird es wohl so sein...

Gruß Sebastian

jagdfalke
22.11.2005, 18:08
Ja Kabel ist richtig verbunden. Ich leider keinerlei überbleibsel aus der Bascom-Zeit (liegt schon ziemlich lange zurück). Wäre nett, wenn du mir was posten könntest.

izaseba
22.11.2005, 20:51
Hallo ich habe eine eine Datei angehängt, entferne das .txt, dann kannst Du sie normal "enttaren".

Das muß klappen, habe gerade auf meinem STK500 ausprobiert...

EDIT:

UPS, Du hast doch Mega32 , oder ?
Wenn ja editiere Makefile und ersetze
MCU = atmega16

in

MCU = atmega32

danach nochmal make :oops:

Ich hatte keinen Mega32 zur Hand, sondern einen 16 deswegen...

jagdfalke
22.11.2005, 21:17
Danke für die Mühe, es hat aber leider zu nichts geführt. Sobald RX und TX vom PC an TX und RX vom Controller hängen bekomm ich auf Tastenanschläge ein falsches Echo.
:(

izaseba
22.11.2005, 21:29
Es gibt da noch eine Möglichkeit, und zwar sollte man zuerst minicom starten,
und erst dann den µC einschalten.
Wenn man das genau anders herum macht, kommt natürlich nur Müll raus.

Gruß Sebastian

jagdfalke
22.11.2005, 21:43
Auch keine Änderung.
So wie ich den Code vestehe sollte Minicom doch mit Zeichen überflutet werden oder? Es kommt aber rein garnichts von selbst an, nur komische Echos.

Beim kompilieren stand sowas wie: "Mit der Uhr stimmt was nicht" usw. Kann es daran liegen?

izaseba
22.11.2005, 22:03
Mit der Uhr stimmt was nicht

Und das auf deutsch ?
mache mal make clear und make > log.txt
und sende mal die log.txt
Das verstehe ich auch nicht :-(
oder machmal cat /dev/ttyS0 und dann den µC einschalten,
mal sehen was dann in die Konsole reinkommt,
es kann doch nicht so schwer sein :-(

Gruß Sebastian

stochri
22.11.2005, 22:07
Ja das merkt man: Krank wie viel Code man brauch um was über UART auszugeben. In Bascom hat print() gereicht

C ist eher was für professionelle Programmierer. Wenn alles mit Bascom funktioniert was Du machen willst und Du nicht den Anspruch hast, Deine Kenntnisse zu erweitern, kannst Du einfach bei Bascom bleiben. :roll:

Gruss,
stochri

jagdfalke
22.11.2005, 22:08
also hier ist log.txt:


set -e; avr-gcc -MM -mmcu=atmega32 -I. -g -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-ahlms=uart.lst uart.c \
| sed 's,\(.*\)\.o[ :]*,\1.o \1.d : ,g' > uart.d; \
[ -s uart.d ] || rm -f uart.d
set -e; avr-gcc -MM -mmcu=atmega32 -I. -g -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-ahlms=uart.lst uart.c \
| sed 's,\(.*\)\.o[ :]*,\1.o \1.d : ,g' > uart.d; \
[ -s uart.d ] || rm -f uart.d
-------- begin --------
avr-gcc --version
avr-gcc (GCC) 4.0.2
Copyright (C) 2005 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

avr-gcc -c -mmcu=atmega32 -I. -g -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-ahlms=uart.lst uart.c -o uart.o
avr-gcc -mmcu=atmega32 -I. -g -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-ahlms=uart.o uart.o --output uart.elf -Wl,-Map=uart.map,--cref -lm
avr-objcopy -O ihex -R .eeprom uart.elf uart.hex
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 -O ihex uart.elf uart.eep
avr-objdump -h -S uart.elf > uart.lss
Size after:
uart.elf :
section size addr
.text 196 0
.data 0 8388704
.bss 0 8388704
.noinit 0 8388704
.eeprom 0 8454144
.stab 1356 0
.stabstr 1283 0
Total 2835


Errors: none
-------- end --------



In der Konsole steht aber trotz ">log.txt"das hier:


mathias@linux:~/uart> make > log.txt
make: Warning: File `uart.c' has modification time 2,3e+04 s in the future
make: Warning: File `uart.c' has modification time 2,3e+04 s in the future
uart.c:42:3: warning: no newline at end of file
make: Warnung: Mit der Uhr stimmt etwas nicht.
Die Bearbeitung könnte unvollständig sein.



Wenn ich minicom starte sendet er irgendwelche signale vom PC rüber. Die werden dann in der Konsole angezeigt. Man kann sie im minicom -s einstellen. Könnten die irgendwas damit zu tun haben?

izaseba
22.11.2005, 22:22
Ich denke ein "touch uart.c" sollte das Problem mit der Uhr beheben.


uart.c:42:3: warning: no newline at end of file

Da kannst Du am Programmende Enter drücken und speichern, wann ist es auch weg....
Vergess ich immer wieder
Es sind aber keine Fehler, das Programm müßte dann i.O sein...
und was passiert mit "cat /dev/ttyS0" und dann µC starten?
Was kommt in die Konsole rein ?

Gruß Sebastian

EDIT: Hast Du Deine Uhr falsch eingestellt? meine stimmt jedenfalls.....
Auf jedem Fall komm ich aus der Zukunft :-)

jagdfalke
22.11.2005, 22:24
STOOOOP!
Ich hab mir mal ein neues Kabel gebaut, dachte das alte wäre vielleicht kaput obwohl es von Außen gut aussah. Und tatsächlich: jetzt gehts es kommt immer "xy" + Zeilenumbruch ist doch richtig so oder?

izaseba
22.11.2005, 22:29
](*,) ](*,) ](*,) ](*,)

Ja genau, so ist es richtig....

Also doch Userfehler ...
Jetzt kannst Du Dich ruhig der Programmiersprache C widmen, und Dich nicht mehr mit so nem Sch.... rumärgern.

Gruß Sebastian

jagdfalke
22.11.2005, 22:35
Ja, ich hab mir schon etwas sorgen gemacht: So viel Zeit nur um "HelloWorld" hinzubekommen :D
Dann bin ich mal gespannt ob ich selber rausbekomme welche Register ich wie setzten muss damit das passiert was ich will :D

Danke für die Geduld und die Code-Beispiele!
mfg
jagdfalke

askazo
01.12.2005, 12:34
Noch mal was zu printf: Man kann sie doch benutzen. Man muss dem Compiler nur mit fdevopen() sagen, wie er die Ausgabe machen soll. die Routine zur Ausgabe eines einzelnen Zeichens muss man also selber schreiben, das zusammenstellen der Strings erledigt printf(). Folgender Code ist getestet und funktioniert:


#include <io.h>
#include <stdio.h>

#define F_CPU 8000000 // 8 MHz Taktfrequenz
#define UART_BAUD_RATE 2400
#define UART_BAUD_SELECT (F_CPU/(UART_BAUD_RATE*16l)-1)

int uart_putchar(char c)
{

if (c == '\n')
uart_putchar('\r');
loop_until_bit_is_set(UCSR0A, UDRE);
UDR0 = c;
return 0;
}

void UartInit(void)
{
UCSRB = 0x08

UBRRL = UART_BAUD_SELECT;

}


int main (void)
{

UartInit(); //Schnittstelle initialisieren
fdevopen(uart_putchar, NULL, 0);

printf ("HelloWorld");

}

Gruß,
askazo

jagdfalke
01.12.2005, 17:14
Ahh danke. Das erspart viel Code.

mfg
jagdfalke