Der Fehler liegt hier drin
amal schrieb:> unsigned int zx=0,zy=0;
Du musst die Variablen zx und als volatile deklarieren. Sonst weiß der
kompiler nicht das zx auch von außerhalb der ISR gesetzt werden kann und
das er sie nicht bei jeder ausfürhugn der ISR neu initialisieren soll.
Mir ist in der ISR beim genaueren betrachten folgendes aufgefallen:
amal schrieb:> ISR(TIMER1_OVF_vect)> {> zx++;> if(zx>100)> {> PORTB&=~(1<<PB0);> TCCR1B&=~(1<<CS10);> }> zx=0;> }
Du zählst zx am Anfang hoch udn vergleichst dann, und am Ende setzt du
es wieder auf 0 zurück. natürlich wird es so niemals 100 erreichen da es
immer wieder bei 0 anfängt. Du musst zx=0 in die if-Abfrage packen.
das liegt daran das du zx direkt wieder auf 0 setzt
das muss in die if anweisung
ulp schrieb:> das liegt daran das du zx direkt wieder auf 0 setzt>> das muss in die if anweisung
Kannst du mit deiner Entwicklungsumgebnung (welche?) den Programmablauf
nicht simulieren und dabei die Variablenwerte verfolgen? Dann würdest du
sofort sehen, wenn etwas anders läuft als vorgesehen.
AVR-Strudio 4.18 z.B. konnte das.
Tip schrieb:> Kannst du mit deiner Entwicklungsumgebnung (welche?) den Programmablauf> nicht simulieren und dabei die Variablenwerte verfolgen? Dann würdest du> sofort sehen, wenn etwas anders läuft als vorgesehen.> AVR-Strudio 4.18 z.B. konnte das.
ich könnte das nur wenn ich mit Assembler programmiere, in C weiß ich
nicht wie das geht, weil du gar nicht weißt wo dein Prog steht. auf
jedenfall der Fehler liegt daran, dass ich nie einen OVF erreichen kann,
weil in CTC Mode 4 erreicht man OVF nur bei Max=FFFF, deswegen wird ich
jetzt anderen Weg nehmen, und zwar über ISR(TIMER1_COMPA_Vect).übrigens
ich habe AVR4.14
Albert ... schrieb:> Du musst die Variablen zx und als volatile deklarieren. Sonst weiß der> kompiler nicht das zx auch von außerhalb der ISR gesetzt werden kann und> das er sie nicht bei jeder ausfürhugn der ISR neu initialisieren soll.
Falsch.
Nikos schrieb:> Globale Variablen müssen mit volatile deklariert werden wenn sie in der> ISR routine verändert werden sollen
Auch falsch. Aber schon ein wenig besser... ;-)
Variablen müssen als volatil deklariert werden, wenn sie unverhofft von
ausserhalb einer Funktion geändert werden könnten. Wenn z.B. in einer
"normalen" Funktion ein Wert verwendet wird, sich dieser Wert aber von
aussen ändern kann (z.B. ein Timer oder ein Pin oder eine globale
Variable), dann muß dem Compiler gesagt werden, er soll diesen Wert doch
bitte jedesmal neu einlesen. Und dieses "der Wert kann sich unvermittlet
ändern" bedeutet volatil (=flüchtig).
Eine globale Variable, die in einer nicht unterbrechbaren
Interuptroutine nur gelesen wird, braucht dieses Schlüsselwort also
sicher nicht.
Eine globale Variable, die nur in 1 Interuptroutine verwendet, braucht
dieses Schlüsselwort auch nicht.
Ein Problem wurde schon genannt:
1
ISR(TIMER1_OVF_vect)
2
{
3
zx++;// hochzählen
4
if(zx>100)
5
{
6
PORTB&=~(1<<PB0);
7
TCCR1B&=~(1<<CS10);
8
}
9
zx=0;// zu Null setzen
10
}
zx wird NIEMALS größer 100.
zx hatt immer nur die Werte 0 und 1.
Die meiste Zeit ist zx = 0.
@ amal
Formatier deinen Quelltext mit Einrückungen, dann siehst du das gleich..
Hallo,
Du must beim Hochzählen beachten, dass du wirklich zwei Möglichkeiten
programmierst.
ISR(TIMER1_OVF_vect)
{
zx++; // hochzählen
if(zx>100) {
PORTB&=~(1<<PB0);
TCCR1B&=~(1<<CS10);
}
zx=0; // zu Null setzen
}
Bei dem hier gibt es nur eine Möglichkeit da zx den Wert 100 nie
erreichen kann.
ISR(TIMER1_OVF_vect)
{
if(zx>100)
{
PORTB&=~(1<<PB0);
TCCR1B&=~(1<<CS10);
zx=0; // zu Null setzen
}esle{
zx++; // hochzählen
}
}
Bei dieser Variante wird zx nur dann auf 0 gesetzt, wenn die Abfrage
zutrifft.
Gruß Jannis
ich habe jetzt den COMP Interrupt benutzt, ich möchte jetzt zum beispiel
100schritte machen dann auf einem PIN eine PWM signal ausgeben, dann
nochmal 100 Schritte, das ganze 10mal,das heißt der Motor soll sich 1000
Schritte machen und 10 mal pwm signal ausgeben. und das habe ich so
realisiert, ich bitte um Korrektur.
1
#include<avr/io.h>
2
#include<avr/interrupt.h>
3
4
5
6
7
8
volatileuint16_tzx=0,zy=0;
9
voidmotorxR(void);
10
11
voidsleep_ms(unsignedintms);
12
13
14
15
16
17
18
intmain()
19
{
20
21
22
DDRB=(1<<PB0)|(1<<PB1)|(1<<PB2)|(1<<PB3)|(1<<PB4)|(1<<PB5);// PIN0-5 als Ausgang für die Motoren definieren // PortB als Ausgang definieren
23
DDRC=0;//PORTC als Eingang für PCINT MASK 1 definieren
24
25
26
// Timer 1 einstellen
27
//
28
// Modus 15:
29
// Fast PWM, Top von OCR1A
30
//
31
// WGM13 WGM12 WGM11 WGM10
32
// 0 1 0 0
33
//
34
// Timer Vorteiler: 1
35
// CS12 CS11 CS10
36
// 0 0 1
37
//
38
// Steuerung des Ausgangsport: Set at BOTTOM, Clear at match
Hallo
ISR(PCINT1_vect) //Interrupt Service Routine
{
sei ();
Willst du an dieser Stelle den Interrupt erlauben oder nicht?
Wenn du in abschalten willst dann musst du diesen Befehl benutzen: cli
().
Gruß Jannis
amal schrieb:> ich könnte das nur wenn ich mit Assembler programmiere, in C weiß ich> nicht wie das geht, weil du gar nicht weißt wo dein Prog steht.
Wieso weißt du nicht wie das geht, wenn ich nicht weiß, wo mein "Prog"
steht?
In C unter AVRStudio gibt es im Menü "Debug" einige nützliche
Funktionen. Vielleicht solltest du dich damit mal beschäftigen. Das
würde dir die Fehlersuche deutlich erleichtern.
Hallo,
Um den Interrupt zu löschen musst du aber cli (); schreiben.
sleep_ms(2);
Dafür gibt es delay- Funktion. Du musst also also die Funktion sleep
löschen und ein paar Zeilen ergänzen.
#ifndef F_CPU
#define F_CPU ( Takt in Herz) UL
#endif
#include <util/delay.h>
Die vier Zeilen kopierst du dir unter die anderen Includes.
Anstelle von Sleep schreibst du jetzt _delay_ms(Zeit in Ms);
Gruß Jannis