Datum: 18.07.2008 14:36
Ich trau mich schon fast nicht zu fragen... Wo ist mein Denkfehler. Ich möchte nur ne Led zum Blinken bringen. Die Led leuchtet allerdings ständig. Ich verwende ATMega16 und 11MHz Quarz. Fuse ist auf externer Quarz eingestellt. #include <avr/io.h> #include <avr/interrupt.h> #include <inttypes.h> volatile unsigned char zeit; //Hauptprogramm int main (void) { DDRB= 0xff; //alle Pins als Ausgang PORTB= 0x00; zeit=0; TIMSK |= (1<<TOIE1); //Timer1 Overflow Interrupt enable TCCR1B |= (1<<CS12|1<<CS10); //fosc=1/1024 sei(); //Interrupts enable //Global Interrupt Enable Bit im Status //Register gesetzt while(1) { if(zeit==2){ if ( PINB & (1<<PINB2) ) PORTB &= ~(1<<PB2); //wenn PB2 gesetzt, PB2 auf Null setzen else PORTB |= (1<<PB2); //sonst PB2 auf Eins setzen zeit=0; } } //while Ende } //main Ende ISR (TIMER1_OVF_vect){ //Interrupt alle 6s (1/(11MHz/65536))*1024 zeit++; return; }
Datum: 18.07.2008 14:42
Wenn du Abfragen willst, ob der Port gesetzt ist oder nicht, benutzt man meines Wissens nach trotzdem das PORTx-Register. PIN nur, wenn man den Port als Eingang benutzt. Lasse mich hier aber auch gern verbessern.
Datum: 18.07.2008 14:45
Und: frag doch besser nicht den Pin sondern das Portregister ab. Falls der Ausgangstreiber es nicht schafft, den Pin richtig auf Hi oder Lo zu ziehen, könntest du dir über den Pin den falschen Pegel zurücklesen.
if(zeit==2){
PORTB ^= (1<<PB2); // einfach mal invertieren
zeit=0;
}
|
Datum: 18.07.2008 14:46
deine led wird aber nur dann aus sein wenn zeit == 2 ist, und das sind (11MHz / 1024) / 256 = 41,9 Hz ^= 0,0138s. ich denke da ist nicht all zu viel zu sehen
Datum: 18.07.2008 14:46
bin_ich_blöd_oder_was wrote: > if ( PINB & (1<<PINB2) ) PORTB &= ~(1<<PB2); > //wenn PB2 gesetzt, PB2 auf Null setzen > else PORTB |= (1<<PB2); //sonst PB2 auf Eins setzen Erstens wie Micha schon sagte: Du willst den Zustand des Porttreibers abfragen, und das geht mit PORTx und nicht mit PINx (was hier aber keinen Unterschied machen dürfte). Zweitens kann man das viel kürzer und einfacher schreiben:
PORTB ^= 1 << PB2;
|
@ Micha R.: Was zum Geier ist TMRON?
Datum: 18.07.2008 14:47
willi wrote: > deine led wird aber nur dann aus sein wenn zeit == 2 ist, und das sind > (11MHz / 1024) / 256 = 41,9 Hz ^= 0,0138s. ich denke da ist nicht all zu > viel zu sehen Richtig. Das geht an sich schon schief. Schalte mal direkt in der ISR den Portpin um, das müsste eigentlich klappen.
Datum: 18.07.2008 14:53
willi wrote: > deine led wird aber nur dann aus sein wenn zeit == 2 ist, und das sind > (11MHz / 1024) / 256 = 41,9 Hz ^= 0,0138s. ich denke da ist nicht all zu > viel zu sehen Na regelmäßig blinkt die schon, bei 2 wird immer getoggelt. Sie sollte zumindest dunkler sein. Ich kommm allerdings auf 72 ms. (1000ms / (11MHz 1024 256)) * 3 = 71,5ms
Datum: 18.07.2008 15:01
Micha R. wrote: > Ich kommm allerdings auf 72 ms. > (1000ms / (11MHz 1024 256)) * 3 = 71,5ms Timer 1 hat beim ATMega16 16 Bit (65536)...
Datum: 18.07.2008 15:03
Micha R. wrote:
> Na regelmäßig blinkt die schon, bei 2 wird immer getoggelt.
Nö, sie wird (in der Originalfassung) bei 2 in einen Zustand geschaltet
und bei "nicht 2" wieder in den anderen. Da die Variable immer zu Null
gesetzt wird, wenn der Wert 2 erreicht wurde, ist sie sofort danach
wieder "nicht 2"...
Wenn der OP die Abfrage so ändert, dass nur bei 2 getoggelt wird und
sonst gar nichts, dann dürfte es klappen.
Datum: 18.07.2008 15:04
Johannes M. wrote: > Micha R. wrote: >> Ich kommm allerdings auf 72 ms. >> (1000ms / (11MHz 1024 256)) * 3 = 71,5ms > Timer 1 hat beim ATMega16 16 Bit (65536)... Dann wärens ja sogar 18 Sekunden????
Datum: 18.07.2008 15:06
Johannes M. wrote: > Micha R. wrote: >> Na regelmäßig blinkt die schon, bei 2 wird immer getoggelt. > Nö, sie wird (in der Originalfassung) bei 2 in einen Zustand geschaltet > und bei "nicht 2" wieder in den anderen. Da die Variable immer zu Null > gesetzt wird, wenn der Wert 2 erreicht wurde, ist sie sofort danach > wieder "nicht 2"... > > Wenn der OP die Abfrage so ändert, dass nur bei 2 getoggelt wird und > sonst gar nichts, dann dürfte es klappen. Ein besser formatierter Original-Code sagt anderes: if(zeit==2) { if ( PINB & (1<<PINB2) ) PORTB &= ~(1<<PB2); //wenn PB2 gesetzt, PB2 auf Null setzen else PORTB |= (1<<PB2); //sonst PB2 auf Eins setzen zeit=0; } Also wenn Zeit = 2 wird der Port getoggelt und anschließend wird wieder von vorn begonnen.
Datum: 18.07.2008 15:06
Micha R. wrote:
> Dann wärens ja sogar 18 Sekunden????
Hä?
Datum: 18.07.2008 15:08
Micha R. wrote:
> Ein besser formatierter Original-Code sagt anderes:
Autsch, ja, hast Recht...
Datum: 18.07.2008 15:10
Johannes M. wrote: > Micha R. wrote: >> Dann wärens ja sogar 18 Sekunden???? > Hä? >

Dazu kommt aber noch das Zählen von 0 bis 2. Also hab ich die 6s mit 3 multipliziert?
Datum: 18.07.2008 15:12
Micha R. wrote: > Dazu kommt aber noch das Zählen von 0 bis 2. > Also hab ich die 6s mit 3 multipliziert? Und warum mit 3? zeit ist am Anfang Null und wird nach dem ersten Überlauf auf 1 erhöht. Beim zweiten Überlauf wird auf 2 erhöht und damit im Hauptprogramm nach zwei Überläufen das Umschalten durchgeführt. Und nicht nach 3 Überläufen...
Datum: 18.07.2008 15:15
Johannes M. wrote: > Micha R. wrote: > Und warum mit 3? zeit ist am Anfang Null und wird nach dem ersten > Überlauf auf 1 erhöht. Beim zweiten Überlauf wird auf 2 erhöht und damit > im Hauptprogramm nach zwei Überläufen das Umschalten durchgeführt. Und > nicht nach 3 Überläufen... Stimmt, hast recht. Es sind zwei Durchläufe... also 12 Sekunden. ;-)
Datum: 18.07.2008 15:39
Hi >Wenn du Abfragen willst, ob der Port gesetzt ist oder nicht, benutzt man >meines Wissens nach trotzdem das PORTx-Register. >PIN nur, wenn man den Port als Eingang benutzt. Lasse mich hier aber >auch gern verbessern. Also das mit PORT und PIN wusste ich nicht. Danke für den Hinweise. Würde das nun bedeuten (mal abgesehen vom Sinn oder nicht), dass ich auch if ( PORTB & (1<<PORTB2) ) PORTB &= ~(1<<PB2); //wenn PB2 gesetzt, PB2 auf Null setzen else PORTB |= (1<<PB2); //sonst PB2 auf Eins setzen anstatt if ( PINB & (1<<PINB2) ) PORTB &= ~(1<<PB2); //wenn PB2 gesetzt, PB2 auf Null setzen else PORTB |= (1<<PB2); //sonst PB2 auf Eins setzen schreiben könnte? Leider funktioniert das Blinken im 12s Takt immer noch nicht.
Datum: 18.07.2008 15:58
Ja, das müsste funktionieren. Füg mal den kompletten Code an.
Datum: 18.07.2008 16:08
Also mehr ist das nicht.
#include <avr/io.h>
#include <avr/interrupt.h>
#include <inttypes.h>
volatile unsigned char zeit;
//Hauptprogramm
int main (void) {
DDRB= 0xff; //alle Pins als Ausgang
PORTB= 0xff;
zeit=0;
TIMSK |= (1<<TOIE1); //Timer1 Overflow Interrupt enable
TCCR1B |= (1<<CS12|1<<CS10);
sei(); //Interrupts enable
while(1) {
if(zeit==2){
PORTB ^= (1<<PB2); //invertieren
zeit=0;
}
} //while Ende
} //main Ende
ISR (TIMER1_OVF_vect){ //Interrupt alle (1/(CPU/65536))*Vorteiler
zeit++;
return;
}
Datum: 18.07.2008 16:27
Ja...
beim Toggeln hast du den else-Zweig vergessen.
if ( PORTB & (1<<PORTB2) )
PORTB &= ~(1<<PB2);
//wenn PB2 gesetzt, PB2 auf Null setzen
else
PORTB |= (1<<PB2); //sonst PB2 auf Eins setzen
Datum: 18.07.2008 16:30
Übrigens kann man bei den Atmel Prozessoren die Ausgänge auch toggeln, indem man eine 1 an der entprechenden Stelle in das PINx-Register schreibt. Also PINB = (1<<PB2);
Datum: 18.07.2008 16:34
Öhm... wozu soll das "return" am Ende der ISR gut sein?!
Datum: 18.07.2008 16:37
>Ja... >beim Toggeln hast du den else-Zweig vergessen. > if ( PORTB & (1<<PORTB2) ) > PORTB &= ~(1<<PB2); > //wenn PB2 gesetzt, PB2 auf Null setzen > else > PORTB |= (1<<PB2); //sonst PB2 auf Eins setzen Häää???? Was meinst du? Ich habs doch nun nach euren Vorschlägen hin auf while(1) { if(zeit==2){ PORTB ^= (1<<PB2); //invertieren zeit=0; } } //while Ende geändert.
Datum: 18.07.2008 16:40
>beim Toggeln hast du den else-Zweig vergessen.
nönö er macht ja jetzt nen exclusiv-oder, da brauchts kein else
Datum: 18.07.2008 17:45
Detlev T. wrote: > Übrigens kann man bei den Atmel Prozessoren die Ausgänge auch toggeln, > indem man eine 1 an der entprechenden Stelle in das PINx-Register > schreibt. Also > > PINB = (1<<PB2); Beim Mega16 geht das aber nicht! Deshalb ist die Aussage "Bei den ATMEL-Prozessoren..." nicht nur wegen der Verallgemeinerung "ATMEL = AVR" falsch. ATMEL baut auch andere "Prozessoren" als AVRs... Das return ist tatsächlich flüssiger als Wasser, dürfte so aber auch zumindest nicht zu Fehlfunktionen führen.
Datum: 18.07.2008 18:22
@Johannes M.: Du hast in allen Punkten recht. Das geht tatsächlich nur mit Tiny-AVRs. Mein Irrtum.
Datum: 18.07.2008 20:09
Detlev T. wrote: > @Johannes M.: > Du hast in allen Punkten recht. Das geht tatsächlich nur mit Tiny-AVRs. > Mein Irrtum. Auch das ist falsch. Es geht mit allen neueren AVRs, auch mit ATMegaXYZ, aber es sind nach wie vor einige AVRs älteren Entwicklungsdatums auf dem Markt, die dieses Feature noch nicht haben (z.B. ATMega8, ATMega16/32, ATMega162, ATMega64/128). Der aktuelle ATMega16-Nachfolger ATMega164 hat z.B. die von Dir angesprochene Möglichkeit, über die PINx-Register die Pins zu toggeln. Gleiches gilt z.B. für ATMega48/88/168 usw.
Datum: 19.07.2008 04:07
Müssen die Interrupts nicht auch erst per FUSE angeschaltet werden? Ist das sei nicht überflüssig?
Datum: 19.07.2008 13:46
saeckereier wrote: > Müssen die Interrupts nicht auch erst per FUSE angeschaltet werden? Ist > das sei nicht überflüssig? Unsinn. Die globale Interrupt-Freigabe erfolgt durch sei() und nicht anderes. Die Fuses haben nichts mit der Interrupt-Bearbeitung zu tun.
Datum: 20.07.2008 11:27
Könnte es sein, dass dein Proz immer noch mit 1MHz läuft? Dann wird die LED zwar blinken, jedoch nur alle 11*12=132s. Das kann man schon fast als Dauerleuchten interpretieren... Überprüf mal die Fuses.
Datum: 20.07.2008 14:49
Probiers mal so:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <inttypes.h>
//Interrupt alle (1/(CPU/65536))*Vorteiler
ISR (TIMER1_OVF_vect)
{
static uint8_t zeit = 0;
if (++zeit >= 2)
{
PORTB ^= ( 1 << PB2 );
zeit = 0;
}
}
//Hauptprogramm
int main (void)
{
DDRB= 0xff; //alle Pins als Ausgang
PORTB= 0xff;
TIMSK |= (1<<TOIE1); //Timer1 Overflow Interrupt enable
TCCR1B |= (1<<CS12|1<<CS10);
sei(); //Interrupts enable
while(1)
{
// ggf. noch nen sleep um Energie zu sparen
}
}
Antwort schreiben
Die Angabe einer Email-Adresse ist freiwillig. Wenn Sie automatisch per Email über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.
Wichtige Regeln - erst lesen, dann posten!
- Suchfunktion und Betreffsuche benutzen - vielleicht gibt es schon einen ähnlichen Beitrag
- Aussagekräftigen Betreff wählen
- Im Betreff angeben um welchen Controllertyp es geht (AVR, PIC, ...)
- Groß- und Kleinschreibung verwenden
- Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang
- JPEG-Dateien (.jpg) nur für Fotos und Scans verwenden
- Schaltpläne, Screenshots usw. als PNG oder GIF anhängen
Formatierung (mehr Informationen...)
- [c]C-Code[/c]
- [avrasm]AVR-Assembler-Code[/avrasm]
- [pre]vorformatierter Text (z.B. Code in anderen Sprachen)[/pre]
- [math]Formel in LaTeX-Syntax[/math]
- [[Titel]] - Link zu Artikel