-
Hallo,
also ich häng jetz mal mein Beispiel für den mega8 ms timer an.
Code:
#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 16000000
#define timer (256-F_CPU/64/1000)
int ms;
ISR(TIMER0_OVF_vect) //Timer Interrupt Vector
{TCNT0 = timer;
ms++;
}
int main(void)
{
//Ports Init
DDRC |= (1<<PORTC3);
//Timer Init
TIMSK |= (1<<TOIE0); //Timerinterrupt freigeben
TCCR0 |= (1<<CS00) | (1<<CS01) | (!(1<<CS02)); //Timer Prescaler = 64
sei(); //Interrupts global aktivieren
//main Schleife
for (;;)
{ if(ms >=100)
{PORTC ^= (1<<PORTC3);ms = 0;}
}
}
läuft nur timer0 über so wird in die timer isr gesprungen. hoffe ich konnt dir helfen. Ach übrigens 0x05 ist 0b00000101.
mfg franz
-
Vielen dank für die antwort, es tut sich schonmal was.
Ich wäre froh wen du mir zwei dinge noch erklären könntest.
zum einen was passiert hier?:
Code:
ISR(TIMER0_OVF_vect) //Timer Interrupt Vector
{TCNT0 = timer;
ms++;
}
Timer wird ja durch: (256-F_CPU/64/1000)
ersetzt. Was passiert den hier genau?
TCNT0 ist ja das Daten Register des Timer 0.
Hier wird diesem Register ja ein Wert zugewissen.... wird nicht normal ein Wert aus diesem Register gelesen?
Die Variable ms wird nach jedem Interupt um 1 erhöht... richtig?
Code:
{if(ms >=100)
{PORTB ^= (1<<PORTB0);ms = 0;}
Und was geschieht hier?
Wen die Variable ms grösser oder gleich 100 ist... also nach 100 interupts...
Wird PORTB im zustand gewechselt... also High zu low und low zu High... anschliessend wird die Variable ms auf null gesetzt und die Schleife beginnt von vorn?
-
Hi,
also zu 1. ich weise timer0 einen erechneten Wert zu um genau auf 1ms zu kommen. Das heißt jeder Interrupt ist 1ms. Dann springt das Programm alle ms in die ISR und weißt dem Register wieder diesen Wert zu und zählt meine Variable 1 hoch. Die Variable timer errechnet sich aus 256(weil der timer0 8-bit breit ist) - Quarztakt/Prescaler/1000 (wegen ms).
zu 2. ja richtig erkannt nach 100ms wird der Zustand des Ports gewechselt und meine Variable auf 0 zurückgesetzt, dadurch beginnt der Vorgang erneut.
hoffe es ist jetz klarer sonst frag einfach nochmal nach
mfg franz
-
Es klappt.. endlich. Nur etwas will nicht.
Ich hab mir folgenden code zusammengeschrieben:
Code:
#include <avr\io.h>
#include <inttypes.h>
#include <avr\interrupt.h>
#define F_CPU 3686400
#define timer (256-F_CPU/64/1000)
#define RotH PORTB0
#define RotV PORTB1
#define BlauV PORTB2
int ms;
void initPorts()
{
DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2);
}
ISR(TIMER0_OVF_vect) //Timer Interrupt Vector
{
TCNT0 = timer;
ms++;
}
int main(void)
{
initPorts(); // Timer Interrupt initialisieren
TIMSK |= (1<<TOIE0);
TCCR0=0x05; // 0b00000011, Vorteiler 1024 ca. 4khz
sei(); // enable interrupts
do
{
PORTB &= ~( (1<<RotH) | (1<<PORTB1) | (1<<PORTB2)); //PORTB Pins 0,1,2 auf low
if(ms >= 5)
{
PORTB |= (1<<RotH); //Rot High
if(ms >=30)
{
PORTB |= (1<<RotV); //Gelb High
if(ms >= 100)
{
PORTB &= ~(1<<RotH); //ROT Low
PORTB |= (1<<BlauV); //GRUEN High
if(ms >= 200)
{
ms = 0; //ms auf NULL
}
}
}
}
}
while (true);
}
//======================================================================
Dieser funktioniert auch, ausser das das setzten von PORTB0 auf low nicht klappt.
Ich meinte einmal gelesen zu haben, das es damit zusammenhäng wie man die PORT's definiert und schaltet. Also ob man sie erst als Ausgänge setzt und dann auf High oder umgekehrt.
Kann mir da vieleicht jemand behilflich sein?
-
Die Ports werden ja immer nur sehr kurz auf HIGH gesetzt, weil sie in jedem Durchlauf der do-Schleife wieder auf LOW gesetzt werden. Ähmliches gilt nochmals für PORTB0. Du solltest hier komplett in if-then-else verzweigen und immer das setzen/löschen, was gerade angesagt ist statt die Werte immer wieder hin- und her zu setzen.
Noch was generelles:
-- korrekt schreibt man avr/io.h, nicht avr\io.h (auch unter Win32)
-- der Zugriff auf ms müsste eigentlich atomar sein, sollte aber für das Programm hier trotzdem zu keinen Ausfällen wie Kernschmelze führen ;-)
-
Damit dieses Problem weg ist möste ich einen Operator haben mit dem ich abfragen könnte ob ms zum Beispiel zwischen 50 und 70 liegt anstatt nur grösser/gleich als.
if(ms >=50 & <= 70) klappt nicht.
Oder muss ich das ganz anderst machen?
Wäre sehr froh wen mir jemand ein Beispiel machen könnte wie man es richtig macht.
Dankeschön
-
Hi,
also du musst wenn dann schreiben if(ms>=50 & ms<=70) dann klappts auch , hoffe ich konnt dir helfen.
mfg franz
-
Sehr schön, so klappts. danke euch vielmals
-
Ich hab das programm nun auf den Tiny geschrieben.
Nur scheint es darauf nicht zu funktionieren. Das ist mein Code:
Code:
#include <avr/io.h>
#include <inttypes.h>
#include <avr/interrupt.h>
#define F_CPU 3686400
#define timer (256-F_CPU/64/1000)
#define RotH PORTB0
#define RotV PORTB1
#define BlauV PORTB2
int ms;
void initPorts()
{
DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2);
}
ISR(TIMER0_OVF_vect) //Timer Interrupt Vector
{
TCNT0 = timer;
ms++;
}
int main(void)
{
initPorts(); // Timer Interrupt initialisieren
TIMSK |= (1<<TOIE0);
TCCR0A=0x05; // 0b00000011, Vorteiler 1024 ca. 4khz
sei(); // enable interrupts
do
{
if(ms <= 1)
{
PORTB &= ~( (1<<RotH) | (1<<RotV) | (1<<BlauV)); //PORTB Pins 0,1,2 auf low
}
if(ms >= 5& ms <= 100)
{
PORTB |= (1<<RotV);
}
if(ms >= 100& ms <= 210)
{
PORTB |= (1<<RotH);
}
if(ms >= 210& ms <= 400 )
{
PORTB |= (1<<BlauV);
PORTB &= ~(1<<RotV);
}
if(ms >= 600)
{
ms = 0;
}
}
while (true);
}
Ich habe einzig den TCCR0=0x05; auf TCCR0A=0x05; gewechselt da der beim Tiny anderst heisst. Hab ich sonst noch einen Fehler?
Auf dem Mega 8 hat es wunderbar funktioniert
-