Hallo zusammen, möchte den ATtiny13 im Fast PWM-Mode (7) betreiben und zwar so das OC0A-PB0(Pin5) und OC0B-PB1(Pin6) parallel geschaltet werden können. Zusätzlich möchte ich an PB2 (Pin7) mittels Timer0 Overflow eine LED als Programmlaufanzeige (PLA) blinken lassen. Das blinken der LED an PB2 (Pin7) funktioniert auch, allerdings nur solange bis ich im Timer/Counter0 Control Register B (TCCR0B) das Bit 3 (WGM02) und nur dieses zusätzlich setze, dann blinkt die LED an PB2 nicht mehr Sichtbar bzw. ist ständig an. in A,TCCR0A ;...Timer/Counter0 Control Register A laden... ori A,0b10100011 ;...clear on Match, set at Top... out TCCR0A,A ;...fuer OC0A und OC0B einstellen. in A,TCCR0B ori A,0b00001010 out TCCR0B,A ldi A,0b00000010 ;Timer/Counter0 Overflow Interrupt... out TIMSK0,A ;...enablen (TOIE0) Habe keine FUSE oder LOCK-Bits geändert. Habe im AVR-Simulator die Bits nochmals geprüft und das Datenblatt öfters zu Rate gezogen, kann den Fehler jedoch nicht entdecken. Hoffe jemand von euch tut es. Habe das komplette Programm als Dateianhang hinzugefügt. Bis dann Bernd_Stein
Es ist ne blöde Idee, im Main und Interrupt die gleichen Register (A,B) zu verwenden. Der Interrupt zerstört die Werte des Main oder man muß die Register extra push-/popen. Du hast 32 Register, da ist übertriebenes Sparen unnötig. Peter
Hi >möchte den ATtiny13 im Fast PWM-Mode (7) betreiben und zwar so das >OC0A-PB0(Pin5) und OC0B-PB1(Pin6) parallel geschaltet werden können. Im PWM-Mode7 ist OCR0A Das Register für Top. Damit steht es nicht mehr als PWM-Kanal zur Verfügung. Die Initialisierung der OC-Register fehlt auch. MfG Spess
Peter Dannegger schrieb: > Es ist ne blöde Idee, im Main und Interrupt die gleichen Register (A,B) > zu verwenden. > > Der Interrupt zerstört die Werte des Main oder man muß die Register > extra push-/popen. > > Du hast 32 Register, da ist übertriebenes Sparen unnötig. Oh ja Danke, eigentlich weiß ich so etwas, habe aber wohl vor lauter Bäumen den Wald nicht gesehen. Habe dies korrigiert und weiß dadurch und durch spess53, das es nicht am Bit3 (WGM02) im TCCR0B liegt, sondern daran das ich die OC0RA & OCR0B Register nicht initialisiert habe. Somit kommen zwei Dinge zum Tragen. Zum einen Note 1. auf den Datenblattseiten 68 & 69 " A special case occurs when OCR0A equals TOP and COM0A1 is set. In this case, the Compare Match is ignored, but the set or clear is done at TOP. See “Fast PWM Mode” on page 63 for more details. " Was bedeutet das im Fast PWM-Mode 7 wo TOP = OCR0A ist und die Bits COM0A1 & COM0B1 bei mir gesetzt sind - das die Ausgänge immer auf eins sind. Zum anderen der Ausschnitt aus dem Datenblatt Seite 64 ..." The extreme values for the OCR0A Register represents special cases when generating a PWM waveform output in the fast PWM mode. If the OCR0A is set equal to BOTTOM, the output will be a narrow spike for each MAX+1 timer clock cycle. "... Was meinem Fehlerbild sehr entspricht, da die LED, wenn sie nach GND (0) geschaltet wird leuchtet. Und ich habe ja durch nicht initialisieren der OCR0A & OCR0B Register diese bei dem Wert Null belassen was ja BOTTOM entspricht. Also habe ich nur ein paar Spikes erzeugt und andauernd einen Timer/Conunter0 Overflow erzeugt, da das TOV0-Flag bei TOP ( in diesem Fall TOP = OCR0A = 0 ) gesetzt wird. Bis demnächst Bernd_Stein
spess53 schrieb: > Im PWM-Mode7 ist OCR0A Das Register für Top. Damit steht es nicht mehr > als PWM-Kanal zur Verfügung. > > Die Initialisierung der OC-Register fehlt auch. > > MfG Spess Herzlichen Dank, die Initialisierung der OCR0x-Register war genau die Ursache. Die Erklärung hierzu habe ich bei Peter Dannegger geschrieben. Bis demnächst Bernd_Stein
1 | #define SM1_DDR DDRE
|
2 | #define SM1_PORT PORTE
|
3 | #define SM1_TAKT ( 1<<PE3 ) //5 //( 1<<PE3 ) // OC3A-Pin
|
4 | |
5 | void setup() |
6 | {
|
7 | SM1_DDR |= SM1_TAKT; // PE3 bzw. OC3A als Compare Match A Ausgang |
8 | SM1_PORT &= ~SM1_TAKT; // Zunaechst Low-Pegel |
9 | |
10 | |
11 | TCCR3A = 0; // Weil Arduino |
12 | TCCR3B = 0; // |
13 | TCCR3C = 0; // |
14 | |
15 | // TCCR3A |= 0b01<< COM3A0; // OC3A-Pin Toggeln
|
16 | TCCR3A &= ~0b11<< WGM30; // CTC-MODE 4 Low Bits |
17 | OCR3A = 32768; //minSpeed; // Niedrige Frequenz |
18 | TCCR3B |= 0b01<< WGM32; // CTC-MODE 4 High Bits |
19 | TCCR3B |= 0b001<< CS30; // Vorteiler = 1 und Timer3 starten |
20 | TCCR3B &= ~0b110<< CS30; // Vorteiler = 1 und Timer3 starten |
21 | TIMSK3 |= 1<<OCIE3A; // Output Compare Interrupt freigeben |
22 | }
|
23 | |
24 | void loop() |
25 | {
|
26 | // put your main code here, to run repeatedly:
|
27 | }
|
28 | |
29 | ISR( TIMER3_COMPA_vect ) |
30 | {
|
31 | SM1_PORT &= ~SM1_TAKT; // Schrittimpuls vorbereiten |
32 | SM1_PORT |= SM1_TAKT; // Schrittimpuls vollenden |
33 | }
|
Mein DSO sagt Impulsdauer 132ns. Könnt gut hinhauen bei 16MHz CPU-Takt. Logik-Analyser sagt 250ns - Hm. Da war doch früher mal was. Ach ja Mega-Sample pro Sekunde unzureichend. Jo, mit 8 MS/s kommt es schon eher hin. Problem ist nur, dass wenn im OCR3A-Register der Wert 32768 steht, der Interrupt ca, alle 4,096ms auftreten sollte. Der LA sagt aber 2,063ms. Wo ist der Fehler? Bernd_Stein
Bernd S. schrieb: > Wo ist der Fehler? > > wenn im OCR3A-Register der Wert 32768 steht, der > Interrupt ca, alle 4,096ms auftreten sollte. Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.
Dieser Programmabschnitt kann doch keine 5µs, bei 16MHz ( 62,5ns ) CPU-Takt dauern. Erlaubt diese Arduino-Klamotte, dass ein Interrupt durch einen anderen unterbrochen werden darf ?
1 | ISR( TIMER3_COMPA_vect ) |
2 | {
|
3 | //-------------------------------------------------------------------------------
|
4 | //
|
5 | // CTC3 MODE 4 Normaler Ausgang
|
6 | // SM-Sinusrampe abfahren, Schrittmotorschritte runterzaehlen und
|
7 | // Schrittimpuls erzeugen.
|
8 | //
|
9 | //-------------------------------------------------------------------------------
|
10 | ///////////////////////////////////////////////////////////////////////////////
|
11 | // Hin und her fahren und am Startpunkt wird eine kurze Pause einlegt
|
12 | //
|
13 | if( stepCount != 0 ) { |
14 | OCR3A = rampeArray[ rampeArrayZeiger ]; // |
15 | SM1_PORT &= ~SM1_TAKT; // Schrittimpuls vorbereiten |
16 | |
17 | // Geschwindigkeit verlangsamen und begrenzen
|
18 | if( stepCount <= rampenLaenge ) { |
19 | rampeArrayZeiger ++; |
20 | |
21 | if( rampeArrayZeiger > rampenLaenge -1 ) rampeArrayZeiger = rampenLaenge -1; |
22 | }
|
23 | // Geschwindigkeit erhoehen und begrenzen
|
24 | else if( stepCount > rampenLaenge ) { |
25 | rampeArrayZeiger --; |
26 | |
27 | if( rampeArrayZeiger <= 0 ) rampeArrayZeiger = 0; |
28 | }
|
29 | stepCount --; // Schrittmotor Schrittanzahl runterzaehlen |
30 | |
31 | // Nur jedes 2te mal ist dieses Bit gesetzt bzw. geloescht
|
32 | if( stepCount == 0 ) flagRegister ^= EINS; |
33 | |
34 | SM1_PORT |= SM1_TAKT; // Schrittimpuls vollenden |
35 | }
|
36 | } // Ende ISR( TIMER3_COMPA_vect ) |
Bernd_Stein
:
Bearbeitet durch User
Bernd S. schrieb: > Erlaubt diese Arduino-Klamotte, dass ein Interrupt durch einen anderen > unterbrochen werden darf ? Darauf hat Arduino keinen Einfluss. Das steuerst du über deinen Quelltext. Wenn innerhalb deiner ISR ein sei() steht, dann ermöglichst du eine Unterbrechung. Sonst nicht. Falls du damit experimentieren willst: Verschachtelte Interrupts bringen einen Rattenschwanz von Fallstricken mit sich. Der offensichtlichste: Erhöhter Speicherbedarf auf dem Stack. Die weniger offensichtlichen führen manchmal zu zeitraubender Fehlersuche mit losen Haaren auf dem Tisch und Kratzern am Hinterkopf. Also lass das besser sein.
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.