简单来说这段代码是用来做FIR+RMS计算的。FIR的部分是直接用TI的例程的。RMS算法部分是自己写了。
AD采集得到数据由CLA读取中断和采样结果,并且进行数字滤波。
RMS算法的部分就是每次滤波完的数据都求一次平方,并且累加。同时设定某一个阀值Vth,当电压超过Vth时认为是采样满了一个周期,得到将所得平方和开放求平均开方得到有效值。再输出到CLA的通讯RAM中。代码如下,内含错误若干。已经改了几个通宵了,第一次写汇编被这么简单的程序纠结了。。望各位大哥帮小弟个忙。没看懂的程序部分请留言。
@dontium ~
- MMOV32 MR0,@_X4 ;1 Load MR0 with X4
- MMOV32 MR1,@_A4 ;2 Load MR1 with A4
- MNOP ;3 Wait till I8 to read result
- MNOP ;4 Wait till I8 to read result
- MNOP ;5 Wait till I8 to read result
- MNOP ;6 Wait till I8 to read result
- MNOP ;7 Wait till I8 to read result
- MUI16TOF32 MR2, @_AdcResult.ADCRESULT1 ;8 Read ADCRESULT1 and convert to float
- MMPYF32 MR2, MR1, MR0 ; MR2 (Y) = MR1 (A4) * MR0 (X4)
- || MMOV32 @_X0, MR2
- MMOVD32 MR0,@_X3 ; Load MR0 with X3, Load X4 with X3
- MMOV32 MR1,@_A3 ; Load MR1 with A3
-
- MMPYF32 MR3, MR1, MR0 ; MR3 (Y) = MR1 (A3) * MR0 (X3)
- || MMOV32 MR1,@_A2 ; Load MR1 with A2
- MMOVD32 MR0,@_X2 ; Load MR0 with X2, Load X3 with X2
- MMACF32 MR3, MR2, MR2, MR1, MR0 ; MR3 = A3*X3 + A4*X4
- || MMOV32 MR1,@_A1 ; MR2 = MR1 (A2) * MR0 (X2)
- MMOVD32 MR0,@_X1 ; Load MR0 with X1, Load X2 with X1
- MMACF32 MR3, MR2, MR2, MR1, MR0 ; MR3 = A2*X2 + (A3*X3 + A4*X4)
- || MMOV32 MR1,@_A0 ; MR2 = MR1 (A1) * MR0 (X1)
- MMOVD32 MR0,@_X0 ; Load MR0 with X0, Load X1 with X0
- MMACF32 MR3, MR2, MR2, MR1, MR0 ; MR3 = A1*X1 + (A2*X2 +A3*X3 + A4*X4)
- || MMOV32 MR1,@_A0 ; MR2 = MR1 (A0) * MR0 (X0)
- MADDF32 MR3, MR3, MR2 ; MR3 = A0*X0 + (A1*X1 + A2*X2 +A3*X3 + A4*X4)
- MF32TOUI16 MR2, MR3 ; Get back to Uint16 value
- MMOV16 @_VoltFilt, MR2 ; Output
- .if CLA_DEBUG == 1
- MDEBUGSTOP
- .endif
- MMOV32 MR1, @_Vavr
- MSUBF32 MR3, MR3, MR1 ; use the current average votage for blocking
- MMOV32 MR1, @_Vavrc ; calculate the total votage for the average calc
- MADDF32 MR1, MR1, MR3
- MMOV32 @_Vavrc, MR1
- MMPYF32 MR2, MR3, MR3 ; calculate the total power for the rms calc
- || MMOV32 MR1, @_Vrmsc
- MADDF32 MR1, MR1, MR2
- MMOV32 @_Vrmsc, MR1
- MMOVZ16 MR1, @_calcnum ; N+1
- MMOVZ16 MR0, @_TRUE_Value
- MADD32 MR1, MR0, MR1
- MMOV16 @_calcnum, MR1
- MUI16TOF32 MR2, @_Vth ; load MR2 with the votage threshold
- MCMPF32 MR3,MR2 ; compare the votage and its threshold
- MNOP
- MNOP
- MNOP
- MBCNDD aboveVth,GT ; if votage is larger than its threshold,then jump to the aboveVth and do the calcalation
- MNOP
- MNOP
- MNOP
- ;MMOVIZ MR0, #0.0 ; clear the check flag
- ;MF32TOUI16 MR0, MR0
- ;MMOV16 @_Frag, MR0
- MMOV16 MAR0, @_FALSE_Value
- MMOV16 @_Frag, MAR0
- MNOP
- MNOP
- MNOP
- MBCNDD Tsk7STOP, UNC ; jump to the end of the task
- MNOP
- MNOP
- MNOP
- aboveVth: MUI16TOF32 MR2, @_Frag ; load MR2 with the Flag
- .if CLA_DEBUG == 1
- MDEBUGSTOP
- .endif
- MMOVF32 MR0, #0.0
- ;MF32TOI32 MR0, MR0
- MCMPF32 MR2, MR0 ; compare Frag with 0
- MNOP
- MNOP
- MNOP
- MBCNDD Tsk7STOP,GT ; if Frag is biger than 0,which means it has been set to 1 and has been calclated ,Jump to the end
- MNOP
- MNOP
- MNOP
- MMOV16 MAR0,@_TRUE_Value ; set the Frag
- MMOV16 @_Frag,MAR0
- MNOP
- MNOP
- MNOP
- MNOP
- MMOV32 MR1, @_calcnum ;calc the average of the RMS
- MMOV16 MAR1, @_calcnum
- MNOP
- MNOP
- MNOP
- MNOP
- MMOV16 @_calcPRD, MAR1
- MNOP
- MNOP
- MNOP
- MNOP
- MEINVF32 MR0, MR1
- MMOV32 MR1, @_Vrmsc
- MMPYF32 MR2, MR0, MR1
- MMOV32 @_Vrms, MR2 ;load the Vrms with MR2
- MDEBUGSTOP
- ;MMOV32 MR0, @_invn ;calc the average of the RMS
- MMOV32 MR1, @_Vavrc
- MMPYF32 MR2, MR0, MR1
- MMOV32 @_Vavr, MR2 ;load the Vrms with MR2
- MMOVIZ MR0, #0.0
- MUI16TOF32 MR0, MR0
- MMOV32 @_Vavrc, MR0
- MMOV32 @_Vrmsc, MR0
- MMOVI16 MAR0, #0
- MMOV16 @_calcnum,MAR0
- MNOP
- MNOP
- MNOP
- MNOP
- Tsk7STOP: MSTOP ; End task
看了好久,也没看出什么名堂。给你提点建议吧:
1、第8行前可以不用NOP,------只要不是提前产生EOC。
2、第10行以后的运算,最好一步一步地调试。在语句中很难发现错误所在。
即,执行每一步后,寄存器的值是多少,然后验算一下是不是这个值。我调试时就采用这种办法,不然很难发现寄存器应用错误。
3、第36行,可以不用这样处理。因为CLA只有在调试时连接它时MDEBUGSTOP语句才使程序暂停,其它情况,即使在调试时,只要未连接它或非DEBUG模式,它只作为NOP指令。
4、从存储器中取连续数据并运算时,可以考虑使用象MMOV32 MR0, *MAR0[2]++形式。
5、取数,也可以考虑使用MMOVD32 MRa, mem32
; sum = X0*B0 + X1*B1 + X2*B2 + Y1*A1 + Y2*B2
;
; X2 = X1
; X1 = X0
; Y2 = Y1
; Y1 = sum
;
_Cla1Task2:
MMOV32 MR0, @_B2 ; MR0 = B2
MMOV32 MR1, @_X2 ; MR1 = X2
MMPYF32 MR2, MR1, MR0 ; MR2 = X2*B2
|| MMOV32 MR0, @_B1 ; MR0 = B1
MMOVD32 MR1, @_X1 ; MR1 = X1, X2 = X1
MMPYF32 MR3, MR1, MR0 ; MR3 = X1*B1
|| MMOV32 MR0, @_B0 ; MR0 = B0
MMOVD32 MR1, @_X0 ; MR1 = X0, X1 = X0
; MR3 = X1*B1 + X2*B2, MR2 = X0*B0
; MR0 = A2
MMACF32 MR3, MR2, MR2, MR1, MR0
|| MMOV32 MR0, @_A2
MMOV32 MR1, @_Y2 ; MR1 = Y2
; MR3 = X0*B0 + X1*B1 + X2*B2, MR2 = Y2*A2
; MR0 = A1
MMACF32 MR3, MR2, MR2, MR1, MR0
|| MMOV32 MR0, @_A1
MMOVD32 MR1,@_Y1 ; MR1 = Y1, Y2 = Y1
MADDF32 MR3, MR3, MR2 ; MR3 = Y2*A2 + X0*B0 + X1*B1 + X2*B2
|| MMPYF32 MR2, MR1, MR0 ; MR2 = Y1*A1
MADDF32 MR3, MR3, MR2 ; MR3 = Y1*A1 + Y2*A2 + X0*B0 + X1*B1 + X2*B2
MMOV32 @_Y1, MR3 ; Y1 = MR3
40行以后的也没有见你写算式,更难看懂。
十分感谢十分感谢。
我再继续改改调试下。加点注释。希望能好来。
先问两个小问题:
1我在task结束的地方有一句MSTOP,但每次一旦执行到那儿以后。就会卡在那儿,CLA就不能在仿真了。显示的是CLA_0: Can't Single Step Target Program:只能重新仿真才能继续。
2另外如何查看变量。?直接在expressions框内添加对应的变量,及时切换到CLA的仿真也不能查看对应变量。导致我单步仿真一直不好弄。
1、一般地,执行MSTOP后,CLA的任务已经结束,如果再次运行,需要再次触发。
但是个别时候,调试时运行到MSTOP时并不能清除RUN状态,导致无法再次运行,可以在结束前,即运行MSTOP时点DEBUG窗口的“运行”图标。
2、有CLA寄存器窗口,直接看具体的寄存器好了。如果没有CLA寄存器窗口,可以设置一下。
那看来是不能单步到MSTOP语句上。我用的是ccs6.0的。改了下程序。单步仿真了好像这两个语句还有点问题。
- MMOV32 MR1, @_calcnum ; calc the average of the RMS
- MEINVF32 MR0, MR1 ; 计算点数1/n用于求平均 将起暂时放在MR0中
calcnum是uint16的。需要求算程float32型的1/n用来求平均好像算出来不大正常但不知道怎么改。先不说精度的问题。
没看到什么大错误。但是直接跑起来还是不大正常。我加了一些注释。希望有时间的朋友能帮忙注意下。万分感谢了。
- MMOV32 MR0,@_X4 ;1 Load MR0 with X4
- MMOV32 MR1,@_A4 ;2 Load MR1 with A4
- MNOP ;3 Wait till I8 to read result
- MNOP ;4 Wait till I8 to read result
- MNOP ;5 Wait till I8 to read result
- MNOP ;6 Wait till I8 to read result
- MNOP ;7 Wait till I8 to read result
- MUI16TOF32 MR2, @_AdcResult.ADCRESULT1 ;8 Read ADCRESULT1 and convert to float
- MMPYF32 MR2, MR1, MR0 ; MR2 (Y) = MR1 (A4) * MR0 (X4)
- || MMOV32 @_X0, MR2
- MMOVD32 MR0,@_X3 ; Load MR0 with X3, Load X4 with X3
- MMOV32 MR1,@_A3 ; Load MR1 with A3
-
- MMPYF32 MR3, MR1, MR0 ; MR3 (Y) = MR1 (A3) * MR0 (X3)
- || MMOV32 MR1,@_A2 ; Load MR1 with A2
- MMOVD32 MR0,@_X2 ; Load MR0 with X2, Load X3 with X2
- MMACF32 MR3, MR2, MR2, MR1, MR0 ; MR3 = A3*X3 + A4*X4
- || MMOV32 MR1,@_A1 ; MR2 = MR1 (A2) * MR0 (X2)
- MMOVD32 MR0,@_X1 ; Load MR0 with X1, Load X2 with X1
- MMACF32 MR3, MR2, MR2, MR1, MR0 ; MR3 = A2*X2 + (A3*X3 + A4*X4)
- || MMOV32 MR1,@_A0 ; MR2 = MR1 (A1) * MR0 (X1)
- MMOVD32 MR0,@_X0 ; Load MR0 with X0, Load X1 with X0
- MMACF32 MR3, MR2, MR2, MR1, MR0 ; MR3 = A1*X1 + (A2*X2 +A3*X3 + A4*X4)
- || MMOV32 MR1,@_A0 ; MR2 = MR1 (A0) * MR0 (X0)
- MADDF32 MR3, MR3, MR2 ; MR3 = A0*X0 + (A1*X1 + A2*X2 +A3*X3 + A4*X4)
- MF32TOUI16 MR2, MR3 ; Get back to Uint16 value MR3一直保存着当前采样值
- MMOV16 @_VoltFilt, MR2 ; Output
- MDEBUGSTOP
- MMOV32 MR1, @_Vavr ; 用以前计算的平均值来做电压隔值。MR3=MR3-Vavr
- MSUBF32 MR3, MR3, MR1 ; use the current average votage for blocking
- MMOV32 MR1, @_Vavrc ; calculate the total votage for the average calc
- MADDF32 MR1, MR1, MR3 ; Vavr=Vavr+MR3
- MMOV32 @_Vavrc, MR1
- MMPYF32 MR2, MR3, MR3 ; calculate the total power for the rms calc
- || MMOV32 MR1, @_Vrmsc
- MADDF32 MR1, MR1, MR2 ; Vrmsc=Vrmsc+MR3*MR3
- MMOV32 @_Vrmsc, MR1
- MMOVZ16 MR1, @_calcnum ; N+1
- MMOVZ16 MR0, @_TRUE_Value ; calcnum=calcnum+1 表示一个周期内计算了多少个点
- MADD32 MR1, MR0, MR1
- MMOV16 @_calcnum, MR1
- MUI16TOF32 MR2, @_Vth ; load MR2 with the votage threshold
- MCMPF32 MR3,MR2 ; compare the votage and its threshold
- ;比较当前电压和门限值,高了转去aboveVth
- MNOP
- MNOP
- MNOP
- MBCNDD aboveVth,GT ; if votage is larger than its threshold,then jump to the aboveVth and do the calcalation
- MNOP
- MNOP
- MNOP
- ;MMOVIZ MR0, #0.0 ; clear the check flag
- ;MF32TOUI16 MR0, MR0
- ;MMOV16 @_Frag, MR0
- MMOV16 MAR0, @_FALSE_Value ; 将Frag标志位清零
- MMOV16 @_Frag, MAR0
- MNOP
- MNOP
- MNOP
- MBCNDD Tsk7STOP, UNC ; jump to the end of the task
- MNOP
- MNOP
- MNOP
- aboveVth: MUI16TOF32 MR2, @_Frag ; load MR2 with the Flag
- MMOVF32 MR0, #0.0
- ;MF32TOI32 MR0, MR0
- MCMPF32 MR2, MR0 ; compare Frag with 0
- ; 比较标志位是否为零;
- MDEBUGSTOP
- MNOP
- MNOP
- MNOP
- MBCNDD Tsk7STOP,GT ; if Frag is biger than 0,which means it has been set to 1 and has been calclated ,Jump to the end
- MNOP ; 如果标志位为1 则跳转至结束。
- MNOP
- MNOP
- MMOV16 MAR0,@_TRUE_Value ; set the Frag
- MMOV16 @_Frag,MAR0 ; 将标志位置位。
- MMOV16 MAR1, @_calcnum ; 将计算点数输出至calcPRD变量
- MMOV16 @_calcPRD, MAR1
- MMOV32 MR1, @_calcnum ; calc the average of the RMS
- MEINVF32 MR0, MR1 ; 计算点数1/n用于求平均 将起暂时放在MR0中
-
- MMOV32 MR1, @_Vrmsc ; VRMS=VRMSC * 1/n
- MMPYF32 MR2, MR0, MR1 ; 结果保存在VRMS中
- MMOV32 @_Vrms, MR2 ; load the Vrms with MR2
- MMOV32 MR1, @_Vavrc ; calc the average of the RMS
- MMPYF32 MR2, MR0, MR1 ; Vavr=Vavrc * 1/n 结果保存在Vavr中
- MMOV32 @_Vavr, MR2 ; load the Vrms with MR2
- MMOVIZ MR0, #0.0 ; 将Varvc、Vrmsc和calcnum清零
- MUI16TOF32 MR0, MR0
- MMOV32 @_Vavrc, MR0
- MMOV32 @_Vrmsc, MR0
- MMOVI16 MAR0, #0
- MMOV16 @_calcnum,MAR0
- MNOP
- MNOP
- MNOP
- MNOP
- Tsk7STOP: MSTOP ; End task
引用: a828378 发表于 2014-11-14 19:47
那看来是不能单步到MSTOP语句上。我用的是ccs6.0的。改了下程序。单步仿真了好像这两个语句还有点问题。
calcnum是uint16的。需要求算程float32型的1/n用来求平均好像算出来不大正常但不知道怎么改。先不说精度的问题。
没看到什么大错误。但是直接跑起来还是不大正常。我加了一些注释。希望有时间的朋友能帮忙注意下。万分感谢了。
MEINVF32 是约等运算,你可以看看手册中的说明,可以更逼近1/n。
不正常的话,可能是运算中出了问题,看嘛是很难看出来的,有时候寄存器搞错了就会得到错误的结果。 --- 所以我建议你单步运行后,将每一步的结果与手工计算作一比较,这样才能发现问题所在。我在调试时就是这样做的,如果你有更好的办法不仿告诉我。
引用: dontium 发表于 2015-1-19 21:37
MEINVF32 是约等运算,你可以看看手册中的说明,可以更逼近1/n。
不正常的话,可能是运算中出了问题,看嘛是很难看出来的,有时候寄存器搞错了就会得到错误的结果。 --- 所以我建议你单步运行后,将每一步的结果与手工计算作一比较,这样才能发现问题所在。我在调试时就是这样做的,如果你有更好的办法不仿告诉我。
非常感谢!后来调试出来了。就是在算倒数和开方后面的用牛顿法毕竟的时候寄存器倒来倒去倒错了。现在已经改正。但我现在遇到另一个问题希望能求指点。有些变量我是存放在flash。开机的时候在startup里面把他们全部复制到RAM里。然后再运行程序的。我在运行的时候会更改这些数据。但我希望能掉电保存他们。我可能就需要获得他们在flash里面存放的地址。然后去修改?》请问如何做到?