Timer1, CTC, Interrupt, REST, mega8, Problematik

Gast #2089266
Lesenswert?

Hallo alle zusammen,

also ich steh voll auf dem Schlauch! Bin jetzt seit 3 Tagen dran mich in 
die Timer einzuarbeiten und komme an einem REST-Problem nicht weiter. 
Hab wirlich alle möglichen Forenbeiträge durchgelesen.
Vielleicht bin ich auch nur Betriebsblind!

Ich möchte mit dem Timer1 im CTC Mode den Interrupt alle 1 Sekunde 
auslösen lassen. Alles funktioniert, nur das beim Interrupt Auslösen der 
uC resetet.
Ich hab auch versucht per ISR(BADISR_vect) was abzufangen, aber ging 
auch nicht. Die Routine wurde garnicht angesprochen.

- uC mega8
- Board AVR-P28 (Rev.B)
- Quarz 8000000 Hz

Hier der Code
1
#define F_CPU 8000000UL
2

3
#include <avr/interrupt.h>
4
#include <avr/io.h>
5

6
volatile uint16_t count1=0;
7
volatile uint16_t count2=0;
8

9

10
ISR(TIMER1_COMPA_vect)//ISR(BADISR_vect)
11
{
12

13
  count2=0;
14
  while(1)
15
  {
16
    count2++;
17

18
    if(count2 == 10000)
19
    {
20
      PORTC ^= (1<<PC5);
21

22
      count2=0;
23
    }
24
  }
25

26
}
27

28

29
int main(void)
30
{
31

32
  cli();
33
  DDRC |= (1<<PC5);
34
  PORTC = (1<<PC5);
35

36
  OCR1A = 7812; // 8000000/1024
37
  TCCR1A = (0 << COM1A1)|(0 << COM1A0)|(0 << COM1B1)|(0 << COM1B0)|(0 << FOC1A)|(0 << FOC1B)|(0 << WGM11)|(0 << WGM10);
38
  TCCR1B = (0 << ICNC1)|(0 << ICES1)|(0 << WGM13)|(1 << WGM12)|(1 << CS12)|(0 << CS11)|(1 << CS10); //Prescaler auf 1024,  CTC-Mode
39
  TIMSK = (0 << OCIE2)|(0 << TOIE2)|(0 << TICIE1)|(1 << OCIE1A)|(0 << OCIE1B)|(0 << TOIE1)|(0 << TOIE0);
40

41
  sei();
42

43
  count1=0;
44
  while (1)
45
  {
46

47
    count1++;
48

49
    if(count1 == 65000)
50
    {
51
      PORTC ^= (1<<PC5);
52

53
      count1 = 0;
54
    }
55

56
  }
57

58
  return 0;
59
}

Wäre sehr froh, wenn mir jemand ein Tipp hätte.

Gruß
Gast #2089323
Lesenswert?

@"ich":
Danke für den Tip, aber das bringt mir nicht viel.

@Karl Heinz Buchegger:
Also eine Endlosschleife in einer ISR ist nicht sinnvoll, das ist mir 
klar. Ich möchte damit erkennen können ob die ISR angesprungen wird.
Ich kann wohl die LED blinken, bzw. flimmern sehen, hab die gleiche 
Schleife in der main() ausprobiert.
Gast #2089328
Lesenswert?

>Alles funktioniert, nur das beim Interrupt Auslösen der uC resetet

Woher weißt Du das?

Probier mal als minimalistisches Testprogramm das hier:
1
#define F_CPU 8000000UL
2

3
#include <avr/interrupt.h>
4
#include <avr/io.h>
5

6
volatile uint16_t count1=0;
7
volatile uint16_t count2=0;
8

9

10
ISR(TIMER1_COMPA_vect)//ISR(BADISR_vect)
11
{
12
  PORTC = 0x00;
13
}
14

15

16
int main(void)
17
{
18
  DDRC  = 0xFF;
19
  PORTC = 0xFF;
20

21
  OCR1A = 10; // 8000000/1024
22
  TCCR1A = (0 << COM1A1)|(0 << COM1A0)|(0 << COM1B1)|(0 << COM1B0)|(0 << FOC1A)|(0 << FOC1B)|(0 << WGM11)|(0 << WGM10);
23
  TCCR1B = (0 << ICNC1)|(0 << ICES1)|(0 << WGM13)|(1 << WGM12)|(1 << CS12)|(0 << CS11)|(1 << CS10); //Prescaler auf 1024,  CTC-Mode
24
  TIMSK = (0 << OCIE2)|(0 << TOIE2)|(0 << TICIE1)|(1 << OCIE1A)|(0 << OCIE1B)|(0 << TOIE1)|(0 << TOIE0);
25

26
  sei();
27

28
  while (1)
29
  {
30
    count1=0;
31
  }
32

33
  return 0;
34
}

Wegen OCR1A = 10 sollte die LED unmittelbar nach dem Einschalten 
angehen. Wenn sie das tut, weißt Du, dass die ISR ausgeführt wurde. 
Anschließend hast Du immer noch Zeit für Modifikationen am Code.

Funktioniert dieses Programm?
#2089338
Lesenswert?

mn schrieb:
> @"ich":
> Danke für den Tip, aber das bringt mir nicht viel.
>
> @Karl Heinz Buchegger:
> Also eine Endlosschleife in einer ISR ist nicht sinnvoll, das ist mir
> klar. Ich möchte damit erkennen können ob die ISR angesprungen wird.
> Ich kann wohl die LED blinken, bzw. flimmern sehen, hab die gleiche
> Schleife in der main() ausprobiert.

Probier doch erst mal das hier
1
#define F_CPU 8000000UL
2

3
#include <avr/io.h>
4
#include <avr/interrupt.h>
5

6
ISR(TIMER1_COMPA_vect)
7
{
8
  PORTC ^= (1<<PC5);
9
}
10

11
int main(void)
12
{
13

14
  DDRC |= (1<<PC5);
15
  PORTC = (1<<PC5);
16

17
  OCR1A = F_CPU / 1024;   // Prescaler = 1024
18
  TCCR1B = (1 << WGM12) | (1 << CS12) | (0 << CS11) | (1 << CS10); //Prescaler auf 1024,  CTC-Mode
19
  TIMSK =  (1 << OCIE1A);
20
  
21
  sei();
22

23
  while (1)
24
  {
25
    ;
26
  }
27

28
  return 0;
29
}


Nichts gegen deine Ausfzählung aller Bits im Register. Aber das ist 
ordentlich unübersichtlich. Man kann alles übertreiben. Wenn ich eine 
60-Zeichen lange Zeile erst 5 mal von links nach rechts und wieder 
zurück absuchen muss, bis ich die entscheidende '1' gefunden habe, dann 
habe ich übertrieben.

Dein LED müsste jede Sekunde hell bzw dunkel werden.

Wenn sich nach 1 Sekunde noch nichts tut, dann warte weitere 7 Sekunden. 
Dann kann es sein, dass dein µC gar nicht mit 8Mhz läuft, sondern noch 
im Auslieferungszustand ist: 1Mhz
Gast #2089348
Lesenswert?

@Karl Heinz Buchegger:
Ja ist ein wenig unübersichtlich.
Dein Quellcode läut auch nicht.

Hab vergessen zu erwähnen das ich mit AVR-GCC unter Linux arbeite und 
den Optimizer auf "-Os" gestell habe. Die Fusebits sind auch im 
Auslieferungszustand nur das ich den 8MHz Quarz (nicht Oszillator) 
eingestellt habe).

Ich hab auch mal einen zweiten baugleichen (neuen) uC genommen und das 
Ergebnis war das Gleiche.
Gast #2089372
Lesenswert?

Dann würde ich als erstes überprüfen, ob der Controller überhaupt läuft.

Testprogramm:
1
#define F_CPU 8000000UL
2

3
#include <avr/interrupt.h>
4
#include <avr/io.h>
5

6
uint16_t c=0;
7
uint16_t p=0;
8

9
int main(void)
10
{
11
  DDRC = 0xFF;
12

13
  while (1)
14
  {
15
    c++;
16
    if (c==0)
17
    {
18
      p++;
19
      PORTC = uint8_t(p >> 4);
20
    }
21
  }
22

23
  return 0;
24
}

Bei F_CPU = 8 MHz sollte die LED damit hektisch blinken (8000000 Hz 
geteilt durch 2^20 sind etwa 7.6 Hz).
Gast #2089387
Lesenswert?

@Vuvuzelatus:

Also dein Code hat nicht ganz funktioniert, aber mit dem folgenden kann 
ich die LED sehr gut blinken sehen
1
#define F_CPU 8000000UL
2

3
#include <avr/interrupt.h>
4
#include <avr/io.h>
5

6
volatile uint16_t count1=0;
7

8
int main(void)
9
{
10
  PORTC |= (0<<PC5);
11
  DDRC |= (1<<PC5);
12

13
while (1)
14
{
15
  count1=0;
16
  while (1)
17
  {
18

19
    count1++;
20

21
    if(count1 == 65000)
22
    {
23
      PORTC ^= (1<<PC5);
24

25
      count1 = 0;
26
    }
27

28
  }
29
}
30

31
return 0;
32
}


Ich habe auch mit der Weile ein neues Projekt unter Eclipse angelegt um 
weitere Fehlerquellen auszuschließen. Hat nichts gebracht.
Gast #2089537
Lesenswert?

Ich hab mal ein anderes Beispiel:
Hier sollte in der Hauptschleife die LED Blinken.
Und sobald der Interrupt vom Timer1 ausgelöst wird, müsste das Blinken 
aufhören. Wenn ich die Zeile
1
TIMSK = (1 << OCIE1A);
 auskommentiere, dann blinkt die LED ganz normal. Wenn ich die Zeile 
drin lasse, dann sieht man ganz deutlich das die LED schneller und 
abgehackt blinkt. Als resetet der uC.
1
#define F_CPU 8000000UL
2

3
#include <avr/io.h>
4
#include <avr/interrupt.h>
5

6
volatile int a=0;
7
volatile uint16_t count1=0;
8

9
ISR(TIMER1_COMPA_vect)
10
{
11
  if(a==1)
12
  {
13
    a=0;
14
  }
15
}
16

17
int main(void)
18
{
19

20
  DDRC = (1<<PC5);
21
  PORTC = (0<<PC5);
22

23
  OCR1A = 2000;
24
  TCCR1B = (1 << WGM12) | (1 << CS12) | (0 << CS11) | (1 << CS10);//Prescaler auf 1024,  CTC-Mode
25
  TIMSK = (1 << OCIE1A);
26

27
  a=1;
28
  count1=0;
29
  sei();
30

31
  while(1)
32
  {
33
    if(a==1)
34
    {
35
    count1++;
36
    if(count1 == 65000)
37
    {
38
      PORTC ^= (1<<PC5);
39
      count1 = 0;
40
    }
41
    }
42

43
  }
44

45
  return 0;
46
}

Beis mir gerade echt die Zähne aus... .
Gast #2089617
Lesenswert?

@Peter:

Als meine Makefile sieht so aus. Ich habe das Plugin in Eclipse genutzt.
1
################################################################################
2
# Automatically-generated file. Do not edit!
3
################################################################################
4

5
-include ../makefile.init
6

7
RM := rm -rf
8

9
# All of the sources participating in the build are defined here
10
-include sources.mk
11
-include subdir.mk
12
-include objects.mk
13

14
ifneq ($(MAKECMDGOALS),clean)
15
ifneq ($(strip $(C_DEPS)),)
16
-include $(C_DEPS)
17
endif
18
ifneq ($(strip $(ASM_DEPS)),)
19
-include $(ASM_DEPS)
20
endif
21
ifneq ($(strip $(S_DEPS)),)
22
-include $(S_DEPS)
23
endif
24
ifneq ($(strip $(S_UPPER_DEPS)),)
25
-include $(S_UPPER_DEPS)
26
endif
27
endif
28

29
-include ../makefile.defs
30

31
# Add inputs and outputs from these tool invocations to the build variables 
32
LSS += \
33
testtimer1.lss \
34

35
SIZEDUMMY += \
36
sizedummy \
37

38

39
# All Target
40
all: testtimer1.elf secondary-outputs
41

42
# Tool invocations
43
testtimer1.elf: $(OBJS) $(USER_OBJS)
44
  @echo 'Building target: $@'
45
  @echo 'Invoking: AVR C Linker'
46
  avr-gcc -Wl,-Map,testtimer1.map -mmcu=atmega8 -o"testtimer1.elf" $(OBJS) $(USER_OBJS) $(LIBS)
47
  @echo 'Finished building target: $@'
48
  @echo ' '
49

50
testtimer1.lss: testtimer1.elf
51
  @echo 'Invoking: AVR Create Extended Listing'
52
  -avr-objdump -h -S testtimer1.elf  >"testtimer1.lss"
53
  @echo 'Finished building: $@'
54
  @echo ' '
55

56
sizedummy: testtimer1.elf
57
  @echo 'Invoking: Print Size'
58
  -avr-size --format=avr --mcu=atmega8 testtimer1.elf
59
  @echo 'Finished building: $@'
60
  @echo ' '
61

62
# Other Targets
63
clean:
64
  -$(RM) $(OBJS)$(C_DEPS)$(ASM_DEPS)$(ELFS)$(LSS)$(S_DEPS)$(SIZEDUMMY)$(S_UPPER_DEPS) testtimer1.elf
65
  -@echo ' '
66

67
secondary-outputs: $(LSS) $(SIZEDUMMY)
68

69
.PHONY: all clean dependents
70
.SECONDARY:
71

72
-include ../makefile.targets
Gast #2089638
Lesenswert?

>Als resetet der uC

Hm... schreib mal ganz an den Anfang Deines Programms ein Stück Code, 
das z. B. Pin D3 kurzzeitig auf GND outputtet und häng noch ne LED an 
diesen Pin (und VCC). Wann immer der µC resettet wird: Diese LED wird es 
Dir durch Aufblitzen anzeigen.
#2089686
Lesenswert?

mn schrieb:
> Alles funktioniert, nur das beim Interrupt Auslösen der
> uC resetet.

mn schrieb:
> Hab vergessen zu erwähnen das ich mit AVR-GCC unter Linux arbeite

Mal wieder jemand, der das ELF-File in den Controller programmiert?

mn schrieb:
> Als meine Makefile sieht so aus.

Ja, ist wohl so, denn ich kann dort nicht erkennen, dass da irgendwo ein 
korrektes HEX-File erzeugt wird.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren