Forum: Mikrocontroller und Digitale Elektronik atmega32 Zähler


von benny (Gast)


Lesenswert?

Hallo,

ich bin nicht fit in C und Mikrocontroller und wollte daher kurz fragen 
ob die Timer so gehen könnten.

Zum einen bekomme ich Warnungen, dass meine inline Funktionen declared 
but never defined sind. Woran liegt das?

Hier meine Dateien.
timer.h
1
#ifndef _TIMER_H_
2
  #define _TIMER_H_
3
4
5
#include <inttypes.h>
6
7
8
9
static volatile uint8_t ms = 0;
10
11
12
extern inline void init_timer0(void);
13
14
extern inline void start_timer0(void);
15
16
extern inline void stop_timer0(void);
17
18
19
#endif // _TIMER_H_

timer.c
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
#include "timer.h"
5
6
7
inline void init_timer0(void)
8
{
9
  TCCR0 = (1 << WGM01);
10
11
  OCR0 = 250;
12
13
  TIMSK = (1 << OCIE0);
14
15
16
}
17
18
inline void start_timer0(void)
19
{
20
  TCCR0 |= (1 << CS01) | (1 << CS00);
21
}
22
23
inline void stop_timer0(void)
24
{
25
  TCCR0 &= ~((1 << CS01) | (1 << CS00));
26
}
27
28
29
ISR(TIMER0_COMP_vect)
30
{
31
  if(ms < 0xFF) {
32
    ++ms;
33
  }
34
}

main.c
1
#include <avr/interrupt.h>
2
3
#include "timer.h"
4
5
6
7
int main(void)
8
{
9
  init_timer0();
10
  sei();
11
  start_timer0();
12
13
  while(1) {
14
    if(ms > 10) {
15
      asm volatile("nop");
16
    }
17
  }
18
}

Im Simulator scheint das nicht richtig zu laufen (AVRStudio scheint 
hängen zu bleiben). Dazu kommt, dass der Simulator keine 16 MHz kann.

Das Ganze soll auf einem ATmega32 mit 16 MHz jede Millisekunden die 
Variable ms hochzählen, die dann in verschiedensten Dateien des 
Projektes zugreifbar sein soll.

von Sven P. (Gast)


Lesenswert?

benny schrieb:
> Zum einen bekomme ich Warnungen, dass meine inline Funktionen declared
> but never defined sind. Woran liegt das?

Naja, es liegt daran, dass sie deklariert, aber nicht definiert sind...

Überleg mal: In dem Header steht quasi 'inline prototyp();', den 
Funktionsrumpf packst du in ein eigenes Modul ('C-Datei'). Nun übersetzt 
du das ganze.

Wenn du jetzt in einem anderen Modul diesen Header mit den 
Inline-Dingern einbaust und den übersetzt, woher soll der Compiler denn 
wissen, was er überhaupt 'inlinen' soll? Die Funktionsrümpfe sieht er 
doch garnicht!

von benny (Gast)


Lesenswert?

Kennt der Compiler nicht alle Dateien? Oder warum kennt der die 
Funktionsdefinitionen nicht?
Muss ich für so kleine inline Sachen dann die Definition in die .h 
packen? Dachte genau das soll man nicht tun.

Stimmt den die Configuration des Timers oder habe ich da was vergessen?

von benny (Gast)


Lesenswert?

Hallo, ich nochmal.

Habe nun meinen Timer auf der Hardware getestet und nichts geht.

timer.h
1
#ifndef _TIMER_H_
2
  #define _TIMER_H_
3
4
5
#include <inttypes.h>
6
7
8
9
extern volatile uint8_t ms0;
10
11
12
13
void init_timer0(void);
14
15
void start_timer0(void);
16
17
void stop_timer0(void);
18
19
20
#endif // _TIMER_H_

timer.c
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
#include "timer.h"
5
6
volatile uint8_t ms0 = 0;
7
8
9
void init_timer0(void)
10
{
11
  TCCR0 = (1 << WGM01);
12
13
  OCR0 = 250;
14
15
  TIMSK |= (1 << OCIE0);
16
17
18
}
19
20
void start_timer0(void)
21
{
22
  TCCR0 |= (1 << CS01) | (1 << CS00);
23
}
24
25
void stop_timer0(void)
26
{
27
  TCCR0 &= ~((1 << CS01) | (1 << CS00));
28
}
29
30
31
ISR(TIMER0_COMP_vect)
32
{
33
  if(ms0 < 0xFF) {
34
    ++ms0;
35
  }
36
}

main.c
1
#ifndef F_CPU
2
  #define F_CPU 16000000UL
3
#endif // F_CPU
4
5
6
#include <avr/interrupt.h>
7
#include <avr/io.h>
8
#include <util/delay.h>
9
10
#include "timer.h"
11
12
13
int main(void)
14
{
15
  DDRB |= (1 << DDB0);
16
17
  PORTB |= (1 << PB0);
18
19
  _delay_ms(1000);
20
21
  PORTB &= ~(1 << PB0);
22
23
  init_timer0();
24
  sei();
25
  start_timer0();
26
27
  while(1)
28
  {
29
    if(ms0 >= 1000)
30
    {
31
      PORTB ^= (1 << PB0);
32
      ms0 = 0;
33
    }
34
  }
35
}

Anscheinend funktioniert das mit der globalen volatile Variable in der 
timer.h nicht. Habe allerdings auch keine wirklichen C Erfahrungen, also 
bin mir auch nicht sicher ob das wirklich so geht.

Das IF scheint irgendwie wegoptimiert zu werden.

.lss
1
  init_timer0();
2
      aa:  0e 94 2f 08   call  0x105e  ; 0x105e <init_timer0>
3
  sei();
4
      ae:  78 94         sei
5
  start_timer0();
6
      b0:  0e 94 37 08   call  0x106e  ; 0x106e <start_timer0>
7
8
  while(1)
9
  {
10
    if(ms0 >= 1000)
11
      b4:  80 91 dc 01   lds  r24, 0x01DC
12
      b8:  fd cf         rjmp  .-6        ; 0xb4 <main+0x22>

Habe ich bei der globalen Variable und/oder beim Timer ansich etwas 
falsch gemacht? Ich denke schon, nur was?

An Port B0 hängt eine LED, die eigentlich jede Sekunden umschalten 
sollte.

von holger (Gast)


Lesenswert?

>volatile uint8_t ms0 = 0;
>if(ms0 >= 1000)

Fällt dir da gar nichts auf? Wertebereich beachten.

von Gast (Gast)


Lesenswert?

> volatile uint8_t ms0 = 0;
> if(ms0 >= 1000)

Der COmpiler denkt sich wohl:
ms0 wird wohl immer kleiner als die 1000 sein, also wozu das if?

von benny (Gast)


Lesenswert?

Args ganz übersehen. Als uint16_t geht es natürlich.

von holger (Gast)


Lesenswert?

>Der COmpiler denkt sich wohl:
>ms0 wird wohl immer kleiner als die 1000 sein, also wozu das if?

Das braucht der Compiler gar nicht zu denken. Der Programmierer
tut selbst alles daß es auch so ist ;)

  if(ms0 < 0xFF) {
    ++ms0;
  }

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.