Hallo zusammen, ich bin frischer Einsteiger in die µC-Technik und habe folgendes Problemchen: Ich möchte mit dem ATtiny2313 eine Hardware-PWM erzeugen bzw. auf einem Ausgang ausgeben, bin bisher aber erfolglos. Ich habe den Timer zwar zum laufen gebracht, der Ablauf stimmt auch (OCRnx als TOP, Intterupt flag bei compare match, etc.), die Interrupt Flags tauchen auch alle auf (Simulation mit AVR-Studio 4), aber an meinem Ausgang am PORTB tut sich nix... Das Setzen von prescaler, COMnx, WGM und dergleichen krieg ich ja alles hin, aber der Ausgang macht keinen Mucks... Wenn ich das Datenblatt vom ATtiny2313 richtig verstanden habe, müsste ich eigentlich alles richtig gemacht haben (auch wenn ich stellenweise den Eindruck habe, dass das Datenblatt manches nicht vollständig erklärt). Das ganze müsste doch ohne Interrupt handler funktionieren, oder? Ich liefere heut abend mal meinen sourcecode, vielleicht weiß jemand nen typischen Anfänger-Fallstrick? Grüße FoxAlpha
Ja das geht ohne ISR. Hast du daran gedacht mit DDRx den Pin auf Ausgang zu setzen? Hier ist ein Beispiel mit LED Fading: http://www.mikrocontroller.net/articles/Pollin_Funk-AVR-Evaluationsboard#Blinky_Reloaded Mode 5 non-inverted PWM on OC1A, 8 Bit Fast PWM
So, hier bin ich nochmal mit code... unschwer zu erkennen, möchte ich erstmal assemblerprogrammierung lernen/üben.
1 | .include "tn2313def.inc" |
2 | |
3 | init: |
4 | ldi r16, RAMEND ;stackinit (128byte RAM--> 8bit SP) |
5 | out SPL, r16 |
6 | ldi r16, 0b11111111 ;portb als output |
7 | out DDRB, r16 |
8 | ldi r16, 0 ;portb aus |
9 | out PORTB, r16 |
10 | ldi r16, (1<<WGM00) | (1<<WGM01) | (1<<COM0A1) | (0<<COM0A0) | (1<<COM0B1) | (0<<COM0B0) |
11 | ;fast PWM ;set OC0A at top, clear on compare match fuer A und B |
12 | out TCCR0A, r16 |
13 | ldi r16, 156 ;zwei werte fuer OCR0x |
14 | out OCR0A, r16 |
15 | ldi r16, 12 |
16 | out OCR0B, r16 |
17 | ldi r16, (1<<CS00) | (0<<CS01) | (0<<CS02) | (1<<WGM02) ;teiler 1, timer obergrenze OCR0A |
18 | out TCCR0B, r16 |
19 | ldi r16, (1<<OCIE0A) | (1<<OCIE0B) ;interrupt ein (braucht man das ueberhaupt?) |
20 | out TIMSK, r16 |
21 | |
22 | main: |
23 | ; einfach nixtun und den Timer arbeiten lassen ;) |
24 | rjmp main |
Portb setze ich als Ausgang und nulle den erstmal. Dann kommt der waveform generation mode als fast PWM mit OCR0A als TOP dran (und weil OCR0A = TOP, ist bei dem WGM OC0A immer gesetzt, OC0B dient als eigentliches Signal). OCR0x werden mit Zahlenwerten gefüttert, dann der Prescaler und der "Rest" vom WGM. Die Interrupts hab ich mal eingeschaltet, weiß der Geier, ob das notwendig ist... Ziel des ganzen ist die Ansteuerung eines Modellbauservos. Zum Simulieren steht der Prescaler noch auf 1, später mit prescaler 1024 kommt eine Frequenz von ca. 50Hz raus, an PB4 (OC0B) sollte dann ein PWM-Signal mit einem 20ms-Takt und rund 1,5ms "Ein"-Zeit rauskommen (Mittenstellung Servo). Mit dem 16bit Timer wäre das ganze etwas genauer, aber darauf kommts mir noch nicht an, ich muss erstmal lernen, mit dem Timer umzugehen. Wenn jetzt jemandem was auffällt, was ich besser machen kann, kann er sich gerne dazu äußern. Grüße FoxAlpha
(irgendwie hat das mit dem posten das erste mal nicht geklappt, deswegen nochmal...) So, hier bin ich nochmal mit code... unschwer zu erkennen, möchte ich erstmal assemblerprogrammierung lernen/üben.
1 | .include "tn2313def.inc" |
2 | |
3 | init: |
4 | ldi r16, RAMEND ;stackinit (128byte RAM--> 8bit SP) |
5 | out SPL, r16 |
6 | ldi r16, 0b11111111 ;portb als output |
7 | out DDRB, r16 |
8 | ldi r16, 0 ;portb aus |
9 | out PORTB, r16 |
10 | ldi r16, (1<<WGM00) | (1<<WGM01) | (1<<COM0A1) | (0<<COM0A0) | (1<<COM0B1) | (0<<COM0B0) |
11 | ;fast PWM ;set OC0A at top, clear on compare match fuer A und B |
12 | out TCCR0A, r16 |
13 | ldi r16, 156 ;zwei werte fuer OCR0x |
14 | out OCR0A, r16 |
15 | ldi r16, 12 |
16 | out OCR0B, r16 |
17 | ldi r16, (1<<CS00) | (0<<CS01) | (0<<CS02) | (1<<WGM02) ;teiler 1, timer obergrenze OCR0A |
18 | out TCCR0B, r16 |
19 | ldi r16, (1<<OCIE0A) | (1<<OCIE0B) ;interrupt ein (braucht man das ueberhaupt?) |
20 | out TIMSK, r16 |
21 | |
22 | main: |
23 | ; einfach nixtun und den Timer arbeiten lassen ;) |
24 | rjmp main |
Portb setze ich als Ausgang und nulle den erstmal. Dann kommt der waveform generation mode als fast PWM mit OCR0A als TOP dran (und weil OCR0A = TOP, ist bei dem WGM OC0A immer gesetzt, OC0B dient als eigentliches Signal). OCR0x werden mit Zahlenwerten gefüttert, dann der Prescaler und der "Rest" vom WGM. Die Interrupts hab ich mal eingeschaltet, weiß der Geier, ob das notwendig ist... Ziel des ganzen ist die Ansteuerung eines Modellbauservos. Zum Simulieren steht der Prescaler noch auf 1, später mit prescaler 1024 kommt eine Frequenz von ca. 50Hz raus, an PB4 (OC0B) sollte dann ein PWM-Signal mit einem 20ms-Takt und rund 1,5ms "Ein"-Zeit rauskommen (Mittenstellung Servo). Mit dem 16bit Timer wäre das ganze etwas genauer, aber darauf kommts mir noch nicht an, ich muss erstmal lernen, mit dem Timer umzugehen. Wenn jetzt jemandem was auffällt, was ich besser machen kann, kann er sich gerne dazu äußern. Grüße FoxAlpha
So, hier bin ich nochmal mit code... unschwer zu erkennen, möchte ich erstmal assemblerprogrammierung lernen/üben. Portb setze ich als Ausgang und nulle den erstmal. Dann kommt der waveform generation mode als fast PWM mit OCR0A als TOP dran (und weil OCR0A = TOP, ist bei dem WGM OC0A immer gesetzt, OC0B dient als eigentliches Signal). OCR0x werden mit Zahlenwerten gefüttert, dann der Prescaler und der "Rest" vom WGM. Die Interrupts hab ich mal eingeschaltet, weiß der Geier, ob das notwendig ist... Ziel des ganzen ist die Ansteuerung eines Modellbauservos. Zum Simulieren steht der Prescaler noch auf 1, später mit prescaler 1024 kommt eine Frequenz von ca. 50Hz raus, an PB4 (OC0B) sollte dann ein PWM-Signal mit einem 20ms-Takt und rund 1,5ms "Ein"-Zeit rauskommen (Mittenstellung Servo). Mit dem 16bit Timer wäre das ganze etwas genauer, aber darauf kommts mir noch nicht an, ich muss erstmal lernen, mit dem Timer umzugehen. Wenn jetzt jemandem was auffällt, was ich besser machen kann, kann er sich gerne dazu äußern. Grüße FoxAlpha
...mist, jetzt ist doch alles gepostet worden... die zwei überflüssigen posts (und den hier) darf jemand löschen, wer kann...
Doofe Frage: Hast du schon Hardware oder schaust du im AVRStudio auf die Bits in PORTB? In PORTB tut sich nämlich nichts, der Pin wird "an PORTB vorbei" gesetzt bzw. gelöscht. Siehe auch http://atmel.com/dyn/resources/prod_documents/doc8246.pdf Bild 11-4. Zu deiner Frage bezüglich Interrupts: Braucht man nicht. Würde ich auch dafür nicht aktivieren, ist eine zusätzliche Fehlerquelle - denn ohne ISR macht der Controller unter Umständen dumme Sachen ;) In deinem Programm ist das aber egal, denn du setzt das globale IRQ-Flag nicht. MfG, Heiko
Guten Morgen allerseits, die richtige Frage wäre gewesen: "Schaust du auch auf die richtigen Ports?" Ich habe erst späääät festgestellt, dass OC0B ja in PORTD steckt und nicht in PortB... /*aua/* Plötzlich funktioniert alles wie es soll. ;) Sorry für die blöden Fragen. Grüße FoxAlpha
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.