×
单片机 > 单片机程序设计 > 详情

pic12C508 DTMF拔号程序

发布时间:2020-05-16 发布时间:
|

pIC12C508 DTMF拔号程序
; | Name:         MAIN.ASM                                             |

; | Description:  DTMF -> RS232 converter (for use with PC NummerViser)| 
; |               Detects DTMF and ringing, and transmits to a std.    | 
; |               RS232 port, at 2400 baud.                            | 
; |                                                                    |                                            |
; +--------------------------------------------------------------------+ 
; | Platform:     PIC12C508(A) (using internal 4MHz RC-oscillator)     | 
; | Uses:         90-342W/512W program-mem (all ’switches’ set to 0/1) | 
; |               6B/25B data-mem                                      | 
; | Assembler:      MPASM 2.20 (MPLAB 4.00.00)                           | 
; | Comments:     -                                                    | 
; +====================================================================+ 

    TITLE        ’DTMF to RS232 converter’ 

    PROCESSOR    12C508 

     __CONFIG    _CP_OFF & _MCLRE_OFF & _IntRC_OSC & _WDT_ON 
    INCLUDE         

    RADIX        DEC 
    __IDLOCS    h’0104’ 


OTP    SET    1    ;Use factory-stored cal.-value (on OneTimeProgrammable) 

TMR0CLK    SET    1    ;Use TMR0 external clock at 3,579545MHz (instead of IntRC). 
PARITY    SET    1    ;Use even parity-bit when transmitting to the serial port. 
CLIONLY    SET    1    ;Transmits CLI (A-numbers) only. 
RING    SET    1    ;Transmits ringing. 
IDENTTX    SET    1    ;Transmits ’ident’ when pressing ’***’ (DTMF). 
PWRUPID    SET    1    ;Transmits short ’ident’ at powerup. 
ASCII    SET    1    ;Transmits ASCII-chars instead of binary: 
            ;Digit    ASCII    Binary        Digit    ASCII    Binary 
            ;0    0 (48d)    00000000    9    9 (57d)    00001001 
            ;1    1 (49d)    00000001    A    A (65d)    00001010 
            ;2    2 (50d)    00000010    B    B (66d)    00001011 
            ;3    3 (51d)    00000011    C    C (67d)    00001100 
            ;4    4 (52d)    00000100    D    D (68d)    00001101 
            ;5    5 (53d)    00000101    *    * (42d)    00001110 
            ;6    6 (54d)    00000110    #    # (35d)    00001111 
            ;7    7 (55d)    00000111    Ring    R (82d)    00010000 
            ;8    8 (56d)    00001000 


;---+++***  Constants  ***+++--- 

    IF    TMR0CLK == 0        ;Internal oscillator 
OPTION_REG    equ b’10000001’        ;’Default’ timer/prescaler setup 
    ENDIF 

    IF    TMR0CLK == 1        ;External TMR0 source (3,579545MHz) 
OPTION_REG    equ b’10100011’        ;’Default’ timer/prescaler setup 
    ENDIF 

#define    DTMF0    GPIO, 0            ;Bit0 (LSB) from MT8870 
#define    DTMF1    GPIO, 1            ;Bit1 from MT8870 
#define    DTMF2    GPIO, 3            ;Bit2 from MT8870 / _Ring-detector 
#define DTMF3    GPIO, 4            ;Bit3 from MT8870 / TxD-output (high = sPACe) 
#define    DTMFOK    GPIO, 5            ;DTMF detected, and ready at DTMF0-3 


;---+++***  Variable declaration  ***+++--- 
    cblock    0Ch 
     DTMFval 
     identval 
     misc 
     temp1, temp2, teMP3        ;Temp-variables 
    endc 

#define    CLIP    misc, 0            ;Set when CLIP detected 
#define    CLIPend    misc, 1            ;Set by CLIPdet when # received 
#define    IdentOK    misc, 2            ;Set when ’ident’ detected (***) 


;---+++***  Reset vector  ***+++--- 
    ORG    0h 
rst_vector: 
    MOVwf    OSCCAL            ;Set oscillator calibration. 

    call    init 

    IF    PWRUPID == 1 
     goto    pwrupident 
pwrupidentreturn: 
    ENDIF 

    goto    main 



;---+++***  Identity (located ’low’ because of no CP identtable: 
    IF    IDENTTX == 1 
     addwf    PCL, F 
     dt    " +++ PC NummerViser +++ ", 13 
     dt    "     Firmware v1.04     ", 13, 13 
     dt    "  JaCOB BlichfELDt ’98  ", 13, 13, 13, 0 
    ENDIF 

pwrupidenttable: 
    IF    PWRUPID == 1 
     addwf    PCL, F 
     dt    "DTMFTORS232", 60, "0104", 62, 0 
    ENDIF 


;---+++***  Initialization  ***+++--- 
init: 
; Setup I/O-direction (GP0-3, 5 = input, GP4 = output) 
    MOVlw    b’11101111’ 
    tris    GPIO 

; TxD = Space (GP4 = low) 
    MOVlw    b’00000000’ 
    MOVwf    GPIO 

; Enable port B pull-up, dISAble wake-up on PIN change 
; Setup T0 = inc. on either OSC. or TMR0, prescaler = 4/16 (depends on TMR0CLK) 
    clrwdt 
    MOVlw    OPTION_REG 
    option 

    clrf    misc 
    clrf    identval 

    retlw    0 


;---+++***  Power-up identity transmission  ***+++--- 
    IF    PWRUPID == 1 
pwrupident: 

     MOVlw    4                ;wait approx. 1 second 
     MOVwf    temp3 
pwrup11: clrf    temp2 
pwrup12     clrf    temp1 
pwrup13: clrwdt 
     decfsz    temp1, F 
     goto    pwrup13 
     decfsz    temp2, F 
     goto    pwrup12 
     decfsz    temp3, F 
     goto    pwrup11 

     MOVlw    h’0FF’ 
     MOVwf    temp3 
pwrup2:     clrwdt 
     incf    temp3, F 
     MOVf    temp3, W 

     call    pwrupidenttable            ;Fetch text 

     clrf    temp2 
     subwf    temp2, F 
     btfsc    STATUS, Z            ;End of table? 
     goto    pwrupend 
     call    txser 
     goto    pwrup2 

pwrupend: 
     goto    pwrupidentreturn 
    ENDIF 


;---+++***  Main  ***+++--- 
main:    goto    DTMFdet 
DTMFdetreturn: 
    goto    ringdet 
ringdetreturn: 
    goto    main            ;Repeat main 


; Read DTMF-bits from 8870, converts to nibble, and returns in W. 
readDTMF: 
    MOVf    GPIO, W 
    andlw    b’00000011’            ;Get bit0-1 
    MOVwf    DTMFval 

    bsf    DTMFval, 2            ;Get bit 2 
    btfss    DTMF2 
    bcf    DTMFval, 2 

    MOVlw    b’11111111’            ;Get bit 3 (DTMF3 = input) 
    bcf    DTMFval, 3 
    tris    GPIO 
    MOVlw    b’11101111’ 
    btfsc    DTMF3 
    bsf    DTMFval, 3 
    tris    GPIO                ;DTMF3 = Output 
    bcf    DTMF3 

    MOVf    DTMFval, W            ;Convert from 8870 -> ’normal’ 
    andlw    b’00001111’ 
    call    DTMFtable 
    MOVwf    DTMFval 
    retlw    0 

DTMFtable: 
    addwf    PCL, F 
    retlw    b’00001101’            ;DTMF ’D’ 
    retlw    b’00000001’            ;DTMF ’1’ 
    retlw    b’00000010’            ;DTMF ’2’ 
    retlw    b’00000011’            ;DTMF ’3’ 
    retlw    b’00000100’            ;DTMF ’4’ 
    retlw    b’00000101’            ;DTMF ’5’ 
    retlw    b’00000110’            ;DTMF ’6’ 
    retlw    b’00000111’            ;DTMF ’7’ 
    retlw    b’00001000’            ;DTMF ’8’ 
    retlw    b’00001001’            ;DTMF ’9’ 
    retlw    b’00000000’            ;DTMF ’0’ 
    retlw    b’00001110’            ;DTMF ’*’ 
    retlw    b’00001111’            ;DTMF ’#’ 
    retlw    b’00001010’            ;DTMF ’A’ 
    retlw    b’00001011’            ;DTMF ’B’ 
    retlw    b’00001100’            ;DTMF ’C’ 


; Converts received DTMF to ASCII (returns in W) 
conASCII: 
    IF    ASCII == 1 
     addwf    PCL, F 
     retlw    A’0’ 
     retlw    A’1’ 
     retlw    A’2’ 
     retlw    A’3’ 
     retlw    A’4’ 
     retlw    A’5’ 
     retlw    A’6’ 
     retlw    A’7’ 
     retlw    A’8’ 
     retlw    A’9’ 
     retlw    A’A’ 
     retlw    A’B’ 
     retlw    A’C’ 
     retlw    A’D’ 
     retlw    A’*’ 
     retlw    A’#’ 
    ENDIF 


; Tests for 3 subsequent ’*’. 
ident:     
    IF     IDENTTX == 1 
     bcf    IdentOK 
     MOVlw    b’00001110’            ;DTMF ’*’ 
     subwf    DTMFval, W 
     btfss    STATUS, Z 
     goto    ident1 
     incf    identval, F 

     MOVlw    d’3’ 
     subwf    identval, W 
     btfss    STATUS, Z 
     goto    identend 
     bsf    IdentOK 
ident1:     clrf    identval 

identend: 
     retlw    0 
    ENDIF 


; Transmits W at 2400bps/std. RS232. Calculates parity-bit. Returns when done. 
txser:     
    MOVwf    temp1 

    bcf    STATUS, C            ;Transmit start-bit 
    call    txcarry 

    MOVlw    d’8’                ;Transmit 8 databits 
    MOVwf    temp2 
txbits:    clrwdt 
    rrf    temp1, F 
    call    txcarry 
    decfsz    temp2, F 
    goto    txbits 

    IF    PARITY == 1 
     rrf    temp1, F            ;calculate parity (even) 
     swapf    temp1, W 
     xorwf    temp1, W 
     MOVwf    temp1 
     rrf    temp1, F 
     rrf    temp1, F 
     xorwf    temp1, F 
     rrf    temp1, W 
     xorwf    temp1, F 
     bcf    STATUS, C 
     btfsc    temp1, 0 
     bsf    STATUS, C 
     call    txcarry 
    ENDIF 

    bsf    STATUS, C            ;Transmit 2*stop-bit 
    call    txcarry 
    bsf    STATUS, C 
    call    txcarry 
     
    retlw    0 

;transmit carry-flag 
    IF    TMR0CLK == 0 
txcarry:MOVlw    (256-104)            ;2400 = 416,666us = 1666,666c/16 = 104,17 
    ENDIF 

    IF    TMR0CLK == 1 
txcarry:MOVlw    (256-93)            ;2400 = 416,666us = 1491,477c/16 = 93,22 
    ENDIF 


txndone:btfsc    TMR0, 7                ;Last bit transmitted (TMR0 ovfl.)? 
    goto    txndone 

    bsf    DTMF3                ;Space 
    btfsc    STATUS,C            ;Set to mark (-12 V) if Carry = 1 
                        ;(RS232 inverts output) 
    bcf    DTMF3                ;Mark 

    MOVwf    TMR0 

    retlw    0 


; Recognizes CLIP (DTMF received in A), and sets/clears CLIP. 

    IF    CLIONLY == 1 
CLIPdet: 
     MOVwf    temp1 
     MOVlw    b’00001010’            ;DTMF ’A’ 
     subwf    temp1, W 
     btfss    STATUS, Z 
     goto    CLIPdet2 
     bsf    CLIP 
     goto    CLIPdetend 

CLIPdet2:MOVlw    b’00001101’            ;DTMF ’D’ 
     subwf    temp1, W 
     btfss    STATUS, Z 
     goto    CLIPdet3 
     bsf    CLIP 
     goto    CLIPdetend 

CLIPdet3:btfss    CLIP 
     goto    CLIPdetend 
     MOVlw    b’00001111’            ;DTMF ’#’ 
     subwf    temp1, W 
     btfss    STATUS, Z 
     goto    CLIPdetend 
     bcf    CLIP 
     bsf    CLIPend 

CLIPdetend: 
     retlw    0 
    ENDIF 


; DTMF-detection - Calls readDTMF, CLIPdet, conASCII and txser if DTMF is present. 
;                  Returns when DTMF is reMOVed. 
DTMFdet:clrwdt 
    btfss    DTMFOK 
    goto    DTMFdetreturn 
    goto    $+1                ;Double nop 
    btfss    DTMFOK 
    goto    DTMFdetreturn 

    call    readDTMF            ;DTMF present, read! 

    IF    IDENTTX == 1            ;Transmit ident if ’***’ received 
     call    ident 
     btfss    IdentOK 
     goto    DTMFdet2 

     MOVlw    h’0FF’ 
     MOVwf    temp3 

DTMFdet1:clrwdt 
     incf    temp3, F 
     MOVf    temp3, W 

     call    identtable            ;Fetch text 

     clrf    temp2 
     subwf    temp2, F 
     btfsc    STATUS, Z            ;End of table? 
     goto    DTMFdet2 
     call    txser 
     goto    DTMFdet1 
    ENDIF 

DTMFdet2: 
    MOVf    DTMFval, W 
    IF    CLIONLY == 1            ;Transmit only CLI 
     call    CLIPdet 
     btfss    CLIPend                ;Last digit in CLI (#)? 
     goto    DTMFdet21 
     bcf    CLIPend 
     goto    DTMFdet22 
DTMFdet21: 
     btfss    CLIP 
     goto    DTMFoff 
DTMFdet22: 
     MOVf    DTMFval, W 
    ENDIF 

    IF    ASCII == 1            ;Convert to ASCII 
     MOVf    DTMFval, W 
     call    conASCII 
    ENDIF 

    call    txser                ;Transmit to serial port 

DTMFoff:clrwdt                    ;Wait for DTMF to stop 
    btfsc    DTMFOK 
    goto    DTMFoff 

DTMFend:goto    DTMFdetreturn 



; Ring-detection - If ringing is present, calls txser with W = (ascii) ’R’. 
;                  Returns when ringing ends or DTMF is present. 
ringdet:clrwdt 
    IF    RING == 1 
     btfsc    DTMF2 
     goto    ringend 

ringdet2:                    ;Wait for ringing-pulse to  
     clrwdt                    ;stop (or DTMF present). 
     btfsc    DTMFOK 
     goto    ringend 
     btfss    DTMF2 
     goto    ringdet2 

     MOVlw    b’10000111’            ;Setup timer: 50ms before overflow. 
     option 
     MOVlw    d’50’ 
     MOVwf    TMR0 

ringdet3:clrwdt                    ;Wait for new ringing-pulse 
     MOVlw    0 
     subwf    TMR0, W 
     btfsc    STATUS, Z 
     goto    ringend 
     btfsc    DTMF2 
     goto    ringdet3 
                        ;New pulse present. 
     MOVlw    OPTION_REG            ;Restore old prescaler 
     option 
     MOVlw    A’R’                ;Transmit ’R’ 
     call    txser 
     bcf    CLIP                ;Terminate CLIP-sequence (ring det.) 
     MOVlw    b’10000111’            ;Setup timer: 50ms before overflow. 
     option 

ringdet4:MOVlw    d’50’ 
     MOVwf    TMR0 

ringdet5:clrwdt                    ;Wait for ringing to end 
     btfss    DTMF2 
     goto    ringdet4 

     MOVlw    0 
     subwf    TMR0, W 
     btfsc    STATUS, Z 
     goto    ringend 
     btfss    DTMFOK 
     goto    ringdet5 

ringend: MOVlw    OPTION_REG            ;Restore old prescaler 
     option 
    ENDIF 
    goto    ringdetreturn 



    IF    OTP == 0 
     ORG    h’1FF’                ;(old 12C508 calibration-val.) 
     MOVlw    h’0A0’ 
    ENDIF 

    END 


  +---------------------------------------------------------------------+ 
  | History                                | 
  +---------------------------------------------------------------------+ 

Rev.    Change                    Reason            Date 
-------------------------------------------------------------------------------- 
0.0a    Source-file created.            -            24.03.98 

0.5a    Hierarchisch diagram finished.        -            25.03.98 

1.0a    Everything implemented, ready for test.    -            26.03.98 

1.0b    Tested in ’real life’... Everything ok,    -            27.03.98 
     (minor bugs reMOVed). 

1.0    First version, ’in use’.        -            27.03.98 

1.01    Fixed ’#’ not transmitted when CLIP=1.    -            29.03.98 
    Fixed ’D’-sequences not recognized as 
     CLIP (not transmitted when CLIP=1). 
    Implemented PwrUpIdent.            Gives possibility of 
                         auto-detection, and 
                         FW-version detection. 

1.02    Implemented possibility of using ext.    More precise than    09.04.98 
     TMR0 source, as timebase for RS232-     internal RC-oscillator. 
     communication. 
    Bugfixed CLIPdet.            ASCII-table located in 
                         upper page when all 
                         switches = 1. 

1.03r    +++ First ’public’ release. +++        In case the CLI-    02.05.98 
    Break CLIP-sequence if ring detected.     sequence is not termi- 
                         nated probably (because 
                         of linenoise etc.) 
     

1.04r    Minor changes/bugfixes:                        18.03.99 
     Changed TX-timing.            Transmitted at ~2325bps. 
     Changed format from 8E1 to 8E2        Enables receiver to re- 
      (2 stopbits).                 syncronize between each 
                         byte, thereby supressing 
                         framing-errors. 
     Minimized ’read-DTMF’ timing.        ReMOVes unwanted 10us 
                         glitch on TX just before 
                         transmitting a digit. 


Ideas/future changes: 
------------------------------------------------------------------------------- 
Add EEPROM and change power-supply, to enable reception/storing of DTMF, when  
 the PC is turned off. 

Add offhook detector, to enable ’length of conversation’, and ’answered/not  
 answered call’ logging. 




『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
AVR单片机为何要写1作为清0中断标志位