OVF1 und PCMSK Problem (BASCOM)

Cassio

Aktives Mitglied
29. Okt. 2008
4.027
17
38
Region Hannover
Sprachen
  1. BascomAVR
Hallo zusammen!

Ich habe da ein kleines Problem und möchte eigentlich nur wissen, ob ich einen Fehler gemacht habe.... oder es generell nicht funktioniert.

Folgendes...
Als Hardware dient ein ATTiny45v.
Ich nutze den Timer1, um jede Sekunde einen Overflow zu produzieren und in eine Subroutine zu springen.
In der Sub wird eigentlich nur der Pwm0a mit der Variable versorgt und der Timer1 wieder neu gestartet.

Code:
Tccr1 = &B00000000                                          'Timer1 Stopp

Pwm0a = Stellwert

Tcnt1 = 11
Tccr1 = &B00001101                                          'Prescale 4096

Return

Das funktioniert auch bestens!


Gleichzeitig habe ich im Rumpf die PCMSK für die Pins 3 und 4 aktiviert.
Sobald einer der Pins auf Low geht, springt das Programm in die zugehörige Sub.
Auch DAS funktioniert ohne Probleme. (LEDs signalisieren mir den Zustand)


Wenn ich nun aber die Variable "Stellwert" innerhalb meiner SUB vom PCMSK verändere..... die ja meinen Pwm0a steuert (siehe Code oben)... dann reagiert der PWM-Ausgang leider nicht. :mad:

Wo liegt nun das Problem?
Wird kein OVF produziert solange ich mich in der Sub befinde, die mittels PCMSK aufgerufen wurde?
Wird der Timer1 durch PCMSK gestoppt?
Kann die Variable "Stellwert" in der SUB vom OVF nicht jede Sekunde aktualisiert werden, weil sie in der SUB vom PCMSK geändert wird?
Muss ich die Variable irgendwie "globalisieren".... oder hat es etwas mit dem Deklarieren von Subroutinen zu tun (dessen Funktion ich bis jetzt noch nicht gebraucht habe..... und auch nicht richtig verstanden habe :stupido2: )?

Vielleicht weiß ja einer der BASCOM-Spezialisten einen Rat. :adore:


Danke schon mal und schöne Grüße,
Cassio
 
source code please

Casio,

sei doch bitte so lieb und stell uns mal den gesamten Code zur Verfügung. Ich würd emir das Thema gerne Ganzheitlich ansehen und dazu bräuchte ich ALLEs um es zu verstehen. Danke!

Grüße,
Ma
 
Hallo Markus!

Natürlich stelle ich den ganzen Code hier gerne mal ein.
Es war bis jetzt aber nur ein Versuch bzw. Experiment..... und daher noch lange nicht fertig. ;)

Vielleicht dient es aber ja der Problemlösung.

Mir geht es auch nur um das Verständnis.... sicher könnte ich das Problem auch umgehen und anders realisieren. Letztlich hilft mir das dann aber nicht wirklich weiter.

Nun erst mal der Code, vom Testprogramm:

Code:
$regfile = "attiny45.dat"
$crystal = 1000000

$hwstack = 32                                               ' default use 32 for the hardware stack
$swstack = 8                                                ' default use 10 for the SW stack
$framesize = 25


Ddrb = &B00_111                                             '1 ist Ausgang 0 ist Eingang
Portb = &B11_001                                            'auf Hi oder Low setzen


' ---------------------------------------------
' PCINT = Pin Change Interrupt aktivieren
' Pin Change Mask 0 (PCINT0-7) benutzen
Enable Pcint0
' Bei einem Interrupt, springe zur ISR Aktiv
On Pcint0 Aktiv
' Überwache PCINT 3, 4
Pcmsk = &B11_000
' ---------------------------------------------

Config Timer0 = Pwm , Compare A Pwm = Clear Up , Prescale = 1

' ================================================
' Konfiguriere Timer1
Tcnt1 = 11
Tccr1 = &B00001101                                          'Prescale 4096
' 256 x (4096 / 1000000)=  1,05s
' Timer1 Auflösung: 0,0041s
' 1s = 244bit

On Timer1 Ausgabe
Enable Timer1
' ================================================
Enable Interrupts
' ================================================

Dim Z1 As Word , Stellwert As Byte , Stellwert_sp As Byte

' ================================================

Z1 = 0
Stellwert = 0
Pwm0a = Stellwert

' ================================================

Do
Portb.1 = 1
For Stellwert = 1 To 254
Wait 7
Next
Portb.1 = 0

Wait 3

Portb.2 = 1
For Stellwert = 254 To 1 Step -1
Wait 7
Next
Portb.2 = 0

Wait 3

Loop


' ================================================
Aktiv:

If Pinb.3 = 0 Then
Waitms 25
Bitwait Pinb.3 , Set

   If Stellwert < 250 Then
   Stellwert_sp = Stellwert
   Portb.1 = 1
   Portb.2 = 0
   Stellwert = 255
   Do
   Waitms 25
   Toggle Portb.1
   Toggle Portb.2
   Loop Until Pinb.3 = 0
   Bitwait Pinb.3 , Set
   Stellwert = Stellwert_sp
   Portb.1 = 0
   Portb.2 = 0
   Else
   End If
Else
End If


If Pinb.4 = 0 Then
Waitms 25
Bitwait Pinb.4 , Set

   If Stellwert = 255 Then
   For Stellwert = 254 To 1 Step -1
   Pinb.1 = 1
   Waitms 250
   Pinb.1 = 0
   Waitms 250
   Next
   Wait 1
   For Stellwert = 1 To 254
   Pinb.2 = 1
   Waitms 250
   Pinb.2 = 0
   Waitms 250
   Next
   Else
   End If
Else
End If

Return

' ================================================
Ausgabe:
Tccr1 = &B00000000                                          'Timer1 Stopp

Pwm0a = Stellwert

Tcnt1 = 11
Tccr1 = &B00001101                                          'Prescale 4096

Return

End


Nun noch schnell eine kurze Einweisung, wie es denn funktionieren sollte. ;)

Nach dem Anlegen der Spannung wird die Variable "Stellwert" herauf gezählt und durch den OVF von Timer1 (jede Sekunde) wird der PWM0a mit dem neuen Wert von "Stellwert" versorgt bzw. geändert.

Nach einer Pause von 3 Sekunden wird die Variable "Stellwert" wieder herunter gezählt.... und auch der Pwm0a wieder angepasst.

Durch die Überwachung von Pinb.3 und Pinb.4, mittels PCMSK, wird die SUB "Aktiv" aufgerufen.
Sollte Pinb.3 gedrückt worden sein und ist der Wert von "Stellwert" kleiner las 250, dann wird der aktuelle Wert von "Stellwert" in einer anderen Variablen gespeichert und "Stellwert" auf 255 eingestellt. Dieser Zustand bleibt so lange, bis der Pinb.3 wieder gedrückt wird. Danach wird der alte Wert zurück geholt und (sofern nicht gleichzeitig Pinb.4 gedrückt) die SUB verlassen.
An den Ports B.1 und B.2 sind nur LEDs als Zustandsanzeige angeschlossen.

Sollte Pinb.4 gedrückt worden sein und ist "Stellwert" = 255, dann wird in schneller Folge die Variable "Stellwert" erst herunter und dann wieder herauf gezählt. Danach geht es zurück zum Hauptprogramm.


So weit, so gut!
Durch den OVF von Timer1, müsste ja jede Sekunde der Pwm0a mit dem neuen Wert von "Stellwert" versorgt werden.
DIES geschieht aber nicht!
Nun frage ich mich..... Warum? :stupido3:

Habe ich einen Denkfehler, oder gibt es mal wieder ein "Geheimnis" bzw. eine Eigenart die ich dank meines mangelnden Fachwissens nicht berücksichtigen kann?


Schöne Grüße,
Cassio
 
Von Interrupts und Prioritäten....

Hallo Casio,

ich glaube Du hast ein Problem mit den Prioritäten der Interrupts. Ich habe Deinen Code mal kurz überflogen. Zunächst erscheint er mir von der BASCOm Programmierseite her als logisch und zunächst Fehlerfrei. Aber schauen wir und folgendes mal an:

- PCINT0 ist an INT-Vector Position 3
- Timer-Counter1 Overflow ist an INT-Vector 5
- Der Timer0 für das PWM-Signal ist Free-Running und muss nicht betrachtet werden

Je niedriger die Vecotr-Position des höher der Interrupt. Dies bedetet doch nach Adam Riese übertragen auf Deinen Code, solange die Interrupt-Routine Ausgabe läuft (von PCINT0) kann die Routine Aktiv (Timer1) nicht laufen da ein niederpriorer Interrupt nie einen höherprioren Interrupt unterbrechen kann.

Nach meinem Verständnis kann somit Stellwert garnicht neu gesetzt werden da die Interrupt-Routine nicht beendet wird und wenn sie beendet wird ist Stellwert wieder auf dem alten Wert. So sieht das zunächst für mich aus.

Du könntest diesen Seiteneffekt dadurch umgehen, dass Du in der Interrupt-Routine nur ein Flag setzt und nicht die Verarbeitung machst. Setze ein Flag und verlasse die Interrupt-Routine wieder. Die Auswertung würde ich in der Hauptschleife machen. Das ist sowieso immer sauberer.
Es gibt bzgl. ISR's eine kleine Regel die da lautet, mache so wenig wie möglich und so viel wie nötig.

Ohen mich nun in Dein Programm weiter zu vertiefen und es selber mal auf meinem STK500 auszuprobieren würde ich aber zunächst den Fehler in dem von mir geschilderten Zusammenhang sehen.

Ich hoffe ich habe es verständlich genug erklärt. Wenn nicht frag einfach nochmal nach.

Grüße,
Markus
 
Hallo Markus!

DAS muss es sein!

- PCINT0 ist an INT-Vector Position 3
- Timer-Counter1 Overflow ist an INT-Vector 5

Nun habe ich mir die Tabelle der Interrupt Vectors (vom Tiny45) auch mal etwas genauer angesehen.... :cool:

Demnach kann es ja nur so sein!

Dann werde ich das in Zukunft mal berücksichtigen. ;)

Kann aber ggf. auch mal ganz nützlich sein, dass bestimmte Interrupts vorang haben.


Danke dir also, für den wichtigen Hinweis und die verständliche Erklärung!

Schöne Grüße,
Cassio
 
Gerne,

schönen Sonntag,

Markus
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)