单片机程序设计规范与技巧.docx

上传人:b****5 文档编号:8020786 上传时间:2023-01-28 格式:DOCX 页数:12 大小:20.70KB
下载 相关 举报
单片机程序设计规范与技巧.docx_第1页
第1页 / 共12页
单片机程序设计规范与技巧.docx_第2页
第2页 / 共12页
单片机程序设计规范与技巧.docx_第3页
第3页 / 共12页
单片机程序设计规范与技巧.docx_第4页
第4页 / 共12页
单片机程序设计规范与技巧.docx_第5页
第5页 / 共12页
点击查看更多>>
下载资源
资源描述

单片机程序设计规范与技巧.docx

《单片机程序设计规范与技巧.docx》由会员分享,可在线阅读,更多相关《单片机程序设计规范与技巧.docx(12页珍藏版)》请在冰豆网上搜索。

单片机程序设计规范与技巧.docx

单片机程序设计规范与技巧

单片机软件设计规范

1.学习软件设计规范的目的

学习软件设计规范的目的就是编写高质量的软件,降低编码阶段的错误率。

设计一个高质量的软件有以下几点要求:

1)软件设计模块化,具有好的可重用性和可移植性。

2)程序代码干净整洁,具有好的可维护性。

3)不使用晦涩的语句,简洁易懂,具有好的易懂性。

4)代码设计简明扼要,提高程序的运行效率以及程序所占用的内存空间。

5)使用充足的程序说明,程序具有好的可读性。

综上所述:

可重用性、可移植性、可维护性、易懂性、高效率性以及可读性是衡量一个软件质量基本要求。

2.排版规范

1.程序块采用缩进风格编写,缩进为4个空格位,通常采用TAB键来进行缩进,也可直接敲入4个空格位,但排版不能混合使用空格和TAB键。

2.函数体的开始,类的定义,结构的定义,if、for、do、while、switch及case语句中的程序都应采用缩进方式,‘{’符号与‘}’独占一行并且位于同一列。

示例:

如下例子不符合规范

if(……){

……}

应如下书写

if(……)

{

……

}

3.相对独立的程序块之间、变量说明之后必须加空行。

示例:

如下例子不符合规范

if(!

valid_ni(ni))

{

...//programcode

}

repssn_ind=ssn_data[index].repssn_index;

repssn_ni=ssn_data[index].ni;

应如下书写

if(!

valid_ni(ni))

{

...//programcode

}

repssn_ind=ssn_data[index].repssn_index;

repssn_ni=ssn_data[index].ni;

4.一行最多写一条语句。

示例:

如下例子不符合规范

i++;j++;

应如下书写

i++;

j++;

5.不同类型的操作符混合使用时,使用括号给出优先级。

示例:

如下例子不符合规范

if(i!

=1||j!

=2&&k!

=3)

应如下书写

if((i!

=1)||((j!

=2)&&(k!

=3)))

6.较长的语句(>80字符)要分成多行书写,长表达式要在低优先级操作符处划分新行,操作符放在新行之首,划分出的新行要进行适当的缩进,使排版整齐,语句可读。

示例(书写正确):

perm_count_msg.head.len=NO7_TO_STAT_PERM_COUNT_LEN

+STAT_SIZE_PER_FRAM*sizeof(_UL);

7.在两个以上的关键字、变量、常量进行对等操作时,它们之间的操作符之前、之后或者前后要加空格;进行非对等操作时,如果是关系密切的立即操作符(如->),后不应加空格。

说明:

采用这种松散方式编写代码的目的是使代码更加清晰。

示例:

(1)逗号、分号只在后面加空格。

inta,b,c;

(2)比较操作符,赋值操作符"="、"+=",算术操作符"+"、"%",逻辑操作符"&&"、"&",位域操作符"<<"、"^"等双目操作符的前后加空格。

if(current_time>=MAX_TIME_VALUE)

a=b+c;

a*=2;

a=b^2;

(3)"!

"、"~"、"++"、"--"、"&"(地址运算符)等单目操作符前后不加空格。

*p='a';//内容操作"*"与内容之间

flag=!

isEmpty;//非操作"!

"与内容之间

p=&mem;//地址操作"&"与内容之间

i++;//"++","--"与内容之间

(4)"->"、"."前后不加空格。

p->id=pid;//"->"指针前后不加空格

(5)if、for、while、switch等与后面的括号间应加空格,使if等关键字更为突出、明显。

if(a>=b&&c>d)

3.注释规范

1.一般情况下,源程序有效注释量必须在20%以上

说明:

注释的原则是有助于对程序的阅读理解,在该加的地方都加了,注释不宜太多也不能太少,注释语言必须准确、易懂、简洁。

2.说明性文件(如头文件.h文件、.inc文件)头部应进行注释,注释必须列出:

版权说明、版本号、生成日期、作者、内容、功能、与其它文件的关系、头文件的注释中还应有函数功能简要说明。

示例:

下面为一头文件的头部注释的模板

/*************************************************

Copyright(C),2005,HUST

Filename:

test.h//文件名

Author:

Version:

Date:

//作者、版本及完成日期

Description:

//用于详细说明此程序文件完成的主要功能,与其他模块

//或函数的接口,输出值、取值范围、含义及参数间的控

//制、顺序、独立或依赖等关系

Others:

//其它内容的说明

FunctionList:

//主要函数列表,每条记录应包括函数名及功能简要说明

*************************************************/

3.源文件头部应进行注释,列出:

版权说明、版本号、生成日期、作者、模块目的/功能、主要函数及其功能等。

示例:

下面为一源文件的段头注释的模板

/************************************************************

Copyright(C),2005,HUST

FileName:

test.c

Author:

Version:

Date:

Description:

//模块描述

Version:

//版本信息

FunctionList:

//主要函数及其功能

1.-------

***********************************************************/

4.函数头部应进行注释,列出:

函数的目的/功能、输入参数、输出参数、返回值等。

示例:

下面为一函数头部注释的模板

/*************************************************

Function:

//函数名称

Description:

//函数功能、性能等的描述

Input:

//输入参数说明,包括每个参数的作

//用、取值说明及参数间关系。

Output:

//对输出参数的说明。

Return:

//函数返回值的说明

Others:

//其它说明

*************************************************/

5.注释应与其描述的代码相近,对代码的注释应放在其上方或右方(对单条语句的注释)相邻位置,不可放在下面,如放于上方则需与其上面的代码用空行隔开。

示例:

如下例子不符合规范。

例1:

/*getreplicatesubsystemindexandnetindicator*/

 

repssn_ind=ssn_data[index].repssn_index;

repssn_ni=ssn_data[index].ni;

例2:

repssn_ind=ssn_data[index].repssn_index;

repssn_ni=ssn_data[index].ni;

/*getreplicatesubsystemindexandnetindicator*/

应如下书写

/*getreplicatesubsystemindexandnetindicator*/

repssn_ind=ssn_data[index].repssn_index;

repssn_ni=ssn_data[index].ni;

6.注释与所描述内容进行同样的缩排。

这样可使程序排版整齐,并方便注释的阅读与理解。

示例:

如下例子,排版不整齐,阅读稍感不方便。

voidexample_fun(void)

{

/*codeonecomments*/

CodeBlockOne

/*codetwocomments*/

CodeBlockTwo

}

应改为如下布局。

voidexample_fun(void)

{

/*codeonecomments*/

CodeBlockOne

/*codetwocomments*/

CodeBlockTwo

}

7.将注释与其上面的代码用空行隔开。

示例:

如下例子,显得代码过于紧凑。

/*codeonecomments*/

programcodeone

/*codetwocomments*/

programcodetwo

应如下书写

/*codeonecomments*/

programcodeone

/*codetwocomments*/

programcodetwo

4.高效率代码设计规范

代码效率分为全局效率、局部效率、时间效率及空间效率。

全局效率是站在整个系统的角度上的系统效率;局部效率是站在模块或函数角度上的效率;时间效率是程序处理输入任务所需的时间长短;空间效率是程序所需内存空间,如机器代码空间大小、数据空间大小、栈空间大小等。

1.仔细分析有关算法,并进行优化。

(1)用移位来代替2的次幂的乘除法

示例:

(A/D采样时的均值滤波:

每次采样16个点,求16个点的均值)

以下代码不规范:

sum/=16;

应书写为:

sum>>=4;

(2)用减法代替任意的除法

示例:

(在LED/LCD显示中,常需要将一个无符号整型数的个、十、百位取出来)

以下代码不规范:

temprature=253;

led1=temperature/100;

temperature%=100;

led2=temperature/10;

temperature%=10;

led3=temperature;

应书写为:

temprature=253;

led1=led2=led3=0;

while(temperature<100)

{

led1++;

temperaturn-=100;

}

………………………………

(3)用定点数代替浮点数的运算

说明:

用定点数代替浮点数的基本原则就是单元变换。

比如,要对某个电压值进行运算处理,电压的具体值是用浮点数变量voltage_f来表示的,单位是V,精度是mV,即当voltage_f=1.234时,则表示当前电压是1.234V,经过单位变换,将最小单位换成mV就可以将浮点换成定点来进行运算,整型变量voltage_i来表示电压,对应于之前的1.234V,voltage_i=1234;

2.在多重循环中,应将最忙的循环放在最内层。

说明:

减少CPU切入循环层的次数。

示例:

如下代码效率不高。

for(row=0;row<100;row++)

{

for(col=0;col<5;col++)

{

sum+=a[row][col];

}

}

可以改为如下方式,以提高效率。

for(col=0;col<5;col++)

{

for(row=0;row<100;row++)

{

sum+=a[row][col];

}

}

3.避免循环体内含判断语句,应将循环语句置于判断语句的代码块之中。

说明:

目的是减少判断次数。

循环体中的判断语句是否可以移到循环体外,要视程序的具体情况而言,一般情况,与循环变量无关的判断语句可以移到循环体外,而有关的则不可以。

示例:

如下代码效率稍低。

for(ind=0;ind

{

if(data_type==RECT_AREA)

{

area_sum+=rect_area[ind];

}

else

{

rect_length_sum+=rect[ind].length;

rect_width_sum+=rect[ind].width;

}

}

因为判断语句与循环变量无关,故可如下改进,以减少判断次数。

if(data_type==RECT_AREA)

{

for(ind=0;ind

{

area_sum+=rect_area[ind];

}

}

else

{

for(ind=0;ind

{

rect_length_sum+=rect[ind].length;

rect_width_sum+=rect[ind].width;

}

}

4.编程时,要随时留心代码效率;优化代码时,要考虑周全。

5.不应花过多的时间拼命地提高调用不很频繁的函数代码效率。

6.命名规范

1.自己特有的命名风格,要自始至终保持一致,不可来回变化。

2.对于变量命名,禁止取单个字符(如i、j、k...),建议除了要有具体含义外,还能表明其变量类型、数据类型等,但i、j、k作局部循环变量是允许的。

3.变量的命名规范。

变量的命名规范可参照匈牙利命名法:

 [作用范围域前缀]+[前缀]+基本类型+变量名

其中前缀是可选项,以小写字母表示

基本类型是必选项,以小写字母表示

变量名是必选项,可多个单词(或缩写)合在一起,每个单词首字母大写。

示例:

g_pCounter:

g是前缀,代表是gobal变量,p表示类型是指针,Couter是变量名。

基本类型列表:

基本类型

意义

举例

c

Char字符

cMyChar

i或n

Intger整数

nTestNumber

u

unsignedinteger无符号整数

uCount

ul

unsignedLong   无符号长整数

ulTime

w

word字

wPara

dw

DoubleWord  双字

dwPara

l

long长整型

lPara

f

float浮点数

fTotal

s

String字符串

sTemp

4.宏和常量的命名

宏和常量的命名规则:

单词的字母全部大写,各单词之间用下划线隔开。

命名举例:

#define  MAX_SLOT_NUM        8

constintMAX_ARRAY

5.函数的命名

单词首字母为大写,其余均为小写,单词之间不用下划线。

函数名应以一个动词开头。

命名举例:

voidPerformSelfTest(void);

voidGetKeyNum(int*nKey);

7.提高代码正确性设计规范

1.严禁使用未经初始化的变量。

引用未经初始化的变量可能会产生不可预知的后果,特别是引用未经初始化的指针经常会导致系统崩溃,需特别注意。

声明变量的同时初始化,除了能防止引用未经初始化的变量外,还可能生成更高效的机器代码。

2.注意变量的有效取值范围,防止表达式出现上溢或下溢。

示例:

死循环代码

例子1:

chari;

for(i=0;i<200;i++)

{

……;

}

应书写为:

unsignedchari;

for(i=0;i<200;i++)

{

……;

}

例子2:

unsignedcharcIndex=10;    

while(cIndex--  >=0)

{

}        //将出现下溢

当cIndex等于0时,再减1不会小于0,而是0xFF,故程序是一个死循环。

应书写为:

charcIndex=10;    

while(cIndex--  >=0)

{

}   

3.防止内存操作越界。

 说明:

内存操作主要是指对数组、指针、内存地址等的操作。

内存操作越界是软件系统主要错误之一,后果往往非常严重,所以进行这些操作时一定要仔细小心。

(1)数组越界

charaMyArray[10];

for(i=0;i<=10;i++)

{

    aMyArray[i]=0;    //当i等于10时,将发生越界。

}

(2)指针操作越界

charaMyArray[10];

char*pMyArray;

pMyArray=aMyArray;

--pMyArray;        //越界

pMyArray=aMyArray;

pMyArray+=10;    //越界

8.可移植性代码设计规范

可移植性代码是指可方便移植到其它系统上运行的代码,编写可移植性代码的关键在于使用宏。

1.将读写访问硬件资源的基本代码定义为宏。

示例:

(将外部计数器使能)

*P_IOA_DATA|=0x0001;

#defineENABLE_COUTER*P_IOA_DATA|=0x0001;

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 总结汇报 > 学习总结

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1