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.