单片机软件编程规范Word文档格式.docx
- 文档编号:18086692
- 上传时间:2022-12-13
- 格式:DOCX
- 页数:19
- 大小:44.85KB
单片机软件编程规范Word文档格式.docx
《单片机软件编程规范Word文档格式.docx》由会员分享,可在线阅读,更多相关《单片机软件编程规范Word文档格式.docx(19页珍藏版)》请在冰豆网上搜索。
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<
filename.h>
格式来引用标
准库的头文件(编译器将从标准库目录开始搜索)。
用#“elude“filename.h”格式来引用非标准
库的头文件(编译器将从用户的工作目录开始搜索)。
#include<
lib_header.h>
#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程序的版式
统一使用编辑器的TAB键进行缩进,同时设定其缩进量为系统默认
程序要采用统一缩进风格编写。
在下列情况下,必须采用缩进:
函数或过程、类的定义、结构的定义、枚举的定义、判断和循环语句中的程序都要采用如上的缩进方式。
但如果同一程序块的缩进级数太多(一般不超过5级),可考虑使用函数减少缩进级数。
示例:
//风格良好的格式
voidFunction(floatx,floaty,floatz)
if(…)
while(…)
}//endofwhile
}//endofif
//风格很差的格式
相对独立的程序块之间、变量说明之后必须加空行
空行起着分隔程序段落的作用。
空行得体(不过多也不过少)将使程序的布局更加
清晰。
空行不会浪费内存,虽然打印含有空行的程序是会多消耗一些纸张,但是值得。
所以不要舍不得用空行。
如下例子不符合规范。
if(!
IsValidNI(ni))
...//programcode
repssnInd=ssnData[index].repssnIndex;
repssnNI=ssnData[index].NI;
应如下书写
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等语句自占一行
执行语句不得紧跟其后。
不论执行语句有多少都要加{}。
这样可以防止书写失误
if(width<
height)
DoSomeThing();
for(initialization;
condition;
update)
DoSomeThing();
height)DoSomeThing();
Other();
4.3.3程序块的分界符独占一行
行并且位于同
程序块的分界符(如C/C++语言的大括号‘{'
和‘}'
)应各独占一列,同时与引用它们的语句左对齐。
for(...){
if(...)
voidExampleFun(void)
应如下书写。
for(...)
}voidExampleFun(void)
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<
c&
d由于
8|low=(high<
8)|low,
a|b&
c=(a|b)&
c),
(1)
(2)不会出错,但语句不易理解;
a|b<
d=a|(b<
c)&
d,(3)造成了判断条件出错。
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<
MAX_ACT_TASK_NUMBER)
(IsStatItemValid(statItem))
(actTaskTable[taskNo].ResultData!
=0));
4.5.2循环、判断等语句要在低优先级操作符处划分新行
循环、判断等语句中若有较长的表达式或语句,则要进行适应的划分,长表达式要在低优先级操作符处划分新行,操作符放在新行之首。
if((taskNo<
maxActTaskNumber)
(IsStatItemValid(statItem)))
for(i=0,j=0;
(i<
BufferKeyword[wordIndex].WordLength)
(j<
NewKeyword.WordLength);
i++,j++)
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加1,
6.3函数接口的注释格式
对函数接口进行正确而必要的注释,有助于该函数的使用和维护,甚至有助于在代码级上测试该函数。
函数接口的注释
//函数介绍:
//输入参数:
//输出参数:
//返回值:
//备注:
//过程参数:
(汇编中,过程参数也是需要注明的。
)
voidDrawTriangle(floatx,floaty,floatz)
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注释与所描述内容进行同样的缩排
可使程序排版整齐,并方便注释的阅读与理解。
//如下例子,排版不整齐,阅读稍感不方便
//codeonecomments
CodeBlockOne
//codetwocomments
CodeBlockTwo
//应改为如下布局。
6.6将注释与其上面的代码用空行隔开
使人能很清晰的看出,注释与被注释的代码。
如下例子,显得代码过于紧凑。
programcodeone
//codetwocomm
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 单片机 软件 编程 规范