Hey Jungs,
ich habe ein Problem mit folgendem Code:
1
#define F_CPU 4800000L
2
#include<avr/io.h>
3
#include<util/delay.h>
4
#include<stdlib.h>
5
6
intzufall(intmin,intmax){
7
returnmin+(rand()%max);
8
}
9
10
voidmain(){
11
DDRB=0xFF;
12
PORTB=0xFF;
13
srand(1);
14
15
while(1){
16
// Zwischen einer und drei Sekunde warten, ...
17
inti=zufall(100,200);
18
for(;i>0;i--){
19
_delay_ms(10);
20
}
21
22
// ..., dann PORTB togglen.
23
PORTB^=0xFF;
24
}
25
}
Wenn ich i eine beliebige Konstante zuweise, funktioniert das alles. Mit
meiner kleine "Zufallsfunktion" allerdings nicht. Die scheint irgendwie
immer 0 zurückzugeben.
Ich brauche keine wirklich zufälligen Zahlen. Deshalb reicht es mir,
wenn jedesmal die gleiche Reihenfolge kommt => daher srand(1). Sollte
doch eigentlich gehen, oder nicht?
Hoffe, Mann/man kann mir helfen :)
Pia
meinte ich auch. Hatte nur rumprobiert und das rausgenommen. Und
vergessen, es wieder einzufügen.
Das da scheinbar immer 0 zurückgegeben wird, erkenne ich daran, dass die
an PB3 angeschlossene LED nicht - oder schneller als meine Äuglein es
wahrnehmen können, blinkt.
Bei
1
intzufall(intmin,intmax){
2
returnmin+100;
3
}
blinkt die LED ganz gleichmäßig. Das Problem muss also irgendwo bei dem
"(rand() % (max-min))" liegen.
Ich weiß keine Lösung für dein Problem, kann aber zwei Sachen dazu
sagen:
1.
Wenn man dein Programm mit dem gcc kompiliert und zufall() ein paarmal
aufruft, kommen "Zufallszahlen" bei raus, also die Funktion gibt nicht
immer nur 0 zurück.
2.
Der Vorschlag von Lothar Miller war nicht richtig, da du der Funktion ja
Werte 100 und 200 übergibst, aber bis zu 300 erhalten willst, wie ich
das verstehe, also war deine alte Zufallsfunktion richtig.
Ich weiß nicht was das macht: PORTB ^= 0xFF; Das ist aber richtig, ja?
wird rand wirklich einen integer zurückgeben??
ich erinnere mich an ein rand , was immer float geliefert hat - beim
runden
bleibt dann nix ...
nur so eine vermutung
anfänger schrieb:
> wird rand wirklich einen integer zurückgeben??> ich erinnere mich an ein rand , was immer float geliefert hat - beim> runden> bleibt dann nix ...
Das war bei Java so^^
> Der Vorschlag von Lothar Miller war nicht richtig, ...> also war deine alte Zufallsfunktion richtig.
Schon schön, aber dann wären ja die Namen der Übergabewerte extremst
unintiutiv gewählt. Das mit dem max-1 war mir klar. Richtig müsste die
Funktion also heissen:
1
intzufall(intmin,intmax){
2
returnmin+(rand()%(max+1-min));
3
}
> Ich weiß nicht was das macht: PORTB ^= 0xFF; Das ist aber richtig, ja?
Ja, das invertiert einfach alle Bits vom Port B
Habe das ganze soeben mal auf einen ATmega48 draufgeschubst. Da gibt's
aber genau das gleiche Problem - am Code kanns also eigentlich nicht
liegen, weil der Mega48 dem Atmega8 ja recht ähnlich ist und es auf dem
läuft.
Komplieren tu ich das mit
1
avr-gcc -Os -o main.hex main.c
, auf den uc schubs ich's mit
1
avrdude -c avrispv2 -p m48 -P usb -U flash:w:main.hex
Programmer ist ein AVRISP MKII.
> hey pia,> wie wärs mit nem bild und ner telefonnummer ??> lach!
Bist du aber auch der einzige, der lacht. Lustig war das nämlich nicht
...
Und ob zufall() nun werte von 100 bis 200, von 100 bis 201 oder von 100
bis 299 liefert, ist für den Anfang eigentlich egal. Bei all diesen
Werten müsste man eigentlich ein gut sichtbares, unregelmäßiges Blinken
sehen :S
Versuch doch mal alles etwas lesbarer zu schreiben :-), dann kannst du
auch versuchen schrittweise einzugrenzen.
> int zufall(int min, int max) {
int result;
result = rand();
result %= max;
result += min;
return(result);
> return min + (rand() % max);> }> void main() {> DDRB = 0xFF;> PORTB = 0xFF;> srand(1);>> while(1) {> // Zwischen einer und drei Sekunde warten, ...> int i = zufall(100, 200);
??? -> wird die initialisierung in jeder while loop aufgerufen
oder nur einmal ???
??? -> deklaration am beginn der Funktion und nicht mittendrin
(auch wenn es möglicherweise funktioniert)
i = zufall(100,200);
> for(; i > 0; i--) {> _delay_ms(10);> }>> // ..., dann PORTB togglen.> PORTB ^= 0xFF;> }> }
Hatte in der Tat nichts mit dem Code zu tun. Wenn man das ganze vom gcc
als .elf-Datei kompiliert und anschließend mit avr-objcopy ins Intel
Hex-Format umwandelt und dann draufstubst, geht es.
Jemand eine passende Erklärung parat? :D
Du hast immer den gleichen falschen und alten Code eingespielt.
Eine Codeänderung brachte daher nie etwas.
Kannst Du mal Dein Makefile und die Ausgaben beim Compilieren schicken?
Das vereinfacht die Erklärung.
jl schrieb:
> ??? -> wird die initialisierung in jeder while loop aufgerufen> oder nur einmal ???> [...]> ??? -> deklaration am beginn der Funktion und nicht mittendrin> (auch wenn es möglicherweise funktioniert)
Das Deklarieren von Variablen "mittendrin" funktioniert nicht nur
"moeglicherweise" sondern ist seit bestimmt 10 Jahren C-Standard.
Mehrfaches Deklarieren einer Variablen gilt es jedoch in der Tat zu
vermeiden.
Christian H. schrieb:
> Du hast immer den gleichen falschen und alten Code eingespielt.> Eine Codeänderung brachte daher nie etwas.
Ich kann Deinen Gedankengang nicht so ganz nachvollziehen. Alleine schon
weil
Pia schrieb:
> Wenn ich i eine beliebige Konstante zuweise, funktioniert das alles.
Volker
P.S.:
Ein Makefile habe ich nicht. Habe avr-gcc und avrdude "per Hand"
aufgerufen:
> avr-gcc -Os -o main.hex main.c> avrdude -c avrispv2 -p m48 -P usb -U flash:w:main.hex
Die Konsolenausgaben kann ich dir schicken, sobald ich zuhause bin.
Da war aber weder ein Fehler, noch eine Warnung oder sonstwas. Alles
erfolgreich.
Also funktioniert jetzt alles oder gibt es noch Probleme?
Pia schrieb:
>>> Hatte in der Tat nichts mit dem Code zu tun. Wenn man das ganze vom gcc>>> als .elf-Datei kompiliert und anschließend mit avr-objcopy ins Intel>>> Hex-Format umwandelt und dann draufstubst, geht es.
Das ist der von Hand-und-zu-Fuß-Weg. Automatisieren kann man das in
einem Makefile.
> avr-gcc -Os -mmcu=atmega48 -o main.hex main.c> avrdude -c avrispv2 -p m48 -P usb -U flash:w:main.hex
IMHO fehlt da die Umwandlung der Binärausgabe in das Intel-Hex-Format
mit dem Tool avr-objcopy.
Avrdude mosert das auch an:
> avrdude: input file main.hex auto detected as raw binary
Ich habe bisher d.h. bis eben :) noch nie gelesen, dass man diesen
Schritt mit avr-objcopy überspringen kann indem man per -o Option die
Hexdatei erzeugt.
In der GCC Doku
(http://gcc.gnu.org/onlinedocs/gcc-4.3.2//gcc/index.html) taucht hex als
Ausgabeformat auch nicht auf:
1
-o file
2
Place output in file file. This applies regardless to whatever
3
sort of output is being produced, whether it be an executable file,
4
an object file, an assembler file or preprocessed C code.
Es ist die Frage, was avr-gcc jetzt erzeugt hat... irgendein "raw
binary". Ist das ein "executable file" oder "an object file". D.h. wurde
die Library mit der rand()-Funktion zum Objektcode aus dem Quelltext
dazugelinkt oder nicht?
Auf RN (http://www.rn-wissen.de/index.php/Avr-gcc/Interna) gibt es eine
schöne Übersicht, wie aus Quelltext ein FLASHROM-Inhalt wird.
Dort steht ein Hinweis zu einer bestimmten Option, um aus avr-gcc heraus
die Hexdatei direkt zu erzeugen. Diese Option -Wl,--oformat=ihex sehe
ich bei deiner Kommandozeile nicht. Sie kann aber in deine avr-gcc
Version einkompiliert sein.
Um das zu kontrollieren und ob avr-gcc den Linker aufgerufen hat oder
nicht, könntest du -v in die avr-gcc Kommandozeile aufnehmen.
1
-v
2
Print (on standard error output) the commands executed to run
3
the stages of compilation. Also print the version number of the
4
compiler driver program and of the preprocessor and the compiler
Man kann
* eine Frage so formulieren, bzw. vor dem Absenden noch einmal
korrekturlesen.
Dabei darauf auchten: Jemand der nicht mit mir vor dem Bildschirm
sitzt, kann der mein Problem zweifelsfrei nachvollziehen?
* einen eigenen Thread für sein Problem aufmachen und nícht einfach
irgendeinen anderen für eine Frage zweckentfremden
Versuchs noch einmal