打印

AD转换程序如何与FIR程序接口实现DSP的实时滤波?

[复制链接]
4078|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
yuxingming|  楼主 | 2009-2-18 11:20 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
现在的教科书上的DSP的数字滤波器例子程序都只给出了FIR算法实现的程序,输入波形数据要在电脑中做成数据文件注入,这不符合实际。本人编写了一个通过TLC320AD50C采样后输入FIR程序进行滤波的汇编语言程序,但可能是AD转换程序与FIR程序的接口部分程序没有写好,滤波器没有成功。我把程序写在这里,请大虾指教!
;*********************** On Line FIR Filter **************************    

STACK_ADDR    .set    0x0500
SIZE        .set    10
    
    .bss    Buffer_new, 16        ;(10 for circular buffer)
    .bss    Buffer_old, 16        ;(10 for circular buffer)
    .bss    Input, 1
    .bss    Output, 1
    .include MMRegs.h

    .global    main
    
    .text

main:
;******************InitC5402***************************************
    
    NOP
    LD #0, DP ; reset data–page pointer
    STM #0, CLKMD             ; software setting of DSP clock
    STM #0, CLKMD             ; (to divider mode before setting)
TstStatu1:
        LDM CLKMD, A
        AND #01b, A                 ;poll STATUS bit
        BC TstStatu1, ANEQ    
    STM #0xF7FF, CLKMD         ; set C5402 DSP clock to 10MHzv            
******* Configure C5402 System Registers *******
    STM #0x7fff, SWWSR         ; 2 wait cycle for IO space & 0 wait cycle                         ; for data&prog spaces
    STM #0x0000,BSCR             ; set wait states for bank switch:
                        ; 64k mem bank, extra 0 cycle between
                        ; consecutive prog/data read
    stm    #STACK_ADDR, SP
                    
******* Set up Timer Control Registers *******
    STM #0x0010, TCR             ; stop on–chip timer0
    STM #0x0010, TCR1             ; stop on–chip timer1
; Timer0 is used as main loop timer
;    STM #2499, PRD ; timer0 rate=CPUCLK/1/(PRD+1)
; =40M/2500=16KHz
* STM #6249, PRD ; if CPU at 100M/6250=16KHz  

    
******* Initialize McBSP1 Registers *******
    STM SPCR1, McBSP1_SPSA ; register subaddr of SPCR1
    STM #0000h, McBSP1_SPSD ; McBSP1 recv = left–justify
; RINT generated by frame sync
    STM SPCR2, McBSP1_SPSA ; register subaddr for SPCR2
; XINT generated by frame sync
    STM #0000h, McBSP1_SPSD ; McBSP1 Tx = FREE(clock stops
; to run after SW breakpoint
    STM RCR1, McBSP1_SPSA ; register subaddr of RCR1
    STM #0040h, McBSP1_SPSD ; recv frame1 Dlength = 16 bits
    STM RCR2, McBSP1_SPSA ; register subaddr of RCR2 
    STM #0040h, McBSP1_SPSD ; recv Phase = 1
; ret frame2 Dlength = 16bits
    STM XCR1, McBSP1_SPSA ; register subaddr of XCR1
    STM #0040h, McBSP1_SPSD ; set the same as recv
    STM XCR2, McBSP1_SPSA ; register subaddr of XCR2
    STM #0040h, McBSP1_SPSD ; set the same as recv
    STM PCR, McBSP1_SPSA ; register subaddress of PCR
    STM #000eh, McBSP1_SPSD ; clk and frame from external (slave)
; FS at pulse–mode(00)
******* Finish DSP Initialization *******
    STM #0x0000, IMR ; disable peripheral interrupts
    STM #0xFFFF, IFR ; clear the intrupts’ flags
    NOP
    NOP 
    

******************************************
******************************************
_OpenMcBSP:

    stm    1000h,ar0
       st         00,*ar0
    portw     *ar0,8001h               ;reset AD50  XF=0
    NOP
    NOP
    NOP
    NOP
    STM     SPCR1, McBSP1_SPSA     ; enable McBSP1 RX for ADC data in
    LDM     McBSP1_SPSD,A
    OR         #0x0001, A
    STLM     A, McBSP1_SPSD
    STM     SPCR2, McBSP1_SPSA     ; enable McBSP1 TX for DTMF out
    LDM     McBSP1_SPSD,A
    OR         #0x0001, A
    STLM     A, McBSP1_SPSD
    LD         #0h, DP             ; load data page 0
    RPT         #23
    NOP  
    STM      1000h, AR0
    ST       0xff, *AR0
    PORTW      *AR0,8001h         ;out reset aD50 XF=1
    NOP
    NOP

    CALL IfTxRDY1
    STM #0x0001, McBSP1_DXR1    ;request secondary communication
    NOP
    CALL IfTxRDY1 
    STM #0100h, McBSP1_DXR1    ;write 00h to register 1

    CALL IfTxRDY1
    STM #0000h, McBSP1_DXR1 
    
    NOP
    NOP
    RPT    #20h
    NOP
           
    CALL     IfTxRDY1
    STM     #0x0001, McBSP1_DXR1    ;request secondary communication
    CALL     IfTxRDY1 
    STM     #0200h, McBSP1_DXR1    ;write 00h to register 2 
    
    CALL     IfTxRDY1
    STM     #0000h, McBSP1_DXR1     
                
       CALL     IfTxRDY1
    STM     #0x0001, McBSP1_DXR1    ;request secondary communication
    CALL     IfTxRDY1 
    STM     #0300h, McBSP1_DXR1    ;write 00h to register 3

    CALL     IfTxRDY1
    STM     #0000h, McBSP1_DXR1 

    CALL     IfTxRDY1
    STM     #0x0001, McBSP1_DXR1    ;request secondary communication
    CALL     IfTxRDY1 
    STM     #0490h, McBSP1_DXR1        ;write 00h to register 4
                                    ;bypass internal DPLL
                                    ;and select the Sample Frequency  

    CALL     IfTxRDY1
    STM     #0000h, McBSP1_DXR1 
    
;    CALL     IfTxRDY1
;    STM     #0x0001, McBSP1_DXR1
;    CALL     IfTxRDY1
;    STM     #0102h, McBSP1_DXR1     ;enable digital loopback     
        
;    CALL     IfTxRDY1
;    STM     #0x0001, McBSP1_DXR1
;    CALL     IfTxRDY1
;    STM     #0208h, McBSP1_DXR1     ;enable analog loopback

    NOP
    NOP


_READAD50:
    CALL       IfRxRDY1
    NOP
    NOP
    ldm      McBSP1_DRR1,b
    stl      b, *(Input)
    
    nop
    nop 
    
;------------------------------------------------------------------------------

    ;clear buffer
    stm        #Buffer_new, AR2
    rptz        A, #SIZE-1
    stl        A, *AR2+

    stm        #Buffer_old, AR3
    rptz        A, #SIZE-1
    stl        A, *AR3+

    ;add last half coefficients for FFT display
    stm        #FIR_Coeff, AR4
    stm        #FIR_Coeff+2*SIZE-1, AR2
    rpt        #SIZE-1
    mvdd        *AR4+, *AR2-

    stm        #Buffer_new, AR2
    stm        #Buffer_old, AR3
    stm        #SIZE, BK
    stm        #-1, AR0
fir_loop:
    ;read input
    ld        *(Input), A
    stl        A, *AR2

    ;filtering
    add        *AR2+0%, *AR3+0%, A
    rptz        B, #SIZE-1
    firs        *AR2+0%, *AR3+0%, FIR_Coeff
    sth        B, *(Output)            ;store output
    call     IfTxRDY1 
    ldu        *(Output), B
    and     #0fffeh, B             ;mask the LSB
    stlm        B, McBSP1_DXR1
    NOP
    mar        *+AR2(2)%
    mar        *AR3+%
    mvdd        *AR2, *AR3+0%             ;update buffer
    b        fir_loop
    nop
    nop


;------------------------------------------------------------------------------
    .data
FIR_Coeff:
    .word    53, 190, -364, -277, 152
    .word    -124, 3789, -2052, -8950, 7631
;------------------------------------------------------------------------------


;******* Waiting for McBSP0 RX Finished *******
IfRxRDY1:
    NOP
    STM     SPCR1, McBSP1_SPSA         ; enable McBSP1 Rx
    LDM     McBSP1_SPSD, A
    AND     #0002h, A                 ; mask RRDY bit
    BC     IfRxRDY1, AEQ             ; keep checking
    NOP
    NOP
    RET                         ; return
    NOP
    NOP

******* Waiting for McBSP0 TX Finished *******
IfTxRDY1:
    NOP
    STM     SPCR2, McBSP1_SPSA         ; enable McBSP1 Tx
    LDM     McBSP1_SPSD, A
    AND     #0002h, A                 ; mask TRDY bit
    BC     IfTxRDY1, AEQ             ; keep checking 
    NOP
    NOP
    RET                         ; return
    NOP
    NOP

;-------------------------------------------------------------------------------------------
dead_loop:
    nop
    nop
    nop
    nop
    b        dead_loop

;------------------------------------------------------------------------------
    .sect    "vectors"
int_RESET:
    b        main
    nop
    nop

    .space    124*16
    
    .end
*********************************************************************
** End of File –– InitC5402.asm
*********************************************************************


相关帖子

沙发
yuxingming|  楼主 | 2009-2-18 11:31 | 只看该作者

AD转换程序如何与FIR程序接口实现DSP的实时滤波?

原来的DSP初始化程序及AD数据采样程序是这样的:
    .global _InitC5402 
    .global _OpenMcBSP
    .global _CloseMcBSP 
    .global _READAD50 
    .global _WRITEAD50
    .include MMRegs.h
_InitC5402:
    NOP
    LD #0, DP ; reset data–page pointer
    STM #0, CLKMD ; software setting of DSP clock
    STM #0, CLKMD ; (to divider mode before setting)
TstStatu1:
    LDM CLKMD, A
    AND #01b, A ;poll STATUS bit
    BC TstStatu1, ANEQ    
    STM #0xF7FF, CLKMD ; set C5402 DSP clock to 10MHzv            
* STM #0x4007, CLKMD ; set C5402 DSP clock to 100MHz
; (based on DSK crystal at 20MHz)
******* Configure C5402 System Registers *******
    STM #0x7fff, SWWSR ; 2 wait cycle for IO space &
; 0 wait cycle for data&prog spaces
    STM #0x0000,BSCR ; set wait states for bank switch:
; 64k mem bank, extra 0 cycle between
; consecutive prog/data read
;    STM #0x1800,ST0 ; ST0 at default setting
;    STM #0x2900,ST1 ; ST1 at default setting(note:INTX=1)
;    STM #0x00A0,PMST ; MC mode & OVLY=1, vectors at 0080h
******* Set up Timer Control Registers *******
    STM #0x0010, TCR ; stop on–chip timer0
    STM #0x0010, TCR1 ; stop on–chip timer1
; Timer0 is used as main loop timer
;    STM #2499, PRD ; timer0 rate=CPUCLK/1/(PRD+1)
; =40M/2500=16KHz
* STM #6249, PRD ; if CPU at 100M/6250=16KHz  


    
******* Initialize McBSP1 Registers *******
    STM SPCR1, McBSP1_SPSA ; register subaddr of SPCR1
    STM #0000h, McBSP1_SPSD ; McBSP1 recv = left–justify
; RINT generated by frame sync
    STM SPCR2, McBSP1_SPSA ; register subaddr for SPCR2
; XINT generated by frame sync
    STM #0000h, McBSP1_SPSD ; McBSP1 Tx = FREE(clock stops
; to run after SW breakpoint
    STM RCR1, McBSP1_SPSA ; register subaddr of RCR1
    STM #0040h, McBSP1_SPSD ; recv frame1 Dlength = 16 bits
    STM RCR2, McBSP1_SPSA ; register subaddr of RCR2 
    STM #0040h, McBSP1_SPSD ; recv Phase = 1
; ret frame2 Dlength = 16bits
    STM XCR1, McBSP1_SPSA ; register subaddr of XCR1
    STM #0040h, McBSP1_SPSD ; set the same as recv
    STM XCR2, McBSP1_SPSA ; register subaddr of XCR2
    STM #0040h, McBSP1_SPSD ; set the same as recv
    STM PCR, McBSP1_SPSA ; register subaddress of PCR
    STM #000eh, McBSP1_SPSD ; clk and frame from external (slave)
; FS at pulse–mode(00)
******* Finish DSP Initialization *******
    STM #0x0000, IMR ; disable peripheral interrupts
    STM #0xFFFF, IFR ; clear the intrupts’ flags
    RET ; return to main
    NOP
    NOP 
    
******* Waiting for McBSP0 RX Finished *******
IfRxRDY1:
    NOP
    STM SPCR1, McBSP1_SPSA ; enable McBSP1 Rx
    LDM McBSP1_SPSD, A
    AND #0002h, A ; mask RRDY bit
    BC IfRxRDY1, AEQ ; keep checking
    NOP
    NOP
    RET ; return
    NOP
    NOP
******* Waiting for McBSP0 TX Finished *******
IfTxRDY1:
    NOP
    STM SPCR2, McBSP1_SPSA ; enable McBSP1 Tx
    LDM McBSP1_SPSD, A
    AND #0002h, A ; mask TRDY bit
    BC IfTxRDY1, AEQ ; keep checking 
    NOP
    NOP
    RET ; return
    NOP
    NOP

******************************************
******************************************
_OpenMcBSP:

    stm    1000h,ar0
    st     00,*ar0
    portw *ar0,8001h   ;reset AD50  XF=0
    NOP
    call wait
    NOP
    NOP
    NOP
    STM SPCR1, McBSP1_SPSA ; enable McBSP1 RX for ADC data in
    LDM McBSP1_SPSD,A
    OR #0x0001, A
    STLM A, McBSP1_SPSD
    STM SPCR2, McBSP1_SPSA ; enable McBSP1 TX for DTMF out
    LDM McBSP1_SPSD,A
    OR #0x0001, A
    STLM A, McBSP1_SPSD
    LD #0h, DP ; load data page 0
    rpt #23
    NOP  
    stm  1000h,ar0
    st    0xff,*ar0
    portw  *ar0,8001h ;out reset aD50 XF=1
    NOP
    NOP
   ; STM 0x4007,CLKMD    
;    CALL IfTxRDY1
;    STM #0x0101, McBSP1_DXR1
    
;    CALL IfTxRDY1
;    STM #0x0208, McBSP1_DXR1

;;    rsbx    xf
;;  NOP
;;NOP       
    CALL IfTxRDY1
    STM #0x0001, McBSP1_DXR1;request secondary communication
    NOP
    CALL IfTxRDY1 
    STM #0100h, McBSP1_DXR1;write 00h to register 1

    CALL IfTxRDY1
    STM #0000h, McBSP1_DXR1 
    
    NOP
    NOP
    rpt #20h
    nop
           
    CALL IfTxRDY1
    STM #0x0001, McBSP1_DXR1;request secondary communication
    CALL IfTxRDY1 
    STM #0200h, McBSP1_DXR1;write 00h to register 2 
    
    CALL IfTxRDY1
    STM #0000h, McBSP1_DXR1     
                
       CALL IfTxRDY1
    STM #0x0001, McBSP1_DXR1;request secondary communication
    CALL IfTxRDY1 
    STM #0300h, McBSP1_DXR1;write 00h to register 3

    CALL IfTxRDY1
    STM #0000h, McBSP1_DXR1 

    CALL IfTxRDY1
    STM #0x0001, McBSP1_DXR1;request secondary communication
    CALL IfTxRDY1 
    STM #0490h, McBSP1_DXR1;write 00h to register 4
                            ;bypass internal DPLL
                            ;and select the Sample Frequency  

    CALL IfTxRDY1
    STM #0000h, McBSP1_DXR1 
    
;    CALL IfTxRDY1
;    STM #0x0001, McBSP1_DXR1
;    CALL IfTxRDY1
;    STM #0102h, McBSP1_DXR1 ;enable digital loopback     
        
;    CALL IfTxRDY1
;    STM #0x0001, McBSP1_DXR1
;    CALL IfTxRDY1
;    STM #0208h, McBSP1_DXR1 ;enable analog loopback

    RET
    NOP
    NOP

 
*********************
_CloseMcBSP:
    STM SPCR1, McBSP1_SPSA ; disable McBSP0 RX
    LDM McBSP1_SPSD,A
    AND #0xFFFE, A
    STLM A, McBSP1_SPSD
    STM SPCR2, McBSP1_SPSA ; disable McBSP0 TX
    LDM McBSP1_SPSD,A
    AND #0xFFFE, A
    STLM A, McBSP1_SPSD
    RPT #5
    RET
    NOP
    NOP



_READAD50:
    stm        0x00ff,ar3
    stm        0x3000,ar2
    
loopa:
    CALL IfRxRDY1
    ldm      McBSP1_DRR1,b
    stl      b,*ar2+
    banz  loopa,*ar3- 
    
    nop
    nop 
    ret
    nop
    nop
    
_WRITEAD50:
    stm        0x00ff,ar3
    stm        0x3100,ar2
loopb:
    CALL     IfTxRDY1   
    ldu        *ar2+,B
    and     #0fffeh,b ;mask the LSB
    stlm    B, McBSP1_DXR1
    banz    loopb,*ar3-
    nop
    nop
    ret
    nop
    nop 
    
wait: 
    stm     20h,ar3
loop1:              
    stm     020h,ar4
loop2:
    banz     loop2,*ar4-
    banz     loop1,*ar3-
    ret     
    nop
    nop
    nop
    nop
    
    .end
************************************************************************
** End of File –– InitC5402.asm
************************************************************************


而FIR程序是这样的:
STACK_ADDR        .set        0x0500
SIZE            .set        10
    .global input
    .bss    Buffer_new, 16        ;(10 for circular buffer)
    .bss    Buffer_old, 16        ;(10 for circular buffer)
    .bss    Input, 1
    .bss    Output, 1

    .mmregs
    .global    main

;------------------------------------------------------------------------------
    .text
main:
    stm        #STACK_ADDR, SP
    stm        #0x00a8, PMST        ;store IPTR
    stm        #0x0000, SWWSR

    ssbx    FRCT
    ssbx    OVM
    ssbx    SXM

    ;clear buffer
    stm        #Buffer_new, AR2
    rptz        A, #SIZE-1
    stl        A, *AR2+

    stm        #Buffer_old, AR3
    rptz        A, #SIZE-1
    stl        A, *AR3+

    ;add last half coefficients for FFT display
    stm        #FIR_Coeff, AR4
    stm        #FIR_Coeff+2*SIZE-1, AR2
    rpt        #SIZE-1
    mvdd        *AR4+, *AR2-

    stm        #Buffer_new, AR2
    stm        #Buffer_old, AR3
    stm        #SIZE, BK
    stm        #-1, AR0
fir_loop:
    ;read input
    ld        *(Input), A
    stl        A, *AR2

    ;filtering
    add        *AR2+0%, *AR3+0%, A
    rptz        B, #SIZE-1
    firs        *AR2+0%, *AR3+0%, FIR_Coeff
    sth        B, *(Output)        ;store output
    mar        *+AR2(2)%
    mar        *AR3+%
    mvdd        *AR2, *AR3+0%     ;update buffer
    b        fir_loop

dead_loop:
    nop
    nop
    nop
    nop
    b        dead_loop

;------------------------------------------------------------------------------
    .sect    "vectors"
int_RESET:
    b        main
    nop
    nop

    .space    124*16
;------------------------------------------------------------------------------
    .data
FIR_Coeff:
    .word    53, 190, -364, -277, 152
    .word    -124, 3789, -2052, -8950, 7631
;------------------------------------------------------------------------------

;end of lab6.s54        

如何把这两个程序连接起来,实现实时的滤波功能?请大虾指教,最好帮助连接好,不胜感激!
















使用特权

评论回复
板凳
yuxingming|  楼主 | 2009-2-20 20:43 | 只看该作者

AD转换程序如何与FIR程序接口实现DSP的实时滤波?

怎么一个帮忙的都没有!好失望.........
老狼,老狼呢?

使用特权

评论回复
地板
老狼| | 2009-2-21 00:59 | 只看该作者

晕!

1:开一个定时器,在定时器里面进行AD转化,同时设定FIR_START_LBL=0;这是为了保证每个采样点间的等间隔。采样数据存储到一个数组里面,每采集一次,counter加一,,counter=0,这个数组最好大于你的基波采样点的10倍,这样方便调程序。
2:FIR放到主程序,当数组的数据达到你的FIR参数长度时,FIR_START_LBL=1;开始启动一次FIR程序(只进行一次FIR,就是去掉你FIR程序外面的那个大循环),输出第一个滤波数据,AD采集一次,启动一次FIR.
3:当counter到数组尾的时候,停止程序,看输出波形。如果你能调到这一步,就基本上能看到实时滤波的效果了。
4:修改上述程序,达到真正的实时滤波。主要是AD采样数组循环存贮!这部分你动一下脑子!

算法可以用汇编写,主程序就用C吧!看着麻烦!修改起来也不方便!

使用特权

评论回复
5
老狼| | 2009-2-21 01:27 | 只看该作者

最近发现自己的语言表达能力真的很差!

unsigned char FIR_START_LBL=0;//FIR启动标志,当数组的数据达到你的FIR参数长度时,FIR_START_LBL=1
unsigned short int counter;//AD每采集一次,counter加一
unsigned ADInput[320];//假设每个波采集32点
unsigned char AD_NewData_Lbl;
Timer()
{
    ADInput[counter]=AD_Start()//采集一次,采样数据存储到一个数组里面,
   counter++
   AD_NewData_Lbl=1;//有新的数据进来
   if(counter>=320)
   {
       counter=0;  //断点设在这里,前3步在这里调试完,第4步,需要修改这里。怎么修改?自己想!
   }
}

main()
{
......
   FIR_START_LBL=0;
   while(1)
   {
      ......
      if(counter>FIRCOF)//FIRCOF FIR参数长度
      {
          FIR_START_LBL=1;
      }

      if(1==FIR_START_LBL)
      {
         if(1==AD_NewData_Lbl)//采集一个点,启动一次FIR程序
         {
             AD_NewData_Lbl=0;
             FirOut[FirOutCounter]= FIR_OnlyOne();
             FirOutCounter++;
         }
      }
      
   }

}

//基本上,就是这个逻辑了!

使用特权

评论回复
6
computer00| | 2009-2-21 09:56 | 只看该作者

通常实时滤波不是这么干的吧...

俺用的是像卷积那样的,每输入一个数据,然后移位,做乘加运算,输出一个结果。

使用特权

评论回复
7
老狼| | 2009-2-21 12:26 | 只看该作者

computer00

‘像卷积那样的,每输入一个数据,然后移位,做乘加运算,输出一个结果’
--------这部分在函数FIR_OnlyOne()中实现的。

对于FIR,实际上,输入的缓冲区大小,对于N级的FIR滤波器,在数据存储器中开辟一个称之为滑窗的N个单元的缓冲区,滑窗中存放最新的N个输入样本。每次输入新的样本时,一新样本改写滑窗中的最老的数据,而滑窗中的其他数据不需要移动。这些在第4部进行修改,也可以不这样修改,加大输入输出缓冲区,是为了可以在Graph中,方便看到滤波的效果。而且,很多时候,需要保存原始数据和滤波后的数据。

这里还加了一个输入缓冲区的控制FIR_START_LBL,必须先有N个数据,才能做一次FIR_OnlyOne(),输出一个数据,结果保存在FirOut[]中。也可以方便的用
Graph看到。

使用特权

评论回复
8
yuxingming|  楼主 | 2009-2-22 21:51 | 只看该作者

AD转换程序如何与FIR程序接口实现DSP的实时滤波?

谢谢老狼,谢谢大家!
我再试试.

使用特权

评论回复
9
小研究| | 2009-2-25 09:10 | 只看该作者

滤波通常是采样一点滤波一点

滤波完事之后再扔到存储区里。

使用特权

评论回复
10
zhu_chunyan86| | 2015-1-8 10:06 | 只看该作者

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

4

帖子

0

粉丝