mikrocontroller.net

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


Autor: mn (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

#define F_CPU 8000000UL

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

volatile uint16_t count1=0;
volatile uint16_t count2=0;


ISR(TIMER1_COMPA_vect)//ISR(BADISR_vect)
{

  count2=0;
  while(1)
  {
    count2++;

    if(count2 == 10000)
    {
      PORTC ^= (1<<PC5);

      count2=0;
    }
  }

}


int main(void)
{

  cli();
  DDRC |= (1<<PC5);
  PORTC = (1<<PC5);

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

  sei();

  count1=0;
  while (1)
  {

    count1++;

    if(count1 == 65000)
    {
      PORTC ^= (1<<PC5);

      count1 = 0;
    }

  }

  return 0;
}


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

Gruß

Autor: Serieller (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>   while(1)

In der ISR???

Autor: mn (Gast)
Datum:

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

Autor: ich (Gast)
Datum:

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

http://www.mikrocontroller.net/articles/Absolute_B...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: mn (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Vuvuzelatus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Alles funktioniert, nur das beim Interrupt Auslösen der uC resetet

Woher weißt Du das?

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

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

volatile uint16_t count1=0;
volatile uint16_t count2=0;


ISR(TIMER1_COMPA_vect)//ISR(BADISR_vect)
{
  PORTC = 0x00;
}


int main(void)
{
  DDRC  = 0xFF;
  PORTC = 0xFF;

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

  sei();

  while (1)
  {
    count1=0;
  }

  return 0;
}

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?

Autor: mn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab es probiert und es geht nicht.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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
#define F_CPU 8000000UL

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

ISR(TIMER1_COMPA_vect)
{
  PORTC ^= (1<<PC5);
}

int main(void)
{

  DDRC |= (1<<PC5);
  PORTC = (1<<PC5);

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

  while (1)
  {
    ;
  }

  return 0;
}


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

Autor: mn (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Vuvuzelatus (Gast)
Datum:

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

Testprogramm:
#define F_CPU 8000000UL

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

uint16_t c=0;
uint16_t p=0;

int main(void)
{
  DDRC = 0xFF;

  while (1)
  {
    c++;
    if (c==0)
    {
      p++;
      PORTC = uint8_t(p >> 4);
    }
  }

  return 0;
}

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

Autor: mn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Vuvuzelatus:

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

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

volatile uint16_t count1=0;

int main(void)
{
  PORTC |= (0<<PC5);
  DDRC |= (1<<PC5);

while (1)
{
  count1=0;
  while (1)
  {

    count1++;

    if(count1 == 65000)
    {
      PORTC ^= (1<<PC5);

      count1 = 0;
    }

  }
}

return 0;
}



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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Martin (Gast)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mage8 hat kein JTAG

Autor: mn (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: mn (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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
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.
#define F_CPU 8000000UL

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

volatile int a=0;
volatile uint16_t count1=0;

ISR(TIMER1_COMPA_vect)
{
  if(a==1)
  {
    a=0;
  }
}

int main(void)
{

  DDRC = (1<<PC5);
  PORTC = (0<<PC5);

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

  a=1;
  count1=0;
  sei();

  while(1)
  {
    if(a==1)
    {
    count1++;
    if(count1 == 65000)
    {
      PORTC ^= (1<<PC5);
      count1 = 0;
    }
    }

  }

  return 0;
}

Beis mir gerade echt die Zähne aus... .

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: mn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Peter:

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

-include ../makefile.init

RM := rm -rf

# All of the sources participating in the build are defined here
-include sources.mk
-include subdir.mk
-include objects.mk

ifneq ($(MAKECMDGOALS),clean)
ifneq ($(strip $(C_DEPS)),)
-include $(C_DEPS)
endif
ifneq ($(strip $(ASM_DEPS)),)
-include $(ASM_DEPS)
endif
ifneq ($(strip $(S_DEPS)),)
-include $(S_DEPS)
endif
ifneq ($(strip $(S_UPPER_DEPS)),)
-include $(S_UPPER_DEPS)
endif
endif

-include ../makefile.defs

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

SIZEDUMMY += \
sizedummy \


# All Target
all: testtimer1.elf secondary-outputs

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

testtimer1.lss: testtimer1.elf
  @echo 'Invoking: AVR Create Extended Listing'
  -avr-objdump -h -S testtimer1.elf  >"testtimer1.lss"
  @echo 'Finished building: $@'
  @echo ' '

sizedummy: testtimer1.elf
  @echo 'Invoking: Print Size'
  -avr-size --format=avr --mcu=atmega8 testtimer1.elf
  @echo 'Finished building: $@'
  @echo ' '

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

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

.PHONY: all clean dependents
.SECONDARY:

-include ../makefile.targets


Autor: Vuvuzelatus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: mn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jetzt geht alles!

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

Vielen Dank an alle :-)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.