![]() ![]() INFO - FAQ - CC2-Forum - CCPro-Forum |
|
' =========================================================================== ' DTMF-Signale mittels PWM mit 25 kHz Taktfrequenz und 7 Bit Werteauflösung ' In OCBASIC 1.11a fĂŒr Open-Maxi von Dietmar Harlos am 01. August 2020 ' =========================================================================== ' Es werden an DA[1] einer Open-Maxi DTMF-Signale ausgegeben. Es kann ein ' Piezotöner ohne Elektronik direkt angeschlossen werden. ' DTMF-Signale werden beim Mehrfrequenzwahlverfahren eingesetzt: ' https://de.wikipedia.org/wiki/Mehrfrequenzwahlverfahren ' Dieses Programm geht zurĂŒck auf DTMFBPWM.BAS im ZIP-Archiv zum OCBASIC- ' Compiler. Dort werden DTMF-Signale mit den kleinen OM-Controllern erzeugt. ' An dieser Stelle möchte ich mich bei Norbert Klein und bei Dirk vom L-Team ' fĂŒr ihre UnterstĂŒtzung bedanken. ' --- Definitionen ---------------------------------------------------------- INCLUDE "omax.def" 'Definitionen fĂŒr die Open-Maxi DIM a,b,c BYTE 'temporĂ€re Variablen DIM char BYTE DIM z1h BYTE 'zum Datenaustausch mit Assembler-Interruptroutinen DIM z1l BYTE DIM i1h BYTE DIM i1l BYTE DIM z2h BYTE DIM z2l BYTE DIM i2h BYTE DIM i2l BYTE ' --- Unsere eigene Assembler-Interruptroutine ------------------------------ ' Die folgende Assembler-Interruptroutine befindet sich im "Timer/PWM-Module ' 2 - Overflow (TPM2OVF)"-Interrupt und wird gestartet, wenn ein Overflow ' im PWM-Modul stattfindet; die PWM also einen neuen Wert benötigt. ' Die folgenden Subroutinen sollten sinnvollerweise in einer INCLUDE-Datei ' untergebracht werden. ' Das SchlĂŒsselwort INLASM kennzeichnet die folgende PROCEDURE als ' Assemblerroutine (IAR). Dadurch, und daĂ 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. ' Der OCBASIC-Compiler setzt automatisch ein "GOTO main" vor diese Routine. PROC iiar_tpm2ofl INLASM ! cbeqa #iTPM2OFL,is_tpm2ofl ! jmp iiar_tpm2ofl_next+2 'zur nĂ€chsten IIAR springen #is_tpm2ofl ! ldx z1h ! lda sin,x '-63..63 ! ldx z2h ! add sin,x '-126..126 ! add #128 '2..254 ! ldx #3 ! mul '6..762 ! stx TPM2C0VH 'darf bis 799 ! sta TPM2C0VL ! lda z1l 'die beiden Zeiger inkrementieren ! add i1l '(fĂŒr bessere Frequenzauflösung muĂ mit 16 Bit gearbeitet ! sta z1l ' werden, aber nur das Highbyte wird als Zeiger verwendet) ! lda z1h ! adc i1h ! sta z1h ! lda z2l ! add i2l ! sta z2l ! lda z2h ! adc i2h ! sta z2h ! clc 'Betriebssystemfunktion soll aktiviert bleiben ! rts 'RĂŒcksprung zum Betriebssystem END PROC ' Tabelle mit den Werten einer Sinusschwingung - 7 Bit Auflösung TABLE sin BYTE 0 2 3 5 6 8 9 11 12 14 15 17 18 20 21 23 24 26 27 28 30 31 32 34 35 36 38 39 40 41 42 43 45 46 47 48 49 50 51 52 52 53 54 55 56 56 57 58 58 59 59 60 60 61 61 61 62 62 62 63 63 63 63 63 63 63 63 63 63 63 62 62 62 61 61 61 60 60 59 59 58 58 57 56 56 55 54 53 52 52 51 50 49 48 47 46 45 43 42 41 40 39 38 36 35 34 32 31 30 28 27 26 24 23 21 20 18 17 15 14 12 11 9 8 6 5 3 2 0 -2 -3 -5 -6 -8 -9 -11 -12 -14 -15 -17 -18 -20 -21 -23 -24 -26 -27 -28 -30 -31 -32 -34 -35 -36 -38 -39 -40 -41 -42 -43 -45 -46 -47 -48 -49 -50 -51 -52 -52 -53 -54 -55 -56 -56 -57 -58 -58 -59 -59 -60 -60 -61 -61 -61 -62 -62 -62 -63 -63 -63 -63 -63 -63 -63 -63 -63 -63 -63 -62 -62 -62 -61 -61 -61 -60 -60 -59 -59 -58 -58 -57 -56 -56 -55 -54 -53 -52 -52 -51 -50 -49 -48 -47 -46 -45 -43 -42 -41 -40 -39 -38 -36 -35 -34 -32 -31 -30 -28 -27 -26 -24 -23 -21 -20 -18 -17 -15 -14 -12 -11 -9 -8 -6 -5 -3 -2 END TABLE ' Das TPM2-Modul fĂŒr DTMF-Ausgabe konfigurieren ' DA[1] liegt an TPM2CH0 ' DA[2] liegt an TPM2CH1 PROC inittpm2 INLASM ! mov #%01001000,TPM2SC 'TPM clock input = 20e6/1 = 20 MHz & Timer Overflow Interrupt Enable ! ldhx #799 'Timer 2 Counter Modulo Registers (TPMxMODH:TPMxMODL) ! sthx TPM2MODH 'von 0 bis inklusive 799 zĂ€hlen (also Modulo 800) - (kein 100% duty cycle) ! lda #%00101000 'PWM-Frequenz: 20e6/1/800 = 25.0 kHz ! sta TPM2C0SC 'Timer 2 Channel 0 Status and Control Register \ Edge-aligned PWM ! sta TPM2C1SC 'Timer 2 Channel 1 Status and Control Register / High-true pulses ! rts END PROC ' Das TPM2-Modul wieder so konfigurieren, wie vom OS erwartet ' DA[1] liegt an TPM2CH0 ' DA[2] liegt an TPM2CH1 PROC resettpm2 INLASM ! mov #%00001101,TPM2SC 'TPM clock input = 20e6/32 = 625 kHz -> PWM-Frequenz 2441 Hz ! ldhx #$00ff 'Timer 2 Counter Modulo Registers (TPMxMODH:TPMxMODL) ! sthx TPM2MODH 'von 0 bis inklusive 255 zĂ€hlen (also Modulo 256) - (kein 100% duty cycle) ! lda #%00101000 'PWM-Frequenz: 20e6/32/256 = 2441.40625 Hz ! sta TPM2C0SC 'Timer 2 Channel 0 Status and Control Register \ Edge-aligned PWM ! sta TPM2C1SC 'Timer 2 Channel 1 Status and Control Register / High-true pulses ! clrh ! clrx ! sthx TPM2C0VH 'Timer 2 Channel Value Registers (TPM2CnVH:TPM2CnVL) ! sthx TPM2C1VH ! rts END PROC ' Tabelle mit den Konstanten zur Erzeugung von DTMF-Signalen TABLE dtmf_tab WORD 2467, 3502 ' "0" 1827, 3169 ' "1" ' Hz 1209 1336 1477 1633 1827, 3502 ' "2" '697 1 2 3 A 1827, 3872 ' "3" '770 4 5 6 B 2019, 3169 ' "4" '852 7 8 9 C 2019, 3502 ' "5" '941 * 0 # D 2019, 3872 ' "6" 2233, 3169 ' "7" 'f[Hz] = 25000*N/65536 2233, 3502 ' "8" 'N = 65536*f/25000 2233, 3872 ' "9" 2467, 3169 ' "*" 2467, 3872 ' "#" 1827, 4281 ' "A" 2019, 4281 ' "B" 2233, 4281 ' "C" 2467, 4281 ' "D" ' 1, 1 ' unbekannt 2621, 2621 ' 1 kHz zum Testen END TABLE ' IIAR-Variablen passend laden, um DTMF-Signal zu einem Zeichen zu erzeugen ' benutzte Variablen: char, a, i1h, i1l, i2h, i2l, z1h, z1l, z2h, z2l PROC dtmf(char) ' Offset in der Tabelle berechnen IF char>="0" AND char<="9" THEN a=char-"0" ELSEIF char="*" THEN a=10 ELSEIF char="#" THEN a=11 ELSEIF char>="A" AND char<="D" THEN a=char-"A"+12 ELSE a=16 END IF a=a*4 ' Variablen fĂŒr Interruptroutine laden i1h=LOOKTABBYTE(dtmf_tab,a) i1l=LOOKTABBYTE(dtmf_tab,a+1) i2h=LOOKTABBYTE(dtmf_tab,a+2) i2l=LOOKTABBYTE(dtmf_tab,a+3) z1h=0 : z1l=0 z2h=0 : z2h=0 ' IIAR-Assemblerroutine in den TOFL-Interrupt hĂ€ngen und aktivieren UIRTpm2Ofl=ON inittpm2 ' Die Töne werden jetzt generiert. Das Programm lĂ€uft normal weiter. PUT char PAUSE 10 ' alles wieder rĂŒckgĂ€ngig machen resettpm2 UIRTpm2Ofl=OFF ' 100 ms Break-Time PAUSE 5 RETURN #iiar_tpm2ofl_next ' --- Hauptprogramm --------------------------------------------------------- #main 'durch die IIAR am Programmbeginn wird ein "GOTO main" erzeugt 'dtmf "E" : goto main 'Test: 1 kHz-Signal ' Subroutine zum Erzeugen von DTMF-Signalen aufrufen dtmf "0" dtmf "1" dtmf "2" dtmf "3" dtmf "4" dtmf "5" dtmf "6" dtmf "7" dtmf "8" dtmf "9" dtmf "*" dtmf "#" dtmf "A" dtmf "B" dtmf "C" dtmf "D" PAUSE 50 ' Lied: "Merrily We Go Along" dtmf "9" : dtmf "5" : dtmf "1" : dtmf "5" : PAUSE 2 dtmf "9" : dtmf "9" : dtmf "9" : PAUSE 5 dtmf "5" : dtmf "5" : dtmf "5" : PAUSE 5 dtmf "9" : dtmf "9" : dtmf "9" : PAUSE 5 dtmf "9" : dtmf "5" : dtmf "1" : dtmf "5" : PAUSE 2 dtmf "9" : dtmf "9" : dtmf "9" : PAUSE 5 dtmf "9" : dtmf "5" : dtmf "5" : PAUSE 5 dtmf "9" : dtmf "5" : dtmf "1" : PAUSE 5 ' ZurĂŒck in den Hostmodus. Neustart mit RETURN-Taste. PRINT "Programmende." End2Host=ON END ' --- Programmende --------------------------------------------------------- Passender Link: Infosite zu den OM-Mikrocontrollern Meine Homepage: http://ccintern.dharlos.de |
Antwort schreiben |