Hallo, ich versuche gerade auf einem Port unterschiedliche PWM´s zu programmieren. Es bleiben aber leider alle LED´s gleich hell, also es läuft nicht. Könnte mir bitte jemand helfen ? (Trotz Bascom......) Danke !!! CODE: $regfile = "m16def.dat" $crystal = 16000000 Config Portb = Output Config Timer0 = Timer , Prescale = 256 On Timer0 Timer_irq Dim X As Byte Dim Pwm_led(8) As Byte For X = 1 To 8 Read Pwm_led(x) Next Enable Timer0 Enable Interrupts Portb = 255 Do Loop Timer_irq: For X = 0 To 7 If Pwm_led(x + 1) <= Timer0 Then Portb.x = 0 Else Portb.x = 1 End If Next Return End Data 55 , 55 , 255 , 255 , 255 , 255 , 255 , 255
So wie ich das sehe hast du da eine Kleinigkeit übersehen, nämlich: Der Timer-INT wird beim Überlauf der Timer-Registers ausgelöst, sprich beim 8-bit-Timer0 alle 256 Timer-Takte. Das bedeutet, wenn du das Timer-Register in der Zeile "If Pwm_led(x + 1) <= Timer0 Then" ausliest, dann ist Timer0 immer 0, weil der Überlauf gerade stattgefunden hat. Alternativ könntest du z.B. eine Variable vom Typ Byte nehmen, die du bei jedem Timer-INT um eine Stelle erhöhst. Was das setzen der Port-Pins angeht, kannst du das einfach machen: Setz die Portpins auf ON, immer wenn die Variable den Wert 0 hat und schalte sie (einzeln!) ab, wenn die Variable den zum Pin zugehörigen PWM-Wert überschreitet. Da die Variable beim hochzählen beim erreichen von Werten > 255 automatisch auf 0 zurückspringt, musst du nur im INT mit einer IF-Bedingung prüfen, ob sie den Wert 0 hat und dann "Portb = 255" setzen. Also z.B. Dim PWM As Byte Timer_irq: If PWM = 0 Then portb = 255 For X = 0 To 7 If Pwm_led(x + 1) <= PWM Then Portb.x = 0 End If Next Incr PWM Return Gruß Mario
Danke für deinen rat. Habe es wie unten gebessert, aber es sind immernoch alle led´s gleich hell (an). $regfile = "m16def.dat" $crystal = 16000000 Config Portb = Output Config Timer0 = Timer , Prescale = 256 On Timer0 Timer_irq Dim X As Byte Dim Pwm_led(8) As Byte , Pwm_counter As Byte For X = 1 To 8 Read Pwm_led(x) Next Enable Timer0 Enable Interrupts Portb = 255 Do Loop Timer_irq: If Pwm_counter = 0 Then Portb = 255 For X = 0 To 7 If Pwm_led(x + 1) <= Pwm_counter Then Portb.x = 0 End If Next Incr Pwm_counter Return End Data 255 , 255 , 255 , 100 , 100 , 255 , 255 , 255
Hallo Kann das sein das der IRQ Routine nicht ganz durchlaufen wird und dann sich selbst aufruft? Hast du mal das im Simulator getestet wie hoch PWM_Counter kommt und was die anderen Werte stehen. Bascom-Projekte auf http://www.comwebnet.de
In der Interrupt-Routine solltest du grundsätzlich möglichst wenig Zeit verbringen. Deshalb setze ich dort nur ein Flag, das ich in der main loop abfrage. Bascom stellt sich mit Interrupts ziemlich blöd an: er pushed und popped ALLE Register, ob sie in der Interrupt-Routine benutzt werden oder nicht. Deshalb sollte man (mit AVR-Studio) nachsehen welche Register benutzt werden und nur diese gezielt sichern. Dann kann mein beim On Interrupt Befehl den Parameter Nosave angeben, so dass Bascom von sich aus nichts sichert. Teste mal diesen Code: $regfile = "m16def.dat" $crystal = 16000000 Config Portb = Output Config Timer0 = Timer , Prescale = 256 On Timer0 Timer_irq Nosave Dim X As Byte Dim Pwm_led(8) As Byte , Pwm_counter As Byte Dim Pwm_update As Byte For X = 1 To 8 Read Pwm_led(x) Next Enable Timer0 Enable Interrupts Portb = 255 Do If Pwm_update = 1 Then Pwm_update = 0 Incr Pwm_counter For X = 0 To 7 If Pwm_led(x + 1) <= Pwm_counter Then Portb.x = 0 Else Portb.x = 1 End If Next End If Loop End Timer_irq: 'Wenn weitere Befehle in der ISR ausgeführt werden sollen, 'muss überprüft werden welche Register diese benutzen und diese 'Register müssen dann ebenfalls auf den Stack gerettet werden!!! PUSH R24 'Nachfolgend wird nur R24 benutzt, dieses also retten IN r24, SREG PUSH R24 Pwm_update = 1 POP R24 !Out Sreg , R24 POP R24 Return Data 255 , 255 , 255 , 100 , 100 , 255 , 255 , 255
So, habe folgenden Code geschrieben. Wenn ich den Teiler auf 8 oder 1 stelle, läuft der PWM-Teil super, kann aber nix anderes mehr machen. Z.B. ausgabe auf dem LCD ist extrem langsam. Stelle ich den Teiler wider auf 256, ist der PWM-Teil zu lahm, aber der rest geht. Kann mann es nicht machen, das der PWM-Teil funktioniert, und der AVR noch was anderes machen kann ? Bitte um hilfe !!! @Erwin, bei deinem beispiel ist es das selbe.
ach, der code........ $regfile = "m16def.dat" $crystal = 16000000 Config Portb = Output Config Timer0 = Timer , Prescale = 256 On Timer0 Timer_irq Const Timervorgabe = 6 Dim X As Byte Dim Pwm_led(8) As Byte Dim Pwm_counter As Byte Restore Pwm_daten For X = 1 To 8 Read Pwm_led(x) Next Enable Timer0 Enable Interrupts Cls Cursor Off Portb = 0 Do Locate 1 , 1 Lcd "Moin" Waitms 60 Loop Timer_irq: Timer0 = Timervorgabe Incr Pwm_counter For X = 0 To 7 If Pwm_counter < Pwm_led(x + 1) Then Portb.x = 1 Else Portb.x = 0 End If Next Return Pwm_daten: Data 10 , 20 , 30 , 40 , 40 , 30 , 20 , 10
In der Artikel-Sammlung gibt es einen sehr interessanten Artikel zum Thema Soft PWM, ich denke von Falk(?) Leider ist der Programmcode in C. Ich hab mal versucht, das unten beschriebene 'intelligente' Verfahren in ein verbesserungsfähiges Bascom Programm umzusetzten. Schau doch mal, ob diese Routine weniger Rechenzeit braucht! $regfile = "m16def.dat" $crystal = 8000000 Config Portb = Output Config Timer0 = Timer , Prescale = 256 On Timer0 Timer_irq Nosave Dim X As Byte Dim Pwm_led(8) As Byte Dim Pwm_zeit(8) As Byte Dim Action As Byte Dim Zustand As Byte Dim Lcdwait As Byte Restore Helligkeit For X = 1 To 8 Read Pwm_zeit(x) Next Enable Timer0 Enable Interrupts Portb = 0 Do If Action = 1 Then Action = 0 Stop Timer0 If Zustand = 0 Then Portb = 0 Decr Zustand Else Decr Zustand Set Portb.zustand End If Zustand = Zustand + 2 Timer0 = Pwm_zeit(zustand) If Zustand = 10 Then Zustand = 0 Start Timer0 Incr Lcdwait End If If Lcdwait = 10 Then 'nur jeden 10. Durchlauf LCD schreiben Lcdwait = 1 Locate 1 , 1 Lcd "Moin" End If Loop End Timer_irq: 'Wenn weitere Befehle in der ISR ausgeführt werden sollen, 'muss überprüft werden welche Register diese benutzen und diese 'Register müssen dann ebenfalls auf den Stack gerettet werden!!! PUSH R24 'Nachfolgend wird nur R24 benutzt, dieses also retten Action = 1 POP R24 Return Helligkeit: Data 255 , 249 , 237 , 219 , 193 , 156 , 230 , 253 ' 1 7 19 37 63 100 26 3 "An-Zeit" = 256-Data Summe =256
Wegen des LCD-Zugriffs flackern die LEDs in meinem Programm von 23:09Uhr. Sorry, hab ich nicht bemerkt. Hier jetzt flimmert nix mehr, ich habe es gerade getestet. Ob die LCD-Ausgabe schnell genug ist, musst du selbst sehen, ich habe gerade keines angeschlossen. Das Programm muss für die praktische Anwendung noch ergänzt werden: Das Array Pwm_zeit(8) enthält jetzt erstmal die Zeitdifferenzen zwischen den 8 einzelnen PWM-Kanäle. Eigentlich will man aber das Tastverhältnis der 8 Kanäle in einem Array haben. Das erfordert ein zweites Array. Nach einer Änderung der Werte dieses zweiten Arrays müssen die Abstände in Pwm_zeit(8) neu berechnet werden. $regfile = "m16def.dat" $crystal = 8000000 $baud = 57600 Config Lcdpin = Pin , Db4 = Portc.0 , Db5 = Portc.1 , Db6 = Portc.2 , Db7 = Portc.3 , E = Portc.4 , Rs = Portc.5 Config Portb = Output Config Timer0 = Timer , Prescale = 256 On Timer0 Timer_irq Nosave Dim X As Byte Dim Pwm_zeit(8) As Byte Dim Action As Byte Dim Zustand As Byte Restore Helligkeit For X = 1 To 8 Read Pwm_zeit(x) Next Enable Timer0 Enable Interrupts '----------------------------------------------------------- 'Main Schleife Do Locate 1 , 1 Lcd "Moin" Waitms 100 Loop '----------------------------------------------------------- End Timer_irq: 'Wenn weitere Befehle in der ISR ausgeführt werden sollen, 'muss überprüft werden welche Register diese benutzen und diese 'Register müssen dann ebenfalls auf den Stack gerettet werden!!! PUSH R27 PUSH R26 PUSH R25 PUSH R24 PUSH R16 PUSH R11 PUSH R10 IN R24, SREG PUSH R24 Stop Timer0 If Zustand = 0 Then Portb = 0 Decr Zustand Else Decr Zustand Set Portb.zustand End If Zustand = Zustand + 2 Timer0 = Pwm_zeit(zustand) If Zustand = 10 Then Zustand = 0 Start Timer0 POP R24 !OUT SREG, R24 POP R10 POP R11 POP R16 POP R24 POP R25 POP R26 POP R27 Return Helligkeit: Data 255 , 249 , 237 , 219 , 193 , 156 , 230 , 253 ' 1 7 19 37 63 100 26 3 "An-Zeit" = 256-Data Summe =256
Das hatte ich mir leichter vorgestellt. Hat der M128 nicht von hause aus 8 PWM kanäle, die ich unabhängik nutzen kann ?
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.