PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Mehrere Software Pwm auf einem µC



ACsenf
07.04.2006, 09:17
Hallo!

Ich habe folgende Problematik, ich benötige 4 in der Frequenz frei skalierbare PWMs. Soweit habe ich es auch schon, der Bereich geht von 50Hz bis 250Hz. Dazu muss ich schon 2 timer verbraten (Timer0 und Timer1), weil Bascom immernoch den bug hat, das ich zumindest bei den mega 32 und mega 16 in meinem µC Programm den Prescaler nicht verändern kann...also man kann schon wie es sich gehört, alles programmieren, aber der µC ändert später nichts. Das muss ich nochmals an Mark schreiben. Wenn das nicht bald behoben wird muss ich Bascom in Rente schicken...

So nun zur eigentlichen Frage die momentan 4 synchron laufenden PWM Ausgänge meiner Sofr-PWM, sollen nun um unterschiedliche Verzögerungszeiten zu Kanal 1 laufen. Jeweils alle mit der selben Frequenz und Tastverhältnis, nur halt versetzt. Mit 5 Timern wüsste ich, wie man dem Ganzen beikommen könnte, aber mit den Voraussetzungen auf dem Chip hm...ehrlichgesagt, keine Ahnung.

Eine etwas aufwändiger Methode schwirrt mir noch im Kopf herum, einen Master mit 4 Slaves aufzubauen, der dann die anderen µC synchronisiert, oder halt versetzt startet und über SPI mit Daten versorgt... Ist halt ne Menge zum Aufbauen, weshalb ich das ganz gerne in einem Chip unterbringen würde.

Mal gespannt auf eure Ideen und Anregungen.

Gruß

Sven

linux_80
07.04.2006, 19:11
Hallo,
theoretisch reicht doch ein Timer, diesen z.B. alle 0,1ms takten (oder wie genau die Auflösung sein soll), und dann muss man nur pro SoftPWM mitzählen, wann man einen Ausgang auf high und low setzen muss.

Was ist das Problem mit dem Prescaler, ich weiss zwar jetzt nichts von dem Bascom-Fehler, aber Du weisst, das es nur einen Prescaler für die Timer gibt, bzw. ein Prescaler ist für mehrere Timer ?!
Timer0 und 1 verwenden den gleichen Prescaler, nur Timer2 hat einen eigenen Prescaler.

E-Fan
07.04.2006, 22:28
...weil Bascom immernoch den bug hat, das ich (...) den Prescaler nicht verändern kann...also man kann schon wie es sich gehört, alles programmieren, aber der µC ändert später nichts. Das muss ich nochmals an Mark schreiben. Wenn das nicht bald behoben wird muss ich Bascom in Rente schicken...

Dann solltest Du Schnarchnase mal nen Blick in die Bedienungsanleitungen der Controller werfen! :cheesy:
Der Mega32 und Mega16 bieten bei Timer0 und Timer1 nur folgende Prescale-Möglichkeiten: 0,8,64,256 und 1024
Die 16-Bit Timer hängen an diesem Prescaler mit dran wenn ich es richtig verstanden hab.
Bascom hat in diesem Zusammenhang wohl doch keinen Bug. ;)

Ich würd an Deiner Stelle vier Slaves (Tiny 13 oder sowas in der Richtung) nehmen die durch den Master Synchronisiert werden. Mit einem Controller wird das, durch die fehlende Möglichkeit Variablen parallel zu bearbeiten, nicht sauber funktionieren.

ACsenf
08.04.2006, 00:23
Hallo E-Nase ;-)

Das mit dem Prescaler ist mir schon bekannt, ebenso die verfügbaren Auflösungen! Und wenn man mit dem 16 Bit kleinere, wie auch größere Frequenzen erzeugen möchte, muss ich eben diesen Prescaler in meiner Software in einer If Verzweigung von z.B. 8 auf 64 umschalten, was beim 8515 einwandfrei klappt, aber eben bei diesen beiden Megas tut der Compiler nicht das richtige! Dieser Bug wurde hier auch schonmal erwähnt! Probiere es mal aus und schreibe ein Proggi, das zwei Prescalerwerten umschalten muss und dann messe mal mit einem Oszi ob das was du vorausberechnet hast auch mit der Realität übereinstimmt.
Bei klappt das jedenfalls nicht. Die idee mit den Slaves werde ich vermutlich auch umsetzen um in "Echtzeit" synchronisieren zu können.

Ich krame mal meinen Code raus mit dem es nicht ging, geht.

Gruß

Sven

E-Fan
10.04.2006, 17:23
hmmm... :-k
Haste die Chose schon mal alleine im Controller ausgetestet? Also ohne dat andere Codegedöns und nur die Umschaltung der Prescalerwerte?

ACsenf
10.04.2006, 21:29
So hier ist mein code mit den Timern, wo sich der Prescalerwert nicht ändert! Der Compiler setzt alles ohne zu murren um, aber ab 29Hz kommt nur noch Mist heraus.


'************************************************* ******************************
'Frequenzgenerator
'Prozessor: Atmel Mega 32
'Programm: Test_Prescaler verändern
'************************************************* ******************************
'$sim
$regfile = "M32DEF.DAT"
$crystal = 16000000
$baud = 9600

'-----------------------------Variablendeklaration--------------------------------
Dim Rel_flag As Bit
Dim S As String * 10

'------------------------Variablen zur Frequenzberechnung-------------------------
Dim F As Single
Dim Fein As Single
Dim Fcalc As Single
Dim Check As Single
Dim Calc As Single
Dim Pre As Integer 'Prescaler
Dim Presc As Integer 'Prescaler Uebergabewert
Dim Vorteiler As Long 'Prescaler berechnet
Dim Reload1 As Word
Dim Count0 As Byte
Dim Count1 As Byte
Const Fosc = 16000000 'Frequenz µC
Const Aufl = 65536 'Timeraufloesung
Dim T As Single 'Periode
Declare Sub Aus
Declare Sub Neue_frequenz
Declare Sub Reloadsub

'-----------------------------Portkonfiguration-----------------------------------

'Der PortC wird als Ausgang programmiert
Config Pinc.0 = Output
Config Pinc.1 = Output
Config Pinc.2 = Output
Config Pinc.3 = Output
Config Pinc.4 = Output
Config Pinc.5 = Output
Config Pinc.6 = Output
Config Pinc.7 = Output
Config Pina.7 = Output
Config Pina.6 = Output
Config Pina.5 = Output
Config Pina.4 = Output

'Der Port B und D wird als Eingang programmiert
Config Pinb.0 = Input
Config Pinb.1 = Input
Config Pinb.2 = Input ' Interrupt 2 für Zuendung Slave IN sync
Config Pinb.3 = Input
Config Pinb.4 = Input
Config Pinb.5 = Input
Config Pinb.6 = Input
Config Pinb.7 = Input
Config Pind.2 = Input ' Interrupt 0 für ON/OFF
Config Pind.3 = Input 'Interrupt 1 Sammelinterrupt Stoerung
Config Pind.4 = Input
Config Pind.5 = Input
Config Pind.6 = Input
Config Pind.7 = Input

'Pullup einschalten nur bei PD3 noetig!
Portd.3 = 1

'Hier geben wir der Definition einen schoeneren Namen
_out Alias Portc.0
Sync Alias Portc.1
_rdy Alias Portc.2
Reserve_out Alias Portc.3
Stoerung_out Alias Portc.4
Outp Alias Portc.5
Led1 Alias Portc.6
Led2 Alias Portc.7
Led3 Alias Porta.7
Led4 Alias Porta.6
Ok Alias Porta.5
Relais Alias Porta.4

'-----------------------------Timerkonfiguration----------------------------------
'Hier wird der Timer und der Teiler festgelegt
Config Timer0 = Timer , Prescale = 64
Config Timer1 = Timer , Prescale = 8

'Hier wird das Unterprogramm festgelegt, das
'in dem eingestellten Intervall aufgerufen wird
On Timer0 Timer0_irq 'Nosave
On Timer1 Timer1_irq 'Nosave

Const Reload0 = 6
Reload1 = 30534

'Hier werden die Timer aktiviert
Enable Timer0
Enable Timer1
Enable Interrupts


Call Aus
Start Timer1

Do
If Ischarwaiting() <> 0 Then Call Neue_frequenz
nop
Loop

Timer0_irq: '1 Pausenteil 1ms
Timer0 = Reload0
Outp = 0 'EIN
Stop Timer0
Waitus 500
Outp = 1 'AUS
Waitus 1000 '2.Pausenteil 1ms
Led1 = 0
Start Timer1

Return


Timer1_irq: 'lange Zeit 17,5ms
Timer1 = Reload1
Led1 = 1
Stop Timer1
Start Timer0
Return

'----------------------------Funktion Ausschalten---------------------------------

Sub Aus

Portc = &HFF ' alle LEDs aus
Led1 = 1
Led2 = 1
Led3 = 1 ' alle LEDs aus
Led4 = 1 ' alle LEDs aus
Ok = 1
Outp = 1 ' alle LEDs aus
Waitms 200

If Rel_flag = 0 Then
Relais = 1 ' alle LEDs aus
End If

End Sub

'--------------------------Funktion Frequenzberechnung----------------------------
Sub Neue_frequenz
Stop Timer0
Stop Timer1
Waitms 200

Call Aus
S = Inkey()
Print "Frequenz ohne dezimale eingeben, d.h 500 entspricht 50Hz"
Eingabe:
Input " neue Frequenz: " , Fein

If Fein > 500 Then
Print "Fequenz zu Gross!!!"
Goto Eingabe
End If
F = Fein / 10
Check = Frac(f) 'nur Nachkommastelle
If Check = 0.5 Or Check = 0 Then
Print " neue Frequenz: " ; F ; "Hz"
Else
Print "falsche Eingabe! Nur 0,5Hz Schritte moeglich!"
Goto Eingabe
End If

T = 1 / F
T = T - 0.0025
Fcalc = 1 / T
Vorteiler = T * Fosc
Vorteiler = Vorteiler \ Aufl

If Vorteiler <= 1 Then
Pre = 1
Presc = Pre
Call Reloadsub
Reload1 = Round(calc)
End If

If Vorteiler > 1 And Vorteiler <= 8 Then
Pre = 8
Presc = Pre
Call Reloadsub
Reload1 = Round(calc)
End If

If Vorteiler > 8 And Vorteiler <= 64 Then
Pre = 64
Presc = Pre 'Prescaler
Call Reloadsub
Reload1 = Round(calc)
End If

If Vorteiler > 64 And Vorteiler <= 256 Then
Pre = 256
Presc = Pre 'Prescaler
Call Reloadsub
Reload1 = Round(calc)
End If

If Vorteiler > 256 And Vorteiler <= 1024 Then
Pre = 1024
Presc = Pre 'Prescaler
Call Reloadsub
Reload1 = Round(calc)
End If


Start Timer1
End Sub

Sub Reloadsub
'Berechnung von Reload1
Calc = Fosc / Pre
Calc = Calc / Fcalc
Calc = Aufl - Calc
Tccr1b = Tccr1b And &HF8
Tccr1b = Tccr1b Or Presc

End Sub

E-Fan
11.04.2006, 15:55
:-k
Wenn ich es richtig sehe müllst Du durch diese Art der Prescalerumstellung nur das Kontrollregister B des Timer1 zu und schreibst schon beim ersten Umstellem &hFF da rein (weil &h08 AND &hF8 = &hFF). Das kann nicht funktionieren weil Du damit den Timer1des ATmega32 auf externe Synchronisation umstellst.
Anbei mal ein Screenshot der Registerbitbelegung von TCCR1B:
Die Bits sollten daher anders manipuliert werden. ;)

ACsenf
11.04.2006, 17:02
Ah gut zu wissen! Hm man sollte nicht alles glauben was man hier so geraten bekommt. Hatte diese Version halt versucht. Hatte vorher dem Prescaler eine Zahl zugewiesen, wie bei der ersten Initializiereung, das ging aber auch nicht.
Nun die große Frage...wie geht dem???

so habe es mal geändert:


'************************************************* ******************************
'Frequenzgenerator
'Prozessor: Atmel Mega 32
'Programm: Test_Prescaler verändern
'************************************************* ******************************
'$sim
$regfile = "M32DEF.DAT"
$crystal = 16000000
$baud = 9600

'-----------------------------Variablendeklaration--------------------------------
Dim Rel_flag As Bit
Dim S As String * 10

'------------------------Variablen zur Frequenzberechnung-------------------------
Dim F As Single
Dim Fein As Single
Dim Fcalc As Single
Dim Check As Single
Dim Calc As Single
Dim Pre As Integer 'Prescaler
Dim Presc As Byte 'Prescaler Uebergabewert
Dim Vorteiler As Long 'Prescaler berechnet
Dim Reload1 As Word
Dim Count0 As Byte
Dim Count1 As Byte
Const Fosc = 16000000 'Frequenz µC
Const Aufl = 65536 'Timeraufloesung
Dim T As Single 'Periode
Declare Sub Aus
Declare Sub Neue_frequenz
Declare Sub Reloadsub

'-----------------------------Portkonfiguration-----------------------------------

'Der PortC wird als Ausgang programmiert
Config Pinc.0 = Output
Config Pinc.1 = Output
Config Pinc.2 = Output
Config Pinc.3 = Output
Config Pinc.4 = Output
Config Pinc.5 = Output
Config Pinc.6 = Output
Config Pinc.7 = Output
Config Pina.7 = Output
Config Pina.6 = Output
Config Pina.5 = Output
Config Pina.4 = Output

'Der Port B und D wird als Eingang programmiert
Config Pinb.0 = Input
Config Pinb.1 = Input
Config Pinb.2 = Input ' Interrupt 2 für Zuendung Slave IN sync
Config Pinb.3 = Input
Config Pinb.4 = Input
Config Pinb.5 = Input
Config Pinb.6 = Input
Config Pinb.7 = Input
Config Pind.2 = Input ' Interrupt 0 für ON/OFF
Config Pind.3 = Input 'Interrupt 1 Sammelinterrupt Stoerung
Config Pind.4 = Input
Config Pind.5 = Input
Config Pind.6 = Input
Config Pind.7 = Input

'Pullup einschalten nur bei PD3 noetig!
Portd.3 = 1

'Hier geben wir der Definition einen schoeneren Namen
_out Alias Portc.0
Sync Alias Portc.1
_rdy Alias Portc.2
Reserve_out Alias Portc.3
Stoerung_out Alias Portc.4
Outp Alias Portc.5
Led1 Alias Portc.6
Led2 Alias Portc.7
Led3 Alias Porta.7
Led4 Alias Porta.6
Ok Alias Porta.5
Relais Alias Porta.4

'-----------------------------Timerkonfiguration----------------------------------
'Hier wird der Timer und der Teiler festgelegt
Config Timer0 = Timer , Prescale = 64
Config Timer1 = Timer , Prescale = 8

'Hier wird das Unterprogramm festgelegt, das
'in dem eingestellten Intervall aufgerufen wird
On Timer0 Timer0_irq 'Nosave
On Timer1 Timer1_irq 'Nosave

Const Reload0 = 6
Reload1 = 30534

'Hier werden die Timer aktiviert
Enable Timer0
Enable Timer1
Enable Interrupts


Call Aus
Start Timer1

Do
If Ischarwaiting() <> 0 Then Call Neue_frequenz
nop
Loop

Timer0_irq: '1 Pausenteil 1ms
Timer0 = Reload0
Outp = 0 'EIN
Stop Timer0
Waitus 500
Outp = 1 'AUS
Waitus 1000 '2.Pausenteil 1ms
Led1 = 0
Start Timer1

Return


Timer1_irq: 'lange Zeit 17,5ms
Timer1 = Reload1
Led1 = 1
Stop Timer1
Start Timer0
Return

'----------------------------Funktion Ausschalten---------------------------------

Sub Aus

Portc = &HFF ' alle LEDs aus
Led1 = 1
Led2 = 1
Led3 = 1 ' alle LEDs aus
Led4 = 1 ' alle LEDs aus
Ok = 1
Outp = 1 ' alle LEDs aus
Waitms 200

If Rel_flag = 0 Then
Relais = 1 ' alle LEDs aus
End If

End Sub

'--------------------------Funktion Frequenzberechnung----------------------------
Sub Neue_frequenz
Stop Timer0
Stop Timer1
Waitms 200

Call Aus
S = Inkey()
Print "Frequenz ohne dezimale eingeben, d.h 500 entspricht 50Hz"
Eingabe:
Input " neue Frequenz: " , Fein

If Fein > 500 Then
Print "Fequenz zu Gross!!!"
Goto Eingabe
End If
F = Fein / 10
Check = Frac(f) 'nur Nachkommastelle
If Check = 0.5 Or Check = 0 Then
Print " neue Frequenz: " ; F ; "Hz"
Else
Print "falsche Eingabe! Nur 0,5Hz Schritte moeglich!"
Goto Eingabe
End If

T = 1 / F
T = T - 0.0025
Fcalc = 1 / T
Vorteiler = T * Fosc
Vorteiler = Vorteiler \ Aufl

If Vorteiler <= 1 Then
Pre = 1
Presc = &B00000001
Call Reloadsub
Reload1 = Round(calc)
End If

If Vorteiler > 1 And Vorteiler <= 8 Then
Pre = 8
Presc = &B00000010
Call Reloadsub
Reload1 = Round(calc)
End If

If Vorteiler > 8 And Vorteiler <= 64 Then
Pre = 64
Presc = &B00000011 'Prescaler
Call Reloadsub
Reload1 = Round(calc)
End If

If Vorteiler > 64 And Vorteiler <= 256 Then
Pre = 256
Presc = &B00000100 'Prescaler
Call Reloadsub
Reload1 = Round(calc)
End If

If Vorteiler > 256 And Vorteiler <= 1024 Then
Pre = 1024
Presc = &B00000101 'Prescaler
Call Reloadsub
Reload1 = Round(calc)
End If


Start Timer1
End Sub

Sub Reloadsub
'Berechnung von Reload1
Calc = Fosc / Pre
Calc = Calc / Fcalc
Calc = Aufl - Calc
'Tccr1b = Tccr1b And &HF8
Tccr1b = Presc

End Sub

geht aber trotzdem nicht!

Bleibe bei dem hier schonmal erwähnten...daß Bascom da einen Bug hat, lasse mich aber gerne eines Besseren belehren.

Gruß

Sven

hrei
11.04.2006, 18:37
Bleibe bei dem hier schonmal erwähnten...daß Bascom da einen Bug hat, lasse mich aber gerne eines Besseren belehren.


Den Fehler der nichtangenommenen Veränderung des Prescalers gab es tatsächlich mal bei einer Version, ist aber schon länger behoben.

Das dies stimmt, kann man leich anhand dieses völlig fehlerfrei funktionierenden Testprogrammes überprüfen (habe jetzt nicht forenfreundlich gekürzt):



'Frequenzgenerator Atmega 8/168 oder M32 mit Menue - HR - 2006
'################################################# ######

'$regfile = "m8def.dat"
'$regfile = "m168def.dat"
$regfile = "m32def.dat"
$crystal = 7372800
'$crystal = 14745000
'$crystal = 16000000

$baud = 9600

$hwstack = 64
$swstack = 64
$framesize = 64



'$lib "i2c_twi.lbx" 'Hardware I2C!

'Config Lcdpin = Pin , Db4 = Pd.4 , Db5 = Pd.5 , Db6 = Pd.6 , Db7 = Pd.7 , _
'E = Pd.3 , Rs = Pd.2
'
'Config Scl = Portc.5 'für Mega8 und 168
'Config Sda = Portc.4

'Config Scl = Portd.0 'für Mega16 und 32
'Config Sda = Portd.1

'-------------------------------------------------------------------------------
$lib "Lcd_i2c.lib" 'i2c Treiber für das LCD
Dim _lcd_e As Byte 'Nötig für die Enable Auswahl
'Const Pcf8574_lcd = 112 'Adresse des LCD-PCF
'Const Pcf8574_lcd = 64
Waitms 200
_lcd_e = 128 'Für LCDs mit 1 Controller

'Config Scl = Portc.5 'für Mega8 und 168
'Config Sda = Portc.4
Config Scl = Portc.0 'für Mega16 und 32
Config Sda = Portc.1


I2cinit 'I2C Initialisierung
'-------------------------------------------------------------------------------
Config Lcd = 16 * 2
Config Adc = Single , Prescaler = Auto 'Für Analogtastatur


'Config Portd.4 = Output 'Test LED-Port

'Config Pina.0 = Input 'Für analog_key
'Keyboard Alias Pina.0 'Aliasname
'Porta.0 = 1 'Pullup Widerstand ein

'-------------------------------------------------------------------------------
Const Pcf8591 = 144 'DA-AD-Wandler auf Basis
Const Eeprom2 = 166 'Eeprom2 auf Basis
Const Eeprom1 = 174 'Eeprom1 oder Ram auf Basis
Const Eeprom0 = 160 'externes Chip Card Eeprom0
Const Pcf8574_1 = 64 'Portext. auf Basis
Const Tda8444 = 78 'DA-Wandler auf Extension-Platine
Const Pcf8574_lcd = 112 'Portextension für LCD
Const Pcf8583_rtc = 162 'RTC auf Extension-Platine

Const Max520 = 94 'für MAX520 (extern)
Const Keyboard = 0 'ADC-Nr.

Config Timer1 = Timer , Prescale = 8
Stop Timer1
On Timer1 Timer_irq Nosave

Enable Timer1
Enable Interrupts 'Interrupts erlauben



Config Adc = Single , Prescaler = Auto
Config Pinb.1 = Output



Config Pinb.4 = Input 'Für Frequenzzählung
Portb.4 = 1 'Pullup Widerstand ein
Flow_in Alias Pinb.4

Config Pinc.2 = Output 'Ausgang für beeper
Beep Alias Portc.2

Config Pinb.0 = Output 'Ausgang für Frequenz

Declare Sub Beep_alarm()
Declare Sub Beep_confirm()
Declare Sub Analog_key_wait() 'Resultat in Taste

Declare Function Analog_key() As Byte
Declare Function Adjust_value_
(byval Up_down As Word , Byval Schritt As Byte)as Word

Declare Function Timer_test() As Word

Dim Timervorgabe As Word
'Timervorgabe = 19456 'für 20Hz bzw 10 Hz an PB0
'Timervorgabe = 34816 'für 30Hz bzw 15 Hz an PB0
Timervorgabe = 56320 'für 100Hz bzw 50 Hz an PB0

Dim Value As Word At &H100
Dim Value_low As Byte At &H100 Overlay
Dim Value_high As Byte At &H101 Overlay
Dim Address As Word At &H102
Dim Address_low As Byte At &H102 Overlay
Dim Address_high As Byte At &H103 Overlay


Dim I As Integer
Dim N As Integer
Dim Hertz_word As Word
Dim Count As Byte
Dim Temp As Word
Dim Schritt As Byte

Dim Command As Byte
Dim Taste As Byte
Dim Counter_ds As Word


Dim Menue_current As Byte
Dim Wert As Byte

'-------------------------------------------------------------------------------

Call Beep_alarm() 'Bin wach -)
Cls
Cursor Off
Lcd " FREQUENZGEN."
'Locate 2 , 1
'Lcd " MEGA8 - Control"
Wait 3
Start Timer1
'------------------------------------------------------------------------------
Beep_confirm
Cls
Menue:
Menue_current = 1

Menue_1:

Taste = Analog_key()
Waitms 100

If Taste = 32 Then
Menue_current = Menue_current + 1
End If

If Taste = 33 Then
Menue_current = Menue_current - 1
End If

If Menue_current > 8 Then Menue_current = 1
If Menue_current < 1 Then Menue_current = 8

If Taste = 10 Then Goto Execute
'-------------------------------------------------------------------------------
Select Case Menue_current 'aktuelle Auswahl anzeigen

Case 1
Locate 1 , 1
Lcd " 10 Hz "
Case 2
Locate 1 , 1
Lcd " 50 Hz "
Case 3
Locate 1 , 1
Lcd " 100 Hz "
Case 4
Locate 1 , 1
Lcd " 1 kHz "
Case 5
Locate 1 , 1
Lcd " 10 kHz "
Case 6
Locate 1 , 1
Lcd " 20 kHz "
Case 7
Locate 1 , 1
Lcd " 50 kHz "
Case 8
Locate 1 , 1
Lcd " FREE "



End Select
Taste = 255
Goto Menue_1

'-------------------------------------------------------------------------------
Execute: 'aktuellen Menuepunkt ausführen
Cls

Select Case Menue_current
Case 1
Cls
Disable Timer1
Config Timer1 = Timer , Prescale = 8
Timervorgabe = 19456 'für 20 bzw. 10 Hz
Enable Timer1

Case 2
Cls
Disable Timer1
Config Timer1 = Timer , Prescale = 8
Timervorgabe = 56320 'für 100 bzw. 50 Hz
Enable Timer1
Cls
Case 3
Cls
Disable Timer1
Config Timer1 = Timer , Prescale = 1
Timervorgabe = 28672 'für 200 bzw. 100 Hz
Enable Timer1
Cls
Case 4
Cls
Disable Timer1
Config Timer1 = Timer , Prescale = 1
Timervorgabe = 61850 + 32 'für 2000 bzw. 1000 Hz
Enable Timer1
Cls
Case 5
Cls
Disable Timer1
Config Timer1 = Timer , Prescale = 1
Timervorgabe = 65167 + 32 'für 20000 bzw. 10000 Hz
Enable Timer1
Cls
Case 6
Cls
Disable Timer1
Config Timer1 = Timer , Prescale = 1
Timervorgabe = 65352 + 32 'für 40000 bzw. 20000 Hz
Enable Timer1
Cls
Case 7
Cls
Disable Timer1
Config Timer1 = Timer , Prescale = 1
Timervorgabe = 65462 + 32 'für 100kHz bzw. 50kHz bei Toggle
Enable Timer1
Cls
Case 8
Cls 'zur Ermittlung der maximal
Locate 2 , 2 'erziebaren Frequenz
Lcd " free running"
Disable Timer1
Do
Set Portb.0
nop
nop
Reset Portb.0
nop
nop
Loop
Enable Timer1



End Select

Goto Menue_1
'-------------------------------------------------------------------------------

End 'Hauptprogramm Ende

'-------------------------------------------------------------------------------


'-------------------------------------------------------------------------------


Sub Beep_alarm()
Sound Beep , 200 , 450
Sound Beep , 200 , 250
End Sub
'-------------------------------------------------------------------------------

Sub Beep_confirm()
Sound Beep , 200 , 450
End Sub
'-------------------------------------------------------------------------------

Sub Analog_key_wait()
Wait_ana_key:
Taste = Analog_key()
If Taste = 255 Then Goto Wait_ana_key
End Sub

'------------------------------------------------------------------------------
'Diese Unterfunktion fragt die Tastatur am analogen Port ab
Function Analog_key() As Byte
Local Ws As Word
Analog_key = 255
Start Adc
Ws = Getadc(keyboard)
If Ws < 900 Then
Select Case Ws
Case 0 To 100
Analog_key = 32
Case 400 To 600
Analog_key = 33
Case 650 To 850
Analog_key = 10
End Select
Call Beep_confirm()
End If
Waitms 100
End Function
'-------------------------------------------------------------------------------

Function Adjust_value(byval Up_down As Word , Byval Schritt As Byte)

Cls

Adj1:
Locate 2 , 1
Lcd Up_down ; " "
Taste = Analog_key()
If Taste = 32 Then Up_down = Up_down + Schritt
If Taste = 33 Then Up_down = Up_down - Schritt
If Taste = 10 Then
Adjust_value = Up_down
Exit Sub
End If

Goto Adj1

End Function
'-------------------------------------------------------------------------------
Timer_irq:

$asm
push R24
push R25
push R26
push R27
push XH
push XL
in R24, SREG
push R24
$end Asm
Timer1 = Timervorgabe
Toggle Portb.0
$asm
pop R24
Out Sreg , R24
pop XL
pop XH
pop R27
pop R26
pop R25
pop R24
$end Asm


Return
'-------------------------------------------------------------------------------


Das Beispiel ist mit Absicht "Klein Fritzchen mäßig" strukturiert.

Grüße
Henrik

ACsenf
11.04.2006, 19:35
Hallo!

Hier nochmal mein Code zu deinem Beispiel, so hatte ich es übrigens auch schonmal und funktioniert bei meinem 8515 wunderbar!
Habe es eben extra nochmal durch den Simulator gejagt. Da kann man schön sehen, daß die Berechnungen richtig sind und sogar das Register korrekt gesetzt wird. Aber in Realität passiert eben genau das nicht!

Anbei nochmal mein Code


'************************************************* ******************************
'Frequenzgenerator
'Prozessor: Atmel Mega 32
'Programm: Test_Prescaler verändern
'************************************************* ******************************
'$sim
$regfile = "M32DEF.DAT"
$crystal = 16000000
$baud = 9600

'-----------------------------Variablendeklaration--------------------------------
Dim Rel_flag As Bit
Dim S As String * 10

'------------------------Variablen zur Frequenzberechnung-------------------------
Dim F As Single
Dim Fein As Single
Dim Fcalc As Single
Dim Check As Single
Dim Calc As Single
Dim Pre As Integer 'Prescaler
Dim Presc As Byte 'Prescaler Uebergabewert
Dim Vorteiler As Long 'Prescaler berechnet
Dim Reload1 As Word
Dim Count0 As Byte
Dim Count1 As Byte
Const Fosc = 16000000 'Frequenz µC
Const Aufl = 65536 'Timeraufloesung
Dim T As Single 'Periode
Declare Sub Aus
Declare Sub Neue_frequenz
Declare Sub Reloadsub

'-----------------------------Portkonfiguration-----------------------------------

'Der PortC wird als Ausgang programmiert
Config Pinc.0 = Output
Config Pinc.1 = Output
Config Pinc.2 = Output
Config Pinc.3 = Output
Config Pinc.4 = Output
Config Pinc.5 = Output
Config Pinc.6 = Output
Config Pinc.7 = Output
Config Pina.7 = Output
Config Pina.6 = Output
Config Pina.5 = Output
Config Pina.4 = Output

'Der Port B und D wird als Eingang programmiert
Config Pinb.0 = Input
Config Pinb.1 = Input
Config Pinb.2 = Input ' Interrupt 2 für Zuendung Slave IN sync
Config Pinb.3 = Input
Config Pinb.4 = Input
Config Pinb.5 = Input
Config Pinb.6 = Input
Config Pinb.7 = Input
Config Pind.2 = Input ' Interrupt 0 für ON/OFF
Config Pind.3 = Input 'Interrupt 1 Sammelinterrupt Stoerung
Config Pind.4 = Input
Config Pind.5 = Input
Config Pind.6 = Input
Config Pind.7 = Input

'Pullup einschalten nur bei PD3 noetig!
Portd.3 = 1

'Hier geben wir der Definition einen schoeneren Namen
_out Alias Portc.0
Sync Alias Portc.1
_rdy Alias Portc.2
Reserve_out Alias Portc.3
Stoerung_out Alias Portc.4
Outp Alias Portc.5
Led1 Alias Portc.6
Led2 Alias Portc.7
Led3 Alias Porta.7
Led4 Alias Porta.6
Ok Alias Porta.5
Relais Alias Porta.4

'-----------------------------Timerkonfiguration----------------------------------
'Hier wird der Timer und der Teiler festgelegt
Config Timer0 = Timer , Prescale = 64
Config Timer1 = Timer , Prescale = 8

'Hier wird das Unterprogramm festgelegt, das
'in dem eingestellten Intervall aufgerufen wird
On Timer0 Timer0_irq 'Nosave
On Timer1 Timer1_irq 'Nosave

Const Reload0 = 6
Reload1 = 30534

'Hier werden die Timer aktiviert
Enable Timer0
Enable Timer1
Enable Interrupts


Call Aus
Start Timer1

Do
If Ischarwaiting() <> 0 Then Call Neue_frequenz
nop
Loop

Timer0_irq: '1 Pausenteil 1ms
Timer0 = Reload0
Outp = 0 'EIN
Stop Timer0
Waitus 500
Outp = 1 'AUS
Waitus 1000 '2.Pausenteil 1ms
Led1 = 0
Start Timer1

Return


Timer1_irq: 'lange Zeit 17,5ms
Timer1 = Reload1
Led1 = 1
Stop Timer1
Start Timer0
Return

'----------------------------Funktion Ausschalten---------------------------------

Sub Aus

Portc = &HFF ' alle LEDs aus
Led1 = 1
Led2 = 1
Led3 = 1 ' alle LEDs aus
Led4 = 1 ' alle LEDs aus
Ok = 1
Outp = 1 ' alle LEDs aus
Waitms 200

If Rel_flag = 0 Then
Relais = 1 ' alle LEDs aus
End If

End Sub

'--------------------------Funktion Frequenzberechnung----------------------------
Sub Neue_frequenz
Stop Timer0
Stop Timer1
Waitms 200

Call Aus
S = Inkey()
Print "Frequenz ohne dezimale eingeben, d.h 500 entspricht 50Hz"
Eingabe:
Input " neue Frequenz: " , Fein

If Fein > 500 Then
Print "Fequenz zu Gross!!!"
Goto Eingabe
End If
F = Fein / 10
Check = Frac(f) 'nur Nachkommastelle
If Check = 0.5 Or Check = 0 Then
Print " neue Frequenz: " ; F ; "Hz"
Else
Print "falsche Eingabe! Nur 0,5Hz Schritte moeglich!"
Goto Eingabe
End If

T = 1 / F
T = T - 0.0025
Fcalc = 1 / T
Vorteiler = T * Fosc
Vorteiler = Vorteiler \ Aufl

If Vorteiler <= 1 Then
Pre = 1
Call Reloadsub
Disable Timer1
Config Timer1 = Timer , Prescale = 1
Reload1 = Round(calc)
Enable Timer1
End If

If Vorteiler > 1 And Vorteiler <= 8 Then
Pre = 8
Call Reloadsub
Disable Timer1
Config Timer1 = Timer , Prescale = 8
Reload1 = Round(calc)
Enable Timer1
End If

If Vorteiler > 8 And Vorteiler <= 64 Then
Pre = 64
Call Reloadsub
Disable Timer1
Config Timer1 = Timer , Prescale = 64
Reload1 = Round(calc)
Enable Timer1
End If

If Vorteiler > 64 And Vorteiler <= 256 Then
Pre = 256
Call Reloadsub
Disable Timer1
Config Timer1 = Timer , Prescale = 256
Reload1 = Round(calc)
Enable Timer1
End If

If Vorteiler > 256 And Vorteiler <= 1024 Then
Pre = 1024
Call Reloadsub
Disable Timer1
Config Timer1 = Timer , Prescale = 1024
Reload1 = Round(calc)
Enable Timer1
End If


'Start Timer1
End Sub

Sub Reloadsub
'Berechnung von Reload1
Calc = Fosc / Pre
Calc = Calc / Fcalc
Calc = Aufl - Calc

End Sub

Mich würde es brennend interessieren, warum das nicht klappt??? Vielleicht packt mal jemand das programm auf seinen Chip.

Gruß

Sven

ACsenf
11.04.2006, 20:26
So hatte eben mein o.g. Proggi mal für mein At90S8515 Board geändert mit dem selben Ergebnis wie auf dem Mega32 :shock:

habe dann nochmal ein altes Progg ausgegraben, das auch den Prescaler wert umschaltet und das funzt einwandfrei...


'16-bit Timer als Rechteckgenerator
'mit Voreinstellung
'Achtung: bei kleinen Zeiten ist die Zeit zur Rettung der Register nicht zu vernachlässigen
'Nosave bringt, wenn möglich eine starke Verbesserung
'$sim
$regfile = "8515DEF.DAT"
$crystal = 4000000

'Hier werden die Variablen deklariert
Dim Zaehler As Byte , Timervorgabe1 As Word , A As Byte

'Hier werden die Variablen definiert

Readeeprom A , 1 'read byte back
If A = 255 Then
A = 10
End If
Zaehler = 0


'Hier wird der Timer und der Teiler festgelegt
Config Timer0 = Timer , Prescale = 1024
Config Timer1 = Timer , Prescale = 8

'Der Portc wird als Ausgang programmiert
Config Pinc.0 = Output
Config Pinc.2 = Output
Config Pinc.3 = Output
Config Pinc.4 = Output
Config Pinc.5 = Output
Config Pinc.7 = Output
Config Pind.7 = Input 'Taster_up
Config Pind.6 = Input 'Taster_down
Config Pind.4 = Input 'Taster_store

Config Debounce = 40 'Tastenentprellung 25ms
'Interne Pullup Widerstände einschalten
Portd.7 = 1
Portd.6 = 1
Portd.4 = 1

'Hier geben wir der Definition einen schöneren Namen
Led0 Alias Portc.0
Led2 Alias Portc.2
Led3 Alias Portc.3
Led4 Alias Portc.4
Led5 Alias Portc.5
Led7 Alias Portc.7


'Hier wird das Unterprogramm festgelegt, das
'in dem eingestellten Intervall aufgerufen wird
On Timer0 Timer0_irq
On Timer1 Timer1_irq

'Diese Vorgabe wurde berechnet um die genaue Intervallfrequenz zu erreichen
Const Timervorgabe0 = 61
Timervorgabe1 = 45536

'Hier werden die Timer aktiviert
Enable Timer1
Enable Timer0
Enable Interrupts

'Hier ist die Programmhauptschleife
Do
'Hauptprogramm
Gosub Taster_up
Gosub Taster_down
Gosub Taster_store

If A = 0 Then
A = 1
Elseif A = 1 Then
Config Timer1 = Timer , Prescale = 256 'Ausgabe 0,5Hz
Timervorgabe1 = 49911
Elseif A = 2 Then
Config Timer1 = Timer , Prescale = 256 'Ausgabe 1Hz
Timervorgabe1 = 57724
Elseif A = 3 Then
Config Timer1 = Timer , Prescale = 256 'Ausgabe 1,5Hz
Timervorgabe1 = 60328
Elseif A = 4 Then
Config Timer1 = Timer , Prescale = 64 'Ausgabe 2Hz
Timervorgabe1 = 49911
Elseif A = 5 Then
Config Timer1 = Timer , Prescale = 64 'Ausgabe 2,5Hz
Timervorgabe1 = 53036
Elseif A = 6 Then
Config Timer1 = Timer , Prescale = 64 'Ausgabe 3Hz
Timervorgabe1 = 55119
Elseif A = 7 Then
Config Timer1 = Timer , Prescale = 64 'Ausgabe 3,5Hz
Timervorgabe1 = 56607
Elseif A = 8 Then
Config Timer1 = Timer , Prescale = 64 'Ausgabe 4Hz
Timervorgabe1 = 57724
Elseif A = 9 Then
Config Timer1 = Timer , Prescale = 64 'Ausgabe 4,5Hz
Timervorgabe1 = 58592
Elseif A = 10 Then
Config Timer1 = Timer , Prescale = 64 'Ausgabe 5Hz
Timervorgabe1 = 59286
Elseif A = 11 Then
Config Timer1 = Timer , Prescale = 64 'Ausgabe 5,5Hz
Timervorgabe1 = 59854
Elseif A = 12 Then
Config Timer1 = Timer , Prescale = 64 'Ausgabe 6Hz
Timervorgabe1 = 60327
Elseif A = 13 Then
Config Timer1 = Timer , Prescale = 64 'Ausgabe 6,5Hz
Timervorgabe1 = 60728
Elseif A = 14 Then
Config Timer1 = Timer , Prescale = 64 'Ausgabe 7Hz
Timervorgabe1 = 61072
Elseif A = 15 Then
Config Timer1 = Timer , Prescale = 64 'Ausgabe 7,5Hz
Timervorgabe1 = 61369
Elseif A = 16 Then
Config Timer1 = Timer , Prescale = 64 'Ausgabe 8Hz
Timervorgabe1 = 61630
Elseif A = 17 Then
Config Timer1 = Timer , Prescale = 64 'Ausgabe 8,5Hz
Timervorgabe1 = 61859
Elseif A = 18 Then
Config Timer1 = Timer , Prescale = 64 'Ausgabe 9Hz
Timervorgabe1 = 62064
Elseif A = 19 Then
Config Timer1 = Timer , Prescale = 64 'Ausgabe 9,5Hz
Timervorgabe1 = 62247
Elseif A = 20 Then
Config Timer1 = Timer , Prescale = 64 'Ausgabe 10Hz
Timervorgabe1 = 62411
Elseif A = 21 Then
Config Timer1 = Timer , Prescale = 64 'Ausgabe 10,5Hz
Timervorgabe1 = 62559
Elseif A = 22 Then
Config Timer1 = Timer , Prescale = 64 'Ausgabe 11Hz
Timervorgabe1 = 62695
Elseif A = 23 Then
Config Timer1 = Timer , Prescale = 64 'Ausgabe 11,5Hz
Timervorgabe1 = 62818
Elseif A = 24 Then
Config Timer1 = Timer , Prescale = 64 'Ausgabe 12Hz
Timervorgabe1 = 62932
Elseif A = 25 Then
Config Timer1 = Timer , Prescale = 64 'Ausgabe 12,5Hz
Timervorgabe1 = 63036
Elseif A = 26 Then
Config Timer1 = Timer , Prescale = 64 'Ausgabe 13Hz
Timervorgabe1 = 63132
Elseif A = 27 Then
Config Timer1 = Timer , Prescale = 64 'Ausgabe 13,5Hz
Timervorgabe1 = 63221
Elseif A = 28 Then
Config Timer1 = Timer , Prescale = 64 'Ausgabe 14Hz
Timervorgabe1 = 63304
Elseif A = 29 Then
Config Timer1 = Timer , Prescale = 64 'Ausgabe 14,5Hz
Timervorgabe1 = 63381
Elseif A = 30 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 15Hz
Timervorgabe1 = 48869
Elseif A = 31 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 15,5Hz
Timervorgabe1 = 49407
Elseif A = 32 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 16Hz
Timervorgabe1 = 49911
Elseif A = 33 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 16,5Hz
Timervorgabe1 = 50384
Elseif A = 34 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 17Hz
Timervorgabe1 = 50830
Elseif A = 35 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 17,5Hz
Timervorgabe1 = 51250
Elseif A = 36 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 18Hz
Timervorgabe1 = 51647
Elseif A = 37 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 18,5Hz
Timervorgabe1 = 52023
Elseif A = 38 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 19Hz
Timervorgabe1 = 52378
Elseif A = 39 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 19,5Hz
Timervorgabe1 = 52716
Elseif A = 40 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 20Hz
Timervorgabe1 = 53036
Elseif A = 41 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 20,5Hz
Timervorgabe1 = 53341
Elseif A = 42 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 21Hz
Timervorgabe1 = 53631
Elseif A = 43 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 21,5Hz
Timervorgabe1 = 53908
Elseif A = 44 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 22Hz
Timervorgabe1 = 54172
Elseif A = 45 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 22,5Hz
Timervorgabe1 = 54425
Elseif A = 46 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 23Hz
Timervorgabe1 = 54666
Elseif A = 47 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 23,5Hz
Timervorgabe1 = 54897
Elseif A = 48 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 24Hz
Timervorgabe1 = 55119
Elseif A = 49 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 24,5Hz
Timervorgabe1 = 55332
Elseif A = 50 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 25Hz
Timervorgabe1 = 55536
Elseif A = 51 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 25,5Hz
Timervorgabe1 = 55732
Elseif A = 52 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 26Hz
Timervorgabe1 = 55920
Elseif A = 53 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 26,5Hz
Timervorgabe1 = 56102
Elseif A = 54 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 27Hz
Timervorgabe1 = 56277
Elseif A = 55 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 27,5Hz
Timervorgabe1 = 56445
Elseif A = 56 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 28Hz
Timervorgabe1 = 56607
Elseif A = 57 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 28,5Hz
Timervorgabe1 = 56764
Elseif A = 58 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 29Hz
Timervorgabe1 = 56915
Elseif A = 59 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 29,5Hz
Timervorgabe1 = 57061
Elseif A = 60 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 30Hz
Timervorgabe1 = 57203
Elseif A = 61 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 30,5Hz
Timervorgabe1 = 57339
Elseif A = 62 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 31Hz
Timervorgabe1 = 57471
Elseif A = 63 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 31,5hz
Timervorgabe1 = 57599
Elseif A = 64 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 32Hz
Timervorgabe1 = 57723
Elseif A = 65 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 32,5Hz
Timervorgabe1 = 57844
Elseif A = 66 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 33Hz
Timervorgabe1 = 57960
Elseif A = 67 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 33,5Hz
Timervorgabe1 = 58073
Elseif A = 68 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 34Hz
Timervorgabe1 = 58183
Elseif A = 69 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 34,5Hz
Timervorgabe1 = 58289
Elseif A = 70 Then
Config Timer1 = Timer , Prescale = 8 'Ausgabe 34,5Hz
Timervorgabe1 = 58393

End If

Loop

Taster_store:
'Debounce Pina.0 , 1 , Pr 'try this for branching when high(1)
Debounce Pind.4 , 1 , Aus_store , Sub 'Taster offen
Debounce Pind.4 , 0 , Ein_store , Sub 'Taster gedrückt

Return

Taster_up:
'Debounce Pina.0 , 1 , Pr 'try this for branching when high(1)
Debounce Pind.7 , 1 , Aus_up , Sub 'Taster offen
Debounce Pind.7 , 0 , Ein_up , Sub 'Taster gedrückt

Return

Taster_down:
'Debounce Pina.0 , 1 , Pr 'try this for branching when high(1)
Debounce Pind.6 , 1 , Aus_down , Sub 'Taster offen
Debounce Pind.6 , 0 , Ein_down , Sub 'Taster gedrückt

Return

Ein_store:
Led7 = 0
Writeeeprom A , 1 'store at first position

Return

Aus_store:
Led7 = 1
Return

'Unterprogramm Rückstellen mit Taste Down
Ein_down:
If A > 0 Then
Decr A
Else
A = 255
End If

Return

'Unterprogramm Ausgaberoutine Taste Down
Aus_down:

Return

'Unterprogramm Rückwärtszählen mit Taste Up
Ein_up:
If A <= 255 Then
Incr A
Else
A = 0
End If

Return

'Unterprogramm Ausgaberoutine Taste Up
Aus_up:

Return

'Dies ist der Programmteil, der in dem gewählten
'Intervall aufgerufen wird
Timer0_irq:
Timer0 = Timervorgabe0

'Beliebige IRQ-Routine
'Dabei sollte man darauf achten das diese nicht mehr Zeit
'benötigt, als das Intervall zuläßt
If Zaehler < 100 Then
Toggle Led4
Incr Zaehler
Elseif Zaehler > 100 And Zaehler < 255 Then
Led4 = 1
Incr Zaehler
Elseif Zaehler < 255 Then
Incr Zaehler
Else
Toggle Led3
Zaehler = 0
End If

'Der Zustand der LED wir umgekehrt, wodurch sich blinken in der halben Frequenz ergibt
'Hohe Frequenzen sind natürlich nicht mehr sichtbar
Toggle Led2

Return

Timer1_irq:
Timer1 = Timervorgabe1

'Hier könnte nun ihre beliebige IRQ-Routine stehen
'Dabei sollte man darauf achten das diese nicht mehr Zeit
'benötigt, als das Intervall zuläßt

'Der Zustand der LED wir umgekehrt, wodurch sich blinken in der halben Frequenz ergibt
'Hohe Frequenzen sind natürlich nicht mehr sichtbar
Toggle Led0

Return

Jetzt kapier ich gar nix mehr...da muss irgendwo nen Fehler hängen...sehs abba net

hrei
11.04.2006, 20:37
Mich würde es brennend interessieren, warum das nicht klappt??? Vielleicht packt mal jemand das programm auf seinen Chip.


Packe mal die beiden ISRs ganz an das Ende des Codes. Soweit ich mich dunkel erinnern kann, gab es bei ISRs "mittendrin" bei mir schon mal Schwierigkeiten. Irgendwo steht diese Empfehlung auch in den Tiefen der Bascom Dokumentationen. Ist aber ein Schuss ins Blaue.

Apropos Ende: Ein END am Ende Der Programmhauptschleife kann auch nicht schaden.

Ich kann Dir nur versichern, daß mein gepostetes Beispiel und auch einige andere in denen ich Prescale umkonfiguriere sowohl auf M8, M168, M32 und M128 ohne Schwierigkeiten korrekt laufen. An einem Fehler im Compiler liegt es also mit Sicherheit nicht.

Deinen Code kann ich bei mir im Augenblick nicht ausprobieren, ist alles belegt.

Grüße
Henrik

ACsenf
11.04.2006, 21:33
Hi Henrik!

Habs korrigiert. Funktioniert trotzdem nicht. D.h. die Version mit schreiben inTCCR1B übernimmts nicht. Und nach deinem Beispiel kommen nun nur noch mHz raus...ich glaube ich gebs auf...

hrei
11.04.2006, 22:09
Hi Henrik!

Habs korrigiert. Funktioniert trotzdem nicht. D.h. die Version mit schreiben inTCCR1B übernimmts nicht. Und nach deinem Beispiel kommen nun nur noch mHz raus...ich glaube ich gebs auf...

Also wie Du siehst, geht es ja bei richtiger Programmierung. Mir fallen in Deinem Code (auch wenn er ohne meckern compiliert wird) reichlich syntaktische Fehler auf. Subs ohne leere Klammern, wenn keine Parameter übergeben werden, gehöhren mit dazu. Auch lädt der Code mit seiner leicht spaghettiförmigen Struktur nicht eben zur Untersuchung ein :-).

Sind denn Deine Stacks ausreichend bemessen? Setze alle drei mal gleich auf 128. Du gehst nicht gerade schonend mit den Ressourcen um.

Fang doch mal klein an, meide zunächst Single, beschränke Dich auf das Wesentliche. Dann schrittweise erweitern und immer wieder im realen System, nicht im Simulator zwischenprüfen.

Sonst wird das nix. Und schimpfe nicht auf Bascom, das findet nicht jeden Fehler, den der Programmierer macht. Andere Hochsprachen auch nicht.

Grüße
Henrik

Hanni
11.04.2006, 23:24
Hmm ... ich hab eigentlich was gegen Basecom und werde daher hier sicherlich nicht die Lösung in nem Basiclisting liefern. Allerdings hab ich mal nen paar Denkansätze zu diesem Problem.

generell benötigt man nur einen Timer für dieses Problem.
nehmen könnte man z.B. den Timer 1 des Mega 32 (so einer sollte doch genommen werden oder)
diesen Timer betreibt man in dem Fall wohl am bestem im Mode 4 - CTC -> Datenblatt (http://atmel.com/dyn/resources/prod_documents/doc2503.pdf) Seite 107
Die Frequenz wird in dem Fall über das Register OCR1A geändert ... höherer Wert -> kleinere Frequenz
Eine Bereichswahl wäre z.B. über den Prescaler möglich ... höherer Wert -> kleinerer Frequenzbereich
Das Tastverhältniss würde ich in einem Register (einer Variable) speichern .. für deinen Fall dürfte 128 der richtige Wert sein.
die 3 Offsetwerte für die Phasenverschiebung in 3 weitere Register ( Variablen)
des weiteren ist noch eine Variable als PWM Zähler notwendig ... (Wertebereich: 8 Bit)
in der ISR des Timers wir die PWM inklusive der Offsets verarbeitet
in der Hauptschleife werden die Frequenz, der Frequenzbereich, das Tastverhältniss sowie die Offsetwerte angepasst.
ansonsten kann ich nur empfehlen mal nen Blick in den Angehängten PAP für die ISR zu werfen.

Grüße, da Hanni.

ACsenf
18.04.2006, 10:33
Hallo Hanni!

Bin gerade an der Soft-PWM dran.

Danke erstmal für deine Ideen! Klar braucht man nur einen Timer!
Wie ich den Timer konfiguriere, denke ich weiß ich. Allerdings hängt der PWM-Zähler in unmittelbarem Zusammenhang mit der gewünschten PWM-Frequenz. Wenn man eine Soft PWM macht gibt man nicht mit dem Timer eine Frequenz vor und macht dann nen Zähler dazu...
Man wählt eine Timerauflösung und inkrementiert einen PWM- Zähler, durch die Timerauflösung und die gewünschte Frequenz ergibt sich die mögliche Schrittweite, oder liege ich da falsch?
In deinem Struktogramm ist grundlegender Denkfehler, wenn man den Offset jedesmal dazuaddiert, erhältst du 4 verschiedene Frequenzen, ausserdem muss der PWM Zähler weiterzählen können als nötig, wodurch es auch noch Probleme gibt. Aber die Idee an sich hat mir den entscheidenden Tipp gegeben :)
Der Offset muss dazu verwendet werden um die 3 anderen PWM-Zähler mit einem Delay zu starten.
Wenns klappt hau ich heut abend mal den Code hier rein.

Gruß

Sven

Hanni
18.04.2006, 14:55
In deinem Struktogramm ist grundlegender Denkfehler, wenn man den Offset jedesmal dazuaddiert, erhältst du 4 verschiedene Frequenzen

nicht 4 Frequenzen sondern 4 verschiedenene Puls Pausenverhälnisse ... ist mir auch grad beim durchguggn noch mal klar geworden ...

Aber ich freue mich, das es dir zumindest den Denkanstoß gegeben hat, der dir fehlte :D


Allerdings hängt der PWM-Zähler in unmittelbarem Zusammenhang mit der gewünschten PWM-Frequenz

Ja und nein ... der PWM Zähler beeinflusst nur die Auflösung der PWM, also in wievielen Schritten du die einstellen kannst und hat damit sicherlich (allerdings nur indirekt) einen Einfluss auf die Frequenz.