Forum: Compiler & IDEs Codeverbesserung ?


von Matthias I. (matze5)


Angehängte Dateien:

Lesenswert?

Hi,

ich bin grade dabei von Bascom auf C umzusteigen.
Nun hab ich folgenden Code fuer meinen Robo gebastelt.
Intressanterweise funktioniert er nicht auf WinAVR mit gcc 4.3
Unter Linux mit gcc 4.8 geht er astrein.

Er enthaelt hoechstwahrscheinlich einige Fehler.
Anbei noch der Programmablauf, Schaltplan.
1
 
2
#define F_CPU 3688000UL 
3
#include <avr/io.h>
4
#include <util/delay.h>
5
#include <stdlib.h>
6
 
7
int main(void) {
8
   DDRB |= (1 << PB0); // Ausgang setzen
9
   DDRB |= (1 << PB1);
10
   DDRB |= (1 << PB2);
11
   DDRB |= (1 << PB3); 
12
13
   DDRD |= (1 << PD5); //  Ausgang LED
14
   DDRD |= (1 << PD4); //  Ausgang Piezzo
15
16
  void long_delay(uint16_t ms)
17
  {
18
  for(; ms>0; ms--) _delay_ms(1);
19
  }
20
21
   while(1) {
22
    if ( PIND & (1 <<3) ){
23
    unsigned char min = 1;
24
        unsigned char max = 2;
25
        unsigned char zufall = 0;
26
       zufall = (rand() % (max-min+1) +min);
27
28
    PORTD |= (1 << PD5); // LED an
29
    PORTB |= (1 << PB0); // Rueckwaerts (default)
30
                PORTB &= ~(1 << PB1);
31
                PORTB |= (1 << PB2);
32
                PORTB &= ~(1 << PB3);
33
    long_delay(1000);
34
35
    if ( zufall == 1 ) {
36
          PORTB |= (1 << PB0); // Drehen (default)
37
          PORTB &= ~(1 << PB1);
38
          PORTB &= ~(1 << PB2);
39
          PORTB |= (1 << PB3);
40
      long_delay(800);
41
    }
42
    else {
43
      PORTB &= ~(1 << PB0); // Drehen (default)
44
                  PORTB |= (1 << PB1);
45
                  PORTB |= (1 << PB2);
46
                  PORTB &= ~(1 << PB3);
47
                  long_delay(800);
48
    }
49
50
    }   
51
       else {
52
    PORTD &= ~(1 << PD5); // led AUS
53
  
54
    PORTB &= ~(1 << PB0); // Vorwaerts (default)
55
    PORTB |= (1 << PB1);
56
    PORTB &= ~(1 << PB2);
57
    PORTB |= (1 << PB3);
58
    }
59
     }
60
   return 0;
61
}
Vieleicht kann mir ja der eine oder andere ein paar Tipps geben.


Gruss Matze

: Verschoben durch User
von Random .. (thorstendb) Benutzerseite


Lesenswert?

Kommentare und Funktions-/Variablennamen auf Englisch. Liesst sich 
leichter.

von Random .. (thorstendb) Benutzerseite


Lesenswert?

ist das compilierbar? Funktion in einer Funktion?

Und: Klammern vernünftig setzen, 2 SPACEs pro Einrückung z.B.

von Dussel (Gast)


Lesenswert?

Random ... schrieb:
> Kommentare und Funktions-/Variablennamen auf Englisch. Liesst sich
> leichter.
Wenn man davon absieht, dass wir in einem deutschsprachigen Forum sind.


Was funktioniert denn nicht? Lässt es sich nicht compilieren oder 
funktioniert es nicht wie es soll? Was für Fehler treten auf?

von Dussel (Gast)


Lesenswert?

Übrigens ist das hier das falsche Forum. Vielleicht kann jemand das zum 
Verschieben melden.

von RaumenergiePotentialwirbel (Gast)


Lesenswert?

Matthias I. schrieb:
> Vieleicht kann mir ja der eine oder andere ein paar Tipps geben.

An den Pins 3,4,5,7 und 9 von JP1 fehlen die Knotenpunkte. ;-)
Ebenso verwirren die Referenzkennzeichen IC1 und IC2, in Eagle muss 
jedes Bauteil U$1...U$x heißen. ;-)

von Julian W. (julian-w) Benutzerseite


Lesenswert?

evtl. wäre das hier aber im GCC Forum besser aufgehoben...

von Karl H. (kbuchegg)


Lesenswert?

Matthias I. schrieb:

> Intressanterweise funktioniert er nicht auf WinAVR mit gcc 4.3
> Unter Linux mit gcc 4.8 geht er astrein.

Ich bin jetzt nicht im Bilde, ob es im 4.3 ein paar bekannte Bugs gab 
oder nicht.

>
>    DDRD |= (1 << PD5); //  Ausgang LED
>    DDRD |= (1 << PD4); //  Ausgang Piezzo


Wenn du dir ein paar #define machst
1
#define F_CPU 3688000UL 
2
#include <avr/io.h>
3
#include <util/delay.h>
4
#include <stdlib.h>
5
6
#define LED    (1<<PD5)
7
#define PIEZO  (1<<PD4)

dann kannst du durch die Textersetzung erreichen, dass sich dieser 
Original-Abschnitt hier so liest
1
   DDRD |= LED;
2
   DDRD |= PIEZO;

(es ginge auch
1
#define LED   PD5
2
#define PIEZO PD4
3
....
4
5
   DDRD |= (1 << LED);
6
   DDRD |= (1 << PIEZO);
)
was den Vorteil hat, dass du dir den Kommentar ganz offensichtlich 
sparen kannst, was an und für sich eine gute Sache ist. Hast du die Wahl 
zwischen einem Kommentar und einer Möglichkeit den Code so 
umzuformulieren, dass der Kommentar überflüssig wird, dann bevorzuge 
letzteres! Denn der Code ist immer das was compiliert wird - sprich: 
Kommentare können auch falsch sein ohne das es jemandem auffällt, der 
nicht genau überprüft ob der Kommentar mit dem Code zusammenstimmt.
Wenn ich hier im Forum Codefehler suche, dann ignoriere ich Kommentare 
zb vollständig. Eben weil sie immer wieder sich mal als falsch 
herausstellen.

>
>   void long_delay(uint16_t ms)
>   {
>   for(; ms>0; ms--) _delay_ms(1);
>   }

Funktionen in Funktionen zu definieren ist in C eigentlich nicht 
zulässig.
Aber eigentlich brauchst du gar keine Funktion long_delay. _delay_ms 
kann derartige Zeiten wunderbar ganz für sich alleine abhandlen. einfach 
_delay_ms( 1000 ); aufrufen und gut ists.

>
>    while(1) {
>     if ( PIND & (1 <<3) ){

Hier dasselbe. An deinem Portbit 3 hängt ein Taster, der vielleicht 
sogar eine Beschriftung hat (sagen wir mal "Bumper") bzw. wenn er nicht 
beschriftet ist, dann hat er zumindest eine logische Funktion (in deinem 
Fall ist das eben der Front-Bumper
1
....
2
#define FRONT_BUMPER    PD3
3
4
....
5
6
7
       if( PIND & ( 1 << FRONT_BUMPER ) )
8
...
liest sich doch gleich viel besser. Und wenn mal mehrere Bumper oder 
Tasten im Spiel sind, dann erleichtert dir ein entsprechender 
Makro-Ersatz auch das Auseinanderhalten im Code, mit welchem externen 
Bumper oder Taster du es hier an dieser Codestelle zu tun hast.

>     unsigned char min = 1;
>         unsigned char max = 2;
>         unsigned char zufall = 0;
>        zufall = (rand() % (max-min+1) +min);
>
>     PORTD |= (1 << PD5); // LED an

Das wäre dann (mit der 2.ten Makro Variante)
1
      PORTD |= ( 1 << LED );
... und wieder ist der Kommentar überflüssig geworden

>     PORTB |= (1 << PB0); // Rueckwaerts (default)
>                 PORTB &= ~(1 << PB1);
>                 PORTB |= (1 << PB2);
>                 PORTB &= ~(1 << PB3);

selbiges auch hier: "Benenne" deine Ausgänge je nach Funktionalität mit 
hilfe eines Makros. Du willst derartige Bezeichnungen wie PB1, PB2, aber 
auch PORTB etc. eigentlich nicht direkt im Code stehen haben!

: Bearbeitet durch User
von Johann L. (radiostar)


Lesenswert?

> Wenn ich hier im Forum Codefehler suche, dann ignoriere ich Kommentare
> zb vollständig. Eben weil sie immer wieder sich mal als falsch
> herausstellen.

Na, immerhin steht im Kommentar, was der Code tun SOLL.

von Karl H. (kbuchegg)


Lesenswert?

Ich würde mir auch Funktionen für die Beschaltung der MOtoren für 
"typische Bewegungsmuster" machen. Eine Funktion frü Vorwärts, eine 
Funktion für Rückwärts, eine für Rechts, eine für Links.
1
void Forward()
2
{
3
  PORTB &= ~(1 << PB0);
4
  PORTB |= (1 << PB1);
5
  PORTB &= ~(1 << PB2);
6
  PORTB |= (1 << PB3);
7
}
8
9
void Backward()
10
{
11
  PORTB |= (1 << PB0);
12
  PORTB &= ~(1 << PB1);
13
  PORTB |= (1 << PB2);
14
  PORTB &= ~(1 << PB3);
15
}
16
17
void TurnRight()
18
{
19
  PORTB |= (1 << PB0);
20
  PORTB &= ~(1 << PB1);
21
  PORTB &= ~(1 << PB2);
22
  PORTB |= (1 << PB3);
23
}
24
25
void TurnLeft()
26
{
27
  PORTB &= ~(1 << PB0);
28
  PORTB |= (1 << PB1);
29
  PORTB |= (1 << PB2);
30
  PORTB &= ~(1 << PB3);
31
}
32
33
int random( int min, max )
34
{
35
  return rand() % (max-min+1) + min;
36
}
37
38
int main()
39
{
40
  ....
41
42
  while( 1 ) {
43
    if ( PIND & (1 << FRONT_BUMPER) ) {
44
45
      PORTD |= (1 << LED);
46
      Backward();
47
48
      _delay_ms( 1000 );
49
50
      if( random( 1, 2 ) == 1 ) {
51
        TurnLeft();
52
      else
53
        TurnRight();
54
55
      _delay_ms( 800 );
56
    }
57
58
    else {
59
      PORTD &= ~(1 << LED);
60
      Forward();
61
   }
62
63
   return 0;

siehst du, um wieviel leichter die Hauptschleife in main() zu verfolgen 
und zu verstehen ist? Das liegt daran, dass ich mich als Leser nicht 
mehr mit den Details von zb. dem Rückwärtsfahren beschäftigen muss. Im 
Code in der Hauptschleife steht einfach Backward() und das genügt mir 
beim Lesen des Codes um zu verstehen, das an dieser Stelle im Code das 
Fahrzeug zurück setzen soll. Wenn mich die Details interessieren, wie 
dieses Rückwärts fahren funktioniert, dann kann ich mir die Funktion 
ansehen. WEnn es aber darum geht, die Logik zu verstehen, wie das 
Fahrzeug einem Hindernis ausweicht, dann muss ich nur wissen, dass das 
Fahreug mit dem Aufruf dieser Funktion rückwärts fährt.

Die in der Hauptschleife kodierte Logik des Ausweichens ist so viel 
kürzer formuliert und auch in problembezogeneren Ausdrücken, so dass es 
viel leichter fällt sich davon zu überzeugen, dass diese Logik 
eigentlich funktionieren müsste, ohne das ich ständig über irgendwelche 
technischen Details stolpere.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

J. L. schrieb:
>> Wenn ich hier im Forum Codefehler suche, dann ignoriere ich Kommentare
>> zb vollständig. Eben weil sie immer wieder sich mal als falsch
>> herausstellen.
>
> Na, immerhin steht im Kommentar, was der Code tun SOLL.

Dein Wort in Gottes Ohr.
Alles schon gehabt:
Code richtig, Kommentar falsch
Code falsch, Kommentar von der Idee her richtig
Code falsch, Kommentar falsch
Code falsch, Kommentar passt überhaupt nicht dazu und redet von etwas 
ganz anderem
Code richtig, Kommentar richtig. Allerdings: Kommentar überflüssig
und natürlich auch
Code richtig, Kommentar richtig und tatsächlich hilfreich

: Bearbeitet durch User
von Sven (Gast)


Lesenswert?

J. L. schrieb:
>> Wenn ich hier im Forum Codefehler suche, dann ignoriere ich
> Kommentare
>> zb vollständig. Eben weil sie immer wieder sich mal als falsch
>> herausstellen.
>
> Na, immerhin steht im Kommentar, was der Code tun SOLL.

Ein guter Kommentar sollte nicht nur das Was sondern das WARUM 
dokumentieren. Das was steht schon da in Form von Code.

Zum Thema verbessern: "Clean code" lesen.

von Matthias I. (matze5)


Lesenswert?

So ich hab mal einiges nach den Vorschlaegen hier geaendert :)
Das ganze ist so etwas uebersichtlicher!
Jetzt muss ich noch den Buzzer zum Piepen bringen.
Mit Bascom ist das ja ganz einfach, so wie es wohl aussieht brauch ich 
unter C eine PWM und einen Timer.
Mal sehen ob ich das zum laufen bekomme.
1
#define F_CPU 3688000UL 
2
#include <avr/io.h>
3
#include <util/delay.h>
4
#include <stdlib.h>
5
6
#define LED (1<<PD5)
7
#define SPEAKER (1<<PD4)
8
#define FRONT_BUMPER PD3
9
#define MOTOR_A (1<<PB0)
10
#define MOTOR_B (1<<PB1)
11
#define MOTOR_C (1<<PB2)
12
#define MOTOR_D (1<<PB3)
13
14
15
void rueckwaerts(){
16
    PORTB |= (1 << PB0);
17
    PORTB &= ~(1 << PB1);
18
    PORTB |= (1 << PB2);
19
    PORTB &= ~(1 << PB3);
20
}
21
22
void vorwaerts(){
23
    PORTB &= ~(1 << PB0);
24
    PORTB |= (1 << PB1);
25
    PORTB &= ~(1 << PB2);
26
    PORTB |= (1 << PB3);
27
}
28
29
void links(){
30
    PORTB |= (1 << PB0);
31
    PORTB &= ~(1 << PB1);
32
    PORTB &= ~(1 << PB2);
33
    PORTB |= (1 << PB3);
34
}
35
36
void rechts(){
37
    PORTB &= ~(1 << PB0);
38
    PORTB |= (1 << PB1);
39
    PORTB |= (1 << PB2);
40
    PORTB &= ~(1 << PB3);
41
}
42
43
int main(void) {
44
   DDRB |= MOTOR_A; // Ausgang setzen
45
   DDRB |= MOTOR_B;
46
   DDRB |= MOTOR_C;
47
   DDRB |= MOTOR_D; 
48
49
   DDRD |= LED;
50
   DDRD |= SPEAKER;
51
52
53
while(1){
54
55
    if ( PIND & (1 << FRONT_BUMPER) )
56
    {
57
    unsigned char min = 1;
58
        unsigned char max = 2;
59
        unsigned char zufall = 0;
60
       zufall = (rand() % (max-min+1) +min);
61
62
    PORTD |= LED; // LED an
63
    rueckwaerts();
64
    _delay_ms(1000);
65
66
    if ( zufall == 1 ) {
67
          links();
68
     _delay_ms(800);
69
    }
70
    
71
    else {
72
     rechts();
73
           _delay_ms(800);
74
    }
75
76
    }   
77
       else {
78
79
    PORTD &= LED; // led AUS
80
    vorwaerts();  
81
    }
82
  }
83
   return 0;
84
}

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

@ Matthias I. (matze5)

>Jetzt muss ich noch den Buzzer zum Piepen bringen.
>Mit Bascom ist das ja ganz einfach, so wie es wohl aussieht brauch ich
>unter C eine PWM und einen Timer.

Kann man machen. Aber du bist ja anscheinend Mr. Jan Delay ;-)

>Mal sehen ob ich das zum laufen bekomme.

Versuchs mal mit einer gescheiten Einrückung, das kann (WILL!) doch 
keiner lesen!

http://www.mikrocontroller.net/articles/Strukturierte_Programmierung_auf_Mikrocontrollern#Formatierung_des_Quelltextes

von Matthias I. (matze5)


Lesenswert?

Btw. hab ich ein Problem pack ich die Funktion in Main() geht alles.
Pack ich sie extra, gehts nicht.

Edit.. ausserdem hab ich ich den Falschen Code oben gepostet.. war die 
Falsche Datei :)

: Bearbeitet durch User
von Matthias I. (matze5)


Lesenswert?

Der richtige Code:


#define F_CPU 3688000UL
#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <motorun.h>

#define LED (1<<PD5)
#define SPEAKER (1<<PD4)
#define FRONT_BUMPER PD3
#define MOTOR_A (1<<PB0)
#define MOTOR_B (1<<PB1)
#define MOTOR_C (1<<PB2)
#define MOTOR_D (1<<PB3)

void rueckwaerts(){
    PORTB |= MOTOR_A;
    PORTB &= MOTOR_B;
    PORTB |= MOTOR_C;
    PORTB &= MOTOR_D;
}

void vorwaerts(){
    PORTB &= ~MOTOR_A;
    PORTB |= MOTOR_B;
    PORTB &= ~MOTOR_C;
    PORTB |= MOTOR_D;
}

void links(){
    PORTB |= MOTOR_A;
    PORTB &= ~MOTOR_B;
    PORTB &= ~MOTOR_C;
    PORTB |= MOTOR_D;
}

void rechts(){
    PORTB &= ~MOTOR_A;
    PORTB |= MOTOR_B;
    PORTB |= MOTOR_C;
    PORTB &= ~MOTOR_D;
}

int main(void) {
   DDRB |= MOTOR_A; // Ausgang setzen
   DDRB |= MOTOR_B;
   DDRB |= MOTOR_C;
   DDRB |= MOTOR_D;

   DDRD |= LED;
   DDRD |= SPEAKER;


while(1){

    if ( PIND & (1 << FRONT_BUMPER) )
    {
    unsigned char min = 1;
        unsigned char max = 2;
        unsigned char zufall = 0;
       zufall = (rand() % (max-min+1) +min);

    PORTD |= LED; // LED an
    rueckwaerts();
    _delay_ms(1000);

    if ( zufall == 1 ) {
          links();
     _delay_ms(800);
    }

    else {
     rechts();
           _delay_ms(800);
    }

    }
       else {

    PORTD &= ~LED; // led AUS
    vorwaerts();
    }
  }
   return 0;
}

Und die Datei motorun.h:
#ifndef MOTORUN_H_INCLUDED
#define MOTORUN_H_INCLUDED

void links();

void rechts();

void rueckwaerts();

void vorwaerts();
#endif


Tjo funktioniert nicht.
Lass ich den Header weg und pack die Funktionen mit in Main() gehts..
Verstehe ich nicht das er die Funktionen nicht aufrufen kann.

Der Weg ist lang und steinig :)

Btw. kann man im Forum irgendwie Syntax Highlight anmachen ?

: Bearbeitet durch User
von Uwe (de0508)


Lesenswert?


von Matthias I. (matze5)


Lesenswert?

So funktionierts uebrigens.. obwohls offensichtlich falsch ist... :
1
#define F_CPU 3688000UL 
2
#include <avr/io.h>
3
#include <util/delay.h>
4
#include <stdlib.h>
5
// #include "motorun.h"
6
7
#define LED (1<<PD5)
8
#define SPEAKER (1<<PD4)
9
#define FRONT_BUMPER PD3
10
#define MOTOR_A (1<<PB0)
11
#define MOTOR_B (1<<PB1)
12
#define MOTOR_C (1<<PB2)
13
#define MOTOR_D (1<<PB3)
14
15
16
int main(void) {
17
   DDRB |= MOTOR_A; // Ausgang setzen
18
   DDRB |= MOTOR_B;
19
   DDRB |= MOTOR_C;
20
   DDRB |= MOTOR_D; 
21
22
   DDRD |= LED;
23
   DDRD |= SPEAKER;
24
25
void rueckwaerts(){
26
    PORTB |= MOTOR_A;
27
    PORTB ~&= MOTOR_B;
28
    PORTB |= MOTOR_C;
29
    PORTB ~&= MOTOR_D;
30
}
31
32
void vorwaerts(){
33
    PORTB &= ~MOTOR_A;
34
    PORTB |= MOTOR_B;
35
    PORTB &= ~MOTOR_C;
36
    PORTB |= MOTOR_D;
37
}
38
39
void links(){
40
    PORTB |= MOTOR_A;
41
    PORTB &= ~MOTOR_B;
42
    PORTB &= ~MOTOR_C;
43
    PORTB |= MOTOR_D;
44
}
45
46
void rechts(){
47
    PORTB &= ~MOTOR_A;
48
    PORTB |= MOTOR_B;
49
    PORTB |= MOTOR_C;
50
    PORTB &= ~MOTOR_D;
51
}
52
53
54
while(1){
55
56
    if ( PIND & (1 << FRONT_BUMPER) )
57
    {
58
    unsigned char min = 1;
59
        unsigned char max = 2;
60
        unsigned char zufall = 0;
61
       zufall = (rand() % (max-min+1) +min);
62
63
    PORTD |= LED; // LED an
64
    rueckwaerts();
65
    _delay_ms(1000);
66
67
    if ( zufall == 1 ) {
68
          links();
69
     _delay_ms(800);
70
    }
71
    
72
    else {
73
     rechts();
74
           _delay_ms(800);
75
    }
76
77
    }   
78
       else {
79
80
    PORTD &= ~LED; // led AUS
81
    vorwaerts();  
82
    }
83
  }
84
   return 0;
85
}

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

@ Matthias I. (matze5)

>So funktionierts uebrigens.. obwohls offensichtlich falsch ist... :

Kannst du oder willst du nicht lesen? Dein Tabulatoren sind SCHROTT!

von Falk B. (falk)


Lesenswert?

1
#define F_CPU 3688000UL 
2
#include <avr/io.h>
3
#include <util/delay.h>
4
#include <stdlib.h>
5
// #include "motorun.h"
6
7
#define LED_ON      PORTD |=  (1<<PD5);
8
#define LED_OFF     PORTD &= ~(1<<PD5);
9
#define SPEAKER_ON  PORTD |=  (1<<PD4);
10
#define SPEAKER_OFF PORTD &= ~(1<<PD4);
11
#define FRONT_BUMPER (PIND & (1<<PD3))
12
#define MOTOR_A (1<<PB0)
13
#define MOTOR_B (1<<PB1)
14
#define MOTOR_C (1<<PB2)
15
#define MOTOR_D (1<<PB3)
16
17
18
void rueckwaerts(){
19
    PORTB |=  MOTOR_A;
20
    PORTB ~&= MOTOR_B;
21
    PORTB |=  MOTOR_C;
22
    PORTB ~&= MOTOR_D;
23
}
24
25
void vorwaerts(){
26
    PORTB &= ~MOTOR_A;
27
    PORTB |=  MOTOR_B;
28
    PORTB &= ~MOTOR_C;
29
    PORTB |=  MOTOR_D;
30
}
31
32
void links(){
33
    PORTB |=  MOTOR_A;
34
    PORTB &= ~MOTOR_B;
35
    PORTB &= ~MOTOR_C;
36
    PORTB |=  MOTOR_D;
37
}
38
39
void rechts(){
40
    PORTB &= ~MOTOR_A;
41
    PORTB |=  MOTOR_B;
42
    PORTB |=  MOTOR_C;
43
    PORTB &= ~MOTOR_D;
44
}
45
46
47
int main(void) {
48
    DDRB |= MOTOR_A;        // Ausgang setzen
49
    DDRB |= MOTOR_B;
50
    DDRB |= MOTOR_C;
51
    DDRB |= MOTOR_D; 
52
53
    LED_ON
54
    SPEAKER_OFF
55
56
    while(1){
57
58
        if ( FRONT_BUMPER )
59
        {
60
            unsigned char min = 1;
61
            unsigned char max = 2;
62
            unsigned char zufall = 0;
63
            zufall = (rand() % (max-min+1) +min);
64
    
65
            LED_ON
66
            rueckwaerts();
67
            _delay_ms(1000);
68
        
69
            if ( zufall == 1 )
70
            {
71
                links();
72
                _delay_ms(800);
73
            }
74
            else
75
            {
76
                rechts();
77
                _delay_ms(800);
78
            }
79
        
80
        }   
81
        else
82
        {
83
            LED_OFF
84
            vorwaerts();  
85
        }
86
    } 
87
    
88
    return 0;
89
}

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Random ... schrieb:
> ist das compilierbar? Funktion in einer Funktion?

Ja, lokale Fnuktionen sind eine GCC-Erweiterung, die in GNU-C zur 
Verfügung steht.  Harrig wird's, wenn die lokale Funktion auf Variablen 
der enthaltenden Funktion zugreift und diese die Adresse der lokalen 
Funktion nimmt.  Instruktives Beispiel:
1
extern void dispatch (void(*)(void));
2
3
int fun (int x)
4
{
5
    void callback (void)
6
    {
7
        x++;
8
    }
9
    
10
    dispatch (callback);
11
    return x;
12
}

callback bekommt von dispatch keine Argumente; es hat das Call-Interface 
jeder anderen void-Funktion.  Die Adresse von x ist zur Ladezeit nicht 
bekannt, und zwischen fun und callback können beliebig viele Callframes 
liegen.  Trotzdem muß callback irgendwie an x rankommen.

Mit avr-gcc ist das übrigens nicht übersetzbar, da dort kein Code auf 
dem Stack ausführbar ist.

von Matthias I. (matze5)


Lesenswert?

Falk: mit deinen Code funktionierts auch nicht.

Das erklaert auch nicht warum das Programm nicht ablaueft wenn die 
Funktionen ausserhalb von Main sind, wo sie hingehoeren.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Es war eine Erklärung und Hintergrundinfo dafür, warum der Compiler für 
long_delay keinen Fehler ausgegeben hat.

von apr (Gast)


Lesenswert?

Matthias I. schrieb:
> Falk: mit deinen Code funktionierts auch nicht.
>
> Das erklaert auch nicht warum das Programm nicht ablaueft wenn die
> Funktionen ausserhalb von Main sind, wo sie hingehoeren.
1
main.c: In function ‘rueckwaerts’:
2
main.c:20:11: error: expected ‘;’ before ‘~’ token
3
     PORTB ~&= MOTOR_B;
4
           ^
5
main.c:22:11: error: expected ‘;’ before ‘~’ token
6
     PORTB ~&= MOTOR_D;
7
           ^

von Falk B. (falk)


Lesenswert?

@ Matthias I. (matze5)

>Falk: mit deinen Code funktionierts auch nicht.

Ich hab nur schön geschrieben, nicht kompiliert oder getestet!

von Falk B. (falk)


Lesenswert?

Ach ja, beim Aufräumen ist wohl ein neuer Bug reingekommen. Die Ausgänge 
für LED und Speaker müssen noch aktiviert werden.

von Dirk B. (dirkb2)


Lesenswert?

Du kannst deinen Zufall noch aufräumen
Von
1
unsigned char min = 1;
2
            unsigned char max = 2;
3
            unsigned char zufall = 0;
4
            zufall = (rand() % (max-min+1) +min);
bleibt dann noch
1
            zufall = rand() % 2;
oder du schreibst das rand() % 2 gleich beim if rein.

von Matthias I. (matze5)


Lesenswert?

Das hab ich schon alles gefunden und behoben, dennoch lauefts nicht :)
Speaker wird eh nicht benutzt im Moment.

Kompilieren tut es astrein, aber die funktionen laufen nur wenn sie in 
main() sind...
Das ist das einzige Problem, egal wie ich da was formatiere.. oder 
Tabulatoren setze..

von Matthias I. (matze5)


Lesenswert?

So funktioniert alles:
1
#define F_CPU 3688000UL 
2
#include <avr/io.h>
3
#include <util/delay.h>
4
#include <stdlib.h>
5
6
#define LED (1 << PD5)
7
#define SPEAKER (1 << PD4)
8
#define FRONT_BUMPER PD3
9
#define MOTOR_A (1 << PB0)
10
#define MOTOR_B (1 << PB1)
11
#define MOTOR_C (1 << PB2)
12
#define MOTOR_D (1 << PB3)
13
14
15
int main(void) {
16
DDRB |= MOTOR_A;
17
DDRB |= MOTOR_B;
18
DDRB |= MOTOR_C;
19
DDRB |= MOTOR_D;
20
21
DDRD |= LED;
22
DDRD |= SPEAKER;
23
24
void rueckwaerts(){
25
  PORTB |= MOTOR_A;
26
  PORTB &= ~MOTOR_B;
27
  PORTB |= MOTOR_C;
28
  PORTB &= ~MOTOR_D;
29
}
30
31
void vorwaerts(){
32
  PORTB &= ~MOTOR_A;
33
  PORTB |= MOTOR_B;
34
  PORTB &= ~MOTOR_C;
35
  PORTB |= MOTOR_D;
36
}
37
38
void links(){
39
  PORTB |= MOTOR_A;
40
  PORTB &= ~MOTOR_B;
41
  PORTB &= ~MOTOR_C;
42
  PORTB |= MOTOR_D;
43
}
44
45
void rechts(){
46
  PORTB &= ~MOTOR_A;
47
  PORTB |= MOTOR_B;
48
  PORTB |= MOTOR_C;
49
  PORTB &= ~MOTOR_D;
50
}
51
52
while(1){
53
  if ( PIND & (1 << FRONT_BUMPER) )
54
  {
55
  unsigned char min = 1;
56
  unsigned char max = 2;  unsigned char zufall = 0;
57
  zufall = (rand() % (max-min+1) +min);
58
  PORTD |= LED; 
59
  
60
  rueckwaerts();
61
  _delay_ms(1000);
62
  
63
  if ( zufall == 1 ) {
64
  links();
65
  _delay_ms(800);
66
  }
67
  
68
  else {
69
  rechts();
70
  _delay_ms(800);
71
  }
72
73
  }   
74
  else {
75
  PORTD &= ~LED;
76
  vorwaerts();  
77
  }
78
  }
79
80
return 0;
81
}


So funktioniert nichts:
1
#define F_CPU 3688000UL 
2
#include <avr/io.h>
3
#include <util/delay.h>
4
#include <stdlib.h>
5
6
#define LED (1 << PD5)
7
#define SPEAKER (1 << PD4)
8
#define FRONT_BUMPER PD3
9
#define MOTOR_A (1 << PB0)
10
#define MOTOR_B (1 << PB1)
11
#define MOTOR_C (1 << PB2)
12
#define MOTOR_D (1 << PB3)
13
14
void rueckwaerts(){
15
  PORTB |= MOTOR_A;
16
  PORTB &= ~MOTOR_B;
17
  PORTB |= MOTOR_C;
18
  PORTB &= ~MOTOR_D;
19
}
20
21
void vorwaerts(){
22
  PORTB &= ~MOTOR_A;
23
  PORTB |= MOTOR_B;
24
  PORTB &= ~MOTOR_C;
25
  PORTB |= MOTOR_D;
26
}
27
28
void links(){
29
  PORTB |= MOTOR_A;
30
  PORTB &= ~MOTOR_B;
31
  PORTB &= ~MOTOR_C;
32
  PORTB |= MOTOR_D;
33
}
34
35
void rechts(){
36
  PORTB &= ~MOTOR_A;
37
  PORTB |= MOTOR_B;
38
  PORTB |= MOTOR_C;
39
  PORTB &= ~MOTOR_D;
40
}
41
42
43
int main(void) {
44
DDRB |= MOTOR_A;
45
DDRB |= MOTOR_B;
46
DDRB |= MOTOR_C;
47
DDRB |= MOTOR_D;
48
49
DDRD |= LED;
50
DDRD |= SPEAKER;
51
52
53
while(1){
54
  if ( PIND & (1 << FRONT_BUMPER) )
55
  {
56
  unsigned char min = 1;
57
  unsigned char max = 2;  unsigned char zufall = 0;
58
  zufall = (rand() % (max-min+1) +min);
59
  PORTD |= LED; 
60
  
61
  rueckwaerts();
62
  _delay_ms(1000);
63
  
64
  if ( zufall == 1 ) {
65
  links();
66
  _delay_ms(800);
67
  }
68
  
69
  else {
70
  rechts();
71
  _delay_ms(800);
72
  }
73
74
  }   
75
  else {
76
  PORTD &= ~LED;
77
  vorwaerts();  
78
  }
79
  }
80
81
return 0;
82
}

Ich steh irgendwie auf dem Schlauch. :o

: Bearbeitet durch User
von Unterschied (Gast)


Lesenswert?

Matthias I. schrieb:
> So funktioniert alles:#define F_CPU 3688000UL
...

Was ist denn jetzt der Unterschied? Ich gehe ganz sicher nicht jede 
Zeile durch.

von Hans (Gast)


Lesenswert?

Rück den Code halt wenigstens mal ordentlich ein. Die wenigsten hier 
haben Lust, erst mal die zusammengehörigen Klammern zu suchen ...

von Steffen R. (steffen_rose)


Lesenswert?

Matthias I. schrieb:
> So funktioniert nichts:

Was heißt das genau? Welches Verhalten zeigt sich?

von Jogi Löw (Gast)


Lesenswert?

Steffen Rose schrieb:
>> So funktioniert nichts:
>
> Was heißt das genau? Welches Verhalten zeigt sich?

Hat er doch schon geschrieben: Es funktioniert nicht. Erwartest Du jetzt 
noch Fehlermeldung (Screenshot) und dergleichen?

von Matthias I. (Gast)


Lesenswert?

Es gibt keine Screenshots der Code compiliert nur laueft das Programm 
nicht ab.
Sobald ich das in den Tiny Flashe tut sich nichts mehr.
Der "Falsche Code" geht astrein.

Nur laueft keine Funktion die ich erstelle.
Ausser sie sind in Main().
Dann gehen sie.

von Steffen R. (steffen_rose)


Lesenswert?

Ich erwarte eine genaue Fehlerbeschreibung.
z.B. Er fährt nur vorwärts. Oder er ändert ständig die Richtung ohne an 
den Buzzer zu kommen.

Du gehts ja auch nicht zum Arzt und sagst nur "Mir gehts nicht gut".

Daher nicht wundern, dass bei solch einer nichtssagenden 
Fehlerbeschreibung nur die Codequalität diskutiert wird. Was soll man 
auch anderes machen, als nach einer falsch gesetzte Klammer zu suchen.

von Steffen R. (steffen_rose)


Lesenswert?

Matthias I. schrieb:
> Sobald ich das in den Tiny Flashe tut sich nichts mehr.

Was sagt die LED (an, aus, flackern)?

Du kannst Das Programm auch erstmal nur auf "vorwärts" reduzieren. Und 
dann Stück für Stück weiter.

Wenn wirklich garnicht geht, prüfen, ob main überhaupt durchlaufen wird. 
Dafür kann man die LED nutzen, wenn man sonst nichts hat.

Wie siehst mit Compilerwarnings aus? Warnungen eingeschaltet? Die 
könnten einen Hinweis geben. Oder warnt der Linker?

Ich bezweifle momentan, dass das Problem am geposteten Code liegt.

von Stefan E. (sternst)


Lesenswert?

Steffen Rose schrieb:
> Ich bezweifle momentan, dass das Problem am geposteten Code liegt.

Vermutlich hat er ein grundlegendes Problem in seinem Build-Prozess. Bei 
der beschriebenen Symptomatik könnte ich mir z.B. vorstellen, dass er 
das ELF-File in den Controller brennt (oder sogar nur ein ungelinktes 
Object-File).

von Matthias I. (matze5)


Lesenswert?

Also fuer Dumm verkaufen lasse ich mich sicher nicht.
Elf file flashen und so. Muss hier ja oft vorkommen.

Der Roboter macht einfach gar nichts, kein LED blinken nichts.
Wenn ich den Code mit den Funktionen in Main() als Hex brenne passt 
alles.
Wenn die Funktionen ausserhalb von Main() sind gehts nicht.
ist das so schwer zu verstehen ?
Geht nicht heisst, es geht nichts.
Da blinkt nichts, Kein Motor dreht, einfach nichts.
Der Controller zuckt kein Bisschen.

avr-gcc -mmcu=attiny2313 -Os -c motorun.c -o motorun.o
avr-gcc motorun.o -o motorun.elf
avr-objcopy -O ihex -j .text -j .data motorun.elf motorun.hex

avrdude  -p t2313 -c avrisp2 -P usb -U flash:w:motorun.hex

ich wuesste nicht was da falsch ist.

Mein Geraet funktioniert und tut auch was es soll.
Nur eben mit den unschoenen Funktionen in der Main()

Edit: wenn der Code minimal reduziert ist funktionierts auch nicht.
Also fehlt wohl irgendwas um Funktionen zu unterstuetzen.

Denn es geht auch keine simple Funktion wie:
(Ausgang natuerlich in main definiert..)

void led_an(){
PORTD |= LED;
}

: Bearbeitet durch User
von Matthias I. (Gast)


Lesenswert?

Ahja der Compiler:
1
Es werden eingebaute Spezifikationen verwendet.
2
COLLECT_GCC=/usr/x86_64-pc-linux-gnu/avr/gcc-bin/4.8.2/avr-gcc
3
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/avr/4.8.2/lto-wrapper
4
Ziel: avr
5
Konfiguriert mit: /var/tmp/portage/cross-avr/gcc-4.8.2/work/gcc-4.8.2/configure --host=x86_64-pc-linux-gnu --target=avr --build=x86_64-pc-linux-gnu --prefix=/usr --bindir=/usr/x86_64-pc-linux-gnu/avr/gcc-bin/4.8.2 --includedir=/usr/lib/gcc/avr/4.8.2/include --datadir=/usr/share/gcc-data/avr/4.8.2 --mandir=/usr/share/gcc-data/avr/4.8.2/man --infodir=/usr/share/gcc-data/avr/4.8.2/info --with-gxx-include-dir=/usr/lib/gcc/avr/4.8.2/include/g++-v4 --with-python-dir=/share/gcc-data/avr/4.8.2/python --enable-languages=c,c++ --enable-obsolete --enable-secureplt --disable-werror --with-system-zlib --enable-nls --without-included-gettext --enable-checking=release --with-bugurl=https://bugs.gentoo.org/ --with-pkgversion='Gentoo 4.8.2 p1.3r1, pie-0.5.8r1' --enable-libstdcxx-time --enable-poison-system-directories --enable-shared --disable-threads --disable-bootstrap --enable-multilib --disable-altivec --disable-fixed-point --disable-libgcj --disable-libgomp --disable-libmudflap --disable-libssp --disable-libquadmath --enable-lto --without-cloog
6
Thread-Modell: single
7
gcc-Version 4.8.2 (Gentoo 4.8.2 p1.3r1, pie-0.5.8r1)

eventuell liegts ja am Compiler ?

von Stefan E. (sternst)


Lesenswert?

Matthias I. schrieb:
> Also fuer Dumm verkaufen lasse ich mich sicher nicht.
> ...
> ist das so schwer zu verstehen ?

Kein Grund hier pampig zu werden.


Matthias I. schrieb:
> ich wuesste nicht was da falsch ist.

Code ist nicht für den richtigen Controller gelinkt.

von Matthias I. (Gast)


Lesenswert?

Besten Dank,

tut mir leid das ich etwas ungehalten war, ich war schlichtweg entnervt.
Nun geht tatsaechlich alles wie es soll..

Gleichzeitig bin ich noch auf einen Bug im Gentoo avr-gcc gestossen
Die Linkerscripte waren nicht verlinkt.
ln -s /usr/lib/binutils/avr/2.24/ldscripts/ /usr/avr/lib/ldscripts
behebt das folgende Problem:
Cannot open linker script file ldscripts/avr25.xn: Datei oder 
Verzeichnis nicht gefunden

Und was ich nicht wusste war:
avr-gcc -mmcu=attiny2313 -O2 -c motorun.c -o motorun.o
avr-gcc -g -mmcu=attiny2313 motorun.o -o motorun.elf
avr-objcopy -O ihex -j .text -j .data motorun.elf motorun.hex

So gehts nun.

von Jogi Löw (Gast)


Lesenswert?

Hast Deinen Code jetzt wenigstens manierlich formatiert mit korrekten 
Tabulatoren und Kommentaren? ;-)

von Matthias I. (Gast)


Lesenswert?

Ich arbeite dran :)

dafuer das ich mir alles selbstbeigebracht hab und weder Ahnung von C 
noch Elektrik hatte ist es ganz gut geworden.

http://www.youtube.com/watch?v=TYfIhrqZPVU

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Matthias I. schrieb:
> Ahja der Compiler:
>
> Konfiguriert mit: --disable-fixed-point

Na prima.  Da wird mit viel Aufwand Assembler-optimerter Fixed-Point 
Support in avr-gcc eingebaut, und dann wird's einfach ausgeknipst...

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

@Johann L. (gjlayde) Benutzerseite

>> Konfiguriert mit: --disable-fixed-point

>Na prima.  Da wird mit viel Aufwand Assembler-optimerter Fixed-Point
>Support in avr-gcc eingebaut, und dann wird's einfach ausgeknipst...

Gefrickel 3.0

Wenn man schon mti Kommandozeile und selbstgestricktem Makefile arbeiten 
will, sollte man es wenigstens können. Da lob ich mir mein AVR-Studio!

F7!

von Matthias I. (Gast)


Lesenswert?

Wenn man immer Fertigkost zu sich nimmt.
Wird es kaum besser.
Immerhin ist der Fehler nicht meiner, sondern der des Maintainers des 
EBuilds :)

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.