单片机软件编程规范.docx

上传人:b****4 文档编号:5120446 上传时间:2022-12-13 格式:DOCX 页数:19 大小:44.85KB
下载 相关 举报
单片机软件编程规范.docx_第1页
第1页 / 共19页
单片机软件编程规范.docx_第2页
第2页 / 共19页
单片机软件编程规范.docx_第3页
第3页 / 共19页
单片机软件编程规范.docx_第4页
第4页 / 共19页
单片机软件编程规范.docx_第5页
第5页 / 共19页
点击查看更多>>
下载资源
资源描述

单片机软件编程规范.docx

《单片机软件编程规范.docx》由会员分享,可在线阅读,更多相关《单片机软件编程规范.docx(19页珍藏版)》请在冰豆网上搜索。

单片机软件编程规范.docx

单片机软件编程规范

1编辑器3

2程序文件的结构3

2.1说明3

2.2编译宏定义4

2.3包含文件4

2.4用户数据类型定义4

2.5管脚定义5

2.6常量5

2.7变量5

2.8正文6

2.8.1正文顺序[推荐]6

2.8.2正文内容6

2.9长的常量数组6

3命名7

3.1常量、编译宏命名7

3.2变量命名7

3.3函数命名8

4程序的版式9

4.1缩进:

统一使用编辑器的TAB键进行缩进,同时设定其缩进量为系统默认9

4.2空行:

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

4.3代码行11

4.3.1一行代码只做一件事情11

4.3.2if、for、while、do等语句自占一行11

4.3.3程序块的分界符独占一行12

4.3.4多运算符的代码行,不使用默认优先级13

4.3.5不要使用难懂的技巧性很高的语句13

4.4空格14

4.4.1必要时留空格,使代码更清晰[推荐]14

4.4.2二元操作符前后留空格14

4.4.3一元操作符前后不留空格14

4.5长行拆分15

4.5.1较长的语句(>80字符)要分成多行书写15

4.5.2循环、判断等语句要在低优先级操作符处划分新行16

4.5.3函数或过程中的参数较长,则要进行适当的划分16

5全局变量定义时初始化16

6注释17

6.1必须加注释的位置[推荐]17

6.2注释应适量且准确[推荐]17

6.3函数接口的注释格式17

6.4变量的注释格式[推荐]18

6.5注释与所描述内容进行同样的缩排19

6.6将注释与其上面的代码用空行隔开20

6.7程序块结束行加注释[推荐]20

7EEPROM数据保护21

8程序失效复位处理[推荐]21

9检查21

9.1数组下标检查21

9.2指针检查22

9.3易混淆操作符检查22

9.4右值变量检查22

9.5差1错误检查22

9.6变量溢出检查23

9.7类型转换检查23

1编辑器

程序统一使用VC的编辑器。

2程序文件的结构

如果没有涉及使用平台化的用户文件,通常只能有一个用户主程序文件。

用户程序文件的内容按说明、编译宏定义、包含文件、用户数据类型定义、管脚定义、常量、变量、正文、长的常量数组的顺序编写。

2.1说明

说明:

说明位于用户程序文件的开头,主要内容有:

(1)版权信息。

(2)文件名称。

(3)程序说明:

说明程序用途、功能及使用方法等。

(4)版本记录。

(5)开发环境。

示例:

//版权信息

//Copyright(c)2001,XXXXXX有限公司产品开发部

//Allrightsreserved.

//文件名称:

filename.c

//程序说明:

XXXXX主程序,,

//版本记录:

//V101:

//1、增加警铃输出延时;

//2、修正****Bug。

//作者:

***//时间:

//V100:

正式发布。

//作者:

***//时间:

//编译工具:

KeilC6.0

2.2编译宏定义说明:

同一产品的不同硬件程序和系列产品的程序,应采用编译宏定义,来减少维护的工作量;

2.3包含文件

说明:

包含引用的标准库头文件以及用户头文件。

用#include格式来引用标

准库的头文件(编译器将从标准库目录开始搜索)。

用#“elude“filename.h”格式来引用非标准

库的头文件(编译器将从用户的工作目录开始搜索)。

示例:

#include

#include“user_header.h”

2.4用户数据类型定义

说明:

定义结构、联合、枚举以及其它非标准的数据类型;

示例:

typedefunionMacData//联合

struct//结构

{

unsignedcharMac;//类型

unsignedcharLen;//长度

unsignedcharAddr;//地址

unsignedcharData[13];//数据

}Msg;

};

#defineuintunsignedint;//自定义数据类型

2.5管脚定义

说明:

定义本程序使用的管脚。

2.6常量

说明:

有特定意义的常数必须进行宏定义;

同一特定意义的常数如在多个地方应用,必须进行宏定义;调试维护需要调整的常数必须进行宏定义;无特定意义的循环上、下限,不需进行宏定义。

2.7变量

说明:

定义程序所使用的变量。

有关联的、相同地址空间、初始化、不需初始化的变量要放在一起;

2.8正文

2.8.1正文顺序[推荐]

说明:

应按主程序和中断程序的共用子程序、各中断相关子程序和中断程序、主程序相关子程序和主程序;

关系紧密的子程序应放在一起,并按照从低到高的层次放。

尽量取消函数的声明,可通过注释说明;

除主程序和中断程序外,在不影响可读性的情况下不应设置只一个地方调用的函

数。

2.8.2正文内容

说明:

包含初始化程序、主循环体程序和中断程序。

2.8.2.1初始化程序[推荐]

说明:

应按管脚初始化、RAM初始化、内部设置初始化、外设初始化、打开定时器、打开

中断的顺序进行初始化。

2.8.2.2主循环程序和中断程序[推荐]

说明:

定时应采用计时器处理,不能存在长时间的停滞等待;

不允许多个事件使用一个软件计时器。

计时器宜采用倒计时;

中断事件的响应如果在主循环能够完成响应,应放在主循环。

2.9长的常量数组

说明:

在此定义长的常量数组,如字库、图案等。

3命名

命名的风格必须保持一致。

3.1常量、编译宏命名

说明:

常量、编译宏全部大写,单词间使用下划线分隔。

示例:

#defineMAIN_DELAY_NUM1

3.2变量命名

说明:

通常,在变量中加入前缀以增进人们对程序的理解。

其前缀的通用格式为:

数据类型缩写+模块名+。

同时,为了区分全局和局部变量,也兼顾命名的方便,特采用如下变量命名规则:

全局变量大小写结合,数据类型缩写后,单词首字母大写;局部变量全部小写,数据类型缩写后,使用下划线分隔各单词;局部变量在不影响可读性的前提下,可以不写数据类型;unsignedchar类型的缩写不写;

汇编中,与MPU数据总线(如8位、16位)一致数据类型的缩写不写。

数据类型缩写:

booleanb

charc

longl

floatf

doubled

inti

unsignedintui

指针p

结构s

输入管脚bi

输出管脚bo

示例:

//管脚定义

sbitbiFire=P1A1;

sbitboFireRelay=P"2;

//全局变量定义

bitbFault;

unsignedcharFireAckNum;

unsignedcharDeviceStatus[242];

unsignedchar*pDevice;

charcSampleValue;

longlTime;

long*plEntry;

floatfRadius;

doubledArea;

intiFireRelayDelay;

unsignedintuiFaultRelayDelay;

unsignedintuiSounderDelay[4];

voidGetSampleValue(void)

{unsignedchartemp;

bitb_fault;longl_fire_delay;

}

3.3函数命名

说明:

函数命名应当直观且可以拼读,可望文知意,不必进行“解码”。

标识符采用英文单词或其组合,便于记忆和阅读,并且每个单词的首字母大写,长单词可以缩写,但缩写要使用大家基本认可的,并且必要是进行注释说明。

下单词的缩写能够被大家基本认可:

temp可缩写为tmp;

flag可缩写为flg;statistic可缩写为stat;increment可缩写为inc;message可缩写为msg;

4程序的版式

4.1缩进:

统一使用编辑器的TAB键进行缩进,同时设定其缩进量为系统默认

说明:

程序要采用统一缩进风格编写。

在下列情况下,必须采用缩进:

函数或过程、类的定义、结构的定义、枚举的定义、判断和循环语句中的程序都要采用如上的缩进方式。

但如果同一程序块的缩进级数太多(一般不超过5级),可考虑使用函数减少缩进级数。

示例:

//风格良好的格式

voidFunction(floatx,floaty,floatz)

{

if(…)

{

while(…)

{

}//endofwhile

}//endofif

}

//风格很差的格式

voidFunction(floatx,floaty,floatz)

{

if(…)

{

while(…)

{

}//endofwhile

}//endofif

}

4.2空行:

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

说明:

空行起着分隔程序段落的作用。

空行得体(不过多也不过少)将使程序的布局更加

清晰。

空行不会浪费内存,虽然打印含有空行的程序是会多消耗一些纸张,但是值得。

所以不要舍不得用空行。

示例:

如下例子不符合规范。

if(!

IsValidNI(ni))

{

...//programcode

}

repssnInd=ssnData[index].repssnIndex;

repssnNI=ssnData[index].NI;

应如下书写

if(!

IsValidNI(ni))

{

...//programcode

}

repssnInd=ssnData[index].repssnIndex;repssnNI=ssnData[index].NI;

4.3代码行

4.3.1一行代码只做一件事情

说明:

如只定义一个变量,或只写一条语句。

这样的代码容易阅读,并且方便于写注释。

示例:

(a)为风格良好的代码行

intwidth;//宽度

intheight;//高度

intdepth;//深度

x=a+b;

y=c+d;

z=e+f;

(b)为风格不良的代码行。

intwidth,height,depth;//宽度高度深度

X=a+b;y=c+d;z=e+f;

4.3.2if、for、while、do等语句自占一行

说明:

执行语句不得紧跟其后。

不论执行语句有多少都要加{}。

这样可以防止书写失误

示例:

(a)为风格良好的代码行

if(width

{

DoSomeThing();

}

for(initialization;condition;update)

{

DoSomeThing();

(b)为风格不良的代码行。

if(width

Other();

for(initialization;condition;update)

DoSomeThing();

Other();

4.3.3程序块的分界符独占一行

行并且位于同

说明:

程序块的分界符(如C/C++语言的大括号‘{'和‘}')应各独占一列,同时与引用它们的语句左对齐。

示例:

如下例子不符合规范。

for(...){

...//programcode

}

if(...)

{

...//programcode

}

voidExampleFun(void)

{

...//programcode

}

应如下书写。

for(...)

{

...//programcode

}

if(...)

{

...//programcode

}voidExampleFun(void)

{

...//programcode

}

4.3.4多运算符的代码行,不使用默认优先级

说明:

注意运算符的优先级,并用括号明确表达式的操作顺序,防止阅读程序时产生误解,防止因默认的优先级与设计思想不符而导致程序出错。

示例:

下列语句中的表达式

word=(high<<8)|low

(1)if((a|b)&&(a&c))

(2)

if((a|b)<(c&d))(3)

如果书写为

high<<8|lowa|b&&a&ca|b

high<<8|low=(high<<8)|low,

a|b&&a&c=(a|b)&&(a&c),

(1)

(2)不会出错,但语句不易理解;

a|b

4.3.5不要使用难懂的技巧性很高的语句

说明:

高技巧语句不等于高效率的程序,实际上程序的效率关键在于算法。

示例:

如下表达式,考虑不周就可能出问题,也较难理解。

*statPoi+++=1;

*++statPoi+=1;

应分别改为如下。

*statPoi+=1;

statPoi++;//此二语句功能相当于“*statPoi+++=1;

++statPoi;

*statPoi+=1;//此二语句功能相当于“*++statPoi+=1;

4.4空格

4.4.1必要时留空格,使代码更清晰[推荐]

说明:

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

如果语句已足够清晰则不需要加空格,如多重括号间不必加空格,像const、virtual、inline、case等关键字之后,为了突出关键字,至少要留一个空格。

像if、for、while等关键字之后应留一个空格再跟左括号’(’,以突出关键字。

4.4.2二元操作符前后留空格

说明:

如“=”、“+=”“>=”、“<=”、“+”、“*”、“%”、“&&”、“||”、“<<”,“八”等二元操作符的前后应当加空格。

4.4.3一元操作符前后不留空格

说明:

一元操作符如“!

”、“~”、“++”、“--”、“&”(地址运算符)等前后不加空

格。

“[]”、“

.”、“->”这类操作符前后不加空格。

示例:

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

inta,b,c;//良好的风格

inta,b,c;//不好的风格

(2)比较操作符,赋值操作符"="、"+=",算术操作符"+"、"%",逻辑操作符"&&"、"&",

位域操作符"<<"、”A"等双目操作符的前后加空格。

if(currentTime>=MAX_TIME_VALUE)

a=b+c;

a*=2;

a=bA2;

(3)"!

"、"~"、"++"、

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

*p='a';

//内容操作"*"与内容之间

flag=!

isEmpty;

//非操作"!

"与内容之间

p=&mem;

//地址操作"&"与内容之间

i++;

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

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

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

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

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

4.5长行拆分

4.5.1较长的语句(>80字符)要分成多行书写

说明:

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

示例:

permCountMsg.head.len=

NO7_TO_STAT_PERM_COUNT_LEN

+STAT_SIZE_PER_FRAM*sizeof(_UL);

actTaskTable[frameId*STAT_TASK_CHECK_NUMBER+index].occupied=statPoi[index].occupied;

actTaskTable[taskNo].durationTrueOrFalse

=sysGetSccpStatisticState(statItem);

reportOrNotFlag=((taskNo

&&(IsStatItemValid(statItem))

&&(actTaskTable[taskNo].ResultData!

=0));

4.5.2循环、判断等语句要在低优先级操作符处划分新行

说明:

循环、判断等语句中若有较长的表达式或语句,则要进行适应的划分,长表达式要在低优先级操作符处划分新行,操作符放在新行之首。

示例:

if((taskNo

&&(IsStatItemValid(statItem)))

{

...//programcode

}

for(i=0,j=0;(i

&&(j

{

...//programcode

}

4.5.3函数或过程中的参数较长,则要进行适当的划分

说明:

若函数或过程中的参数较长,则要进行适当的划分。

示例:

StrCompare((BYTE*)&statObject,

(BYTE*)&(actTaskTable[taskNo].statObject),sizeof(_STAT_OBJECT));

FlashActDuration(statItem,frameId*STAT_TASK_CHECK_NUMBER+index,statObject);

5全局变量定义时初始化

变量定义的同时初始化,未初始化的变量需注释其原因。

6注释

6.1必须加注释的位置[推荐]

/*,

说明:

注释符有块注释“/*…*/”行注释和“〃…”。

应使用“进行注释,使用

/*”进行代码屏蔽。

注释通常用于:

用户程序文件开头的说明;

编译宏定义、结构和联合定义、管脚定义、常量、重要变量;重要的代码行或段落提示;

函数接口说明。

6.2注释应适量且准确[推荐]

说明:

虽然注释有助于理解代码,但不必要过多注释,也不可与代码体现的意思不一致。

注释是对代码的“提示”,而不是文档,应该“点到为止”。

注释不仅要提示代码,还要体现其显示意义。

过多的注释,会让人眼花缭乱。

如果代码本来就是清楚的,则不必加注释;否则多此一举,令人厌烦。

不一致的注释,更让人费解。

应从标识符命名、程序流程上下功夫,让代码本身就能说明自己,进而减少注释。

示例:

多余的注释

i++;//i加1,

6.3函数接口的注释格式

说明:

对函数接口进行正确而必要的注释,有助于该函数的使用和维护,甚至有助于在代码级上测试该函数。

示例:

函数接口的注释

//函数介绍:

//输入参数:

//输出参数:

//返回值:

//备注:

//过程参数:

(汇编中,过程参数也是需要注明的。

voidDrawTriangle(floatx,floaty,floatz)

{

if(…)

{

while(…)

{

}//endofwhile

}//endofif

}

6.4变量的注释格式[推荐]

说明:

全局变量要有较详细的注释,其注释的内容包括:

功能;

取值范围;

存取注意事项;

存取函数或过程;

其它说明;

示例:

变量的注释。

//activestatistictasknumber

#defineMAX_ACT_TASK_NUMBER1000

#defineMAX_ACT_TASK_NUMBER1000//activestatistictasknumber

示例:

可按如下形式说明枚举/数据/联合结构。

//sccpinterfacewithsccpuserprimitivemessagename

enumSCCP_USER_PRIMITIVE

};

示例:

全局变量要有较详细的注释。

//TheErrorCodewhenSCCPtranslate

//GlobalTitlefailure,asfollows//变量作用、含义

//0-SUCCESS

//1-GTTableerror

//2-GTerrorOthers-nouse//变量取值范围

//onlyfunctionSCCPTranslate()in

//thismodualcanmodifyit,andother

//modulecanvisititthroughcall

//thefunctionGetGTTransErrorCode()//使用方法

unsignedcharg_uchGTTranErrorCode;

6.5注释与所描述内容进行同样的缩排

说明:

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

示例:

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

voidExampleFun(void)

{

//codeonecomments

CodeBlockOne

//codetwocomments

CodeBlockTwo

}

//应改为如下布局。

voidExampleFun(void)

{

//codeonecomments

CodeBlockOne

//codetwocomments

CodeBlockTwo

}

6.6将注释与其上面的代码用空行隔开

说明:

使人能很清晰的看出,注释与被注释的代码。

示例:

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

//codeonecomments

programcodeone

//codetwocomm

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

当前位置:首页 > 求职职场 > 简历

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

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