老古开发网首页
导航:老古开发网首页文章索引索引第2427页文章分类DSP数字信号处理第28页→[50%占空比输入(DSP56F805汇编)]
| -文章搜索 - 最新文章 - |

第2516篇:50%占空比输入(DSP56F805汇编)

发布时间:2006年7月26日 点击次数:885
来源:   作者:
 

;==================================
;50%占空比输入:FP_PULSE_IN
;输入量:
;输出量:nowf
;说明:我们对定时器A的计数器0的I/O引脚的输入信号记数来得到一个值N,通过计算来得到当前频率nowf
;nowf=F_MAX*1,000,000,000/(N*FP_PULSE*1000*100)=F_MAX*40000/(N*FP_PULSE)
;我们采用查询的方法,对于采样的N值,我们采用中位值平均滤波法(又称防脉冲干扰平均滤波法)来提高精度
;我们不用冒泡排序法,而是采用插值排序,边采样边排序,算法的时间复杂度要小,空间上可省去数据暂存temp
;我们对<3Hz的频率不于考虑。也就是说N>#$65b9aa时丢弃
;用到了中断,优先级1(最低)
;==================================   
FP_PULSE_IN:      
      ;--初始化定时器寄存器
   ;   bfset #$0100,x:USER1FLAG
   ;   bcc  first_one
               
   ; bfset #$00c0,x:TMRA0_SCR
   ; bra  bg
;first_one:    
      bfset #$04c0,x:TMRA0_SCR  ;上升沿和下降沿都捕捉
;bg:      
      move #$3000,x:TMRA0_CTRL  ;将位5清零,否则会出现只计数一次的情况
      bftsth #$2000,x:TMRA0_SCR  ;判断是否溢出,如果溢出则加1
      jcc  try_result
      move x:n_high16,x0
      add  #1,x0
      move x0,x:n_high16
      cmp  #$cb,x0     ;1分频的最大值的两倍
      jcc  clr_h     ;如果一没有脉冲过来我们变清空,从头开始记数
      bfclr #$2000,x:TMRA0_SCR  ;清溢出标志位
try_result:           
      move x:cap_low,x0   ;来判断是否有计算完了一个脉冲的值      
      cmp  #0,x0
      jeq  cmp_continue   ;如果等于0,则说明
      jmp  result_ok
cmp_continue:      
      move x:cap_high,x0   ;来判断是否有计算完了一个脉冲的值      
      cmp  #0,x0
      jeq  FP_PULSE_IN_END   ;两个值都为0,则说明没有记录完一个数据
      ;--下面的情况则是,记录完一个周期,我们可以把最终结果放到b中,给下面的处理程序用
result_ok:    
      move x:cap_low,b0     
      move x:cap_high,b1
      ;--*****由于使用中断所以产生了延时,分情况来调整采样数据
      move x:F_MAX,x0
      cmp  #30001,x0
      bcs  small_data
      move #$44,y0     ;*****我们用加数来调整结果
      bra  just_quick
small_data:    move #$45,y0   
just_quick:     
      move #0,y1
      add  y,b
     
      move #0,x:cap_low
      move #0,x:cap_high   ;清掉最终结果存放区,等着下一次采集数据的存放
      move #0,x:n_high16   ;清除高16位
      move #0,x:int_num   ;重新清0,从头开始计算
  ; bfset #$0400,x:TMRA0_SCR  ;开中断
      ;最后的数据放在b里面
      ;--下面开始软件滤波,我们选用插值法,排序完成后我们滤去极大极小两个值,然后在求平均值
      move x:n_num,x0      
      add  #1,x0      
      move x0,x:n_num    ;更新数据个数,原来为0的现在更新为1个
      cmp  #1,x0
      jne  big_one 
      ;--说明是第一次有数据进来
      move #$0161,r1    
      nop
      move b0,x:(r1)+    ;指针往后挪一位,指向高字节           
      nop
      move b1,x:(r1)    ;采集的第一个数完成,则回到主循环,等待采集下一个数据   
      jmp  FP_PULSE_IN_END
big_one:    
      ;--说明不是第一次来数据了
      move x:n_num,x0    ;取当前采样的数据个数值,r1作为偏移地址来用
      sub  #1,x0
      lsl  x0      ;一个数据占了两个16位,所以要*2
      add  #$0160,x0
      move x0,r1     ;指针指向采集数据队列的最后一个数据的高位
loop:     
      nop
      move x:(r1)-,y0    ;待比较的数据放y0,此时r1的值已经改变了
      move b1,y1                 
      cmp  y0,y1     ;先比较高16位
      jeq  order_cmp_goon
      jcc  just_caiy_big   ;采样值大的情况
      ;--采样值小的情况,必须还得把最后的数据(比当前采样值大的那个数)往后挪一个位置
      ;--只比较了高位,调整一下指针,然后转到order_cmp_goon中的数据往后移位执行即可
      move r1,x0
      sub  #1,x0
      move x0,r1   
      jmp  just_loop    ;开始移动大的数据
         
order_cmp_goon:  
      nop
      move x:(r1)-,y0    ;再比较低16位         
      move b0,y1
      cmp  y0,y1
      jcc  caiy_big    ;采样值大的情况 
          
      ;--采样值小的情况,必须还得把最后的数据(比当前采样值大的那个数)往后挪一个位置
just_loop:    ;--高、低位都比较过了
      move r1,x0
      add  #1,x0
      move x0,r1
      nop
      move x:(r1)+,y0    ;原先数据列最后一个数据的低16位 
      nop   
      move x:(r1)+,y1    ;高16位
      nop
      move y0,x:(r1)+
      nop
      move y1,x:(r1)    ;此时指针已经是新的数据列的最后一个数的高位了     
      ;--考虑是否已经到了最前面了,如果是,就直接把数据插入,然后判断是否已经记满了10个数据了
      move r1,x0
      cmp  #$164,x0     
      jeq  only_one      
      ;说明还没比较到最开头的一个数据,还可以比较
      move r1,x0
      sub  #4,x0
      move x0,r1     ;使指针指向除去大数以后的新数列的最后一个数据的高位        
      jmp  loop
      
only_one:    move r1,x0
      sub  #2,x0
      move x0,r1
      nop
      move b1,x:(r1)-
      move b0,x:(r1)
      jmp  over_y_n           
      
just_caiy_big:   
      ;--;采样值大的情况,只需要插入当前位置后一个位置即可   
      ;--现在的指针只是比较了一个高位的指针,和下面caiy-big进入的情况不同,它已经比较了低位了
      move r1,x0
      sub  #1,x0
      move x0,r1
            
caiy_big:    
      move r1,x0
      add  #4,x0
      move x0,r1     ;此时指针指向最后空位数据的高位
      nop
      move b1,x:(r1)-
      move b0,x:(r1)    ;此时刚刚采集的数据已经插入了
over_y_n:           
      move x:n_num,x0    ;取数据长度
      cmp  #10,x0     ;看是否采集完成
      jcc  work_sum    ;数据采集已全完成,准备求平均值      
      jmp  FP_PULSE_IN_END   ;一次采集完成
      
work_sum:      
      move #0,b0     ;初始化为0
      move #0,b1
      move #0,x0     ;用来存放加法循环的比较次数
      move #$0166,r1    ;第一个数为最小的,是我们要过滤掉的
      nop
      move x:(r1),y1    ;我们取四个数据的高位和低位来凑成准确的两个数据
      move #$0168,r1
      nop    
      move x:(r1),b1
      nop
      move #$016d,r1
      nop
      move x:(r1),y0
      move #$016f,r1
      nop 
      move x:(r1),b0
      add  y,b

      ;下面计算平均值
      move #0,b2
      rep  #1      ;让下面一条指令执行4次,也就是除以#16
      asr  b      ;****最终的结果n在b中,是个32位的数****
       
     
     ;--如果得到的频率<5Hz则丢弃
      move #$65,x0    ;n最大可能值为#$65b9aa
      cmp  b1,x0
      jcs  FP_PULSE_IN_END
      jeq  may_big
      jmp  start_change
may_big:
      move b0,x0
      cmp  #$b9ab,x0
      jcc  FP_PULSE_IN_END      
        
start_change:
      ;--以下为N值得到nowf的计算程序,我们可以采用自动发波的方法,把n值归到16bit即可,这样可以避免出现32位/32位的情况      
      
      move #0,b2     ;是为了用算术右移而清的0
      move #0,y0     ;用来存放移动次数的
      move y0,x:plus_in
just_in: 
      move b1,y1
      cmp  #0,y1
      jeq  start_now
      asr  b
      add  #1,y0     ;我们可以把y0作为下面的分频来看待,调整后的n在b0
      move y0,x:plus_in
      jmp  just_in 
start_now:    
      ;--低通滤波程序,要变化快,则小的数变大,大的数变小,但是和一定为1024
      move b0,x:jieguo      
      move #51,y0     ;原先是#51
      move x:jieguo,x0
      mpysu x0,y0,a
      asr a
      move #973,y0     ;原先是#973
      move x:jieguo2,x0
      mpysu x0,y0,b
      asr b
      add b,a       ;无符号计算要注意
      rep #6
      asl a       
      move a1,x:jieguo2
      move a1,b0
      ;--低通滤波结束
      
      move x:F_MAX,y0    ;我们先做上限频率*#20000(可以提高精度)这里我们应该乘#40000是因为采集的是一个周期的时间,放到最后调整
      move #20000,x0
      mpysu x0,y0,a 
      asr a
      asl a       ;--调整结果,我们实际得到的是一个周期,所以要*2      
      ;--n是16bit,准备调用div_32by16
      move a0,y0
      move a1,a0    
      move b0,x0     ;b0只有低16位有用,高16位为0,因为上面调整过了         
      ;--得到的结果在a0,y0中
      jsr div_32by16    
      move a0,b1
      move y0,b0     ;将结果放入b中最大值#$2faf0800
      move x:plus_in,y1   ;是n值除2的次数,也可以看成分频数
      cmp  #0,y1     ;如果为0则无须乘该数,否则出错
      jeq  direct
      move #1,x0
      move #2,y0
      do  y1,end
      impy y0,x0,a
      move a1,x0
end:      
      move x0,y1 
      move x:FP_PULSE,y0
      mpysu y0,y1,a
      asr a       ;得到的结果肯定a1=0,最大值10
      jmp  chu
      
direct:     move x:FP_PULSE,a0      
      
chu:
      ;--准备调用div_32by16
      move a0,x0
      
      move b1,a0
      move b0,y0
      jsr div_32by16  
      move a0,a1
      move y0,a0     ;得到的结果最大为#40000,所以只有a0有用
      
      ;--下面我们开始四舍五入调整结果
      move x:F_MAX,x0
      cmp  #10001,x0
      jcs  small_max            
      move #20,x0
      bra  startdiv
small_max:   
      move #10,x0 
startdiv:      
      asl a
      bfclr #$1,sr
      rep  #16
      div  x0,a
      move a0,y1
      add  x0,a
     ; asr  a      ;我们不调整了,直接判断四舍五入 
      move a1,y0
      cmp  y0,x0      
      jcc  small_ok
      add  #1,y1
small_ok: 
      mpysu x0,y1,a 
      asr a       ;得到最终结果
      
      ;--保证不要超过最大频率
      move x:F_MAX,x0
      move a0,y0
      cmp  y0,x0
      jcc  no_problem
      move x0,a0     ;如果超过了最大频率则赋予最大频率值 
no_problem:        
      
      move a0,x:iout00     
      jmp  clr_data
      
clr_h:    
      move #0,x:iout00    ;没有脉冲过来则清0
clr_data:
      move #0,x:n_high16   ;将用来捕捉高16位的数据单元清空,为了下次捕捉      
     ;--初始化接收数据区,最好是系统复位或者是开机时候初始化一下,因为要放到主程序里采集数据所以放在前面初始化不行
      move #0,x:n_num 
      move #0,x:n_buf1_1   
      move #0,x:n_buf1_2 
      move #0,x:n_buf2_1 
      move #0,x:n_buf2_2
      move #0,x:n_buf3_1 
      move #0,x:n_buf3_2 
      move #0,x:n_buf4_1
      move #0,x:n_buf4_2 
      move #0,x:n_buf5_1 
      move #0,x:n_buf5_2 
      move #0,x:n_buf6_1 
      move #0,x:n_buf6_2 
      move #0,x:n_buf7_1 
      move #0,x:n_buf7_2 
      move #0,x:n_buf8_1 
      move #0,x:n_buf8_2
      move #0,x:n_buf9_1 
      move #0,x:n_buf9_2 
      move #0,x:n_buf10_1
      move #0,x:n_buf10_2 
      move #0,x:n_high16
      move #0,x:int_num
      move #0,x:int_cap1
      move #0,x:int_cap3
      move #0,x:int_cap3_h
      move #0,x:plus_in
      
FP_PULSE_IN_END:
    


欢迎进入老古论坛进行讨论
[DSP数字信号处理] 相关文章:
ADC和DAC应用中被忽略的几个关键参数(转)
简介:
ADC和DAC应用中被忽略的几个关键参数 在前面一个讨论7135的贴子里,提到了INL、DNL等几个参数,可是似乎知道这几个参数意义的朋友并不多。 说起来都是教科书害人。几乎所有的教科书、参考书、文献选编都只关心模数器件的分辨率和速度,而忽略了器件的精度。而关系到器件精度的两个非常重要的参数就是INL值和DNL值。小弟觉得非常有必要专门写一篇贴子来普及一下模数器件精度......

430端口介绍
基于TMS320F240的PID和PWM温度控制
ADC输入电路的正确处理(转)
32位MCU-DSP内核结构与嵌入式开发系统
 
下一个:[DSP数字信号处理]50%占空比输出(DSP56F805汇编)
简介:
;50%占空比输出:FP_PULSE_OUT ;输入量:FP_PULSE(5k_10k) ;输出量: ;说明:T=F_MAX/(FP_PULSE*nowf*1000) 我们选1分频,T(s)=N*25(ns)*2,后面*2是因为我们输出的是50%占空比 ;N即为我们要设的预计记数值 ;N=F_MAX*1,000,000,000/(nowf*FP_PULSE*1000*50)=F_MAX*20000/(nowf*FP_PULSE) ;我们对&lt;3Hz的频率不于考虑。也就是说N&l......

上一个:[DSP数字信号处理]TMS320LF2407异步串行例子

老古开发网版权所有 2006年9月 asp.Net V2.0 设计:老古
页面缓存:30分钟 执行时间:63毫秒