话题:谈谈我对C51语言的看法目前单片机的编程中,C51语言可以说是十分盛行,这种语言我也用过,但基本上都是用汇编语言。 C51语言的好处是可读性强、移植性好、浮点运算,除此之外没有别的好处了。我们不妨将两种语言作一个比较: 1、效率方面:我曾对编译后的C51语言分析过,可以发现由它生成的代码数量,至少是汇编语言的两倍以上,有的甚至高达十倍以上。占用空间大了,效率自然低。 2、移植性:C51的可移植性是比汇编好一些,但是单片机程序不同于微机控件程序那样通用,几乎没有一个程序是可以到处移植的。单片机中最常用的移植程序大概就是运算子程序了,在这方面,汇编格式的运算子程序移植起来一个也不比C51逊色。 3、浮点运算:以我的感觉,单片机不适合采用浮点运算,我曾经做过试验,编译了一个1.2+2.3的浮点运算,编译后代码长达2K多,完成这个运算所需要的时间就不用说了。我从八四年就开始研究单片机,到现在做过的系统中,含有单片机的超过五十项,所有系统中的运算,全部都采用定点运算,几个定点子程序成了法宝,代码效率非常高,请看下面的一段: ;W = W130 * (130 / Dia) * (130 / Dia) = W130 * 16900 / (Dia * Dia) CalAndMem: MOV R5, SetPie130War1H MOV R4, SetPie130War1L MOV R3, #HIGH 16900 MOV R2, #LOW 16900 CALL QKMUL ;W130 * 16900 ;双字节乘法子程QKMUL ;(R3、R2)*(R5、R4)=R7、R6、R5、R4 ;R3、R5、R7为高字节 MOV A, SetDiamt MOV B, A MUL AB MOV R3, B MOV R2, A CALL NDIV ; /(Dia * Dia) ;二进制除法子程:NDIV ;入口:R7654=被除数,R7高字节,R32=除数,R3高字节 ;出口:R76=余数,R7高字节,R54=商,R5高字节 ;R765432用于参数传递,不用保护 MOV SetPieWar1H, R5 ;当前缸径下的压力报警点 MOV SetPieWar1L, R4 -------- 其中的子程序都是网上的成品,非常精简。 4、实时性:用汇编编程序的人都知道,单片机的实时性要求很高,经常需要计算这段程序需要多长时间,什么时间来中断,中断后执行多长时间,对原程序有没有妨碍,等等,这都是C51程序难以做到的。 5、节省内存:当然,这和代码效率是成反比的,同样的内存所能完成的功能也就大大提高。 永远记住:高性能的代码是用汇编语言编写出来的,而不是用高级语言生成的,高质量的PCB是有经验的工程技术人员用手工排出来的,而不是软件
自动布线出来的。 回复第1帖 编辑 好评 差评 hmf2006: 第2帖 2006-01-09 22:25: 顶一下! 我正在学习中! 汇编中的乘啊除啊定点浮点的还搞不明白! 请问有书推荐吗? 回复第2帖 编辑 好评 差评 maychang: 第3帖 2006-01-11 01:32: 完全同意楼主看法 再补充一句:最高精度的块规,是手工磨出来的。 回复第3帖 编辑 好评 差评 hxzlz: 第4帖 2006-01-24 11:06: 高手是这样练成的! 回复第4帖 编辑 好评 差评 hotpower: 第5帖 2006-02-01 10:14: 还是C语言快捷,想快就嵌入汇编. http://blog.21ic.org/blog.asp?name=hotpower 回复第5帖 编辑 好评 差评 hotpower: 第6帖 2006-02-03 03:28: 再这样用汇编肯定要被时代淘汰... 现在是大容量高速度的年代. 回复第6帖 编辑 好评 差评 sdjufeng: 第7帖 2006-02-05 21:55: 我没有被淘汰,相反,我搞的系统多数都是高性能的。上面的那段代码,是一个泥浆泵监控系统中的一段,这个程序长达8K(包括3K汉字库),CPU是ADuC812,我用了一周多一点的时间就完成了。大量的计算全都采用定点运算,速度非常快。8K代码是反复压缩后的大小,如果采用C51,这段程序,32K的空间能容得下就不错了。 知道计算机操作系统为什么都是用C语言编写的吗?知道计算机专业人士特别鄙视VB而重视VC吗? 答案只有一个:效率。 回复第7帖 编辑 好评 差评 hotpower: 第8帖 2006-02-07 01:09: 八四年就开始研究单片机... 佩服...但我是从80年JS130开始的... 至于效率,C写好了可以做到汇编的80%,肯定不如汇编... 如果在ARM下用C裸奔都累,还有心情汇编讲代码效率吗??? 60M不够折腾吗??? 没人反对汇编... 建议用任意搜索引擎搜索"HotIns.h",看看什么是C的效率. 用好了,在函数中C和ASM写的一样长,网上有应用的例子... 在这里只是玩玩,不想发表什么"高论"... 可以说我们是同龄人,至今还能站在这里,已经是万幸了... 回复第8帖 编辑 好评 差评 sdjufeng: 第9帖 2006-02-07 15:24: 幸会,我也只是工作之余上来消遣一下而已。 只是我一直用汇编,感到非常灵活高效,并没有感觉到有什么不方便。 回复第9帖 编辑 好评 差评 hotpower: 第10帖 2006-02-07 21:36: 哈哈,随便说说别介意... 不过应该汇编和C都掌握才好... http://www.21icbbs.com/club/bbs/ViewUserEssence.asp?name=hotpower http://blog.21ic.com/blog.asp?name=hotpower 回复第10帖 编辑 好评 差评 sd
jufeng: 第11帖 2006-02-07 22:05: 十 其实单片机一般都是带有很多外围部件的,它的速度一般是与指令系统匹配的,这些部件的应用,只有灵活高效的汇编指令才能将其够发挥出来,很多情况下,C51并不能把它们充分利用起来,现在单片机的价格很低,如果作没有批量的产品,采用高性能的器件完成一般的功能是个可行的办法,但是如果产品有批量,单片机的价格就不能忽视,如何用普通的器件完成高的性能就是个问题,这样可以降低成本,这样的系统C51恐怕就难以胜任。你说的80%,对于一般人是做不到的。常搞电路的人都知道,指令的实时透明是很重要的,因为很难确定C51执行这条语句需要多长时间。当然我也并不是否认C51,应该说各有长短吧 回复第11帖 编辑 好评 差评 hotpower: 第12帖 2006-02-08 01:25: 九 幸会...没想到此论坛里也会有知音... 实际上我是汇编的坚决拥护者,也是编程效率的倡导者... 我曾经在PIC上"创造"过自己的"HPL语言",说实话效率要比C高和ASM等同...我称之为"宏C"... 随着器件工艺的提高,容量和速度都和以前有很大改观. 在编译器上也有很大的进步,特别是在优化上. 随着ARM的介入,价位已和中高端的MCU接近,像LPC2101等,只有1.47$. 可想而知,再有2年ARM肯定能红破半边天,那时不会C该怎么办??? 在ARM一般要跑操作系统,OS几乎都是C/C++编写的,如果还再考虑"资源"已无任何意义!!! 又如同现在编PC软件还有几个人考虑"内存大小,文件大小"??? 要想继续站在这个"战场"上,必须拿起新的"刀枪"... MCU/ARM/DSP/CPLD/FPGA... 这个就是社会的进步和发展..."躺"在这肯定要被什么"车"压倒的... 个人意见... 回复第12帖 编辑 好评 差评 deyun: 第13帖 2006-03-21 18:28: 八 使用C51可以写出跟asm51毫不逊色的程序,这要看编程者的水平了,看下面的例子: // ============================================================ // 功能:计算斜率 // 说明:被除数必须小于除数,返回(n1*256)/n2的商 // 编程:臧德运 unsigned char Div(unsigned char n1, unsigned char n2) { union {unsigned int w; struct {unsigned char h, l;}bytes;}i; unsigned char n; if(n1==0){return(0);} // 被除数等于零返回 i.bytes.h=n1; i.bytes.l=0; // 使用公用体变量便于字节操作 for(n=8;n>0;n--) { i.w=i.w<<1; if(CY==0) { if(ACC } else ACC=ACC-n2; i.bytes.h=ACC; i.bytes.l++; } return(i.bytes.l); } // ============================================================ // 功能:画直线 // 编程:臧德运 void PLine(unsigned char x1, unsigned char y1, unsigned char x2, unsigned char y2, bit mode) { unsig
ned char n, k; unsigned char x, y, x0, y0; // 修正坐标原点为左下角 y1=y1^0x7f; y2=y2^0x7f; // 求X坐标偏移量的绝对值 if(x2 { ACC=~ACC;ACC++; // 求绝对值 n=x1; x1=x2; x2=n; n=y1; y1=y2; y2=n; // 校正画线方向提高效率 } x0=ACC; // 求Y坐标偏移量的绝对值 // 避免使用ABS函数提高效率 if(y2 y0=ACC; x=x1; y=y1; if(x0==y0) // 斜率等于1时画正斜线 { for(n=x0;n>0;n--) { Pixel(x, y, mode); x++; if(y2>y1)y++; else y--; } } else { if(x0>y0) // 小于45度的斜线 { k=Div(y0,x0); for(n=0;n<=x0;n++) { ACC=k;B=n;ACC=ACC*B; y0=B; if(ACC_7)y0++; if(y2>y1){y=y1+y0;}else{y=y1-y0;} Pixel(x1+n, y, mode);x++; } } else // 大于45度的斜线 { k=Div(x0,y0); for(n=0;n<=y0;n++) { ACC=k;B=n;ACC=ACC*B; if(ACC_7)B++; x=B+x1; Pixel(x, y, mode);if(y2>y1){y++;}else{y--;} } } } return; } // ============================================================ // 二(十六)进制转换为十进制 // 返回:低四位十进制编码+B(万位) // 格式:C51 // 编程:臧德运 unsigned int bin2dec(unsigned char bl, unsigned char bh) { union{unsigned int i; struct{unsigned char h, l;}bytes;}d; d.bytes.l=bl; d.bytes.h=bh; B=0;bh=0; // 逐次d.i-10000,不够减退出循环,循环次数就是万位值 while(1) { d.i+=0xd8f0;if(!CY)break; B++; } d.i+=10000; // 把减10000的余数转化为100进制 // bh=100进制高位 // d.bytes.l=余数,也就是100进制低位 for(bl=8;bl!=0;bl--) { bh+=bh; // 100进制高位同步左移 d.i=d.i<<1; // 8次位移逐次求100进位 if(d.bytes.h>=100) // 编译器在编译d.bytes.h>=100时,会有减100操作。 { d.bytes.h=ACC; // 比较时刻运算结果送100进制低位 bh++; // 100进制进位 } } bl=B; // 保护B内容 // 100进制转换为10进制 d.bytes.l=(d.bytes.h/10)<<4; d.bytes.l=d.bytes.l|B; d.bytes.h=(bh/10)<<4; d.bytes.h=d.bytes.h|B; B=bl; // 恢复B内容 return(d.i); } 回复第13帖 编辑 好评 差评 sdjufeng: 第15帖 2006-03-29 23:20: 六 结构体用的不错. 回复第15帖 编辑 好评 差评 sdjufeng: 第14帖 2006-03-29 23:01: 七 我想来到这里的人,大多数都是这方面的高手,上面有这么多人发表了自己的看法,不管怎么说,真正的是非我想大家都有数。 有人感觉还是用C编写单片机程序精炼,效率也不低,甚至和汇编语言差不多。 是,用高级语言编写的程序看上去是很精简,当然这也是个优点,源程序上看不出什么问题来,但不知道他分析过编译软件生成的代码没有,有一个事实,在我们用