Forum: Compiler & IDEs Anfängerproblem: Interner Zähler


von Björn G. (feathyr)


Lesenswert?

Guten Tag,

Ich fange gerade an meine ersten Schritte mit Mikrocontrollern zu wagen. 
Für diese  ersten Versuche habe ich mir einen ATMEGA8535 zugelegt.

Nun habe ich versucht den internen Zähler zu benutzen um mir die 
vergangene Zeit auf einem Port per LEDs anzeigenzu lassen. Idee war den 
so lange zählen zu lassen bis eine Sekunde rum ist und ihn dann per 
Interrupt das Register des Port D zu inkrementieren lassen.

Das Program habe ich mir aber nicht selber ausgedacht sondern es stammt 
hier von der Seite aus dem GCC Tutorial.
Ich benutze AVR Studio 4.17 und einen AVRISP mkII. Sowohl beim 
Simulieren, als auch auf dem Mikroncontroller funktioniert das Programm 
aber nicht. Und ich bin Ratlos wieso.

Hier erstmal das programm:

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

volatile unsigned int  millisekunden=0;
volatile unsigned int  sekunde=0;
volatile unsigned int  minute=0;
volatile unsigned int  stunde=0;


main ()
{
  DDRD=0xFF;

     TCCR0 =(1<<WGM01) |(1<<CS01);
    OCR0=125;
    TIMSK|=(1<<OCIE0);
    sei();

     while(1){
    PORTD=sekunde;
    }
}

ISR (TIMER0_COMP_vect)
{
     millisekunden++;

     if(millisekunden==1000)
     {
      sekunde++;
       millisekunden=0;

      if(sekunde==60)
       {
           minute++;
         sekunde=0;
      }
      if(minute ==60)
        {
         stunde++;
          minute=0;
      }
   }
}


Ich habe beim Simulieren entdeckt, das am Anfang das Register OCR0 nicht 
geschrieben wird, aber später wird das Register ja mit dem Counter 
verglichen, ergo springt er nie in die Interruptroutine. Aber ich bin 
mit meinem bischen Latein am Ende wo es hier hängt.

Grüße Björn

von SF (Gast)


Lesenswert?

Mmm. Bei mir (AvrSTudio16Build628, WinAvr09032009) funktioniert das 
Programm im Simulator 1. Bei 1Mhz Takt wird ein Breakpoint, der in der 
Zeile
1
sekunde++;
liegt, alle 1008ms aufgerufen. Wenn du die Zeile
1
OCR0=125;
zu
1
OCR0=124;
ändern würdest dann hättest du auch exakt 1000ms.

Dein Problem muss irgendwo anders sein. Hast du in den Projektoptionen 
alles richtig eingestellt? Die Kommandozeile beim Compilieren müsste 
etwa so aussehen:
1
avr-gcc  -mmcu=atmega8535 -Wall -gdwarf-2 -std=gnu99 -DF_CPU=1000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT test.o -MF dep/test.o.d  -c  ../test.c
2
avr-gcc -mmcu=atmega8535 -Wl,-Map=test.map test.o     -o test.elf
3
avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature  test.elf test.hex
4
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O ihex test.elf test.eep || exit 0
5
avr-objdump -h -S test.elf > test.lss

von Björn G. (feathyr)


Lesenswert?

Danke erstmal deine Vermutung war richtig, ich hatte den Takt nicht in 
den Projektoptioinen eingestellt :)

Allerdings läuft das Programm immer noch nicht.
Beim Debugging ist mir aufgefallen, das das OCIE0 Bit im TIMSK Register 
nicht gesetzt wird, also springt er ja nicht in die Interrupt Routine. 
Der Zähler funktioniert jetzt richtig, er zählt hoch bis 124 und bricht 
dann ab, bzw beginnt von neuem Hochzuzählen. Allerdings wird die ISR nie 
aufgerufen. Das verstehe ich nicht, laut anweisungen soll er das Bit ja 
setzten, nur warum tut er es bei mir nicht?

Und bei Compilieren erhalte ich jetzt folgende Meldung:
1
Build started 10.8.2009 at 09:57:50
2
avr-gcc  -mmcu=atmega8535 -Wall -gdwarf-2 -std=gnu99 -DF_CPU=1000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT Breadboard.o -MF dep/Breadboard.o.d  -c  ../Breadboard.c
3
../Breadboard.c:12: warning: return type defaults to 'int'
4
avr-gcc -mmcu=atmega8535 -Wl,-Map=Breadboard.map Breadboard.o     -o Breadboard.elf
5
avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature  Breadboard.elf Breadboard.hex
6
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O ihex Breadboard.elf Breadboard.eep || exit 0
7
avr-objdump -h -S Breadboard.elf > Breadboard.lss
8
9
AVR Memory Usage
10
----------------
11
Device: atmega8535
12
13
Program:     298 bytes (3.6% Full)
14
(.text + .data + .bootloader)
15
16
Data:          8 bytes (1.6% Full)
17
(.data + .bss + .noinit)
18
19
20
Build succeeded with 1 Warnings...

c12 meint das Zeile 12 im Original c-code, oder bezieht sich das bereits 
auf das compilierte?

Und was für auswirkungen hat dieses Warnung, ich habe den verdacht, dass 
das vllt Teil des Problems sein könnte.

Gruß Björn

von Karl H. (kbuchegg)


Lesenswert?

Björn Gustäbel schrieb:

>
> c12 meint das Zeile 12 im Original c-code, oder bezieht sich das bereits
> auf das compilierte?

Das wäre ziemlich sinnlos.
Die Zeilennummer bezieht sich auf den Code, so wie du ihn geschrieben 
hast.

> Und was für auswirkungen hat dieses Warnung, ich habe den verdacht, dass
> das vllt Teil des Problems sein könnte.

Es geht um main()
1
main()
2
{
3
  ...
4
}

Auch main ist aus C-Sicht nichts anderes als eine Funktion. So wie jede 
andere Funktion auch, hat auch main() einen Returntyp. Gibst du nichts 
an, dann greifen die C-Default Regeln, welche vorschreiben, das der 
Returntyp einer Funktion int ist. Das kann richtig sein, kann aber auch 
völlig falsch sein. Daher warnt dich der Compiler.

In deinem Fall ist es das Richtige. Trotzdem ist es besser, wenn du dich 
nicht auf Default-Regeln verlässt, sondern die Dinge beim Namen nennst
1
int main( void )
2
{
3
  ...
4
}

von Björn G. (feathyr)


Lesenswert?

Danke sehr euch allen, jetzt habe ich keine Warnung mehr, und das 
Programm läuft, anscheinend hat er sich daran, dass ich nur main() 
geschrieben habe so sehr gestört, dass er das TIMSK Register nicht 
gesetzt hat. Warum auch immer :)

Jetzt funktioniert alles

Besten Dank

von Karl H. (kbuchegg)


Lesenswert?

Björn Gustäbel schrieb:
> Danke sehr euch allen, jetzt habe ich keine Warnung mehr, und das
> Programm läuft, anscheinend hat er sich daran, dass ich nur main()
> geschrieben habe so sehr gestört, dass er das TIMSK Register nicht
> gesetzt hat. Warum auch immer :)

Das kann nicht sein.
Dem Debugger ist es egal, ob du beim Compilieren Warnungen hast oder 
nicht. Der simuliert den Code, so wie ihn der Compiler erzeugt. Und auch 
bei mir läuft der Simulator völlig korrekt durch. Selbst wenn die 
Warnung da ist.

von Björn G. (feathyr)


Lesenswert?

Dann haben heute Nacht irgendwelche Heinzelmännchen meinen Code 
Repariert, weil ich habe da nichts weiter geändert, außer main() zu int 
main (void), achja und den Takt habe ich in den Projektoptionen 
eingestellt, das waren die Unterschiede zu gestern Abend.

Nachdem ich den Takt einstellte lief das Programm immer noch nicht, erst 
als ich die änderung an der main vornahm lief das Programm durch.

Vllt liegts ja auch daran, dass ich AVR Studio 4.17 verwende, das stammt 
ja von der Beta Seite aus Norwegen.

von Karl H. (kbuchegg)


Lesenswert?

Björn Gustäbel schrieb:
> Dann haben heute Nacht irgendwelche Heinzelmännchen meinen Code
> Repariert, weil ich habe da nichts weiter geändert, außer main() zu int
> main (void), achja und den Takt habe ich in den Projektoptionen
> eingestellt, das waren die Unterschiede zu gestern Abend.
>
> Nachdem ich den Takt einstellte lief das Programm immer noch nicht, erst
> als ich die änderung an der main vornahm lief das Programm durch.
>
> Vllt liegts ja auch daran, dass ich AVR Studio 4.17 verwende, das stammt
> ja von der Beta Seite aus Norwegen.

Ich habe 4.13

Und ja, höchstwahrscheinlich gab es noch eine Änderung:
Du hast den Rechner rebootet oder zumindest deine Entwicklungsumgebung 
neu gestartet.
Lach jetzt nicht. Manchmal verklemmt sich tatsächlich der 
Make-Mechanismus und dann werden notwendige Updates nicht gemacht. 
Sollte nicht vorkommen, kommt aber in jeder Entwicklungsumgebung 
manchmal vor. Zb. Microsofts Dev-Studio war zumindest früher berühmt 
dafür, dass ein komplettes Löschen der Generierverzeichnisse so manchen 
seltsamen/unerklärlichen Fehler behoben hat.

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.