如何写出高效的单片机C语言程序代码 如何写一段简洁高效的单片机C语言子程序,实现这样一个功能?

\u5982\u4f55\u5199\u51fa\u9ad8\u6548\u7387\u7a33\u5b9a\u7684\u5355\u7247\u673a\u4ee3\u7801

\u8981\u5199\u51fa\u9ad8\u6548\u7387\u7a33\u5b9a\u7684\u5355\u7247\u673a\u4ee3\u7801\uff1a
1\u3001\u4f7f\u7528\u6c47\u7f16\u8bed\u8a00\u7f16\u5199\u3002
2\u3001\u719f\u7ec3\u638c\u63e1\u548c\u7075\u6d3b\u5e94\u7528\u5404\u79cd\u7b97\u6cd5\u3002

1\u3001\u9996\u5148\u8c03\u7528\uff0c\u8bbe\u7f6e\u72b6\u6001\u9759\u6001\u5bc4\u5b58\u5668\u521d\u503c\uff0c\u8ba1\u6570\u9759\u6001\u5bc4\u5b58\u5668\u521d\u503c\uff1b2\u3001\u8c03\u7528\u4e00\u6b21\uff0c\u68c0\u6d4b\u4e00\u6b21\uff0c\u5bf9\u6bd4\u524d\u6b21\u7684\u9759\u6001\u53d8\u91cf\uff0c\u4e0d\u540c\u5219\u8ba1\u6570\u589e1\u540e\u53cd\u56de\uff0c\u76f8\u540c\u5219\u6e05\u9664\u8ba1\u6570\u8fd4\u56de\uff1b3\u3001\u518d\u8c03\u7528\u4e00\u6b21\uff0c\u68c0\u6d4b\u4e00\u6b21\uff0c\u5bf9\u6bd4\u524d\u6b21\u7684\u9759\u6001\u53d8\u91cf\uff0c\u4e0d\u540c\u5219\u8ba1\u6570\u589e1\u540e\u53cd\u56de\uff0c\u76f8\u540c\u5219\u6e05\u9664\u8ba1\u6570\u8fd4\u56de\uff1b4\u3001\u6700\u540e\u8c03\u7528\u4e00\u6b21\uff0c\u68c0\u6d4b\u4e00\u6b21\uff0c\u4f5c\u5bf9\u6bd4\uff0c\u76f8\u540c\u5219\u6e05\u9664\u8ba1\u6570\uff0c\u4e0d\u540c\u5219\u4fee\u6539\u8981\u66f4\u65b0\u7684\u53d8\u91cf\uff0c\u6539\u53d8\u72b6\u6001\u9759\u6001\u53d8\u91cf\uff0c\u6e05\u9664\u8ba1\u6570\u5668\uff0c\u8fd4\u56de\u3002

由于单片机的性能同电脑的性能是天渊之别的,无论从空间资源上、内存资源、工作频率,都是无法
与之比较的。PC 机编程基本上不用考虑空间的占用、内存的占用的问题,最终目的就是实现功能就可以了。
对于单片机来说就截然不同了,一般的单片机的Flash 和Ram 的资源是以KB 来衡量的,可想而知,单片
机的资源是少得可怜,为此我们必须想法设法榨尽其所有资源,将它的性能发挥到最佳,程序设计时必须
遵循以下几点进行优化:

1. 使用尽量小的数据类型
能够使用字符型(char)定义的变量,就不要使用整型(int)变量来定义;能够使用整型变量定义的变
量就不要用长整型(long int),能不使用浮点型(float)变量就不要使用浮点型变量。当然,在定义变
量后不要超过变量的作用范围,如果超过变量的范围赋值,C 编译器并不报错,但程序运行结果却错了,
而且这样的错误很难发现。

2. 使用自加、自减指令
通常使用自加、自减指令和复合赋值表达式(如a-=1 及a+=1 等)都能够生成高质量的
程序代码,编译器通常都能够生成inc 和dec 之类的指令,而使用a=a+1 或a=a-1 之类
的指令,有很多C 编译器都会生成二到三个字节的指令。

3. 减少运算的强度
可以使用运算量小但功能相同的表达式替换原来复杂的的表达式。
(1) 求余运算
N= N %8 可以改为N = N &7
说明:位操作只需一个指令周期即可完成,而大部分的C 编译器的“%”运算均是调用子程序来
完成,代码长、执行速度慢。通常,只要求是求2n 方的余数,均可使用位操作的方法来代替。
(2) 平方运算
N=Pow(3,2) 可以改为N=3*3
说明:在有内置硬件乘法器的单片机中(如51 系列),乘法运算比求平方运算快得多, 因为浮点数
的求平方是通过调用子程序来实现的,乘法运算的子程序比平方运算的子程序代码短,执行速度快。
(3) 用位移代替乘法除法
N=M*8 可以改为N=M<<3
N=M/8 可以改为N=M>>3
说明:通常如果需要乘以或除以2n,都可以用移位的方法代替。如果乘以2n,都可以生成左移
的代码,而乘以其它的整数或除以任何数,均调用乘除法子程序。用移位的方法得到代码比调用乘除法子
程序生成的代码效率高。实际上,只要是乘以或除以一个整数,均可以用移位的方法得到结果。如N=M*9
可以改为N=(M<<3)+M;
(4) 自加自减的区别
例如我们平时使用的延时函数都是通过采用自加的方式来实现。
void DelayNms(UINT16 t)
{
UINT16 i,j;
for(i=0;i<t;i++)
for(j=0;i<1000;j++)
}
可以改为
void DelayNms(UINT16 t)
{
UINT16 i,j;
for(i=t;i>=0;i--)
for(j=1000;i>=0;j--)
}
说明:两个函数的延时效果相似,但几乎所有的C 编译对后一种函数生成的代码均比前一种代码少1~3
个字节,因为几乎所有的MCU 均有为0 转移的指令,采用后一种方式能够生成这类指令。

4. while 与do...while 的区别
void DelayNus(UINT16 t)
{
while(t--)
{
NOP();
}
}
可以改为
void DelayNus(UINT16 t)
{
do
{
NOP();
}while(--t)
}
说明:使用do…while 循环编译后生成的代码的长度短于while 循环。

5. register 关键字
void UARTPrintfString(INT8 *str)
{
while(*str && str)
{
UARTSendByte(*str++)
}
}
可以改为
void UARTPrintfString(INT8 *str)
{
register INT8 *pstr=str;
while(*pstr && pstr)
{
UARTSendByte(*pstr++)
}
}
说明:在声明局部变量的时候可以使用register 关键字。这就使得编译器把变量放入一个多用途的寄存
器中,而不是在堆栈中,合理使用这种方法可以提高执行速度。函数调用越是频繁,越是可能提高代码的
速度,注意register 关键字只是建议编译器而已。

6. volatile 关键字
volatile 总是与优化有关,编译器有一种技术叫做数据流分析,分析程序中的变量在哪里赋值、在
哪里使用、在哪里失效,分析结果可以用于常量合并,常量传播等优化,进一步可以死代码消除。一般来
说,volatile 关键字只用在以下三种情况:
a) 中断服务函数中修改的供其它程序检测的变量需要加volatile(参考本书高级实验程序)
b) 多任务环境下各任务间共享的标志应该加volatile
c) 存储器映射的硬件寄存器通常也要加volatile 说明,因为每次对它的读写都可能由不同意义
总之,volatile 关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素
更改,比如:操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码
就不再进行优化,从而可以提供对特殊地址的稳定访问。

  • 濡備綍鍐欏嚭楂樻晥鐨勫崟鐗囨満C璇█绋嬪簭浠g爜
    绛旓細N= N %8 鍙互鏀逛负N = N &7 璇存槑锛氫綅鎿嶄綔鍙渶涓涓寚浠ゅ懆鏈熷嵆鍙畬鎴愶紝鑰屽ぇ閮ㄥ垎鐨C 缂栬瘧鍣ㄧ殑鈥%鈥濊繍绠楀潎鏄皟鐢ㄥ瓙绋嬪簭鏉 瀹屾垚锛屼唬鐮侀暱銆佹墽琛岄熷害鎱傞氬父锛屽彧瑕佹眰鏄眰2n 鏂圭殑浣欐暟锛屽潎鍙娇鐢ㄤ綅鎿嶄綔鐨勬柟娉曟潵浠f浛銆傦紙2锛 骞虫柟杩愮畻 N=Pow(3,2) 鍙互鏀逛负N=3*3 璇存槑锛氬湪鏈夊唴缃‖浠朵箻娉曞櫒鐨勫崟...
  • 濡備綍鎻愰珮鍗曠墖鏈篊璇█缂栫▼鑳藉姏?
    绛旓細1.鍏堣嚜宸卞啓涓浜涘皬绋嬪簭锛岀劧鍚庡啀浠庣綉涓婁笅杞戒簺浼樼浠g爜鍥炴潵锛屽姣旇嚜宸辩殑绋嬪簭锛屾壘鍑哄樊鍒紝璁ょ湡瀵规瘮瀛︿範锛屽悆閫忎紭绉绠楁硶锛屾參鎱㈢Н绱2.浠庡皬鐨勬ā鍧楃▼搴忓紑濮嬶紝涓姝ヤ竴姝ヤ紭鍖栬嚜宸辩殑绋嬪簭锛岃繖鏍风殑璇濓紝浠ュ悗鍐欑殑澶х▼搴忓氨鎱㈡參濂戒簡锛屾病浜嬬殑鏃跺欏鐪嬬湅C鐨勪功锛屼笉鎳傜殑瑕佹悶鎳傦紝宸茬粡鎳傜殑瑕佸鎯虫兂鏈夋病鏈夋洿濂界殑鏂规硶銆3鍙﹀锛...
  • 濡備綍鍐涓娈电畝娲楂樻晥鐨勫崟鐗囨満C璇█瀛绋嬪簭,瀹炵幇杩欐牱涓涓姛鑳?
    绛旓細1銆侀鍏堣皟鐢紝璁剧疆鐘舵侀潤鎬佸瘎瀛樺櫒鍒濆硷紝璁℃暟闈欐佸瘎瀛樺櫒鍒濆锛2銆佽皟鐢ㄤ竴娆★紝妫娴嬩竴娆★紝瀵规瘮鍓嶆鐨勯潤鎬佸彉閲忥紝涓嶅悓鍒欒鏁板1鍚庡弽鍥烇紝鐩稿悓鍒欐竻闄よ鏁拌繑鍥烇紱3銆佸啀璋冪敤涓娆★紝妫娴嬩竴娆★紝瀵规瘮鍓嶆鐨勯潤鎬佸彉閲忥紝涓嶅悓鍒欒鏁板1鍚庡弽鍥烇紝鐩稿悓鍒欐竻闄よ鏁拌繑鍥烇紱4銆佹渶鍚庤皟鐢ㄤ竴娆★紝妫娴嬩竴娆★紝浣滃姣旓紝鐩稿悓鍒欐竻闄よ鏁帮紝涓嶅悓...
  • 鎬庢牱鎻愬崌鑷繁鍗曠墖鏈篊璇█缂栫▼鑳藉姏鍟?姹傞珮鎵嬫寚鐐硅糠娲!鎴戠‖浠朵篃鎳備竴鐐 浣...
    绛旓細3銆佸伐绋嬪寲绠$悊婧愮▼搴忥細姣斿瀵逛竴浜涘父鏁般佹帴鍙e湴鍧銆佹暟鎹被鍨嬪畾涔(typedef)銆佹暟鎹粨鏋勫畾涔夈佽嚜瀹氫箟鐨勫嚱鏁板0鏄庣瓑锛屽簲鍐欏叆鍗曠嫭寤虹珛.H鏂囦欢锛岀劧鍚庡湪鍏跺畠.C鏂囦欢涓寘鍚.C鏂囦欢锛屽鏋滆蒋浠跺ぇ鐨勮瘽涔熷敖閲忕殑鎸夌収鍔熻兘鍒嗗埆寤虹珛锛岀劧鍚庡湪宸ョ▼涓寘鍚4銆佹湁鏃讹紝涓涓蒋浠朵細閽堝涓嶅悓鍨嬪彿鐨勮澶囷紝姝ゆ椂搴旈噰鐢#ifdef绛夌紪璇戞帶鍒...
  • 鍗曠墖鏈虹殑C璇█搴旂敤绋嬪簭璁捐鍐呭绠浠
    绛旓細杩欐湰涔﹀叡鍒嗕负13绔狅紝娣卞叆娴呭嚭鍦拌瑙d簡鍗曠墖鏈虹紪绋鐨勬柟鏂归潰闈傞鍏堬紝瀹冩兜鐩栦簡鍩虹鐨凜璇█閮ㄥ垎锛屽Cx51璇█鐨勮繍鐢紝鍖呮嫭鏁版嵁澶勭悊涓庤繍绠椼佹祦绋嬫帶鍒惰鍙ャ佹暟鎹粨鏋勭殑鏋勫缓浠ュ強鍑芥暟涓绋嬪簭璁捐鐨勫熀鏈師鐞嗐傝繖浜涚珷鑺傛棬鍦ㄥ府鍔╄鑰呭缓绔嬭捣鍧氬疄鐨勭紪绋鍩虹銆傛帴鐫锛屼功涓殑搴旂敤閮ㄥ垎鑱氱劍浜嶤x51鍦ㄥ疄闄呴」鐩腑鐨勫簲鐢紝濡傚唴閮...
  • 銆愬崟鐗囨満銆戣鐢C璇█鍐涓涓秴绾х畝鍗鐨勫崟鐗囨満绋嬪簭銆備竾鍒嗘劅璋!!_鐧惧害鐭...
    绛旓細楂樼骇璇█锛屼娇鐢ㄧ殑閮芥槸鍙橀噺銆備竴鑸潵璇达紝閮戒笉鎸囧畾鏌愪釜鍙橀噺鐨 RAM 鐨勫叿浣撳湴鍧鍙风爜銆傛墍浠ワ紝C锛屼笉閫傚疁閽堝 RAM 鐨勫叿浣撳湴鍧鍗曞厓杩涜鎿嶄綔銆
  • 鍗曠墖鏈鏂归潰,鏄笉鏄笉绮鹃氱‖浠跺氨鏃犳硶鍐欏嚭楂樿川閲鐨凜璇█绋嬪簭
    绛旓細浣嗘槸锛鍗曠墖鏈鏂归潰锛屼笉绮鹃氱‖浠跺氨鏃犳硶鍐欏嚭楂樿川閲鐨凜璇█绋嬪簭灏变笉瑙佸緱瀵逛簡锛屽洜涓篊璇█铏界劧涔熻鎺у埗纭欢锛屼絾姣旀眹缂栬瑷瀵圭‖浠剁殑浜嗚В瑕佹眰浣庝簡涓涓。娆°備竴鍙ヨ瘽鎬荤粨锛屾悶鍗曠墖鏈哄紑鍙戝繀椤诲纭欢鏈夋墍浜嗚В锛屽惁鍒欐棤娉曡繘琛岋紝浣嗕笉瑙佸緱闈炲緱绮鹃氾紝涓鑸簡瑙d篃鍙互寮鍙戠▼搴忋傝岃鎴愪负楂樻墜锛屽氨涓嶅彧鏄簿閫氬崟鐗囨満纭欢閭d箞绠鍗曪紝...
  • 璋佽兘甯垜缂栦釜绠鍗鐨勫崟鐗囨満绋嬪簭 鐢C璇█
    绛旓細杩欎釜寰堢畝鍗曠殑锛屼笉杩囪鍒汉缁欎綘鍐娌′粈涔堟剰鎬濓紝绋嬪簭杩欎笢瑗胯鑷繁鍐欐墠鏈夌敤锛屽垰寮濮嬪啓涓嶅嚭鏉ュ氨鍐欏鍑犳灏辫浜嗐74hc154鏄竴涓湁閿佸瓨鍔熻兘鐨勮姱鐗囷紝浣犺鑷繁瀛︿細鍘荤湅涓涓嬭姱鐗囩殑璧勬枡鎵嶈銆傚畠鏄竴涓潪瀛︾畝鍗曠殑鑺墖
  • 姹傚ぇ绁炵敤C璇█鍐欏嚭涓嬪浘鍏充簬鍗曠墖鏈虹殑绋嬪簭浠g爜!鎰熻阿
    绛旓細= 0x2C; ET1 = 1; //--寮瀹氭椂鍣1涓柇 EA = 1; //--寮鎬讳腑鏂 TR1 = 1; //--寮瀹氭椂鍣1 Led = 1; while(1);//---涓绋嬪簭姝诲惊鐜 }void ISR_Timer1(void) interrupt 3{Led = ~Led;TH1 = 0xCF; //--閲嶈浇瀹氭椂鍣紝 TL1 = 0x2C; //瀹氭椂25ms璁℃椂 } ...
  • 鍗曠墖鏈虹殑C璇█绋嬪簭璁捐
    绛旓細鎸夌収51鐨勫啓涓涓惂 include<reg51.h>unsigned char code a[]="I am a student";unsgiend char xdata *p;void main(){ unsigned char i; p=(unsigned char xdata *)0x2000; for(i=0;a[i];i++) *p++=a[i]; while(1); } ...
  • 扩展阅读:学编程一年大概多少钱 ... 单片机自学编程软件 ... c++编程软件 ... 吓人的编程代码 ... 初学编程必背50个 ... 电脑编程 ... 少儿编程是学什么的 ... c语言必背100代码 ... c语言零基础自学 ...

    本站交流只代表网友个人观点,与本站立场无关
    欢迎反馈与建议,请联系电邮
    2024© 车视网