Forum: Mikrocontroller und Digitale Elektronik Frage zur Programmierung.


von Tobias J. (masterofdisaster)


Lesenswert?

Hallo,

ich hab mir hier schon viele Infos aus dem Forum gesammelt und 
erfolgreich umgesetzt. Jetzt wollte ich mal wieder anfangen (nach ein 
paar Jahren) in C zu programmieren. Genaugenommen einem Atmega 16 ein 
wenig Leben einzuhauchen.

Da stellt sich mir gleich folgendes Problem.

Ich habe ein kleines Programm geschrieben, wo ich einen Teil in einen 
"Funktionsblock" auslagern wollte damit die main Funktion übersichtlich 
bleibt.

Leider funkt. das nicht wie erhofft.

Ich habe folgendes gemacht:
1
void machwas(int ms) {
2
   for(int i=0; i<8;i++){
3
   ....
4
}
5
int main(void)
6
{
7
    while(1){   
8
        machwas(100);
9
    }
10
}

So weit so gut... leider wird "machwas" nicht ausgeführt. Im Debugger 
sehe  ich das er beim Aufruf von "machwas" in die Funktion springt, aber 
direkt wieder raus...
Schreibe ich die Anweisungen aus "machwas" in die main Funktion geht 
es...
Wo liegt mein Fehler?

Danke im Voraus... Tobias

von Purzel H. (hacky)


Lesenswert?

Solange "Machwas" selbst wegoptimiert werden kann... Schreib dort doch 
mal ein Register.

von Tobias J. (masterofdisaster)


Lesenswert?

Da steht ja Code drin... wegoptimieren kann er die nicht... ich hab nur 
am Programmierrechner kein Internet, deswegen nur der Auszug...

Die Schleife mit ihrem Inhalt funkt. ja direkt im Main...

von Peter D. (peda)


Lesenswert?

Schau mal in die h-Files Deines (uns unbekannten) Compilers.
Oftmals gibts da eine delay.h, die man dann nimmt.
Oder schau ins Manual.

Zeitvernichtungsfunktionen schreibt man nicht selber, das können die 
Compilerbauer besser als Du.


Peter

von Oliver (Gast)


Lesenswert?

Tobias Jenatschke schrieb:
> Da steht ja Code drin... wegoptimieren kann er die nicht...

Woher weißt du das?
Comopilier das mal ohne Optimierung (-O0), das sollte helfen.

Oliver

Tobias Jenatschke schrieb:
> ich hab nur
> am Programmierrechner kein Internet, deswegen nur der Auszug...
Das ist ganz schlecht. Für Code, der "so so der so ähnlich" abgetippt 
wurde, dazu mit "..." drin, wirst du keine Hilfe bekommen.

Oliver

von Imon (Gast)


Lesenswert?

Tobias Jenatschke schrieb:
> void machwas(int ms) {
>    for(int i=0; i<8;i++){
         ^^^ das ist reinen ISO C nicht gestattet soweit ich weiß.
             in reinen C muss i vor der Schleife deklariert sein.
>    ....
> }
> int main(void)
> {
>     while(1){
>         machwas(100);
>     }
> }

Ansonsten sieht der Code Schnipsel  gut aus, wenn du uns nicht mit mehr 
Informationen versorgen kannst, welcher Compiler, welche Compile 
Optionen, was wird in "...."  gemacht. wird es schwer dir zu sagen wo 
dein Fehler liegt.

von Sven P. (Gast)


Lesenswert?

Imon schrieb:
> Tobias Jenatschke schrieb:
>> void machwas(int ms) {
>>    for(int i=0; i<8;i++){
>          ^^^ das ist reinen ISO C nicht gestattet soweit ich weiß.
>              in reinen C muss i vor der Schleife deklariert sein.
Das geht in Ordnung ab ISO/IEC 9899:1999.

von Tobias J. (masterofdisaster)


Lesenswert?

Danke erstmal...

Ich arbeite mit AVR-Studio + GCC

Habe leider nur Java und PHP gelernt, C basiert nur auf Selbststudium.

>Tobias Jenatschke schrieb:
> Da steht ja Code drin... wegoptimieren kann er die nicht...

>Woher weißt du das?
>Comopilier das mal ohne Optimierung (-O0), das sollte helfen.

Ich vermute das nur, da es ja direkt im Main funktioniert....


Ich versuch heute abend mal den gesamten Code hier zu rein zu posten...

von Tobias J. (masterofdisaster)


Lesenswert?

1
void machwas(uint16_t ms)
2
{
3
//Die variablen sind im headerfile definiert... 
4
 LED_BB_DDR = (1<<LED_BB_0) | (1<<LED_BB_1) | (1<<LED_BB_2) | (1<<LED_BB_3) | (1<<LED_BB_4) | (1<<LED_BB_5)
5
  | (1<<LED_BB_6) | (1<<LED_BB_7);
6
  for(int i=0; i<8; i++){
7
      LED_BB_PORT |= (1<<i);
8
      _delay_ms(ms);
9
           LED_BB_PORT &= ~(1<<i);
10
  }
11
}
12
 
13
int main(void)
14
{
15
  while(1){   //Die Bedingungen folgen später
16
            machwas(50);
17
        }
18
        return 0;
19
}

Das funktioniert nicht... schreib ich jedoch einfach den Code in die 
Main, dann gehts...

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Vermutlich schreibst du dann nicht

_delay_ms(ms);

sondern

_delay_ms(50);

Letzteres ist die richtige Variante: Nur Konstanten sind bei _delay_ms 
und _delay_us erlaubt. Steht auch so in der avr-libc Doku und 1001*mal 
hier im Forum :-)

Du kannst ein variables _delay_ms so erreichen:

{
  uint16_t i;
  for (i=0; i<ms; i++)
    _delay_ms(1);
}

von Tobias J. (masterofdisaster)


Lesenswert?

Oh, sorry, Ich bin wirklich wie ein Schnitzel...(bekloppt von allen 
Seiten)

Das hab ich echt überlesen!

Jetzt dachte ich mir, ich könnte mir eine Funktion basteln, ala...
void langes_warten(uint16_t ms)
1
{
2
  uint16_t i;
3
  for (i=0; i<ms; i++)
4
    _delay_ms(1);
5
}

Allerdings funktioniert das auch nicht....

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Das ist ungewöhnlich.

Aber zu "funktioniert nicht" fällt mir leider nicht viel ein.

Eine buggy _delay_ms() kann man ausschliessen, weil die direkte Variante 
ja schon funktioniert hat. Bei F_CPU und Optimierung hast du hoffentlich 
auch nichts geändert.

Bleiben also die doofen Fragen:

1. Rufst du langes_warten() auch irgendwo auf?

Nicht an die Wand springen. Hat man schon gesehen!

2. Überträgst du das richtige HEX-File?

Das AVR Studio kann da beim ISP Programmieren etwas eigen sein.

3. Hast du den richtigen AVR eingestellt?

Wenn Unterprogramme insgesamt nicht funktionieren, kann ein 
Initialisierungsproblem beim Stack vorliegen. Das kann ein Zeichen für 
einen falschen µC (TARGET) sein. Auch die M103 Fuse beim Atmega128 fällt 
in diese Kategorie (Übersetzt für Atmega128, Werkseinstellung des 
Atmega128 ist aber Atmega103...).

_delay_ms() ist keine statische Funktion, sondern eine inline Funktion. 
Da fällt ein Stackproblem nicht auf.

von Karl H. (kbuchegg)


Lesenswert?

Nicht zu vergessen, dass _delay_ms im Simulator zu, na ja sagen wir mal, 
längeren Wartezeiten führen kann, wenn man mit F10 drüberzusteppen 
versucht. Selbst wenn man alles richtig gemacht hat.

von ekke (Gast)


Lesenswert?

Stefan B. schrieb:
> Letzteres ist die richtige Variante: Nur Konstanten sind bei _delay_ms
> und _delay_us erlaubt. Steht auch so in der avr-libc Doku und 1001*mal
> hier im Forum :-)
Ich dachte, es wäre erlaubt, erzeugt aber sehr großen Code und sollte 
deshalb vermieden werden?

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Erlaubt im Sinn von funktioniert im Sinn von Verzögert die angegebene 
Anzahl Millisekunden.

von ekke (Gast)


Lesenswert?

Stefan B. schrieb:
> Erlaubt im Sinn von funktioniert im Sinn von Verzögert die angegebene
> Anzahl Millisekunden.
Ja, das meinte ich... ;-)

von Karl H. (kbuchegg)


Lesenswert?

ekke schrieb:
> Stefan B. schrieb:
>> Erlaubt im Sinn von funktioniert im Sinn von Verzögert die angegebene
>> Anzahl Millisekunden.
> Ja, das meinte ich... ;-)

Eben.
Mit einer Variablen stimmen die Zeiten ganz einfach nicht mehr.

_delay_ms ist davon abhängig, dass der Optimizer eine komplexe 
Berechnung rausoptimiert. Das geht aber nur dann, wenn er die 
Verzögerungszeit kennt.
Die kennt er wiederrum nur dann, wenn es eine Konstante ist.

von Tobias J. (masterofdisaster)


Lesenswert?

Ich hab gestern abend erstmal hingeworfen. Manchmal sieht man einige 
Stunden später den Fehler. Heute bin ich leider lange unterwegs. Werde 
mich wohl morgen wieder damit befassen.

Es wird etwas einfaches sein... mal schauen.

Wenn ich den Fehler gefunden habe, melde ich mich natürlich wieder...

Danke für die viele Hilfe.

1
void langes_warten(uint16_t ms){
2
  uint16_t i;
3
  for (i=0; i<ms; i++)
4
    _delay_ms(1);
5
}

Bringt ja eh etwas Ungenauigkeit in die Pause, für meinen Zweck reicht 
es jedoch.

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.