⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dtmf.asm

📁 DTMF Generator for AVR
💻 ASM
字号:
;***************************************************************************
;* A P P L I C A T I O N   N O T E   F O R   T H E   A V R   F A M I L Y
;*
;* Number               : AVR314
;* File Name            : "dtmf.asm"
;* Title                : DTMF Generator
;* Date                 : 00.06.27
;* Version              : 1.1
;* Target MCU           : Any AVR with SRAM, 8 I/O pins and PWM
;*
;* DESCRIPTION
;* This Application note describes how to generate DTMF tones using a single
;* 8 bit PWM output.
;*
;***************************************************************************

.include "4414def.inc"

;**************************************************************************
;  REGISTERS
;**************************************************************************
.def   ptr_Ltmp = r1                    ; low  part temporary register
.def   ptr_Htmp = r2                    ; high part temporary register
.def   ptr_Lb   = r3                    ; low  part low frequency pointer
.def   ptr_Hb   = r4                    ; high part low frequency pointer

.def   ptr_La   = r5                    ; low  part high frequency pointer
.def   ptr_Ha   = r6                    ; high part high frequency pointer

.def   addb_out = r7                    ; low  frequency value to be written                            
.def   adda_out = r8                    ; High frequency value to be written

.def   x_SWa = r9                    	; high frequency x_SW
.def   x_SWb = r10                   	; low  frequency x_SW

.def   count    = r18                   ; temporary counter register
.def   tmp      = r16                   ; temp register

.def   input    = r17                   ; input from portB

;**************************************************************************
;**************************************************************************
.equ     Xtal      = 8000000            ; system clock frequency
.equ     prescaler = 1                  ; timer1 prescaler
.equ     N_samples = 128                ; Number of samples in lookup table
.equ     Fck = Xtal/prescaler           ; timer1 working frequency
.equ	 delaycyc  = 10			; port B setup delay cycles

;**************************************************************************
;  PROGRAM START - EXECUTION STARTS HERE
;**************************************************************************
.cseg
.org    $0
    rjmp    start                       ; Reset handler
.org    OVF1addr
    rjmp    tim1_ovf                    ; Timer1 overflow Handle

;**************************************************************************
; Interrupt timer1
;**************************************************************************
tim1_ovf:
   push   tmp    			; Store temporary register
   in     tmp,SREG
   push   tmp                           ; Store status register
   push   ZL
   push   ZH                            ; Store Z-Pointer
   push   r0                            ; Store R0 Register

;high frequency
   mov    ptr_Ltmp,ptr_La
   mov    ptr_Htmp,ptr_Ha
   rcall  getsample                     ; read from sample table
   mov    adda_out,r0                   ; adda_out = high frquency value
   add    ptr_La,x_SWa
   clr    tmp                           ; (tmp is cleared, but not the carry flag)
   adc    ptr_Ha,tmp                    ; Refresh pointer for the next sample

;low frequency
   mov    ptr_Ltmp,ptr_Lb
   mov    ptr_Htmp,ptr_Hb
   rcall  getsample                     ; read from sample table
   mov    addb_out,r0                   ; addb_out = low frequency value
   add    ptr_Lb,x_SWb
   clr    tmp                           ; (tmp is cleared, but not the carry flag)
   adc    ptr_Hb,tmp                    ; refresh pointer for the next sample

; scale amplitude
   ldi     tmp,2
   add     addb_out,tmp
   lsr     addb_out
   lsr     addb_out                     ; divide 4 and round off
   sub     r0,addb_out                  ; 4/4 - 1/4 = 3/4
   mov     addb_out,r0                  ; now addb_out has the right amplitude

   clr     tmp
   out     OCR1AH,tmp
   mov     tmp,adda_out
   add     tmp,addb_out
   out     OCR1AL,tmp                   ; send the sum of the two amplitudes to PWM

   pop     r0                           ; Restore R0 Register
   pop     ZH
   pop     ZL                           ; Restore Z-Pointer
   pop     tmp
   out     SREG,tmp                     ; Restore SREG
   pop     tmp                          ; Restore temporary register;
   reti

;*********************************
; RESET Interrupt
;*********************************
start:
    sbi   DDRD,PD5                      ; Set pin PD5 as output
    ldi   tmp,low(RAMEND)
    out   SPL,tmp
    ldi   tmp,high(RAMEND)
    out   SPH,tmp                       ; Initialize Stackpointer

;Initialization of the registers
    clr   ptr_La
    clr   ptr_Ha
    clr   ptr_Lb
    clr   ptr_Hb                        ; Set both table ponters to 0x0000

;enable timer1 interrupt
    ldi   tmp,(1<<TOIE1)
    out   TIMSK,tmp                     ; Enable Timer1_ovf interrupt

;set timer1 PWM mode
     ldi   tmp,(1<<PWM10)+(1<<COM1A1)
     out   TCCR1A,tmp                   ; 8 bit PWM not reverse (Fck/510)
     ldi   tmp,(1<<CS10)
     out   TCCR1B,tmp                   ; prescaler = 1
     sei                                ; Enable interrupts

;**************************************************************************
; MAIN
; Read from portB (eg: using evaluation board switch) which
; tone to generate, extract mixing high frequency
; (column) and low frequency (row), and then
; fix x_SWa and x_SWb
; row    -> PINB high nibble
; column -> PINB low nibble
;**************************************************************************

main:
;high frequency (Esteem only high nibble that is row)
;PB_High_Nibble:
   ldi   tmp,0x0F
   out 	 DDRB,tmp			; High nibble Input / Low nibble. Outp. 
   ldi   tmp,0xF0
   out   PORTB,tmp			; High nibble PullUp / Low nibble Zero Outp. 
   rcall delay
   clr   count
   in    input,PINB

main10:
   inc   count
   lsl   input	    
   brcc  main20
   ldi   tmp,4
   cp    count,tmp
   brne  main10
   clr   x_SWb
   clr   count
   rjmp  main30

main20:
   dec   count
   ldi   ZL,low(frequencyL*2)
   ldi   ZH,high(frequencyL*2)
   add   ZL,count
   clr   tmp
   adc   ZH,tmp
   lpm
   mov   x_SWb,r0                    	; this is low frequency x_SW
   clr   count
   
;low frequency
;PB_Low_Nibble:
main30:
   ldi   tmp,0xF0
   out 	 DDRB,tmp			; High nibble. Outp. / Low nibble Input  
   ldi   tmp,0x0F
   out   PORTB,tmp			; High nibble Zero Outp. / Low nibble PullUp 
   rcall delay
   in    input,PINB
   swap  input

main40:
   inc   count
   lsl   input	    
   brcc  main50
   ldi   tmp,4
   cp    count,tmp
   brne  main40
   clr   x_SWa
   rjmp  main

main50:                                 ; there is a zero bit in count-1  position
   dec   count
   ldi   ZL,low(frequencyH*2)
   ldi   ZH,high(frequencyH*2)
   add   ZL,count
   clr   tmp
   adc   ZH,tmp
   lpm
   mov   x_SWa,r0                    	; this is high frequency x_SW
   rjmp  main


;******************   DELAY   ***********************************
;****************************************************************
delay:
   ldi	  tmp,delaycyc
loop:
   dec	  tmp
   brne	  loop
ret


;******************   GET SAMPLE   ******************************
;****************************************************************
getsample:
   ldi    tmp,0x0f
   and    ptr_Htmp,tmp

; ROUND	
   ldi    tmp,4
   add    ptr_Ltmp,tmp
   clr    tmp
   adc    ptr_Htmp,tmp

;shift (divide by eight):
   lsr    ptr_Htmp
   ror    ptr_Ltmp
   lsr    ptr_Htmp
   ror    ptr_Ltmp
   lsr    ptr_Htmp
   ror    ptr_Ltmp

   ldi    tmp,0x7f
   and    ptr_Ltmp,tmp                  ; module 128 (samples number sine table)

   ldi    ZL,low(sine_tbl*2)
   ldi    ZH,high(sine_tbl*2)
   add    ZL,ptr_Ltmp
   clr    tmp
   adc    ZH,tmp                        ; Z is a pointer to the correct
                                        ; sine_tbl value
   lpm
   ret

;*************************** SIN TABLE *************************************
; Samples table : one period sampled on 128 samples and
; quantized on 7 bit
;******************************************************************************
sine_tbl:
.db 64,67
.db 70,73
.db 76,79
.db 82,85
.db 88,91
.db 94,96
.db 99,102
.db 104,106
.db 109,111
.db 113,115
.db 117,118
.db 120,121
.db 123,124
.db 125,126
.db 126,127
.db 127,127
.db 127,127
.db 127,127
.db 126,126
.db 125,124
.db 123,121
.db 120,118
.db 117,115
.db 113,111
.db 109,106
.db 104,102
.db 99,96
.db 94,91
.db 88,85
.db 82,79
.db 76,73
.db 70,67
.db 64,60
.db 57,54
.db 51,48
.db 45,42
.db 39,36
.db 33,31
.db 28,25
.db 23,21
.db 18,16
.db 14,12
.db 10,9
.db 7,6
.db 4,3
.db 2,1
.db 1,0
.db 0,0
.db 0,0
.db 0,0
.db 1,1
.db 2,3
.db 4,6
.db 7,9
.db 10,12
.db 14,16
.db 18,21
.db 23,25
.db 28,31
.db 33,36
.db 39,42
.db 45,48
.db 51,54
.db 57,60

;*******************************  x_SW  ***********************************
;Table of x_SW (excess 8): x_SW = ROUND(8*N_samples*f*510/Fck)
;**************************************************************************

;high frequency (coloun)
;1209hz  ---> x_SW = 79
;1336hz  ---> x_SW = 87
;1477hz  ---> x_SW = 96
;1633hz  ---> x_SW = 107

frequencyH:
.db 107,96
.db 87,79

;low frequency (row)
;697hz  ---> x_SW = 46
;770hz  ---> x_SW = 50
;852hz  ---> x_SW = 56
;941hz  ---> x_SW = 61

frequencyL:
.db 61,56
.db 50,46




⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -