任务4.2 程序的风格和可移植.doc_第1页
任务4.2 程序的风格和可移植.doc_第2页
任务4.2 程序的风格和可移植.doc_第3页
任务4.2 程序的风格和可移植.doc_第4页
任务4.2 程序的风格和可移植.doc_第5页
已阅读5页,还剩2页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

4.2 程序的风格和可移植性任务4.2 程序的风格和可移植性4.1.1 任务介绍程序不仅仅要被计算机读,还要给程序员读。一个风格清爽而又严谨的程序更容易被读懂,更容易被修改和排错。良好的编程风格和正确的习惯还有助于保持思维清晰,写出正确无误的代码。特别是一开发团队共同工作时,保持一致的编程风格尤为重要。大多数初学者不太重视编程风格,事实上,每个初学者在项目初期都会因为不良编程习惯而浪费大量时间,因此若能在开始写程序时就重视编程风格问题,对顺利度过提高阶段有很大帮助。在本任务中,谈一下编程风格中几个最基本原则。另外,初学者第一次接触到的单片机是51单片机,但在后期的学习和工作中,可能会接触和使用其它功能更强大的单片机,如AVR、MSP430、PIC或者STM32等。程序从一个平台到另外一个平台,涉及到程序的可移植性问题,如果初学者写出的代码移植性强,则这个工作是快乐而有趣的,否则将是重写大部分代码的枯燥重复劳动。在本任务中,还将介绍提高程序可移植性的方法。本节无具体任务,只有知识准备。4.1.2 知识准备1、编程风格在程序的编程风格中,将从变量命名规则、函数命名规则、排版和注释等几个方面进行阐述。(1)变量命名规则变量命名尽量使用具有说明性的名称,避免使用a、b、c、x、y、z等无意义字符,应当直观且可以拼读,可望文知意,不必进行“解码”。使用范围较大的变量,如全局变量,更应该有一个说明性的名称。变量名尽量使用名词,长度控制在1-4个单词最佳。如果名称包含多个单词,每个单词首字母大写以区分单词。单词不要出现中文拼音,如ge,shi,bai等。uchar KeyValue; /按键值uint InputValue; /输入电压uint Temperature; /温度当单词必须出现空格才好理解时,可以用下划线_代替空格,如:uint Degree_C; /OCuint Degree_F; /OF当单词较长时,可以适当缩写:uchar LedCnt; /LED计数器,其中Cnt是counter的缩写uchar TxBuffer; /发送缓冲器,其中Tx是transit的缩写另外在程序中不要出现名字完全相同的局部变量和全局变量,尽管两者的作用域不同而不会发生语法错误,但会使人误解,也不要出现仅靠大小写区分的相似的变量。对于约定速成的变量,如i、j作为循环变量,p、q作为指针变量等,不要改动,采用更长的变量名反而不习惯。(2)函数命名规则和变量一样,函数命名也应该具有说明性。函数名按照“模块+功能名”的方式命名,其中功能名应使用“动词”或者“动词+名词”的方式。void Seg7Display(); /数码管显示char KeyGetValue(); /从键盘读取按键值void Timer0_Init(); /定时器0初始化void UARTGetChar(); /从串口读取一字节数据void LedTwinkle(); /发光二极管闪烁每个单词首字母大写,便于阅读。遇到太长的单词也可以在不影响阅读的情况下适当缩写,例如用Tx代替单词Transimit,Rx代替单词Receive。和变量一样,一旦约定某种简化方式,以后保持统一的风格。(3)排版 代码缩进为了让程序看起来有层次感,突出程序的结构,C编程时要求语句之间缩进。缩进一般为4个空格,在KeilC51中,Edit-Configuration-Editor中,设置Tab size为4。我们需要缩进时,按Tab键就可以一次缩进4个空格了。什么情况下应该缩进呢?首先花括号单独写成一行,然后按照以下原则缩进。(a)花括号:花括号的正面和花括号前面一行对齐,反面和正面对齐,花括号内所有的语句缩进,花括号反面之后的第一行和花括号反面对齐。(b)for语句:for语句后面的第一行如果不是大括号,则for语句后面第一行要缩进,如果是大括号,则按(a)条来处理。(需要注意的是两个for连着写的时候,第二个for也要缩写)(c)其它的语句如while、if、switch等语句和for语句类似。代码缩进的格式举例如下:void main() uchar LedCnt;Timer0Init(); while(1) if(FlagSystem10Ms=1) FlagSystem10Ms=0;if(+LedCnt=50) LedCnt=0; 较长的语句要分两行来写。对于较长的语句,分两行来写,在第一行语句的末尾加,如if(TwinkOn=1)&(FlagHour=1)&(LedDisPos=0)|(LedDisPos=1) 函数的参数过长,分两行来写。uchar UARTInit( long int Baud, uchar Parity, uchar DataBits, uchar StopBits) 函数体 (4)注释注释是帮组程序读者的一种手段。这里读者不仅包括其他人,也包括编程员本身。一个注释不够详细、明确的程序,过上一段时间之后,连自己都看不懂。代码的注释亮要保持在代码的20%以上,注释不能写成流水账的形式,最好的注释是简洁明了的点名程序的突出特征,或者阐明思路,或者指出特殊之处,以帮助理解程序。 对于每个函数,特别是底层函数,都要注释。在函数前面注释该函数的名称、功能、入口参数、出口参数、说明等。如果参与团队开发,还应该写若干个典型的应用范例,供别人参考。举例:/*函数名称:Seg7Display()*功能 :动态数码管扫描*入口参数:无*出口参数:无*说明 :由1ms时标信号调用,每调用一次,扫描一位数码管*/void Seg7Display()static uchar i=0; P1=0xff; /消隐P0=Seg7CodeDispBufferi; /送段码P1=Seg7Positi; /送位码if(+i=2) i=0; /为扫描下一位数码管做准备 文件头部的说明性文件在.c文件的头部加一些文字说明,举例:/*文件:main.c作者:探索者电子版本:V1.0日期:2014.10.2简介:多功能数字钟,能实现时间的走时,6位数码管显示,按键可以调整时间*/2、程序的可移植性在51单片机入门之后,大部分初学者会转向功能更强大的单片机,如AVR、MSP430、STM32等单片机。我们学习51单片机时编写的每个程序都有可能会移植到不同的硬件环境或者其它的处理器平台上运行,了解一些移植的概念和基本知识对今后的开发会有很大的帮助。(1)消除CPU差异我们先看一段数码管扫描程序void Seg7Display()static uchar i=0; P1=0xff; /消阴P0=Seg7CodeDispBufferi; /送段码P1=Seg7Positi; /送位选if(+i=2) i=0; /为扫描下一位数码管做准备在程序中出现了P2、P0这样的I/O口操作,这段程序移如果不修改,直接移植到AVR单片机或者MSP430单片机,能够运行吗?事实上,每一种单片机对于端口的定义都是不一样的,例如AVR单片机的IO定义为POARTA、PORTB,MSP430单片机的IO端口定义为P1OUT,P2OUT等,不同单片机的I/O口定义是不同的。51单片机编写的程序要移植到别的单片机上,首先要消除这个差异(严格来讲,差异消除不掉,只是把差异压缩到局部)。下面示范用宏定义来消除I/O的差异。#include#define SegData P0#define PositData P1void Seg7Display()static uchar i=0; PositData=0x00; /消隐SegData=Seg7CodeDisp_Buffi;/送段码PositData=Seg7Positi; /送位选if(+i=2) i=0; /为扫描下一位数码管做准备把I/O口宏定义后,再移植到其它单片机中时,直接修改宏定义就可以了,不需要修改函数内部的内容。同样道理I/O位定义也需要做这样的宏定义,举例如下:#includesbit LED=P20;#define LED_ON LED=0 /LED亮#define LED_OFF LED=1 /LED灭(2)软件分层学过计算机文化基础的都知道网络协议分成7个层,它们按照由低到高的顺序分为物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。每层完成一定的功能,每层都为上一层直接提供服务。我们用到的windows/linux等操作系统也是按照分层的思想设计。在单片机系统中,软件分层,更容易将千差万别的硬件层和驱动层、应用层分开,将不同单片机之间的差异消灭在硬件层中。到目前为止,我们学过的程序不多,我们以动态数码管驱动为例,来引入软件分层的思想。在动态数码管驱动程序中,段选和位选一直固定为P0口和P2口。那么在实际电路设计中,这样做合理吗?在电子产品的设计中,通常是先制作硬件,再编写软件,软件要配合硬件。如果硬件工程师在设计数码管驱动电路时,把段选线没有全部放置到P0口,而是P0口接了3个段,P1口接了3个段,P2口接了2段。这时,我们就不能简单的把段码的赋值写成:P0=Seg7CodeDisp_Buffi。位选也存在这样的问题。另外在之前的程序中,数码管的位数最多为6位,我们在写程序时,直接使用了一组I/O口(8个位),造成了I/O口的浪费。以位选为例,写一个端口映射函数来作为数码管驱动的硬件驱动层。2个数码管,位选分别接P1.0和P2.0,端口映射函数如下:#includesbit Posit_1=P10; /位选1接口sbit Posit_2=P20; /位选2接口#define Posit1Set Posit_1=1 /位接口宏定义#define Posit1Reset Posit_1=0#define Posit2Set Posit_2=1#define Posit2Reset Posit_2=0#define SegData P0 /段接口宏定义/位选硬件驱动void Seg7SetPosit(uchar PositData) if(PositData&0x01) Posit1Set; /取段选第一位数据,然后设置对应I/O else Posit1Reset; if(PositData&0x02) Posit2Set; /取段选第二位数据,然后设置对应I/O else Posit2Reset; void Seg7Display()static uchar i=0; Seg7SetPosit(0xff); /消隐SegData=Seg7CodeDispBufferi; /送段码Seg7SetPosit(Seg7Positi); /送位选if(+i=2) i=0; /为扫描下一位数码管做准备在Seg7SetPosit()函数中,根据数码管驱动层函数Seg7Display()函数传递过来的位选信息PositData,然后根据PositData的各个位的高低,再把各自对应的I/O置高或置低。在驱动层函数Seg7Display()中,送位选时,直接调用Seg7SetPosit()就可以了。同样道理,段选的接口也可以通过硬件驱动层来配置。另外,在之前的数码管显示程序中,

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论