Der Nachfolger des WDR-Computerclub mit Wolfgang Back und Wolfgang Rudolph - ...und immer ein Bit übrigbehalten!


Das Forum zur C-Control-1
Welche C-Control-Varianten existieren?
Übersicht - Suchen - Neueste 50 Beiträge - Neuer Beitrag - Login - Registrieren
INFO - FAQ - CC2-Forum - CCPro-Forum 

 Rechtecksignale per Interrupt generieren Kategorie: Open-Micro/Open-Mini/Open-Midi/Open-Macro/Open-Maxi (von Dietmar, Homepage - 9.01.2007 20:57)
 Als Antwort auf Frequenzumrichter für kleine Lasten von Michael - 9.01.2007 12:12
Dietmar nutzt:  CC1-M-Unit V1.1, Advanced CC1-Unit, Open-Micro, Open-Mini, Open-Mini M-Unit, Open-Mini Station, sonstige
Hallo Michael.

> Ich kenne das nur von der C-Control und da ist das kleinste Raster 20ms -> 50Hz

Rechtecksignale mit einer niedrigeren Frequenz als 25 Hz auszugeben ist in der Tat nicht völlig trivial, da der Hardwarezähler vom Timer-Modul auf der OM normalerweise nach 20 ms überläuft. Das kann der Anwender natürlich durch entsprechende Umkonfigurierung des Kontrollers verhindern, doch dann läuft die interne Uhr (RTC) nicht mehr korrekt. Aus diesem Grund habe ich hier einmal ein Softwaremodul erstellt, mit dem sich ein Rechtecksignal mit variabler und sehr fein justierbarer Frequenz per Interrupt, also während der normalen Programmabarbeitung, an PORT[2] generieren läßt. Die normalerweise per Timer-Overflow-Interrupt realisierte RTC funktioniert hier per Channel 0 und läuft deshalb während der Signalausgabe korrekt weiter.

Das folgende Programm läßt sich auch zur Generierung höherer Frequenzen verwenden. Dazu können beispielsweise in der Routine init_tim0and1 die Prescaler Select Bits anders gesetzt werden. Beispielsweise am Ende der Routine mittels "mov #&b00000000,TSC" (gleich "CLR TSC"). Das ergibt Frequenzen zwischen 1265 und 3200 Hertz. Ansonsten kann man die Berechnungsvorschrift für die Inkrementierung von TCH1 in der Routine iiar_tim1 anpassen.

Alle Zeilen zwischen der Definition von "taste" und dem Label "main" können in einer eigenen Sourcecodedatei abgespeichert und per INCLUDE in den Hauptsourcecode eingebunden werden. Dadurch wird das Programm übersichtlicher.

' ----------------------------------------------------------------------------
' Rechtecksignal zwischen 20 und 50 Hz an PORT[2] ausgeben.
' In OCBASIC fuer Open-Micro und Open-Mini von Dietmar Harlos.
' ----------------------------------------------------------------------------

' Das Signal wird per Timer-Channel-1-Interrupt erzeugt. Der normalerweise per
' Timer-Overflow-Interrupt realisierte 20-ms-Interrupt wird mittels Timer-
' Channel-0-Interrupt generiert. Da an einer Stelle direkt ins Betriebssystem
' gesprungen wird, ist dieses Programm nur auf der Open-Micro und Open-Mini
' lauffaehig. Für Open-Midi muß es also angepaßt werden.

' Die exakte Frequenz läßt sich mit der Formel 25000/(3*pdauer+500) berechnen.

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

INCLUDE "om.def"           'Definitionen für die Open-Micro und Open-Mini

DEFINE pdauer BYTE         'Periodendauer festlegen
DEFINE adpoti AD[6]        'auf dem PE-Board liegt hier das AD-Poti
DEFINE taste PORT[4]       'eine Taste vom PE-Board

' --- Unsere eigene Assembler-Interruptroutine ------------------------------

' Die folgende Assembler-Interruptroutine erzeugt eine Rechteckschwingung
' an PORT[2] (genauer: TCH1), indem der Port bei jedem Aufruf getoggelt
' wird. Die Aufrufhaeufigkeit des Interrupts wird durch die Bytevariable
' pdauer festgelegt.

' Das Schluesselwort INLASM kennzeichnet die folgende PROCEDURE als
' Assemblerroutine ("IAR"). Dadurch, und dass sie unmittelbar am Anfang
' des Programms steht, wird sie zu einer IIAR, also zu einer Assembler-
' Interruptroutine, die bei einem aktivierten User-Interrupt gestartet wird.

PROCEDURE iiar_tim1 INLASM

! cbeqa #iTIM1,iiar_tim1_1 'Falls kein Aufruf durch TIM1-Interrupt,
! jmp iiar_tim1_ende+2     'dann zur naechsten IIAR in der Kette.

' In output compare mode (MSxB:MSxA<>0:0), writing to the high byte of the
' TIM channel x registers (TCHxH) inhibits output compares until the low byte
' (TCHxL) is written.

#iiar_tim1_1
! lda pdauer               'TCH1 = TCH1 + pdauer*3 + 500
! ldx #3
! mul
! add #$f4
! pusha
! txa
! adc #$01
! tax
! popa
! add TCH1L
! pusha
! txa
! adc TCH1H
! sta TCH1H
! popa
! sta TCH1L
! clc                      'Ruecksprung ins Betriebssystem
! rts

END PROCEDURE

#iiar_tim1_ende            'hier hinter folgt die naechste IIAR


PROCEDURE iiar_tim0 INLASM

! cbeqa #iTIM0,iiar_tim0_1 'Falls kein Aufruf durch TIM0-Interrupt,
! jmp iiar_tim0_ende+2     'dann zur naechsten IIAR in der Kette.

' In output compare mode (MSxB:MSxA<>0:0), writing to the high byte of the
' TIM channel x registers (TCHxH) inhibits output compares until the low byte
' (TCHxL) is written.

#iiar_tim0_1
! lda TCH0L                'TCH0 = TCH0 + 1000
! add #$e8
! tax
! lda TCH0H
! adc #$03
! sta TCH0H
! stx TCH0L
! ais #2                   'Ruecksprungadresse vom Hardwarestack entfernen
! jmp $f3f2                'Einsprung ins Open-Micro-Betriebssystem

END PROCEDURE


' Mit der folgenden Assemblerroutine wird das Timer Interface Module (TIM)
' passend umkonfiguriert.

PROCEDURE init_tim0and1 INLASM
'"Before changing a channel function by writing to the MSxB or MSxA bit,
' set the TSTOP and TRST bits in the TIM status and control register (TSC)."
! mov #&b00110110,TSC      'TSC: TOF TOIE TSTOP TRST 0 PS2 PS1 PS0
! mov #&b01010000,TSC0     '"Software compare only"
! mov #&b01010100,TSC1     '"Toggle output on compare"
! ldhx #&hffff
! sthx TMODH               'Modulo-Register auf Standardwert $ffff
! clr TCH0H
! clr TCH0L                'Die TIM-Channel-Register sind
! clr TCH1H                ' "indeterminate after reset".
! clr TCH1L
! mov #&b00000110,TSC      'Timer wieder starten
! rts
END PROCEDURE


' Timer Interface Module (TIM) wieder so setzen, wie vom OS erwartet

PROCEDURE reset_tim0and1 INLASM
! mov #&b00110110,TSC      'TSC: TOF TOIE TSTOP TRST 0 PS2 PS1 PS0
! clr TSC0                 'TIM Channel Status and Control Registers
! clr TSC1                 '  TSC0 & TSC1
! ldhx #999                'Modulo-Register zurueck auf OS-Wert
! sthx TMODH
! mov #&b01000110,TSC      'Timer wieder starten
! rts
END PROCEDURE


#iiar_tim0_ende            'hier hinter folgt die naechste IIAR
                           '(sofern vorhanden)

' --- Das Hauptprogramm -----------------------------------------------------

#main                      'Label für Hauptprogramm

pdauer=0                   'Defaultwert fuer Periodendauer

UIRTim1=ON                 'User-Assemblerroutine fuer TIM1 aktivieren
UIRTim0=ON                 'User-Assemblerroutine fuer TIM0 aktivieren
init_tim0and1              'Timer-Modul passend initialisieren

PrintSpc=ON

WHILE taste
  pdauer=adpoti            'Analogwert vom AD-Poti holen und als
WEND                       '  Periodendauer benutzen

reset_tim0and1             'Timer-Modul wieder auf Defaultkonfiguration

WHILE TRUE                 'Demonstration, daß Timer-Modul korrekt arbeitet
  PRINT timer;second
  PAUSE 25
WEND

END                        'Programmende

Viele Grüße
Dietmar

Meine Homepage: http://ccintern.dharlos.de

 Antwort schreiben

Bisherige Antworten:

Re: Rechtecksignale per Interrupt generieren (von Michael - 10.01.2007 19:02)