3319|13

1万

帖子

28

TA的资源

裸片初长成(高级)

楼主
 

不用浮点,胜于浮点。 [复制链接]

本帖最后由 dontium 于 2016-4-3 23:46 编辑

使用的CPU : C28

例:
有一个16位数(以下运算后不会溢出),需要乘以2.38278(它是ADC校准时用的,4096/1419),

如果直接使之乘以2.38278,编译器也不会有任何做不到:
                      Voltage = InputVolt * 2.38278;(  Voltage = InputVolt * 4096/1419 )


然而,它编译后的代码却非常大:
        MOVW      DP,#_InputVolt        ; 段                                                             1周期
        MOV       AL,@_InputVolt        ; 直接寻址                                                      1周期
        LCR       #U$$TOFS              ; 调用编译器内部定义的函数---- 浮点转换        4周期 + n周期
        MOVL      XAR6,ACC              ;                                                                      1周期
        MOV       AL,#32635             ;                                                                      1周期
        MOV       AH,#16408            ;                                                                      1周期
        MOVL      *-SP[2],ACC          ;                                                                      1周期
        MOVL      ACC,XAR6             ;                                                                      1周期
        LCR       #FS$$MPY              ;调用编译器内部定义的函数---- 浮点数相乘       4周期 + n周期
        LCR       #FS$$TOU              ; 调用编译器内部定义的函数---- 浮点数转整型       4周期 + n周期
        MOVW      DP,#_Voltage          ;                                                                      1周期
        MOV       @_Voltage,AL          ;                                                                      1周期


程序中,调用了9条单周期指令、三条4周期指令,三个不同的内部过程,其占用的时间没有去查,肯定不会太短。不讲过程调用,占21个周期,如果每个调用的内部过程按10周期算(没有具体察看它们到底用了多少时间),那么,执行时间超过50个时钟周期


现在把运算办法改一下,即:


                       Voltage = (InputVolt * 1417 *16 )/ 65536 ;

具体语句为:
        temp = (Uint32) InputVolt * 22704;
        Voltage = temp >> 16;


这时再看一下编译结果:

        MOV       T,#22704              ; 这里连段都不用操作了。                               1周期
        MPYXU     ACC,T,@_InputVolt     ; 相乘                                                          1周期
        MOVL      *-SP[6],ACC           ; 临时数据,用汇编编程时可以不用这一句                               1周期,这是由于temp变量产生的,可以去掉
        MOVW      DP,#_Voltage          ; 段操作                                                                               1周期
        MOVH      @_Voltage,ACC << 0    ;将32位的ACC寄存器中的高16位保存 ------ 编译器很聪明,移位16时,不用移位指令而直接使用寄存器的高半部                               1周期


这里可见,仅用5个周期就完成任务。如果没有temp这个中间变量,将是4个时钟周期

两种方法作比较可知,第一种方法占用的时间不仅很长,而且存在浮点数与整数的来回转换,而第二种用时很短。两种方法的结果使程序的执行时间相差10多倍!   在精度上,第一种方法使用来回转换,肯定损失不小,而第二种方法仅将无效的后半部丢弃,保证最好的精度。
以上的两种方法,达到同样的目的,由此可见,一个好的编程方法,对程序的运行关系重大。








最新回复

好例子  学习学习  详情 回复 发表于 2016-9-14 08:25
 
点赞 关注

回复
举报

1297

帖子

2

TA的资源

纯净的硅(中级)

沙发
 
*16 / 65536是为了要那个右移16位,取高16位的效果?比单纯/4096的右移12位还快?

点评

如果使用移位方法,就要加入一条移位指令。而这里实现了16位的移位,却看不到移位指令。  详情 回复 发表于 2016-4-2 16:42
 
 

回复

2700

帖子

0

TA的资源

五彩晶圆(初级)

板凳
 
4096/1417不是2.8906139731827805222300635144672么?

点评

打错了,是4096/1419 一个校正是4096/1419,另一个校正是1419/4096。  详情 回复 发表于 2016-4-2 17:14
 
个人签名作为一个水军,就是尽量的多回帖,因为懂的技术少,所以回帖水分大,见谅!
EEWORLD开发板置换群:309018200,——电工们免费装β的天堂,商家勿入!加群暗号:喵
 
 

回复

1万

帖子

28

TA的资源

裸片初长成(高级)

4
 
johnrey 发表于 2016-4-2 15:34
*16 / 65536是为了要那个右移16位,取高16位的效果?比单纯/4096的右移12位还快?

如果使用移位方法,就要加入一条移位指令。而这里实现了16位的移位,却看不到移位指令。
 
 
 

回复

1万

帖子

28

TA的资源

裸片初长成(高级)

5
 
elvike 发表于 2016-4-2 16:09
4096/1417不是2.8906139731827805222300635144672么?

打错了,是4096/1419

一个校正是4096/1419,另一个校正是1419/4096。

点评

1419/4096很好处理啊,(x*1417)>>12多好,  详情 回复 发表于 2016-4-2 17:18
 
 
 

回复

2700

帖子

0

TA的资源

五彩晶圆(初级)

6
 
dontium 发表于 2016-4-2 17:14
打错了,是4096/1419

一个校正是4096/1419,另一个校正是1419/4096。

1419/4096很好处理啊,(x*1417)>>12多好,

点评

说明你还没有看上面汇编的语句。 如果用左移12位,肯定要用到移位指令,而移位16位就不同了,在32位寄存器的内容中,只取高半部,舍去低半部的16位,也等效于移位16,但却又少了至少一条指令。  详情 回复 发表于 2016-4-2 17:21
 
个人签名作为一个水军,就是尽量的多回帖,因为懂的技术少,所以回帖水分大,见谅!
EEWORLD开发板置换群:309018200,——电工们免费装β的天堂,商家勿入!加群暗号:喵
 
 

回复

1万

帖子

28

TA的资源

裸片初长成(高级)

7
 
elvike 发表于 2016-4-2 17:18
1419/4096很好处理啊,(x*1417)>>12多好,

说明你还没有看上面汇编的语句。

如果用右移12位,肯定要用到移位指令,而移位16位就不同了,在32位寄存器的内容中,只取高半部,舍去低半部的16位,也等效于移位16,但却又少了至少一条指令。
 
 
 

回复

215

帖子

0

TA的资源

一粒金砂(高级)

8
 
聪明!移16位正好可以省掉一个步骤。
 
 
 

回复

6423

帖子

17

TA的资源

版主

9
 
代码写的太精致了吧
 
个人签名training
 
 

回复

75

帖子

0

TA的资源

一粒金砂(中级)

10
 
好巧妙
 
 
 

回复

105

帖子

0

TA的资源

一粒金砂(中级)

11
 
精益求精
 
 
 

回复

29

帖子

0

TA的资源

一粒金砂(中级)

12
 
楼主,看不懂啊 Voltage = InputVolt * 4096/1419 ,怎么转变成 Voltage = (InputVolt * 1417 *16 )/ 65536 ;
貌似不相等啊 另外4096/1419=2.8865

点评

哦,这是另一个运算,具体数据对程序原理没影响。  详情 回复 发表于 2016-4-5 13:22
 
 
 

回复

1万

帖子

28

TA的资源

裸片初长成(高级)

13
 
chenyh85 发表于 2016-4-5 13:14
楼主,看不懂啊 Voltage = InputVolt * 4096/1419 ,怎么转变成 Voltage = (InputVolt * 1417 *16 )/ 655 ...

哦,这是另一个运算,具体数据对程序原理没影响。
 
 
 

回复

27

帖子

1

TA的资源

一粒金砂(中级)

14
 
好例子  学习学习
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表