Archiv verlassen und diese Seite im Standarddesign anzeigen : Pin-Change ATtiny45
Hallo alle, ich habe ein Problem mit meinem ATtiny45.
Ich möchte gerne zu Testzwecken, dass er, sobald Pin PB1 den Zustand ändert, PB0 auf low (0) setzt.
kann sich mal jemand den code ansehen?
#include <avr/io.h>
#include <avr/interrupt.h>
#ifndef F_CPU
#define F_CPU 8000000
#endif
#include <stdint.h>
#include <util/delay.h>
#include <inttypes.h>
int main(void)
{
SREG |=(1<<7);
GIMSK |=(1<<5);
PCMSK |= (1<<1);
DDRB = 0x00;
PORTB = 0xFF;
}
ISR(PCINT1_vect)
{
DDRB = 0x01;
PORTB = 0xFE;
}
danke im Voraus, marco
Warum nicht so?
...
sei();
GIMSK |=(1<<PCIE);
PCMSK |= (1<<PCINT1);
...
Und wo liegt jetzt das Problem? Passiert nicht? Oder geht PB0 sofort auf low? Das könnte daran liegen, dass durch das PORTB=0xFF in der Main sich der Pegel an PB1 schon ändert. Dann wird sofort der Interrupt ausgelöst.
Lösung: erst PORTB auf high, dann erst Interrupt konfigurieren und freigeben.
also, ich habe den code geändert, auf:
#include <avr/io.h>
#include <avr/interrupt.h>
#ifndef F_CPU
#define F_CPU 8000000
#endif
#include <stdint.h>
#include <util/delay.h>
#include <inttypes.h>
int main(void)
{
DDRB = 0x00;
PORTB = 0xFF;
sei();
GIMSK |= (1<<PCIE);
PCMSK |= (1<<PCINT1);
}
ISR(PCINT1_vect)
{
DDRB = 0x01;
PORTB = 0xFE;
}
das Problem ist, das ich den Schalter drücken kann, wie ich will und die LED bleibt dunkel. Sie sollte allerding leuchten, wenn PB0 =0 ist.
Hardware dürfte OK sein, ich habe es vorher mit einer schleife probiert und dort hat es funktioniert
Gibt es bei
ISR(PCINT1_vect)
keine Warning?
So einen Interruptvektor gibt es beim T45 nämlich nicht!
Daher wird die Interruptroutine nicht in der Interrupttabelle eingetragen (sieht man im .lss-File), und beim Auslösen der Interrupts erfolgt ein Reset.
PCINT0_vect wäre richtig.
Das ist ne etwas gewöhnungsbedürftige Sache: es gibt für alle Pins nur einen gemeinsamen Interruptvektor! Bei größeren AVRs teilen sich immer acht Pins einen Interrupt, darum werden die Interrupts von PCINT0 an durchnummeriert. Die 0 hätte Atmel beim T45 auch weglassen können, aber so ist es konsistenter.
PCINT0_vect bedeutet also NICHT, dass es der Interruptvektor für den Pin PCINT0 ist, sondern dass es der erste (= nullte in Informatiker-Zählweise) der Pinchange-Interrupts ist, die jeweils acht Pins umfassen.
danke vielmals!! Ich glaube ich verstehe jetzt. Aber gibt es denn eine möglichkeit, dass "pcint0_vect" nur auf bestimmte ports reagiert? Sonst müsste ich ja in der interrupt-routine jeden port abfragen?!
Welche Pins den Interrupt auslösen, stellst du in PCMSK ein. Aber du hast es schon richtig verstanden: wenn mehrere Pins aktiv sind, musst du in der ISR erst mal abfragen, welchen Pin denn nun wirklich seinen Pegel geändert hat.
na also, jetzt läufts ja. Danke vielmals.
und soo schlimm ist das mit dem abfragen ja auch wieder nicht...
also eine frage habe ich doch noch:
ich habe es jetzt in meinem programm anders gelöst, aber ist es PRINZIPIELL NICHT möglich, dass man ein I/O-register in einer interrupt-routine ändert? also so funktioniert es bei mir nicht:
ISR(PCINT0_vect)
{
DDRB = 0x01;
PORTB = 0xFE;
}
wenn ich es mit einer abfrage im hauptprogramm mache (variablen-abfrage), dann geht es.
wo ist also das problem?
mfg
könnte es sein, dass, wenn ich sei(); vor PCMSK ausführe, andere Interrupts "dazwischenkommen"? oder GIMSK vor PCMSK?
dann gäbe es einen interrupt ohne ISR was ja bekanntlich zum Reset führt...
was glaubt ihr?
achja, für alle, die es interessiert oder das gleiche problem haben, ich habs.
also, ich "sei();" und "GIMSK" vor "PCMSK" getippt. das hat dazu geführt, dass einen kurzen augenblick wohl alle interrupts aktiv waren. und offenbar wurde genau zwischen diesen drei befehlen ein interrupt ausgelöst. und wie man weiss, löst jeder interrupt, der keine ISR (interruptroutine) hat, einen reset aus. tataaa, bug a la carte.
aber danke trotzdem für die hilfe!
mfg
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.