Forum: Mikrocontroller und Digitale Elektronik Timer0 bleibt "kleben/stehen"??


von Sven W. (sickone4)


Lesenswert?

Hallo Leute,

ich hab da eine Frage, leider keinen Quellcode, bin gerade in der Schule 
und kann den  nicht aufrufen.

Also folgendes Problem:
Ich hab mir einen Timer0 programmiert, mit 1ms Overflowzeit. Ich hab in 
dem Projekt nichts anderes drin als dem Timer0 sprich keine 
deklarationen, keine unterprogramme nichts.

was der Timer0 macht ist folgendes: er Taktet mit 1ms und invertiert 
eine LED.

Das funktioniert auch wunderbar. gestern abend lief er locker 1 std und 
blinke vor sich hin. und auf einmal blieb er stehen.

hat jemand schonmal ein solches phänomen gehabt? gibt es da einen timer 
"durchlauf" limit, welches man irgendwie zurücksetzen müsste?

edit die bitinvertierung rufe ich im ISR Timer0_ovf_vect

gruß
sven

von STK500-Besitzer (Gast)


Lesenswert?

Sven Weinmann schrieb:
> leider keinen Quellcode, bin gerade in der Schule
> und kann den  nicht aufrufen.

Die Kristallkugeln sind auch gerade alle in der Wartung.

von Sven W. (sickone4)


Lesenswert?

witzbold....

einfacher timer0 aufruf....
aber werde ihn sobald ich kann natürlich nachreichen

von Martin K. (maart)


Lesenswert?

Sven Weinmann schrieb:
> witzbold....
>
> einfacher timer0 aufruf....

Offenbar nicht, sonst würde es ja funktionieren.
Wie wird der Controller getaktet? Quarz, Oszillator, intern?

von Rolf Magnus (Gast)


Lesenswert?

Sven Weinmann schrieb:
> was der Timer0 macht ist folgendes: er Taktet mit 1ms und invertiert
> eine LED.
>
> Das funktioniert auch wunderbar. gestern abend lief er locker 1 std und
> blinke vor sich hin. und auf einmal blieb er stehen.

Du kannst ein mit 1 ms getaktetes Blinken als solches erkennen?

> hat jemand schonmal ein solches phänomen gehabt? gibt es da einen timer
> "durchlauf" limit, welches man irgendwie zurücksetzen müsste?

Nein. Ich würde jetzt auf ein Schaltungsproblem tippen, z.B. fehlende 
Abblockkondensatoren, Reset-Pullup, instabile Versorung oder irgendwas 
derartiges.

von Bronco (Gast)


Lesenswert?

Oder die LED blinkt per Watchdog...

von Sven W. (sickone4)


Lesenswert?

natürlich kann ich das nicht sehen, hab mit einer laufvariable I bis 100 
zählen lassen und beim überlauf invertiert und I auf 0 gesetzt.
ich poste später den quellcode.


# ->
TCCR0 |= (1<<CS01) | (1<<CS00)

TCNT0 = 198

so hab ich übrigends die 1ms realisiert

von Martin K. (maart)


Lesenswert?

Sven Weinmann schrieb:
> TCCR0 |= (1<<CS01) | (1<<CS00)
        ^---- gefährlich! Was passiert, wenn CS02 schon vorher gesetzt 
war? Richtig, es bleibt nach der Zuweisung noch immer gesetzt
>
> TCNT0 = 198
>
> so hab ich übrigends die 1ms realisiert

von Rolf Magnus (Gast)


Lesenswert?

Also mal wieder Salamitaktik: Nur nicht zu viel auf einmal verraten, 
sonst könnte die Lösung ja zu schnell gefunden werden.
Immerhin kann man aus den Registernamen schon mal erahnen, daß es sich 
vermutlich um einen AVR handelt. Aber jegliche Informationen darüber, 
wie der verschaltet ist, fehlen. Das Programm (vermutlich in C?) fehlt 
ebenso, bis auf zwei Zeilen, die nicht viel aussagen. Keine der 
angegebenen Informationen geben irgendeinen Anhaltspunkt, warum es nicht 
funktionieren sollte.
Das einzige, was einen vagen Hinweis geben könnte, ist, daß es erst nach 
einer Stunde auftritt. Das läßt - wie ich schon geschrieben habe - eher 
ein Hardwareproblem vermuten als ein Softwareproblem. Oder gibt es 
irgendwas in deinem Programm, das nach einer Stunde etwas anders macht 
als davor?

von Thomas E. (thomase)


Lesenswert?

Martin Kreiner schrieb:
> Sven Weinmann schrieb:
>
>> TCCR0 |= (1<<CS01) | (1<<CS00)
>
>         ^---- gefährlich! Was passiert, wenn CS02 schon vorher gesetzt
>
> war? Richtig, es bleibt nach der Zuweisung noch immer gesetzt
Das ist ja nun an den Haaren herbeigezogen. Nach Reset ist das 0.

Rolf Magnus schrieb:
> Also mal wieder Salamitaktik:
Das ist das Smartphone-Problem:

Sven Weinmann schrieb:
> ich hab da eine Frage, leider keinen Quellcode, bin gerade in der Schule
> und kann den  nicht aufrufen.
...und schon dreimal meine Emails gecheckt und immer noch Langeweile.

mfg.

von Me Hanick (Gast)


Lesenswert?

Sven Weinmann schrieb:
> Das funktioniert auch wunderbar. gestern abend lief er locker 1 std und
> blinke vor sich hin. und auf einmal blieb er stehen.

Hatte ich auch. Mit Feinöl aus der Apotheke laufen jetzt alle Timer wie 
geschmiert.

von Sven W. (sickone4)


Lesenswert?

so, entgegen der ganzen dummen kommentare dann hier mal der angekündigte 
quellcode. (dumm deshalb, weil man diese frage, oder dieses phänomen vll 
ja mal beobachtet hätte haben können)
1
#define  F_CPU 3686400UL        // CPU Takt, externer Quarz
2
#define  BAUD 9600            // Baudrate = 9600
3
#include <avr/io.h>            // Einbinden der Bib In/Out
4
#include <util/delay.h>          // Einbinden der Bib Delay
5
#include <stdint.h>            // Einbinden der Bib StandardInteger
6
#include <avr/interrupt.h>        // Einbinden der Bib Interrupt
7
8
// Variablendeklaration "Datentypen" -------------------------------------------------------------------------------
9
int I = 0;
10
int A = 0;
11
12
// Timer0 Interupt Taktgenerator -----------------------------------------------------------------------------------      
13
ISR( TIMER0_OVF_vect )         // Overflow Interrupt Vector
14
{
15
  I = I + 1;
16
  
17
  if ((I == 100) && ( A == 0))
18
  {
19
    PORTB &= ~(1<<4);
20
    PORTB |=  (1<<5);
21
    A = 1;
22
    I = 0;
23
  }
24
  
25
  if ((I == 100) && ( A == 1))
26
  {
27
    PORTB |=  (1<<4);
28
    PORTB &= ~(1<<5);
29
    A = 0;
30
    I = 0;
31
  }  
32
}
33
34
35
36
// Timer0 Einstellungen --------------------------------------------------------------------------------------------
37
void TIMER0(void)
38
{
39
  TCCR0 |= (1<<CS01) | (1<<CS00);    // Prescaler 64
40
  TCNT0 = 198;            // Preload 198
41
  TIMSK |= (1<<TOIE0);        // Overflow Interrupt des Timers freigeben
42
  
43
/*  
44
  Gewünschte Zeit: 0.001 s = 1ms
45
  Verwendeter Prescaler: 64
46
  -> 3,6864 MHz / 64 -> 57,6kHz = 0 - 256 Schritte
47
  Wunschfrequenz = 1kHz -> 58 Schritte abziehen
48
  Preload folglich: 198 (256-58) 
49
*/
50
51
}
52
53
// -----------------------------------------------------------------------------------------------------------------
54
// Hauptprogramm
55
// -----------------------------------------------------------------------------------------------------------------
56
 
57
int main()
58
{  
59
  
60
  UBRRL = 23;                // Quarz: 3.6864MHz, Baudrate 9600
61
  UCSRB = 0b10011000;            // Empfänger, Sender ein UCR = UCSRB
62
    
63
  // Portdeklaration ---------------------------------------------------------------------------------------------
64
65
  DDRB   = 0b11111111;    // Datenrichtung PORTB = AUSGANG
66
  DDRD   = 0b11111111;    // Datenrichtung PORTD = AUSGANG
67
68
  TIMER0();          // Timer0 Aufruf für Schrittmotor
69
  
70
  sei();            // alle Interruptquellen freigeben
71
  
72
  // -------------------------------------------------------------------------------------------------------------
73
  
74
  while(1)  // Endlosschleife
75
  {
76
                    
77
  }  // Ende while(1)
78
}  // Ende main

von Rolf Magnus (Gast)


Lesenswert?

Sven Weinmann schrieb:
> /*
>   Gewünschte Zeit: 0.001 s = 1ms
>   Verwendeter Prescaler: 64
>   -> 3,6864 MHz / 64 -> 57,6kHz = 0 - 256 Schritte
>   Wunschfrequenz = 1kHz -> 58 Schritte abziehen
>   Preload folglich: 198 (256-58)
> */

Ist dir bewußt, daß sich das nur auf den ersten Timer-Durchlauf 
auswirkt?

Sven Weinmann schrieb:
> so, entgegen der ganzen dummen kommentare dann hier mal der angekündigte
> quellcode. (dumm deshalb, weil man diese frage, oder dieses phänomen vll
> ja mal beobachtet hätte haben können)

Diese Frage habe ich dir gleich zu Anfang beantwortet. Die Antwort 
lautete: Nein. Ich denke aber, daß du eigentlich wissen willst, warum es 
bei dir auftritt, und um das zu beantworten, hast du einfach nicht die 
nötigen Infos gebracht. In so einem Fall mußt du halt auch mit Antworten 
rechnen, die eher weniger hilfreich sind.

Nachdem ich mir deinen Code angeschaut habe, kann ich übrigens nur 
bestätigen, was ich schon zweimal geschrieben habe: Es handelt sich 
anscheinend um ein Hardware-Problem.

von STK500-Besitzer (Gast)


Lesenswert?

Wieder ein dummer Kommentar meinerseits:

Sven Weinmann schrieb:
1
 int I = 0;

Der Variablen solltest du noch ein volatile spendieren.
oder in der ISR static deklarieren.

Solche Sachen kann man nicht per Ferndiagnose und "Rate mal mit 
Rosenthal" finden.

von Karl H. (kbuchegg)


Lesenswert?

Gewöhn dir so einen Scheiss ab
1
int main()
2
{  
3
  
4
  UBRRL = 23;                // Quarz: 3.6864MHz, Baudrate 9600
5
  UCSRB = 0b10011000;            // Empfänger, Sender ein UCR = UCSRB

wenn du eine Komponente nicht benutzt, hier die UART, dann lässt du sie 
in Ruhe. Schmeiss dein Code raus!

Gratuliere, die hast mit der kryptischen Zuweisung den Receive Complete 
Interrupt enabled und keine ISR dafür.
Sobald sich der µC auf den UART Pins genügend elektromagnetische Felder 
eingesammelt hat, kommt es irgendwann zum Interrupt und alles geht den 
Bach runter.


Man lässt unbenutzten bzw. unnötigen Code nicht im Programm stehen! 
Niemals! Und schon gar nicht aktiviert man Interrupts für nicht benutzte 
Komponenten.

von Rolf Magnus (Gast)


Lesenswert?

STK500-Besitzer schrieb:
> Wieder ein dummer Kommentar meinerseits:
>
> Sven Weinmann schrieb: int I = 0;
>
> Der Variablen solltest du noch ein volatile spendieren.
> oder in der ISR static deklarieren.

Solange er nur von dieser ISR aus drauf zugreift, spielt das keine 
Rolle. Aber prinzipiell hast du recht. Sowas schießt einem dann später 
ins Knie, wenn man das Programm dann erweitert und nicht mehr daran 
denkt.

von Ingo (Gast)


Lesenswert?

Am besten man legt solche Variablen da an, wo man sie benötigt und macht 
solche normalen Zählvariablen nicht global sondern static und lokal in 
der Funktion wo man sie braucht...

von Schande (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Gratuliere, die hast mit der kryptischen Zuweisung den Receive Complete
> Interrupt enabled und keine ISR dafür.

Peinlich! Da waren die ganzen dummen Kommentare aber wirklich 
berechtigt!

von Sven W. (sickone4)


Lesenswert?

hallo leute!

ich hab mal alles so eingestellt, wie ihr es vorgeschlagen habt, bzw 
parts gelöscht, die nicht benötigt wurden!

der quellcode sieht nun so aus und funktioniert auch wie erwartet, OHNE 
hängenbleiben des timers. (er blinkt seit gestern mittag vor sich hin).

und dann habe ich einen teil eingefügt, aus meiner 
schrittmotorsteuerung:
ich möchte bgerne mit einem taster eine anzahl an schritten aufrufen, 
die dann durch den timer als taktgenerator bei jedem overflow ein bit 
invertiert. hier hab ich einfach eine LED genommen um dies darzustellen. 
aber die "blinkt" nicht, sie leuchtet, mal glimmt sie.

ich mache doch nichts anderes, als beim "drücken" des tasters die 
interupts zu deaktivieren, gebe der variable schritte einen wert und 
aktiviere dann wieder die interupts. warum geht dass denn nicht? was hab 
ich schon wieder nicht beachtet?
1
#define  F_CPU 3686400UL        // CPU Takt, externer Quarz
2
#define  BAUD 9600              // Baudrate = 9600
3
#include <avr/io.h>             // Einbinden der Bib In/Out
4
#include <util/delay.h>         // Einbinden der Bib Delay
5
#include <stdint.h>             // Einbinden der Bib StandardInteger
6
#include <avr/interrupt.h>      // Einbinden der Bib Interrupt
7
8
// Variablendeklaration "Datentypen" ---------------------------------------------------
9
volatile int I = 0;
10
volatile uint16_t Schritte;
11
12
// Timer0 Interupt Taktgenerator -------------------------------------------------------      
13
ISR( TIMER0_OVF_vect )          // Overflow Interrupt Vector
14
{
15
  TCNT0 = 198;                  // Timer-Preload
16
  I = I + 1;
17
  
18
  if (I == 100)
19
  {
20
    PORTB ^= _BV(PB5);
21
    I = 0;
22
  }
23
  
24
  if( Schritte > 0 )            // Schritte gibt Anzahl an Steps vor
25
  {
26
    Schritte--;                 // Zähle Schritte runter
27
    PORTB ^= _BV(PB4);          
28
  }
29
}
30
31
// Timer0 Einstellungen ----------------------------------------------------------------
32
void TIMER0(void)
33
{
34
  TCCR0 |= (1<<CS01) | (1<<CS00);    // Prescaler 64
35
  TIMSK |= (1<<TOIE0);               // Overflow Interrupt des Timers freigeben
36
  
37
/*  
38
  Gewünschte Zeit: 0.001 s = 1ms
39
  Verwendeter Prescaler: 64
40
  -> 3,6864 MHz / 64 -> 57,6kHz = 0 - 256 Schritte
41
  Wunschfrequenz = 1kHz -> 58 Schritte abziehen
42
  Preload folglich: 198 (256-58) 
43
*/
44
45
}
46
47
// -------------------------------------------------------------------------------------
48
// Hauptprogramm
49
// -------------------------------------------------------------------------------------
50
51
int main()
52
{      
53
  // Portdeklaration -------------------------------------------------------------------
54
55
56
  DDRB   = 0b11111111;          // Datenrichtung PORTB = AUSGANG
57
  DDRD   = 0b11111111;          // Datenrichtung PORTD = AUSGANG
58
  
59
  DDRC  |= (1<<4);              // Taster
60
  PORTC |= (1<<4);
61
62
  TIMER0();                     // Timer0 Aufruf für Schrittmotor
63
  
64
  
65
  sei();                        // alle Interruptquellen freigeben
66
67
  // -----------------------------------------------------------------------------------   
68
  
69
  while(1)  // Endlosschleife
70
  {
71
72
  if (bit_is_clear(PINC,4))
73
  {
74
    cli();
75
    Schritte = 1000;            // Motor Schritte = Schritte/2
76
    PORTD |= (1<<2);
77
    sei();
78
  }
79
                            
80
  }  // Ende while(1)
81
}  // Ende main

von STK500-Besitzer (Gast)


Lesenswert?

Sven Weinmann schrieb:
> ich mache doch nichts anderes, als beim "drücken" des tasters die
> interupts zu deaktivieren, gebe der variable schritte einen wert und
> aktiviere dann wieder die interupts. warum geht dass denn nicht?
> was hab ich schon wieder nicht beachtet?

1. auch nach dem Weltuntergang erhöht die Benutzung der Shift-Taste die 
Lesbarkeit eines Textes ;)
2. Du solltest dich mit dem Entprellen von Tasten beschäftigen.
3. Statt eines Timer-Preload solltest du dir lieber die verschiedenen 
Timer-Modi deines AVR mal ansehen. Um eine konstante Frequenz zu 
erzeugen benutzt man besser den CTC-Mode.

1
    DDRC  |= (1<<4);              // Taster
sicher, dass das das macht, was du gerne hättest?
Das Beispiel aus dem hiesigen AVR-Tutotium:
1
 // Alle Pins des Ports B als Ausgang definieren:
2
  DDRB = 0xff; 
3
4
  // Alle Pins auf Eingang:
5
  DDRB = 0x00;

von Sven W. (sickone4)


Lesenswert?

uiuiui ja das mit dem taster hab ich korrigiert.
ob ich da nun eine tasterentprellung bruache für diese eine anwendung 
bezweifel ich mal. natürlich ist das immer wichtig. abver was passiert 
denn schon wenn er nicht entprellt ist?
der wert 1000 wird halt wieder und wieder in die variable geladen, aber 
irgendwann sollte dann trotzdem die 1000 herunter gezählt werden und die 
LED blinken.

was den CTC modus angeht, ich benutze doch den TIMER0 und im Tutorial 
steht, dass es den nur beim TIMER1 gibt.

von STK500-Besitzer (Gast)


Lesenswert?

Sven Weinmann schrieb:
> ob ich da nun eine tasterentprellung bruache für diese eine anwendung
> bezweifel ich mal. natürlich ist das immer wichtig. abver was passiert
> denn schon wenn er nicht entprellt ist?

in deinem Fall?
Bei jedem Prellen wird deine Variable um 1 erhöht.
Und das können schon mal ein paar mehr Welchselvorgänge sein.

Sven Weinmann schrieb:
> was den CTC modus angeht, ich benutze doch den TIMER0 und im Tutorial
> steht, dass es den nur beim TIMER1 gibt.

Das Tutorium arbeit beispielhaft. Wenn du etwas über die Fähigkeiten 
deines Controllers herausfinden willst, bringt es mehr, ins Datenblatt 
zu schauen ( nicht die summary-Version!)

von Karl H. (kbuchegg)


Lesenswert?

Sven Weinmann schrieb:

> der wert 1000 wird halt wieder und wieder in die variable geladen, aber
> irgendwann sollte dann trotzdem die 1000 herunter gezählt werden und die
> LED blinken.

Für einen ersten Test ist das ok.
Aber für ein richtiges Programm ist das nicht zu gebrauchen.
Wenn 1000 Schritte gefragt sind, dann sollten es auch tatsächlich 1000 
Schritte sein und nicht ein paar mehr, weil ich mal etwas länger auf der 
Taste geblieben bin und die Timer-ISR schon angefangen hat mit 
runterzählen.

> was den CTC modus angeht, ich benutze doch den TIMER0 und im Tutorial
> steht, dass es den nur beim TIMER1 gibt.

Jau. Ist beim Mega8 so.
Die Frage ist, ob das nicht ein Grund wäre auf den Timer 1 auszuweichen. 
Denn ob der jetzt rumlungert und nichts zu tun hat, oder dir deine 
Zeitbasis liefert ist dem Mega ja prinzipiell wurscht.

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz Buchegger schrieb:

> Wenn 1000 Schritte gefragt sind, dann sollten es auch tatsächlich 1000
> Schritte sein und nicht ein paar mehr, weil ich mal etwas länger auf der
> Taste geblieben bin und die Timer-ISR schon angefangen hat mit
> runterzählen.

Man kann natürlich auch die Aufgabenstellung umdefinieren :-)

Definier einfach:
Dein Programm soll folgendes machen:
Sobald du die Taste drückst, fängt der Schrittmotor zu laufen an.
Und sobald du loslässt, läuft er noch 500 Schritte nach.


Denn genau das macht dein jetziges Programm :-)

(Aber ewig kann man das natürlich nicht machen. Auf längere Sicht sollte 
sich schon das Programm an die Vorgabe halten und nicht hintennach die 
Aufgabenstellung so angepasst werden, dass sie zu dem passt was man 
programmiert hat :-))

von Sven W. (sickone4)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Die Frage ist, ob das nicht ein Grund wäre auf den Timer 1 auszuweichen.
> Denn ob der jetzt rumlungert und nichts zu tun hat, oder dir deine
> Zeitbasis liefert ist dem Mega ja prinzipiell wurscht.

Bisher war der Plan:

TIMER0 -> 1ms Takt für  den Schrittmotor und einen PI Regler zu nutzen. 
Wollte von dem Takt Laufvariablen steuern im Takt von 1ms

TIMER1 -> Entfernungssensor, zur steuerung eines sensors eben^^

allerdings wenn ich wirklich einen takt von 1ms habe kann ich 
theoretisch auch alle darüber laufen lassen und alles mit laufvariablen 
machen, so hab ich dann EINEN timer, und alle werte wären synchron

Karl Heinz Buchegger schrieb:
> Man kann natürlich auch die Aufgabenstellung umdefinieren :-)

ich hab eben gesagt ich bruache keine entprellung eben genau aus dem 
grund dass es nur zum test ist! im programm selbst kommt später nur ein 
taster zum starten vor, welcher eine variable auf 1 setzt. es war nun 
einfach mal als test, wie ich denn den wert der schritte, also die 1000 
in die ISR reinbringe.

von Karl H. (kbuchegg)


Lesenswert?

Sven Weinmann schrieb:
> Karl Heinz Buchegger schrieb:
>> Die Frage ist, ob das nicht ein Grund wäre auf den Timer 1 auszuweichen.
>> Denn ob der jetzt rumlungert und nichts zu tun hat, oder dir deine
>> Zeitbasis liefert ist dem Mega ja prinzipiell wurscht.
>
> Bisher war der Plan:
>
> TIMER0 -> 1ms Takt für  den Schrittmotor und einen PI Regler zu nutzen.
> Wollte von dem Takt Laufvariablen steuern im Takt von 1ms
>
> TIMER1 -> Entfernungssensor, zur steuerung eines sensors eben^^


OK.
Datenblatt rausgeholt.

Der Timer 2 kann ebenfalls CTC

Problem gelöst :-)


> taster zum starten vor, welcher eine variable auf 1 setzt. es war nun
> einfach mal als test,

Das hab ich auch so verstanden, dass das nur ein Test war - keine Sorge.

von Sven W. (sickone4)


Lesenswert?

so, ein kleines update:

TIMER1 benutzt mit CTC.
Taster semiprofessionell entprellt,
LED 1 blinkt im takt von 1ms/100 (siehe ISR)
LED 2 schritte blinkt nicht! Gleicher Effekt wie eben. Woran kann das 
liegen?
1
#define  F_CPU 3686400UL        // CPU Takt, externer Quarz
2
#define  BAUD 9600            // Baudrate = 9600
3
#include <avr/io.h>            // Einbinden der Bib In/Out
4
#include <util/delay.h>          // Einbinden der Bib Delay
5
#include <stdint.h>            // Einbinden der Bib StandardInteger
6
#include <avr/interrupt.h>        // Einbinden der Bib Interrupt
7
8
// Variablendeklaration "Datentypen" ---------------------------------------------------
9
volatile int I = 0;
10
volatile uint16_t Schritte;
11
12
// Timer1 Interupt Taktgenerator -------------------------------------------------------         
13
ISR(TIMER1_COMPA_vect)
14
{
15
  I = I + 1;  
16
  
17
  if (I == 100)
18
  {
19
    PORTB ^= _BV(PB5);
20
    I = 0;
21
  }
22
  
23
  if( Schritte > 0 )          // Schritte gibt Anzahl an Steps vor
24
  {
25
    Schritte--;            // Zähle Schritte runter
26
    PORTB ^= _BV(PB4);        // Pin D7 => 18, invertieren bei jeden Aufruf
27
  }
28
}
29
30
31
32
33
// Timer1 Einstellungen ----------------------------------------------------------------
34
void TIMER1(void)
35
{  
36
  TCCR1B  = 0x01;      // Teiler 1/1
37
  TCCR1B |= 0x08;      // Modus: Zählen bis Vergleichswert
38
  OCR1A  = 3686;      // Vergleichswert speichern
39
  TIMSK  |= 0x10;      // Interrupt bei Vergleichswert
40
  
41
/*  
42
  Gewünschte Zeit: 0.001 s = 1ms
43
  Verwendeter Prescaler: 64
44
  -> 3,6864 MHz / 64 -> 57,6kHz = 0 - 256 Schritte
45
  Wunschfrequenz = 1kHz -> 58 Schritte abziehen
46
  Preload folglich: 198 (256-58) 
47
*/
48
49
}
50
51
// -------------------------------------------------------------------------------------
52
// Hauptprogramm
53
// -------------------------------------------------------------------------------------
54
55
int main()
56
{      
57
  // Portdeklaration -------------------------------------------------------------------
58
59
60
  DDRB   = 0b11111111;          // Datenrichtung PORTB = AUSGANG
61
  DDRD   = 0b11111111;          // Datenrichtung PORTD = AUSGANG
62
  
63
  DDRC  |= (1<<4);              // Taster
64
  PORTC |= (1<<4);
65
66
  TIMER1();                     // Timer0 Aufruf für Schrittmotor
67
  
68
  
69
  sei();                        // alle Interruptquellen freigeben  
70
  int x;
71
72
  // -----------------------------------------------------------------------------------   
73
  
74
  while(1)  // Endlosschleife
75
  {
76
77
  if (bit_is_clear(PINC,4))
78
  {
79
    cli();
80
    Schritte = 1000;            // Motor Schritte = Schritte/2
81
    PORTD |= (1<<2);
82
    sei();
83
84
    for ( x=0; x<=500; x++ )
85
    { ; }
86
  }
87
                            
88
  }  // Ende while(
89
}  // Ende main

von Karl H. (kbuchegg)


Lesenswert?

Immer noch am gleichen
1
 DDRC  |= (1<<4);              // Taster
2
  PORTC |= (1<<4);

einen Portpin, den du auf Ausgang stellst, wirst du eher selten mit 
einem Taster beeinflussen können. OK. Du erzeugst mit dem Taster einen 
Kurzschluss, wenn du den Ausgangstreiber gegen GND schaltest. Und was 
dann alles passiert hängt auch davon ab, wie stark dein Netzteil ist 
bzw. wie lange der Mega den Kurzschluss überlebt. Bei dir scheint das 
Netzteil aufzugeben, was sehr vernünftig ist.

LOL
1
   for ( x=0; x<=500; x++ )
2
    { ; }
Ob du, oder der Optimizer diese 2 Zeilen rauslöscht schenkt sich nix :-)

von Sven W. (sickone4)


Lesenswert?

mist sry vergess das! das hatte ich eben schon geändert! ich hab nur 
meinen quellcode von oben "nachgebessert"
hatte das nicht mit geändert. im quellcode im AVR studio ist es aber 
korrekt!

ohne quatsch! das entprellen wird so an meiner schule gele"e"rt

von Sven W. (sickone4)


Lesenswert?

statt dem ; könnt ich da auch einfach mal "asm volatile ("nop"::);" 
reinpacken

von Karl H. (kbuchegg)


Lesenswert?

Sven Weinmann schrieb:

> ohne quatsch! das entprellen wird so an meiner schule gele"e"rt

Das Problem ist, dass die meisten EDV-Lehrer (und auch Unis bzw. FHs 
sind keine Ausnahme) nicht wirklich gute Programmierer sind. Drum sind 
sie auch in den Schulen und nicht in der Industrie.

von Sven W. (sickone4)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Das Problem ist, dass die meisten EDV-Lehrer (und auch Unis bzw. FHs
> sind keine Ausnahme) nicht wirklich gute Programmierer sind. Drum sind
> sie auch in den Schulen und nicht in der Industrie.

danke, endlich mal bestätigung von aussen!!

back to topic.

die LED schaltet Ein und bleibt dauerhaft an, bzw flackert ab und an 
mal, im gesamten ist sie aber immer an,

von Karl H. (kbuchegg)


Lesenswert?

Vergiss es einfach für den Moment.
Ob die Taste jetzt entprellt ist oder nicht, ist doch für den Test 
wurscht. Es geht um den Timer.

Und für ein reales Programm kopierst du dir den ISR Teil aus der PeDa 
Entprellung in deine 1ms-ISR rein, nimmt noch die Abfragefunktionen mit 
dazu und du hast eine 1A erstklassige Tastenabfrage und Entprellung.

von Sven W. (sickone4)


Lesenswert?

ich bekomms nicht hin. die LED leuchtet sobald ich einschalte und blinkt 
nicht -.-

nochmal zum verständnis:

der timer läuft bis zum compare und dann wieder unendlich sozusagen. und 
jedesmal führt er beim compare erreichen den interupt aus und arbeitet 
meinen programmcode ab.

d.h. wenn ich schritte z.b. mit 1000 belege und runterzähle, sollte er 
bei jedem interupt 1 abziehen.

von Karl H. (kbuchegg)


Lesenswert?

1
#define  F_CPU 3686400UL        // CPU Takt, externer Quarz
2
#include <avr/io.h>            // Einbinden der Bib In/Out
3
#include <util/delay.h>          // Einbinden der Bib Delay
4
#include <stdint.h>            // Einbinden der Bib StandardInteger
5
#include <avr/interrupt.h>        // Einbinden der Bib Interrupt
6
7
volatile uint16_t Schritte;
8
9
ISR(TIMER1_COMPA_vect)
10
{
11
  static uint8_t Cnt;
12
13
  Cnt++;  
14
  if (Cnt == 100)
15
  {
16
    PORTB ^= _BV(PB5);
17
    Cnt = 0;
18
  }
19
  
20
  if( Schritte > 0 )         
21
  {
22
    Schritte--;
23
    PORTB ^= _BV(PB4);
24
  }
25
}
26
27
void initTimer(void)
28
{  
29
  TCCR1B  = 0x01;         // Teiler 1/1
30
  TCCR1B |= _BV(WGM12);   // Modus: Zählen bis Vergleichswert (CTC)
31
  OCR1A  = 3686;
32
  TIMSK  |= _BV(OCIE1A);  // Interrupt bei Vergleichswert
33
}
34
35
int main()
36
{
37
  DDRB   = 0b11111111;          // Datenrichtung PORTB = AUSGANG
38
  DDRD   = 0b11111111;          // Datenrichtung PORTD = AUSGANG
39
  
40
  initTimer();                     // Timer0 Aufruf für Schrittmotor
41
42
  sei();                        // alle Interruptquellen freigeben  
43
  while(1)  // Endlosschleife
44
  {
45
    cli();
46
    Schritte = 1000;            // Motor Schritte = Schritte/2
47
    PORTD |= (1<<2);
48
    sei();
49
50
    _delay_ms( 2000 );
51
  }
52
}

funktioniert laut Simulator auf einem Mega8
Wenn nicht, muss man sich mal deine Hardwareanbindung ansehen.

von Sven W. (sickone4)


Lesenswert?

hm. ich hab deinen quellcode nunmal bei mir aufgespielt.

gleicher effekt.
ich benutze ein prog board von myAVR -> 
http://shop.myavr.de/Systemboards/myAVR%20Board%20MK2,%20best%C3%BCckt.htm?sp=article.sp.php&artID=40

von Karl H. (kbuchegg)


Lesenswert?

Und wie ist der Schrittmotor angeschlossen?

von Sven W. (sickone4)


Lesenswert?

der ist in diesem beispiel nicht mit drin, ich sagte in irgendeinem 
vorherigen beispiel dass ich den pin des schrittmotortreibers für die 
clock hier symbolisch als LED genommen habe!
deshalb sagte ich ja, dass der nicht blinkt

folgendes update! ich hab einen übertragungsfehler gemacht.

das programm aktualisiert und neu aufgespielt!
der effekt ist nun, dass die LED nur einmal aufleuchtet, erlicht udn 
wieder aufleuchtet!

und jetzt ohne die zeit zu stoppen glaube ich, dass es sich dabei um die 
2s des delays handelt.

eigentlich sollte die led bei jedem CMPMatch invertiert werden!?

von Karl H. (kbuchegg)


Lesenswert?

Sven Weinmann schrieb:

> das programm aktualisiert und neu aufgespielt!
> der effekt ist nun, dass die LED nur einmal aufleuchtet, erlicht udn
> wieder aufleuchtet!


Räusper.
Dir ist aber schon klar, dass du bei einer LED, die alle 1ms 
umgeschaltet wird, die einzelnen Blinker nicht sehen wirst?
Für dich als Mensch zeigt sich die LED als "mit etwas weniger als halber 
Helligkeit". Erst wenn du ein Oszi anhängen würdest, könntest du sehen, 
dass die Schritt-LED tatsächlich 1 Sekunde lang Pulse abgibt.

Und da in der Hauptschleife alle 2 Sekunden das ganze erneut "gestartet" 
wird, weil an Schritte etwas zugewiesen wird, beginnt alles nach 2 
Sekunden erneut.

von STK500-Besitzer (Gast)


Lesenswert?

Sven Weinmann schrieb:
> der effekt ist nun, dass die LED nur einmal aufleuchtet, erlicht udn
> wieder aufleuchtet!

Pack doch mal ein 2-Sekunden-Delay ins Programm, bevor der timer 
initialisiert und gestartet wird.
Oder besser 2 Delays: Bei dem einen schaltest du die LEDs ein, beim 
anderen aus.
Dann kannst du die Schaltrichtung besser als bei einem Blinken erkennen 
(das STK500 bspw. invertiert die LED-Funktion)

von Karl H. (kbuchegg)


Lesenswert?

Und ich denke auch, wir sollten mal klar stellen, welche LED du meinst.
In deinem Hardware Aufbau gibt es 2 LED. Da ist Verwirrung 
vorprogrammiert.

von Sven W. (sickone4)


Angehängte Dateien:

Lesenswert?

das war der grund, warum ich die andere LED, welche nun über Cnt 
getaktet ist bis 100 hab zählen lassen, das ist nun wirklich mal wieder 
extrem high IQ gewesen....

-> bild

LED 1 PB5 -> ( cnt -> 100 ) ist nur beispielhaft dass ich sehe, dass der 
TIMER funktioniert.

LED 2 PB4 -> Schrittmotor CLOCK PIN der eine Anzahl zugeordnet bekommt 
die er takten soll

von Sven W. (sickone4)


Lesenswert?

anhand der Auflösung des Rasters kann man übrigends gut erkennen, dass 
der Timer mit 1ms läuft!
die Zeit steht auf 2ms pro kästchen. bei 1ms schaltet der Pin um.

Danke Karl-Heinz

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.