Hallo.
ich fange mal ganz oben an bei der Beantwortung der Fragen die sich bisher aufgestaut haben.
- Wie kann man einstellen das man nicht den OCR0 Port als Ausgang für den Timer haben will, sondern PortB, 0?
In dem man anstatt der Hardware PWM, die manche Timer generieren können eine Software PWM nutzt.- Ist es nicht möglich das man den OCR einfach mit einem anderen Ausgang verbindet?
Nein, das ist nicht möglich.- ... aber später möchte ich damit ja auch 2 Motoren steuern ...
Wenn du dafür 2 PWM's benötigst, nimm am besten den Timer 1 oder einen µC, der dieMöglichkeit hat mit jedem Timer 2 Hardware PWM's zu generieren.- Wie kann ich jetzt einstellen das ich nur in der Software einen Ausgang haben will, nicht aber bei einem Hardwareausgang?
Du lässt die COM?0 & COM?1 Bits auf 0 stehen.- ... Also wie kann ich einen Interrupt auslösen? ... {Anm: Bezug vorherige Frage}
In dem du im TIMSK Register die einsprechenden Bits setzt.
Damit kann z.B. ein Interupt ausgelöst werden wenn:
a) der Zähler überläuft
b) Der Zählerstand = dem Wert im OCR Register entspricht.- Es muss doch möglich sein, das man einfach mit einer Phase Correct PWM einen Interrupt bei jeder Änderung aufruft oder?
Wenn sich die Aussage auf eine Änderung des Zählerstandens bezieht, also z.B. von 21 auf 22, dannmuss die Antwort NEIN lauten.- Was mich beunruhigt ist das ich für den Timer0 nur einen Eintrag in der Interruptvektortabelle habe. Für alle anderen sind mehrere vorhanden.
Es sind auch mehrere ... du hast uns hier schlicht und einfach einen unterschlagen (schau mal im Datenblatt auf Seite 45).
So, und hier noch ein kleines Codebeispiel (für den ATmega16) zum Thema: "Wie erzeuge ich an jedem X - beliebigen Pin eine Pulsweitenmodulation":
Eine Anmerkung zu diesem Code:Code:.nolist .include "m16def.inc" .list .def sregsave = r4 ; SREG Backup .def ch_1 = r5 ; PWM Werte der LED's .def ch_2 = r6 .def ch_3 = r7 .def ch_4 = r8 .def temp = r16 ; temporäre Daten .def pwm_cnt = r17 .CSEG .ORG 0 jmp isr_reset ; Reset Interupt Handler jmp isr_not_used ; INT 0 Interupt Handler jmp isr_not_used ; INT 1 Interupt Handler jmp isr_not_used ; Timer 2 Compare Interupt Handler jmp isr_not_used ; Timer 2 Overflow Interupt Handler jmp isr_not_used ; Timer 1 Capture Interupt Handler jmp isr_not_used ; Timer 1 Compare A Interupt Handler jmp isr_not_used ; Timer 1 Compare B Interupt Handler jmp isr_not_used ; Timer 1 Overflow Interupt Handler jmp isr_not_used ; Timer 0 Overflow Interupt Handler jmp isr_not_used ; SPI Transfer Complete Interupt Handler jmp isr_not_used ; USART RX Complete Interupt Handler jmp isr_not_used ; USART UDR empty Interupt Handler jmp isr_not_used ; USART TX Complete Interupt Handler jmp isr_not_used ; ADC Conversion Complete Interupt Handler jmp isr_not_used ; EEPROM Ready Interupt Handler jmp isr_not_used ; Analog Comperator Interupt Handler jmp isr_not_used ; TWI Interupt Handler jmp isr_not_used ; INT 2 Interupt Handler jmp isr_t0_cp ; Timer 0 Compare Interupt Handler jmp isr_not_used ; Store Program Memory Ready Interupt Handler isr_reset: ldi temp, high(RAMEND) ; STACK initialisieren out SPH, temp ldi temp, low(RAMEND) out SPL, temp in temp, MCUCSR ; Disable JTAG Interface ori temp, (1<<JTD) out MCUCSR, temp out MCUCSR, temp clr temp ; Ports konfigurieren: ldi temp, (1<<DDA0) ; PIN A0, B0, C0, D0 -> Ausgang +H ; Rest: Eingang + Pullup out DDRA, temp out DDRB, temp out DDRC, temp out DDRD, temp ldi temp, 0xFF out PORTA, temp out PORTB, temp out PORTC, temp out PORTD, temp ldi temp, (1<<WGM01) | (1<<CS00) ; Timer 0 konfigurieren out TCCR0, temp ldi temp, 0x80 out OCR0, temp ldi temp, (1<<OCIE0) ; Timerinterupts aktivieren out TIMSK, temp ldi temp, 0x80 ; Defaultwerte setzen mov ch_1, temp mov ch_2, temp mov ch_3, temp mov ch_4, temp clr temp sei ; Interupts Global aktivieren main_loop: ; Irgendwelcher sonstiger Code ; Irgendwelcher sonstiger Code ; Irgendwelcher sonstiger Code jmp main_loop isr_not_used: ; Blanko für nicht genutzte Interupt Handler reti isr_t0_cp: ; Timer 0 Compare Interupt Handler in sregsave, SREG ; Statusregister sichern inc pwm_cnt ; Hilfszähler für die PWM um eins erhöhen cp ch_1, pwm_cnt ; Vergleiche gewünschtes Tastverhältniss mit aktuellem PWM Hilfszählerstand brlo PC+4 breq PC+3 sbi PORTA, 0 rjmp PC+2 cbi PORTA, 0 cp ch_2, pwm_cnt brlo PC+4 breq PC+3 sbi PORTB, 0 rjmp PC+2 cbi PORTB, 0 cp ch_3, pwm_cnt brlo PC+4 breq PC+3 sbi PORTC, 0 rjmp PC+2 cbi PORTC, 0 cp ch_4, pwm_cnt brlo PC+4 breq PC+3 sbi PORTD, 0 rjmp PC+2 cbi PORTD, 0 out SREG, sregsave ; Statusregister wiederherstellen reti
Speziell auf die PWM bezogen ist er sicherlich nicht das Optimum an Code. Dieses hat unter anderem den ganz einfachen Grund, das der derselbige doch noch irgendwo verständlich erscheinen soll, auch ohne das man erst im groß im Datenblatt nachsehen muss, um beispielsweise herauszufinden: Welche Flags denn in welchem Fall bei diversen Befehlen beeinflusst werden und welche Sonderfälle in der PWM hier nun möglich sind.
Im übrigen, ist eine Software PWM doch eher eine Taktzeitaufwändige Aktion (also in dem Fall 128 * 256 Takte für eine Periode) um die so gedimmten LED's noch flimmerfrei wahrzunehmen (also ich sag mal mit einer Refreshrate von 200 Hz) sollte der µC schon mit ca. 6,55 MHz laufen (128 x 256 x 200) was aufgerundet eben mal 8 MHz sind.
Vielleicht sollte man noch erwähnen, das es einen kleinen Fallstrick beim STK 500 gibt, da dort die LED's nicht mit "H" sondern mit "L" Pegel leuchten.
@ Schokohoernl:
Sicherlich kann man mit einem Vernünftig durchdachtem Code eine 16 oder gar 24 Kanal Software PWM zum Dimmen von LED's erzeugen, aber sicherlich nicht "theoretisch" unendlich viele.
Die limitierenden Faktoren sind direkt:
- die Taktfrequenz des Mikrocontrollers
- der Dauer die die Befehle zum Ausführen benötigen
und indirekt:
- die Programmiersprache des Programmieres.
Grüße,
da Hanni.
Lesezeichen