当前位置:文档之家› 单片机程序设计编程规范

单片机程序设计编程规范

单片机程序设计编程规范本规范适用于松翰科技8-bit MCU部门汇编程序编写准则,同样适用于代理商及重要客户工程师编程规范参考。

本规范的目的为统一编程风格,保证程序编写质量,提高程序的可移植性和维护性。

大部分的规范严格,品质要求高的软件公司对员工编写代码的风格都有硬性规定,例如缩排的使用,TAB的长度,函数变量的命名方式.这些规定的明显好处是可以统一规范不同程序员所编制的代码,提升程序代码的可读性与可维护性,同时统一格式的编程风格也为code review 提供方便.目录一、设计总则二、排版风格三、程序可读性及可维护性四、注释五、变量命名规则六、常量命名规则七、标号命名规则八、文件命名规则及文件分割九、标准程序模块十、附录一、一、设计总则设计总则1.程序质量的评估程序的优劣可以从两个方面进行评估,定量指标和定性指标。

定量指标包括:1)程序代码执行效率;2)程序占用资源多少。

定性指标包括:1)可调试性,即是否方便排除程序语法错误;2)可测试性,即是否方便验证程序功能的正确性;3)可维护性,即是否方便程序的修改和升级;4)可移植性;5)可读性。

2、程序架构为了便于维护和移植,推荐使用层次化的软件设计方法。

可把整个软件分为三层:应用层、界面层和底层驱动层。

各层之间的关系如下图所示。

层次化设计说明:1)底层驱动层主要包含直接和硬件相关的驱动程序,如数码管显示、按键、峰鸣器、继电器和电机控制等。

底层的各个模块间要保持各自的独立性,不产生直接的数据交互,底层也不直接访问应用层,如果有需要,都要通过界面层进行数据交互。

2)界面层主要提供数据交互,为应用层和底层驱动之间以及底层驱动层各模块之间提供数据的交互。

3)应用层主要完成具体功能的实现,它要通过界面层控制底层驱动层各模块来完成所需功能,而不能越过界面层直接访问底层驱动层。

所有的用户接口要在应用层来实现.4)一个好的架构必须将底层硬件包装起来,为应用程序提供一组丰富的函数操作(buffer or parameter),例如在中断的处理中,应用程序不需要资料中断的堆栈如何保护不需要知道地址操作,只需要读取中断产生的旗标动作.5)在即时性软件系统里面,对达到高效率的实时性与反应力,所以程序使用大量的事件触发方式来设计任务.事件有可能来自外部的触发(key ,rx data ,sensor detect,…)也可能是系统内部自行产生的(Timer,alarm,flag),与事件触发方式相对应的是定时查询方式(polling),一般来说polling 效率较差因为有多余的动作而且系统反应时间与查询polling 时间间隔有关,但是在小型的MCU 系统里面用Polling 方式反而简单许多3、设计基本原则1)尽量减少各个子程序功能模块间的耦合度(耦合度是指一个程序的执行对另一个程序的影响力),保证各自的独立性。

一般情况下,建议子程序模块功能的划分要尽可能细化,功能尽量单一,减少子程序模块间的数据交互。

2)在满足功能需求的情况下,可适当牺牲代码的执行速度,以保证程序的透明度。

3)主要子程序模块间的交互,要通过特定的界面跟应用层进行沟通,可使用FIFO (First in ,First out )或是Buffer 两种方式。

每种子程序模块都可以有自己的FIFO 。

例如:就按键来说,一般有Key buffer、Key FIFO或直接进入AP FIFO三种设计方式。

Key buffer:一般用于保存数字按键信息。

例如:在电话机的设计中,需要记录按键内容用于LCD显示、最后数字确认、数字存储等,这时候需要把按键值的信息(0123456789*#)记录在Key buffer中;Key FIFO:一些功能按键可以将相应信息列入到Key FIFO中,等待应用层的取用,这样可根据不同的工作模式进行不同的处理及动作。

这些类似的观念可以应用在许多周边中:输入类:Key、RF Data input、UART data input、Switch input等;输出类:LCD display、LED display、UART data output等。

APP FIFO(应用界面层):主要是将发生的事件储存在APP FIFO里面等待适当的时间依序处理,不然有可能造成系统在某一程序物件里面循环,从而降低系统的实时性(Real-Time)。

4)每个子程序模块只能有唯一一个程序入口地址在程序的首部,只能有唯一一个程序出口地址在程序的尾部。

例如:以下的写法是不规范的(两个RET出口,存在调试时不易设立断点,程序可读性降低等问题):lable:b0bts0fzret…clr yret应该改为(只有一个出口位置,标号为lable90,便于程序检查):lable:b0bts0fzjmp lable90….clr ylable90:ret5)上电复位时要对所有的RAM空间进行初始化(建议用户寄存器清零,系统寄存器进行必要设定),不要使用未经初始化的变量。

RAM未经过完整的初始化,容易导致程序执行的不确定性,这一不良现象往往在批量生产中有所体现。

(这点是工程师经常犯错的地方,须特别注意)6)系统中如果需要等待一些未知的应答信号,如通信或等待输入信号时,必须进行超时或异常处理,以防止程序进入“死等”状态。

例如在红外接收中,由于信号的突然消失或干扰从而无法得到一帧完整或正确的信息,这时需要复位接收程序的入口条件并退出接收程序,而不是一直等待信号的来临。

不然无法进行下次接收甚至会影响到其它程序的执行。

7)通过对系统数据结构的划分与组织的改进,以及对程序算法的优化来提高空间效率。

这种方式是解决软件空间效率的根本办法。

8)保证循环体内的工作量最小化。

应仔细考虑循环体内的语句是否可以放在循环体之外,使循环体内工作量最小,从而提高程序的执行效率。

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

10)中断处理程序应尽量短。

有效的作法为:在中断中进行标记,在主程序中进行处理。

但一些实时性要求较高的程序例外。

此外,进入中断时应该保存涉及到的变量和寄存器。

11)看门狗的正确使用。

看门狗主要用于微控制器死机时的时间溢出复位,需要程序适时清除。

正确的处理方式为:整个系统程序中尽量保证只有一处清看门狗位置,而且应处在主循环的主干位置。

切记不可在定时中断中清狗,因为微控制器有时只是在主循环中死掉。

(所有AC电源的应用程序都必须强迫加入看门狗选项尤其是条件式的看门狗有利于系统发生异常后的重启动)排版风格二、二、排版风格1、程序采用缩进风格编写,缩进为1个Tab键,1个Tab键定义为8个空格位。

2、程序中的标号要从第一列开始书写。

以“.”开头的预编译命令也要从第一列开始书写,其他预编译命令采用缩进风格编写。

例如:1)以“.”开头的预编译命令要从第一列开始书写,其他预编译命令采用缩进风格书写。

.LIST;从第一列开始书写INCLUDESTD macro1.h.CONSTNUMBER EQU55h.DATAwk00DS1.CODEORG0h2)标号要从第一列开始书写。

main:;从第一列开始…jmp main;缩进8个空格位3)变量或常量的定义采用缩进风格。

例如:.DATAkeybuf DS1.CONSTNUMBER EQU84)定义变量或常量时,变量名或常量名与命令符之间使用2个Tab键(相当于16个空格位)分开,命令符与后面的操作数用1个Tab键(相当于8个空格位)分开。

例如:keybuf DS1NUMBER EQU55h5)操作码与操作数之间用1个Tab键(相当于8个空格位)分开。

ORG80hmov a,NUMBERtable:DW1234h6.)程序中两个操作数之间用一个“,”作为分隔符,“#”号与立即数之间不需要分隔符。

例如:mov a,#55h7)标号要单独占一行。

8)相对独立的程序块之间必须加空行。

例如:ORG10hINCLUDE sys.asmINCLUDE int.asmINCLUDE key.asm9)程序语句后面若有注释,所有的注释要遵守上下对齐的原则。

例如:b0mov l,#7fh;use dp0x(hl)pointermov a,#00;set pointer=007fh应该书写为:b0mov l,#7fh;use dp0x(hl)pointermov a,#00;set pointer=007fh程序可读性与可维护性三、三、程序可读性与可维护性1.程序中的语句、标号、变量使用小写英文字母,常量与预编译命令使用大写英文字母,以便和一般的语句进行区分。

例如:NUMBER EQU55h.DATAaccbuf DS1.CODE…mov a,#NUMBER2.表示不同进制的立即数,要在立即数后面加上不同的进制符号。

例如:mov a,#00100011bmov a,#23h不建议使用:mov a,#0x233.一般情况下,变量和常量要分开定义,不要混在一起。

变量在”.DATA”段中定义,采用命令符“DS”,常量在”.CONST”段中定义,采用命令符“EQU”。

.CONSTNUMBER EQU10.DATAaccbuf DS14.程序中不使用未定义或意义不明确的常量。

例如:下面的赋值方法要避免使用:…mov a,#3;不要直接使用意义不明确的数字,在常量中做定义mov r,a…建议采用如下赋值方法:.CONSTNUMBER EQU3;循环次数….CODE…mov a,#NUMBERmov r,a5.整个程序的结尾要以“ENDP”语句结束。

6.当一段代码在程序中有多个地方使用时,建议采用子程序调用或宏命令的方式来替代。

如此,对该代码段的修改就可在一处完成,增强代码的可维护性。

7.程序中关系较为密切的子程序代码尽可能相邻。

8.避免程序中的垃圾代码,预留代码应以注释的方式出现。

程序中的垃圾代码不仅占用额外的空间,而且还可能影响到程序的功能与性能,很可能给程序的测试、维护等造成不必要的麻烦。

注释四、注释四、1.程序应该包括两个部分注释,说明部分和语句注释。

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

2.说明部分:1)源文件说明部分位于每个源文件的最前面,主要描述:文件名、作者、生成日期、联络方式、功能描述、版本号、软硬件平台、版权说明、修改记录等的简要说明,以英文书写。

例如:/*************************************************File name:;文件名Author:;作者Date:;日期Email:;邮箱地址Description:;功能描述Version:;版本号Hardware&IDE;软硬件平台Copyright(C),SONIX TECHNOLOGY Co.,Ltd.History:;修改记录*************************************************/2)子程序说明部分位于每个子程序的最前面,主要描述:子程序名称、功能、设计原理、所用变量、入口条件、出口信息、调用模块、堆栈层数、影响资源、算法简述、使用说明和修改记录等。

相关主题