Forum: Mikrocontroller und Digitale Elektronik Timer1, CTC, Interrupt, REST, mega8, Problematik


von mn (Gast)


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ß

von Serieller (Gast)


Lesenswert?

>   while(1)

In der ISR???

von mn (Gast)


Lesenswert?

Ja, damit der da hängen bleibt und die LED zur Kontroller schneller 
Blinkt.

von ich (Gast)


Lesenswert?

Hier ist ein Beispiel, wenn auch nicht für den CTC mode:

http://www.mikrocontroller.net/articles/Absolute_Beginner-AVR_Steckbrettprojekte

von Karl H. (kbuchegg)


Lesenswert?

mn schrieb:
> Ja, damit der da hängen bleibt und die LED zur Kontroller schneller
> Blinkt.

Was'n das für ein Unsinn?

Die LED in deiner ISR blinkt so schnell, so schnell kannst du gar nicht 
schauen.
Kein Wunder, dass das für dich nach reset aussieht.

von mn (Gast)


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.

von Vuvuzelatus (Gast)


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?

von mn (Gast)


Lesenswert?

Hab es probiert und es geht nicht.

von Karl H. (kbuchegg)


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

von mn (Gast)


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.

von Vuvuzelatus (Gast)


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).

von mn (Gast)


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.

von Karl H. (kbuchegg)


Lesenswert?

mn schrieb:

> Dein Quellcode läut auch nicht.

Dann ist irgendwas ausserhalb des Programms faul.
Bei mir blinkt die (reale)LED am (realen)Prozessor munter vor sich hin.

von Martin (Gast)


Lesenswert?

Hast du die JTAG Fuse deaktiviert? Sonst ist Verzweiflung auf PortC 
vorprogrammiert. Ich spreche aus Erfahrung. ;-)

von Karl H. (kbuchegg)


Lesenswert?

Mage8 hat kein JTAG

von mn (Gast)


Lesenswert?

@Karl Heinz Buchegger:
Fragt sich nur was!
Wie siehts bei dir mit den Fuses aus?
Was für ein Compiler und welche Compileroptimirungen hast du 
eingestellt.

@Marint:
Der hat doch garkein JTAG

von Karl H. (kbuchegg)


Lesenswert?

mn schrieb:
> @Karl Heinz Buchegger:
> Fragt sich nur was!
> Wie siehts bei dir mit den Fuses aus?

Alles Standard. Bis eben: auf 8Mhz intern gefust, damit das Timing 
stimmt.

> Was für ein Compiler und welche Compileroptimirungen hast du
> eingestellt.

-Os
Spielt hier aber keine Rolle.
Mein Compiler ist schon etwas älter

von Karl H. (kbuchegg)


Lesenswert?

Dein Originalprogramm (mit der while in der ISR) präsentiert sich mir 
so:
nach dem Einschalten blinkt die LED ca 3 mal auf um dann in ein Flimmern 
überzugehen. Entspricht so gesehen dem Wortlaut des Programmes.

von mn (Gast)


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... .

von Peter D. (peda)


Lesenswert?

Du hast im Make-File auch das richtige Target angegeben?
AVRs sind nicht binärkompatibel!

Und laß mal diese ollen Zähleschleifen sein.
Nimm gefälligst die "delay.h", dann kann man den Quelltext auch lesen, 
d.h. die tatsächlichen Wartezeiten.


Peter

von mn (Gast)


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

von Vuvuzelatus (Gast)


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.

von Stefan E. (sternst)


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.

von mn (Gast)


Lesenswert?

Jetzt geht alles!

Ich habe ständig das ELF anstatt des HEX-File geflasht!

Vielen Dank an alle :-)

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.