Hallo, folgendes Vorhaben: Ich möchte ein bis zu 40kHz Steuersignal an den Ausgängen eines ATMega32 generieren. Der µC wird mit 14.7456MHz getaktet. 40kHz entsprechen einer Zeit von 25µs und demensprechend ca. 369 Taktzyklen des Prozessor. Während dieser Zeit muss sich der entsprechende Port 3 mal ändern, also alle 123 Taktzyklen. Dazu habe ich mir jetzt gedacht ich setze den Prescalar auf Eins und lade den Timer mit 256 - 123 = 133 vor. Damit sollte die Interrupt-Routine alle ca. 8,33µs ausgeführt werden. Müsste dann so aussehen: 1. Aufruf ;nach 0µs Bit0 am Port setzen 2. Aufruf ;nach 8,33µs Bit1 am Port setzen 3. Aufruf ;nach 16,67µs Bit0 am Port rücksetzen Bit1 am Port rücksetzen 4. Aufruf ;nach 25µs Bit0 am Port setzen 5. Aufruf ;nach 33.33µs Bit1 am Port setzen 6. Aufruf ;nach 41,67µs Bit0 am Port rücksetzen Bit1 am Port rücksetzen ... Ich hoffe es ersichtlich, das sich hier 40kHz ergeben. Nun aber zu meinem Problem. Zwischen jedem 3er Block muss ich ggf. eine Pause einlegen, damit ich die Frequenz varieren kann. Diese Pause sollte bis zu 65535 Prozessortakte betragen. Nun kann ich aber keine Verzögerungsschleife innerhalb der Interrupt-Routine einbauen, da dann in der Zeit keine anderen Interrupts abgearbeitet werden, das muss aber gewährleistet sein. Bin für jede Idee offen. -- Gruß Karsten
Karsten Sosna schrieb: > alle 123 Taktzyklen. Dazu habe ich mir jetzt gedacht ich setze den > Prescalar auf Eins und lade den Timer mit 256 - 123 = 133 vor. In dem Moment, in dem jemand das Wort 'Vorladen' in den Mund nimmt (bei kritischem, schnellen Timing) stellen sich bei mir alle Nackenhaare auf. Das Stichwort für dich lautet: CTC-Modus des Timers > Während dieser Zeit muss sich der entsprechende Port 3 mal ändern Hä? Eine Rechteckschwingung mit einer gewissen Frequenz kann dir der Timer ganz von alleine, rein in Hardware, erzeugen. OK. Du willst 2 Pins mit bestimmten Frequenzen beaufschlagen. > Nun aber zu meinem Problem. Zwischen jedem 3er Block muss ich ggf. > eine Pause einlegen, damit ich die Frequenz varieren kann. Diese > Pause sollte bis zu 65535 Prozessortakte betragen. Schalte den Timer in den CTC-Modus. In der ISR schaltest du die Ausgangspins nach dem gewünschten Schema. Die neue Frequenz wird ausserhalb der ISR durch Variation des Compare Registers und/oder des Vorteilers eingestellt. Wobei ich beim nochmaligen Durchlesen fast sicher bin, dass sich dein Vorhaben mit den richtigen Pins auch durch einen PWM Modus durch Einsatz der Compare Register komplett in Hardware lösen lässt.
Hi >Dazu habe ich mir jetzt gedacht ich setze den Prescalar auf Eins und lade >den Timer mit 256 - 123 = 133 vor. Alle Timer des ATMega32 haben OC-Register. Da kannst du dir das Vorladen sparen. MfG Spess
> Alle Timer des ATMega32 haben OC-Register. Da kannst du dir das Vorladen > sparen. Hallo, Danke, das wusste ich nicht. Werde es gleich mal probieren. -- Gruß Karsten
>> alle 123 Taktzyklen. Dazu habe ich mir jetzt gedacht ich setze den >> Prescalar auf Eins und lade den Timer mit 256 - 123 = 133 vor. > > In dem Moment, in dem jemand das Wort 'Vorladen' in den Mund nimmt (bei > kritischem, schnellen Timing) stellen sich bei mir alle Nackenhaare auf. > > Das Stichwort für dich lautet: CTC-Modus des Timers Ich glaube, wir verstehen uns noch nicht, siehe unten > >> Während dieser Zeit muss sich der entsprechende Port 3 mal ändern > > Hä? Schau doch bitte mal das angehängte Diagramm an. Wie Du sicherlich erkennst ensteht dort eine Frequenz von ca 40kHz. Beachte nur ein Bit. Das Pulse-Pausen-Verhältnis interessiert nicht, das muss so sein. Ich sehe nur eine Möglichkeit die 123 Takte zu erreichen und das ist in dem ich den Timer vorlade. Wenn es noch anders geht, wäre ein kleines Beispiel hilfreich. > Eine Rechteckschwingung mit einer gewissen Frequenz kann dir der Timer > ganz von alleine, rein in Hardware, erzeugen. OK. Du willst 2 Pins mit > bestimmten Frequenzen beaufschlagen. Es ist ein und dieselbe Frquenz, siehe oben. >> Nun aber zu meinem Problem. Zwischen jedem 3er Block muss ich ggf. >> eine Pause einlegen, damit ich die Frequenz varieren kann. Diese >> Pause sollte bis zu 65535 Prozessortakte betragen. > > Schalte den Timer in den CTC-Modus. In der ISR schaltest du die > Ausgangspins nach dem gewünschten Schema. > Die neue Frequenz wird ausserhalb der ISR durch Variation des Compare > Registers und/oder des Vorteilers eingestellt. > > Wobei ich beim nochmaligen Durchlesen fast sicher bin, dass sich dein > Vorhaben mit den richtigen Pins auch durch einen PWM Modus durch Einsatz > der Compare Register komplett in Hardware lösen lässt. Nochmals zum Diagramm: Dort wo der 4.ISR-Aufruf ensteht muß eine variable Pause enstehen. Diese sollte von 0 bis 65535 Prozessortakten gehen. Bei 0 wären es wirklich die ca. 40kHz. Bei 65535 sind es dann 65535+369=65904 Takte welches einer Frequenz von 1/(65904*(1/14745600))= ca. 224Hz entspricht. Hoffe jetzt ist es deutlicher, was ich vorhabe. -- Gruß Karsten
Karsten Sosna schrieb: > Ich glaube, wir verstehen uns noch nicht, siehe unten Doch. Nach der Hälfte deines Urpsrungspostings ist es klarer geworden. > Ich sehe nur eine Möglichkeit die 123 Takte zu erreichen und das ist in > dem ich den Timer vorlade. Und ich sehe nach wie vor die Möglichkeit, den Timer so einzustellen, dass er sich ganz alleine um die 123 Takte kömmert. Von dort Weg gibt es 2 Möglichkeiten * entweder man macht eine ISR, in der die Pins geschaltet werden (mit dem CTC Modus, damit man den Timer eben nicht vorladen muss) * oder aber man benutzt einen der PWM Modi bei einem Timer, dessen PWM + auf eine obere Grenze eingestellt werden kann + 2 Pins ansteuern kann > Nochmals zum Diagramm: Dort wo der 4.ISR-Aufruf ensteht muß eine > variable Pause enstehen. Wozu brauchst du die Pause? Das hab ich noch nicht verstanden.
Hallo Karl Heinz, > * entweder man macht eine ISR, in der die Pins geschaltet werden > (mit dem CTC Modus, damit man den Timer eben nicht vorladen muss) Das habe ich gerade probiert und damit kann arbeiten > * oder aber man benutzt einen der PWM Modi bei einem Timer, dessen > PWM > + auf eine obere Grenze eingestellt werden kann > + 2 Pins ansteuern kann Tut mir leid, aber dort verstehe ich nur Bahnhof >> Nochmals zum Diagramm: Dort wo der 4.ISR-Aufruf ensteht muß eine >> variable Pause enstehen. > > Wozu brauchst du die Pause? > Das hab ich noch nicht verstanden. Das ist ganz einfach. Die ISR mit 3 Aufrufen steuert einen Schrittmotor. Die maximale Frequenz beträgt 40kHz(bei 16 Microsteps), das ist dann die maximale Verfahrgeschwindigkeit. Ich brauche aber eine Arbeitsgeschwindigkeit die einstellbar sein muss. Wenn ich jetzt also zwischen den einzelen 3er Gruppen Pausen einbaue veringert sich die Frequenz und damit sinkt die Verfahrgeschwindigkeit. Welche Bits gesetzt werden müssen erhalte ich über die serielle Schnittstelle, genauso wie lang die Pause sein soll. -- Gruß Karsten
Hi > Die ISR mit 3 Aufrufen steuert einen Schrittmotor. >Die maximale Frequenz beträgt 40kHz(bei 16 Microsteps), das ist dann die >maximale Verfahrgeschwindigkeit. Ich brauche aber eine >Arbeitsgeschwindigkeit die einstellbar sein muss. Also ich habe auch schon Schrittmotoren im Mikroschrittbetrieb angesteuert. Dein Ansatz kommt mir reichlich (vorsichtig ausgedrückt) schräg vor. MfG Spess
> Das ist ganz einfach. Die ISR mit 3 Aufrufen steuert einen Schrittmotor. > Die maximale Frequenz beträgt 40kHz(bei 16 Microsteps), das ist dann die > maximale Verfahrgeschwindigkeit. Ich brauche aber eine > Arbeitsgeschwindigkeit die einstellbar sein muss. Wenn ich jetzt also > zwischen den einzelen 3er Gruppen Pausen einbaue veringert sich die > Frequenz und damit sinkt die Verfahrgeschwindigkeit. > Welche Bits gesetzt werden müssen erhalte ich über die serielle > Schnittstelle, genauso wie lang die Pause sein soll. Ich habe eine Idee: Also den Timer0 benutze ich für meine Aufrufe mit ca. 139 Takten. Jetzt könnte ich doch daher gehen und den Interrupt für diesen Timer nach dem 3. Aufruf disablen. Dafür enable ich den Aufruf des Timer1, dieser ist ja ein 16Bit-Timer, ergo könnte ich meine Pause von bis zu 65535 Takten einlegen. Löst der Timer1 den Interrupt aus, disable ich ihn und enable den Timer0 wieder. Damit könnte das Spiel von vorne beginnen. Müsste doch gehen, oder? -- Gruß Karsten
> Also ich habe auch schon Schrittmotoren im Mikroschrittbetrieb > angesteuert. Dein Ansatz kommt mir reichlich (vorsichtig ausgedrückt) > schräg vor. Dann erkläre mir doch mal, wie Du einen Satz an Steuersignalen via USB auf einem Controller ausgeben willst, wenn Du mit einer maximalen Frequenz von 40kHz arbeiten willst. -- Gruß Karsten
Karsten Sosna schrieb: >> * oder aber man benutzt einen der PWM Modi bei einem Timer, dessen >> PWM >> + auf eine obere Grenze eingestellt werden kann >> + 2 Pins ansteuern kann > > Tut mir leid, aber dort verstehe ich nur Bahnhof Dann musst du dich da einarbeiten. Es geht letzten endes darum, dass du haben willst, dass dir die Hardware die Pulse ganz von alleine erzeugt. >>> Nochmals zum Diagramm: Dort wo der 4.ISR-Aufruf ensteht muß eine >>> variable Pause enstehen. >> >> Wozu brauchst du die Pause? >> Das hab ich noch nicht verstanden. > > Das ist ganz einfach. Die ISR mit 3 Aufrufen steuert einen Schrittmotor. > Die maximale Frequenz beträgt 40kHz(bei 16 Microsteps), das ist dann die > maximale Verfahrgeschwindigkeit. Ich brauche aber eine > Arbeitsgeschwindigkeit die einstellbar sein muss. Wenn ich jetzt also > zwischen den einzelen 3er Gruppen Pausen einbaue veringert sich die > Frequenz und damit sinkt die Verfahrgeschwindigkeit. OK. Auch das kann man mit den PWM Modi immer noch erreichen. Ist letzten Endes nur eine Frage des Zusammenspiels des Top-Wertes und der Compare Werte. > Welche Bits gesetzt werden müssen erhalte ich über die serielle > Schnittstelle, genauso wie lang die Pause sein soll. Die Serielle sollte bei deinen Timing Überlegungen keine Rolle spielen. Du kriegst einen Wert von irgendwo her: Welche Werte müssen TOP und die COmpare-Register des Timers haben, damit der Timer ganz alleine, völlig autonom das gewünschte Pin Muster erzeugt.
> Auch das kann man mit den PWM Modi immer noch erreichen. Ist letzten > Endes nur eine Frage des Zusammenspiels des Top-Wertes und der Compare > Werte. Hallo Karl Heinz, Also der Werte kann ich Dir keine Antwort geben, weil ich nicht weiß was Du darunter verstehst. Wenn ich das mit 2 Timern lösen kann(siehe mein entsprechendes Posting), dann wäre der Compare-Wert für den Timer0 = 123 und für den Timer1 = Delay-Wert in Takten Was Du mit den Top-Werten meinst weiß ich nicht. -- Gruß Karsten
Hi >Dann erkläre mir doch mal, wie Du einen Satz an Steuersignalen via USB >auf einem Controller ausgeben willst, wenn Du mit einer maximalen >Frequenz von 40kHz arbeiten willst. Was haben denn die Signale jetzt mit USB zu tun? MfG Spess
>>Dann erkläre mir doch mal, wie Du einen Satz an Steuersignalen via USB >>auf einem Controller ausgeben willst, wenn Du mit einer maximalen >>Frequenz von 40kHz arbeiten willst. > > Was haben denn die Signale jetzt mit USB zu tun? Der Postprozessor sitzt in der Anwendung auf dem PC. Wen Du über die USB übertragen willst musst Du soviel wie möglich übertragen. Es wird nicht funktionieren wenn Du 1 Byte zum Controller schickst und auf eine Antwort wartest. Der Treiber unter Windows für virtuelle Comports schiebt dann eine Pause von 1 Millisekunde für den Richtungswechsel ein. Damit sinkt Deine Übertragung auf unter 1000 Bytes pro Sekunde. Wenn Du aber 40000 Bytes brauchst kannst Du das Verfahren so vergessen. Es bleibt also nichts so vielwie möglich auch einen Schlag zu senden und dann eine Antwort zu senden. Denn sendest Du bspw. 512 Bytes und schickst dann eine Antwort, tritt diese Millisekunde erst nach den 512 Bytes auf. Nur somit kann man auch genügend Daten an den Controller schicken, damit eine "fast synchrone" Abrbeitung gewährleistet ist. -- Gruß Karsten
Karsten Sosna schrieb: > Nur somit kann man auch genügend Daten an den Controller > schicken, damit eine "fast synchrone" Abrbeitung gewährleistet ist. Schon klar. Aber das alles hat erst mal nichts mit der Signalerzeugung zu tun!
Karsten Sosna schrieb: >> Auch das kann man mit den PWM Modi immer noch erreichen. Ist letzten >> Endes nur eine Frage des Zusammenspiels des Top-Wertes und der Compare >> Werte. > > Hallo Karl Heinz, > Also der Werte kann ich Dir keine Antwort geben, weil ich nicht weiß was > Du darunter verstehst. Dann solltest du dir das mal näher ansehen. > Wenn ich das mit 2 Timern lösen kann(siehe mein entsprechendes Posting), > dann wäre der Compare-Wert für den Timer0 = 123 und für den Timer1 = > Delay-Wert in Takten 1 Timer, der Timer1, reicht dazu völlig aus. Der erzeugt dir völlig autonom deine gewünschten Signale. > Was Du mit den Top-Werten meinst weiß ich nicht. Lies das Datenblatt. Den Abschnitt im Timer 1 über die PWM. Du verschenkst ja die Hälfte der Möglichkeiten, die dir dein Mega32 bietet, wenn du dich nicht darüber informierst, was der alles kann.
> 1 Timer, der Timer1, reicht dazu völlig aus. > Der erzeugt dir völlig autonom deine gewünschten Signale. Hallo Karl Heinz, meinst Du so was? \\\ Timer1_Init: LDI temp, (1<<CS10)|(1<<WGM01) OUT TCCR1B, temp OUT OCR1AH, NormalHigh OUT OCR1AL, NormalLow ;Enable Timer1 overflow interrupt LDI temp, (1<<OCIE1A) ;TOIE0: Interrupt Timer0 Overflow OUT TIMSK, temp Main: SEI ;Enable Interupts MainLoop: RJMP MainLoop TIMER1_Interrupt: INC step CPI step, 0x01 BREQ DoStep1 CPI step, 0x02 BREQ DoStep2 CPI step, 0x03 BREQ DoStep3 CPI step, 0x04 BREQ DoStep4 DoStep1: OUT PORTC, step RJMP Exit_TIMER0_Interrupt DoStep2: OUT PORTC, step RJMP Exit_TIMER0_Interrupt DoStep3: OUT PORTC, step OUT OCR1AH, DelayHigh ;Delaytime OUT OCR1AL, DelayLow RJMP Exit_TIMER0_Interrupt DoStep4: OUT PORTC, step OUT OCR1AH, NormalHigh ;Normaltime OUT OCR1AL, NormalLow LDI step, 0x00 RJMP Exit_TIMER0_Interrupt Exit_TIMER0_Interrupt: RETI /// Habe das auf das Wesentliche gekürzt, sollte aber zeigen wie ich das jetzt versucht habe zu lösen. Die Delaytime(DoStep3) wird später gesetzt. So sollte das doch i.O. gehen, oder? -- Gruß Karsten
Ich würds so machen: Zuallererst würd eich meine Zyklen umschaufeln. Das was du als Pause hintennach bezeichnest, würde ich als Pause davor auffassen. Also so einen Signalverlauf
1 | -+ +----------------------------+ |
2 | Pin 1 | | | |
3 | --------------------+ +-- |
4 | |
5 | -+ +----------------+ |
6 | Pin 2 | | | |
7 | --------------------------------+ +-- |
8 | |
9 | ^ ^ |
10 | | Eine Schwingung | |
11 | +-- hier bis hier --+ |
Dazu nehme ich mir einen PWM Modus, bei dem ich die Frequenz mittels TOP Wert einstellen kann, aber noch die beiden Compare Register frei habe. Modus 14 bietet sich da an. Der Top Wert (und damit: wie weit zählt der Timer) kommt ins ICR1 Register und die OCR1x Register sind zur weiteren Benutzung verfügbar. Damit kann ich schon mal die Frequenz der kompletten Schwingung einstellen. Die Übergänge von 0 auf 1 an jedem der beiden Pins macht mir der Compare Match, repektive die OCR1A bzw. OCR1B Register. Dazu muss aber der Compare Match im jeweiligen Kanal auf Modus COM1A0 / COM1A1 = 1 / 1 = Set OC1A on compare match, clear at BOTTOM COM1B0 / COM1B1 = 1 / 1 = Set OC1B on compare match, clear at BOTTOM eingestellt werden. Hier nochmal, welches Register für welche Flanke zuständig ist:
1 | -+ +----------------------------+ |
2 | Pin 1 | | | |
3 | --------------------+ +-- |
4 | |
5 | -+ +----------------+ |
6 | Pin 2 | | | |
7 | --------------------------------+ +-- |
8 | |
9 | 0 ^ ^ ^ |
10 | | | | |
11 | OCR1A OCR1B ICR1 |
Der Rest ist jetzt einfach nur noch die Werte für ICR1, OCR1A bzw OCR1B korrekt berechnen und die Hardware erzeugt die Pulse ohne weiteres Zutun des Programmes völlig von alleine. Das Programm stellt einfach nur die Modi ein, stellt die Registerwerte ein und ist ansonsten von der Pulsgenerierung befreit und kann Däumchen drehen (oder eine serielle Schnittstelle überwachen) Die Pause soll länger werden? Kein Problem. OCR1A, OCR1A und ICR1 rutschen nach rechts (werden größer) OK. Ich bin auf die Benutzung der speziellen Pins OC1A bzw OC1B angewiesen. Die müsste man hardwaremässig freischaufeln. Aber das wäre es mir wert.
Hallo Karl Heinz, erst mal entschuldige ich mich dafür das ich mich erst jetzt melde, musste noch ein anderes Projekt abschließen. So, Dein Vorschlag gefällt mir gut und ich versuche ihn gerade umzusetzen. Leider bekomme ich das mit dem Timer nicht geregelt. :=( Ich habe das jetzt so initialisiert: \\\ .org 0x00 RJMP Reset .org ICP1addr RJMP TIMER1_Capt .org OC1Aaddr RJMP TIMER1_CompA .org OC1Baddr RJMP TIMER1_CompB ;... Timer1_Init: ;Mode 14, no prescaling LDI temp, 1<<WGM10 | 1<<COM1A0 | 1<<COM1A1 | 1<<COM1B0 | 1<<COM1B1 OUT TCCR1A, temp LDI Temp, 1<<WGM13 | 1<<WGM12 | 1<<CS10 OUT TCCR1B, temp LDI NormalLow, 0x40 OUT OCR1AL, NormalLow LDI NormalLow, 0x60 OUT OCR1BL, NormalLow LDI NormalLow, 0x80 OUT ICR1L, NormalLow ;Enable Timer1 interrupts LDI temp, 1<<TICIE1 | 1<<OCIE1A | 1<<OCIE1B OUT TIMSK, temp SEI MainLoop: RJMP MainLoop /// Nur ist es so, das nur ein Interrupt(TIMER1_CompA) ausgelöst wird, und das gleich beim Start, d.h. so wie Anwendung in die MainLoop läuft. Dort wird auch OC1A gesetzt. Zu diesem Zeitpunkt steht der Timer auf 0x0013. Danach wird keine Interruptroutine mehr aufgerufen. Erreicht der Timer dann 0x0060 wird auch OC1B gesetzt, jedoch kein Interrupt ausgelöst. Bei 0x0080 sollte der Timer dann doch eigentlich wieder zurückgesetzt werden, doch auch das passiert nicht, na ja und der Interrupt wird auch nicht ausgelöst. Ich gehe mal davon aus, dass meine Initialisierung fehlerhaft ist. Wäre nett wenn Du oder irgendjemand anderes das mal prüfen könnte. Bin für jeden Hinweis/ Tipp dankbar. -- Gruß Scotty
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.