Forum: Compiler & IDEs ATmega16-Funktioniert dieser Code bis jetzt?


von Markus B. (pspracers)


Lesenswert?

hi,

Ich bin noch sehr neu in der Microcontroller Welt, wollte jetzt aber 
einfach mal versuchen einen zu programmieren. Da ich aber weder 
Programmiergerät, noch Microcontroller besitze kann ich meinen code 
leider nicht austesten :/

Es handelt sich um diesen Code(mit AVR Studio 5 für einen ATmega16 
geschrieben):
1
/*
2
 * LED_4Mode_Control.c
3
 *
4
 * Created: 13.10.2011 17:41:07
5
 *  Author: Markus
6
 */ 
7
8
#include <avr/io.h>
9
10
typedef unsigned char byte;
11
12
#define RAND_MAX   0b1000
13
int rand(void);
14
15
int main(void)
16
{
17
  
18
  byte test;
19
  
20
  
21
  
22
    while(1)
23
    {
24
        if( PINA & (1<<PINA0) )
25
    {
26
      test = rand();
27
    }
28
29
    }
30
}
derzeit sollte das programm eigentlich nur wenn an PinA0 eine Spannung 
anliegt eine zufallszahl generiert werden, und diese in der variable 
test gespeichert werden.

Ich hab wirklich fast keine Ahnung von der Materie, es wäre also toll 
wenn mir jemand sagen könnte ob ich völlig falsch liege, bzw. etwas 
vergessen habe.

danke
markus

von Peter II (Gast)


Lesenswert?

und warum nimmst du nicht den Simulator?

was soll den rand machen? Du hast zwar definiert aber nicht 
implementiert. Und wozu ist test da wenn du es nicht verwendest?

von ich (Gast)


Lesenswert?

Bin mir nicht sicher, ob 8bit AVRs Zufallszahlen erzeugen können.
Die andere Frage ist, wie viel Gleitkommazahl passt in 8Bit = 1 Byte = 
test. rand() ist ja in [0,1] definiert.

von Markus B. (pspracers)


Lesenswert?

ich hab ewig nach einer funktion für zufallszahlen gesucht und hab dann 
mal rand() gefunden, wie gesagt ich bin neu in dem bereich :/
also brauche ich für rand() einen float(bzw. double)? wird da nicht 
einfach immer die kommazahl gelöscht? also 4,9 zu 4?!

von Peter II (Gast)


Lesenswert?

Markus B. schrieb:
> ich hab ewig nach einer funktion für zufallszahlen gesucht und hab dann
> mal rand() gefunden
dann muss du die passenden header datei einbinden, so wie du es jetzt 
gemacht hast ist es falsch, du hast rand selber definiert.

von Markus B. (pspracers)


Lesenswert?

also so?
1
#include <avr/io.h>
2
3
typedef unsigned char byte;
4
5
#define RAND_MAX   0b1000
6
7
8
int main(void)
9
{
10
  
11
  byte test;
12
  
13
  
14
  
15
    while(1)
16
    {
17
        if( PINA & (1<<PINA0) )
18
    {
19
      test = rand();
20
    }
21
22
    }
23
}

von Peter II (Gast)


Lesenswert?

Markus B. schrieb:
> also so?

nein, du brauche eine header datei wo die rand() funktion deklariert 
ist. (keien Ahnung wo das bei den AVRs ist, ich habe sie noch nie 
gebraucht). Aber das macht eh keinen Sinn weil du test überhaupt nicht 
verwendest, damit wird der code eh wegoptimiert.

von Markus B. (pspracers)


Lesenswert?

Peter II schrieb:
> Markus B. schrieb:
>> also so?
>
> nein, du brauche eine header datei wo die rand() funktion deklariert
> ist. (keien Ahnung wo das bei den AVRs ist, ich habe sie noch nie
> gebraucht). Aber das macht eh keinen Sinn weil du test überhaupt nicht
> verwendest, damit wird der code eh wegoptimiert.

rand() ist offenbar in der stdlib.h deklariert, habe aber vorher auch 
keinen fehler beim erstellen bekommen?!

hab jetzt einen testlauf ohne der bedingung gemacht, und hab bemerkt das 
zufallszahlen die größer als 7 sind generiert werden.  eigentlich wollte 
ich es einschränken durch
1
#define RAND_MAX   0b1000
wie es hier zu finden ist
http://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html

"#define RAND_MAX   0x7FFF

Highest number that can be generated by rand()."

von Peter II (Gast)


Lesenswert?

Markus B. schrieb:
> "#define RAND_MAX   0x7FFF

das wird wohl fest einkompiliert sein, vermutlich kann man es nicht 
ändern ohne das man die lib selber baut.

von ich (Gast)


Lesenswert?

Ich formuliere es mal so, wer mit uCs rumwuseln will, sollte gute 
Kenntnisse in C habe. Die Reihenfolge lautet C lernen, uCs verstehen und 
denn uCs programmieren. Der Irrglaube mit uCs C zu lernen ist totaler 
Blödsinn.

Also die Reihenfolge ist:

1. Grundlagen von C können.
2. Wissen wie uCs funktionieren bzw. aufgebaut sind und warum ein uCs 
nicht die gleichen Eigenschafen hat wie der PC, vor dem man sitzt.
Andere Frage, was sind die Unterschiede und wie müssen sie bei der 
Programmierung berücksichtigt werden.

Wenn 1. und 2. vorhanden sind, dann kann man sich an Schritt 3. wagen.
3. "echtes" Programmieren von uCs. Das bedeutet, dass ich mich nicht 
durch die Programmierung durchraten muss, da ich weiss, was ich mache.

von Markus B. (pspracers)


Lesenswert?

Peter II schrieb:
> Markus B. schrieb:
>> "#define RAND_MAX   0x7FFF
>
> das wird wohl fest einkompiliert sein, vermutlich kann man es nicht
> ändern ohne das man die lib selber baut.

und wenn ich dannach noch durch 32 rechne? damit könnte ich es doch auch 
einschränken?!

EDIT:
Wie schaffe ich es dann den PINDtest(also z.B. PIND5) als ausgang zu 
setzten?
danke für die ganzen antworten :)

von Markus B. (pspracers)


Lesenswert?

ich schrieb:
> Ich formuliere es mal so, wer mit uCs rumwuseln will, sollte gute
> Kenntnisse in C habe. Die Reihenfolge lautet C lernen, uCs verstehen und
> denn uCs programmieren. Der Irrglaube mit uCs C zu lernen ist totaler
> Blödsinn.
>
> Also die Reihenfolge ist:
>
> 1. Grundlagen von C können.
> 2. Wissen wie uCs funktionieren bzw. aufgebaut sind und warum ein uCs
> nicht die gleichen Eigenschafen hat wie der PC, vor dem man sitzt.
> Andere Frage, was sind die Unterschiede und wie müssen sie bei der
> Programmierung berücksichtigt werden.
>
> Wenn 1. und 2. vorhanden sind, dann kann man sich an Schritt 3. wagen.
> 3. "echtes" Programmieren von uCs. Das bedeutet, dass ich mich nicht
> durch die Programmierung durchraten muss, da ich weiss, was ich mache.

also C lerne ich jetzt seit einem Schuljahr. 
Mircocontrollerprogrammierung erlerne ich jetzt seit diesem 
Schuljahr(jedoch nur jeweils 2h/14 Tage)
Ich hab auch schon versucht einige Tutorials zu uCs zu lesen, bzw. zu 
verstehen, diese habe ich aber leider nur teilweise verstanden und auch 
nur wenige Anfängerfreundliche Beispiele gefunden(und wenn auch nur der 
reine Programmcode ohne einen dazu passenden Schaltplan)

von Werner B. (werner-b)


Lesenswert?

Markus B. schrieb:
> Peter II schrieb:
>> Markus B. schrieb:
>>> also so?
>>
>> nein, du brauche eine header datei wo die rand() funktion deklariert
>> ist. (keien Ahnung wo das bei den AVRs ist, ich habe sie noch nie
>> gebraucht). Aber das macht eh keinen Sinn weil du test überhaupt nicht
>> verwendest, damit wird der code eh wegoptimiert.
>
> rand() ist offenbar in der stdlib.h deklariert, habe aber vorher auch
> keinen fehler beim erstellen bekommen?!
>
> hab jetzt einen testlauf ohne der bedingung gemacht, und hab bemerkt das
> zufallszahlen die größer als 7 sind generiert werden.  eigentlich wollte
> ich es einschränken durch
>
1
> #define RAND_MAX   0b1000
2
>
> wie es hier zu finden ist
> http://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html
>
> "#define RAND_MAX   0x7FFF
>
> Highest number that can be generated by rand()."

dann macht ein "C" Programmierer...
1
test = rand() % RAND_MAX;
oder, wenn RAND_MAX eine 2er Potenz ist
1
test = rand() & (RAND_MAX-1);
Der Compiler macht warscheinlich den gleichen Binärcode daraus.

von Markus B. (pspracers)


Lesenswert?

ich hab jetzt ein wenig mehr gelernt und selbst weiterhin versucht das 
programm zu schreiben.
Die Fragen stehen in den Kommentaren, Danke im Voraus :)
1
/*
2
 * LED_4Mode_Control.c
3
 *
4
 * Created: 13.10.2011 17:41:07
5
 *  Author: Markus
6
 */ 
7
8
#include <stdlib.h>
9
#include <avr/io.h>
10
#include <util/delay_basic.h>
11
12
typedef unsigned char byte;
13
14
15
void wait(byte hsec);
16
17
int main(void)
18
{
19
  
20
  byte zufall;
21
  
22
  //PIN => PORT abfragen
23
  
24
  
25
  DDRD = 0xFF;  //PORTD als AUSGANG setzten
26
  DDRA = 0x00;  //PORTA als EINGANG setzten
27
  PORTD = 0x00;  //PORTD Ausgänge AUSSCHALTEN
28
  
29
  
30
  
31
    while(1)
32
    {
33
34
        if(PINA & (1<<PINA0)) //Zufallsausgabe
35
/* Wenn eine Spannung an PINA0 anliegt soll eine Zufallszahl zw. 0 und 7 generiert werden, und dannach der generierte PORTDx aktiviert werden, funktioniert das?*/
36
    {
37
    PORTD = 0x00;
38
    
39
    zufall = (rand() & (255))/32;
40
    
41
    zufall;
42
    PORTD |= (1 << zufall);
43
    wait(50);
44
    
45
    PORTD = 0x00;
46
    
47
    }
48
    if(PINA & (1<<PINA1) ) //genaue Reihenfolge
49
/* Wenn eine Spannung an PINA1 anliegt soll eine genaue Reihenfolge, wie eine Art Lauflicht gestartet werden, Funzt das so?*/
50
    {
51
    PORTD = 0x00;
52
    PORTD = 0b00000001;
53
    wait(500);
54
    PORTD = 0b00000010;
55
    wait(500);
56
    PORTD = 0b00000100;
57
    wait(500);
58
    PORTD = 0b00001000;
59
    wait(500);
60
    PORTD = 0b00010000;
61
    wait(500);
62
    PORTD = 0b00100000;
63
    wait(500);
64
    PORTD = 0b01000000;
65
    wait(500);
66
    PORTD = 0b10000000;
67
    wait(500);
68
    PORTD = 0x00;
69
    }  
70
  
71
    if(PINA & (1<<PINA2) ) /*Blinken, Alles aus, Alles ein, funktioiert das so? */
72
    {  
73
      PORTD = 0x00;
74
      PORTD = 0xFF;
75
      wait(20);
76
      PORTD = 0x00;
77
      wait(20);
78
79
    }
80
  }    
81
}
82
83
void wait(byte hsec)//F = 1MHz
84
{
85
  
86
  byte i;
87
  for(;hsec;hsec--)
88
  {
89
    for(i = 20; i; i--) //10ms
90
    {
91
      
92
      _delay_loop_1(167); //500 μs
93
      
94
    }
95
  }
96
}

nochmals danke
markus

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Werner B. schrieb:
> Markus B. schrieb:
>> hab jetzt einen testlauf ohne der bedingung gemacht, und hab bemerkt das
>> zufallszahlen die größer als 7 sind generiert werden.  eigentlich wollte
>> ich es einschränken durch
1
>> #define RAND_MAX   0b1000
>> wie es hier zu finden ist
>> http://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html
>>
>> "#define RAND_MAX   0x7FFF
>>
>> Highest number that can be generated by rand()."

RAND_MAX hat *rein* informativen Character.

> dann macht ein "C" Programmierer...
1
> test = rand() % RAND_MAX;
Dies ist bereits durch rand sichergestellt, d.h. es gilt
1
unsigned int r = rand();
2
if (r == r % ((unsigned) RAND_MAX+1))
3
{
4
    // Ist *immer* erfüllt
5
}
6
else
7
{
8
    // Ist *nie* erfüllt
9
}

von Markus B. (pspracers)


Lesenswert?

Das hab ich schon des öfteren versucht, bekam aber immer zahlen jenseits 
der 7 ???

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

rand liefert ganze Zahlen von 0 bis 0x7fff = 32767.

Wenn du kleinere Zahlen wie 0...N brauchst geht das per
1
int i = rand() % (N+1);
Vorteil: Leicht zu berechnen, insbesondere wenn N+1 2er Potenz ist.
Nachteil: Die Werte sind nur dann gleichverteilt,  wenn N+1 ein Teiler 
von RAND_MAX+1 ist.
1
unsigned int i;
2
do
3
{
4
    i = rand();
5
} while (i >= N+1);
hat den Nachteil, daß es ineffizient ist, keine Mindestlaufzeit 
angegeben werden kann. Vorteil: gleichverteilte Werte (unter der 
Voraussetzung, daß rand gleichverteilt isr).

Dies lässt sich etwas effizienter machen mit
1
unsigned int i;
2
do
3
{
4
    i = rand();
5
} while (i >= K*(N+1));
6
i = i % (N+1);
für eine geeignete Konstante K, zB:
allerdings bleibt das grundlegende Problem der Schleife bestehen.

von Rolf Magnus (Gast)


Lesenswert?

Johann L. schrieb:
> Nachteil: Die Werte sind nur dann gleichverteilt,  wenn N+1 ein Teiler
> von RAND_MAX+1 ist.

Auch dann nicht unbedingt, da bei den für diese Funktion häufig 
verwendeten Zufallsgeneratoren die Verteilung der unteren Bits nicht so 
gut ist wie die der oberen Bits. Daher wird auch gerne die Division 
statt Modulo verwendet.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.