ImageVerifierCode 换一换
格式:DOCX , 页数:24 ,大小:31.56KB ,
资源ID:5070578      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/5070578.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(单片机程序设计编程规范.docx)为本站会员(b****4)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

单片机程序设计编程规范.docx

1、单片机程序设计编程规范单片机程序设计编程规范本规范适用于松翰科技 8-bit MCU部门汇编程序编写准则,同样适用于代理商及重要客户工程师编程规范参考。本规范的目的为统一编程风格,保证程序编写质量,提高程序的可移植性和维护性。大部分的规范严格, 品质要求高的软件公司对员工编写代码的风格都有硬性规定, 例如缩排的使用,TAB 的长度,函数变量的命名方式。这些规定的明显好处是可以统一规范不同程序员所编制的代码,提升程序代码的可读性与可维护性,同时统一格式的编程风格也为code review提供方便。一、设计总则二、排版风格三、程序可读性及可维护性四、注释五、变量命名规则六、常量命名规则七、标号命名

2、规则八、文件命名规则及文件分割九、标准程序模块十、附录一、设计总则1程序质量的评估程序的优劣可以从两个方面进行评估,定量指标和定性指标。定量指标包括:1) 程序代码执行效率;2) 程序占用资源多少。定性指标包括:1) 可调试性,即是否方便排除程序语法错误;2) 可测试性,即是否方便验证程序功能的正确性;3) 可维护性,即是否方便程序的修改和升级;4) 可移植性;5) 可读性。2、程序架构为了便于维护和移植,推荐使用层次化的软件设计方法。可把整个软件分为三层:应用层、界面层和底层驱动层。各层之间的关系如下图所示。层次化设计说明:1) 底层驱动层主要包含直接和硬件相关的驱动程序,如数码管显示、按键

3、、峰鸣器、继电器和电机控制等。底层的各个模块间要保持各自的独立性,不产生直接的数据交互,底层也不直接访问应用层,如果有需要,都要通过界面层进行数据交互。2) 界面层主要提供数据交互, 为应用层和底层驱动之间以及底层驱动层各模块之间提供数据的交互。3) 应用层主要完成具体功能的实现,它要通过界面层控制底层驱动层各模块来完成所需功能,而不能越过界面层直接访问底层驱动层。所有的用户接口要在应用层来实现。4) 一个好的架构必须将底层硬件包装起来,为应用程序提供一组丰富的函数操作(buffer or parameter),例如在中断的处理中,应用程序不需要资料中断的堆栈如何保护不需要知道地址操作, 只需

4、要读取中断产生的旗标动作。5) 在即时性软件系统里面,对达到高效率的实时性与反应力, 所以程序使用大量的事件触发方式来设计任务。事件有可能来自外部的触发(key , rxdata , sensor detect, )也可能是系统内部自行产生的(Timer, alarm, flag),与事件触发方式相对应的是定时查询方式(polling),一般来说polling 效率较差因为有多余的动作而且系统反应时间与查询polling时间间隔有关, 但是在小型的MCU系统里面用Polling方式反而简单许多。3、设计基本原则1) 尽量减少各个子程序功能模块间的耦合度(耦合度是指一个程序的执行对另一个程序的影

5、响力),保证各自的独立性。一般情况下,建议子程序模块功能的划分要尽可能细化,功能尽量单一,减少子程序模块间的数据交互。2) 在满足功能需求的情况下,可适当牺牲代码的执行速度,以保证程序的透明度。3) 主要子程序模块间的交互,要通过特定的界面跟应用层进行沟通,可使用 FIFO(First in,First out)或是 Buffer 两种方式。每种子程序模块都可以有自己的FIFO。例如:就按键来说,一般有 Key buffer、Key FIFO 或直接进入AP FIFO三种设计方式。Key buffer:一般用于保存数字按键信息。例如:在电话机的设计中,需要记录按键内容用于LCD 显示、最后数字

6、确认、数字存储等,这时候需要把按键值的信息(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里面等待适当的时间依序处理,不然有可能造成系统在某一程序物

7、件里面循环,从而降低系统的实时性(Real-Time)。4) 每个子程序模块只能有唯一一个程序入口地址在程序的首部, 只能有唯一一个程序出口地址在程序的尾部。例如:以下的写法是不规范的(两个RET出口,存在调试时不易设立断点,程序可读性降低等问题):lable:b0bts0 fzretclr yret应该改为(只有一个出口位置,标号为 lable90,便于程序检查):lable:b0bts0 fzjmp lable90clr ylable90:ret5) 上电复位时要对所有的RAM空间进行初始化(建议用户寄存器清零,系统寄存器进行必要设定),不要使用未经初始化的变量。RAM未经过完整的初始化,

8、容易导致程序执行的不确定性,这一不良现象往往在批量生产中有所体现。(这点是工程师经常犯错的地方,须特别注意)6) 系统中如果需要等待一些未知的应答信号,如通信或等待输入信号时,必须进行超时或异常处理,以防止程序进入“死等”状态。例如在红外接收中,由于信号的突然消失或干扰从而无法得到一帧完整或正确的信息,这时需要复位接收程序的入口条件并退出接收程序,而不是一直等待信号的来临。不然无法进行下次接收甚至会影响到其它程序的执行。7) 通过对系统数据结构的划分与组织的改进,以及对程序算法的优化来提高空间效率。这种方式是解决软件空间效率的根本办法。8) 保证循环体内的工作量最小化。 应仔细考虑循环体内的语

9、句是否可以放在循环体之外,使循环体内工作量最小,从而提高程序的执行效率。9) 在多重循环中,应将最忙的循环放在最内层。10) 中断处理程序应尽量短。有效的作法为:在中断中进行标记,在主程序中进行处理。但一些实时性要求较高的程序例外。此外,进入中断时应该保存涉及到的变量和寄存器。11) 看门狗的正确使用。看门狗主要用于微控制器死机时的时间溢出复位,需要程序适时清除。正确的处理方式为:整个系统程序中尽量保证只有一处清看门狗位置,而且应处在主循环的主干位置。切记不可在定时中断中清狗,因为微控制器有时只是在主循环中死掉。(所有AC电源的应用程序 都必须强迫加入看门狗选项尤其是条件式的看门狗 有利于系统

10、发生异常后的重启动)二、排版风格1、程序采用缩进风格编写,缩进为1个Tab 键,1个Tab键定义为8个空格位。2、程序中的标号要从第一列开始书写。以“.”开头的预编译命令也要从第一列开始书写,其他预编译命令采用缩进风格编写。例如:1) 以“.”开头的预编译命令要从第一列开始书写,其他预编译命令采用缩进风格书写。.LIST ;从第一列开始书写INCLUDESTD macro1.h.CONSTNUMBER EQU 55h.DATAwk00 DS 1 .CODEORG 0h2) 标号要从第一列开始书写。main: ;从第一列开始jmp main ;缩进8个空格位3) 变量或常量的定义采用缩进风格。例

11、如:.DATAkeybuf DS 1.CONSTNUMBER EQU 84)定义变量或常量时, 变量名或常量名与命令符之间使用2个Tab键(相当于16个空格位)分开,命令符与后面的操作数用1个Tab键(相当于8个空格位)分开。例如:keybuf DS 1NUMBER EQU 55h5) 操作码与操作数之间用1个Tab键(相当于8个空格位)分开。例如:ORG 80hmov a,NUMBERtable:DW 1234h6.) 程序中两个操作数之间用一个“ ,”作为分隔符,“ ”号与立即数之间不需要分隔符。例如:Mov a,#55h7) 标号要单独占一行。8) 相对独立的程序块之间必须加空行。例如:

12、ORG 10hINCLUDE 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 EQU 55

13、h.DATAaccbuf DS 1.CODEmov a,#NUMBER2.表示不同进制的立即数,要在立即数后面加上不同的进制符号。例如:mov a,#00100011bmov a,#23h不建议使用:mov a,#0x233.一般情况下,变量和常量要分开定义,不要混在一起。变量在“.DATA ” 段中定义,采用命令符 “DS” ,常量在”.CONST ” 段中定义,采用命令符 “EQU” 。例如:.CONSTNUMBER EQU 10.DATAAccbuf DS 14.程序中不使用未定义或意义不明确的常量。例如:下面的赋值方法要避免使用:mov a,#3 ;不要直接使用意义不明确的数字在常量中

14、做定义mov r,a建议采用如下赋值方法:.CONSTNUMBER EQU 3 ;循环次数.CODEmov a,#NUMBERmov r,a5.整个程序的结尾要以“ENDP”语句结束。6.当一段代码在程序中有多个地方使用时,建议采用子程序调用或宏命令的方式来替代。如此,对该代码段的修改就可在一处完成,增强代码的可维护性。7.程序中关系较为密切的子程序代码尽可能相邻。8.避免程序中的垃圾代码,预留代码应以注释的方式出现。程序中的垃圾代码不仅占用额外的空间,而且还可能影响到程序的功能与性能,很可能给程序的测试、维护等造成不必要的麻烦。四、注释1.程序应该包括两个部分注释,说明部分和语句注释。一般情

15、况下,源程序有效注释量必须在30以上。2.说明部分:1) 源文件说明部分位于每个源文件的最前面,主要描述:文件名、作者、生成日期、联络方式、功能描述、版本号、软硬件平台、版权说明、修改记录等的简要说明,以英文书写。例如:/*File name: ;文件名Author: ;作者Date: ;日期Email: ;邮箱地址Description: ;功能描述Version: ; 版本号Hardware&IDE ;软硬件平台Copyright (C), SONIX TECHNOLOGY Co., Ltd.History: ;修改记录*/2)子程序说明部分位于每个子程序的最前面,主要描述:子程序名称、功

16、能、设计原理、所用变量、入口条件、出口信息、调用模块、堆栈层数、影响资源、算法简述、使用说明和修改记录等。例如:/*Subroutine: ;子程序名称Description: ;子程序功能的描述Principium: ;程序设计原理Calls: ;被本子程序调用的子程序清单Variables: ;本子程序中所用到的临时变量Input: ;子程序调用所需要基本参数的说明Output: ;子程序调用后运算结果的说明Stack: ;占用的堆栈层数History: ;修改记录*/3.边写代码边注释, 修改代码的同时修改相应注释,以保证注释与代码的一致性。不再有用的注释要删除。4.要避免在注释中使用缩

17、写,特别是非常用缩写。5.程序在必要的地方必须有注释, 注释要准确、易懂、简洁。注释要有意义,如果有需要,还要详细描述相关含义。例如:以下是无意义的注释mov a,#5 ;把5 赋给 accmov wk00,a ;把 acc 赋给 wk00应该如下注释:mov a,#5 ;设置循环次数为5 次mov wk00,a6.注释应与其描述的代码相近,对代码的注释应放在其上方或右方(对单条语句的注释)的相邻位置,不可放在下方,如放于上方则需与其上面的代码用空行隔开。例如: clr wk00; Check Read index = FiFo Limit cmprs a,r ;Is Read index =

18、 Limit Jmp f7.注释格式尽量统一,对多行注释建议使用“/* */” ,对单行的注释建议使用“;”。8.注释应考虑程序易读及外观排版因素,语言尽量统一。对不能进行准确英文表达的建议使用中文。9.对有含义的变量、常量,如果其命名不是充分自注释的,在声明时都必须加以注释,说明其含义。五、变量命名规则1.变量的名称要采用有意义的英文单词小写缩写。可以采用以下几种方式进行缩写命名:1)去掉所有不在词头的元音字母。如 screen可以简写为scrn。2)使用每个单词的头几个字母。如 channelactivation 可以简写为 chanactiv。3)使用变量名中具有典型意义的单词。如 nu

19、mberofcycle 可以简写为 cyclenumber。4)去掉无用的单词后缀 ing、ed 等。如 pagingrequest 可以简写为 pagreq。5 )尽量使用标准或惯用的缩写形式,缩写应该保持一致性。如 serial peripheralinterface 可以简写为 spi。6)部门已经完成函式的变量名称, 如果没有特别原因, 发展人员延续使用 以增加可读性2.在定义部分要加入注释来说明变量的含义。3.变量的定义要在“.DATA” 段中。4.变量标识符的长度不超过16 个字符。5.序会用到起码三种变量1)全局变量 名称前面不加任何修饰。2)局部变量利用 wk00 , wk01

20、 .wk0n 来表示, 每个独立程序里面用到的Local var.可有效节省RAM。3)中断局部变量中断里面用的 Interrupt local var.利用 Iwk00, Iwk01 以作为区隔(注意中断使用的变量必定要小心的跟主程序区隔开,不然影响系统稳定性相当大)。例如:.DATAaccbuf ds 1 ;全局变量l_number ds 5 ;局部变量6.位定义。程序多处会经常对寄存器的某一位进行操作,可以在变量定义时对需要用到的位进行定义,建议名称以”f_”开头。7.临时工作寄存器的定义。程序中经常需要用到一些临时存储数据的寄存器,我们称之为临时工作寄存器,这些临时工作寄存器的命名方法

21、为“wk”加上一个二位数字组成,这个数字可以从“00”开始随着需要定义的临时工作寄存器的数量的增加而增加。需要特别说明的是,临时工作寄存器的使用可以大量节省 RAM空间,但是要注意相应的生命周期,必须在子程序退出之前,将空间释放以便其它子程序使用。8.在中断处理程序中用到的寄存器,为了和一般的临时工作寄存器作以区分,可以在寄存器前面加英文字母“i”来命名。在使用时需要加以注意,不要和主程序中的变量复用。例如:.DATAwk00 ds 1wk01 ds 1wk02 ds 1iwk00 ds 1 ;中断中要用到的临时工作寄存器iwk01 ds 1 ;中断中要用到的临时工作寄存器.CODEMov a

22、,rMov wk00,amov a,wk01mov r,a六、常量命名规则1.常量的名称要采用有意义的英文单词大写缩写。2.常量要定义在“.CONST”段中。3.在定义部分要加入注释来说明常量含义。4.量标识符的长度不超过16个字符。5.系统寄存器中常用到的某些位可以再额外进行定义,但要有意义:P_key1 EQU P1.0 ;P_ 打头表示为 Port 定义Pm_key1 EQU P1m.0 ;Pm_ 打头表示为 Port 方向定义七、标号命名规则1.标号的名称要采用有意义的英文单词小写缩写。2.子程序标号定义。在同一个子程序中,所有的标号应该有规律可寻。建议第一个标号为子程序名,下面所用到

23、的标号用子程序名添加数字表示,从而便于今后程序的添加和修改。数字尽量使用两位数,在子程序的退出位置,数字一般为”90”。例如:在一段按键扫描程序中,如下的标号是不可取的。Label:LabelOKLabelFailLabelQuitLabelfun:LabelEnd:Ret(设计师要花许多精神命名label, 同时不容易看出子程序的结构关西,所以建议在子程序里面别在花精神命名,都用号码表示)(详细的动作都用注解来说明)应该改为:;*;Sub-routine , Name : label;*Label:If the condition fail then go to Label90;progra

24、m begin hereLabel10:;注解都写在 这里Label20:;最后结尾结束的label都用90当做结尾:有助于程序的阅读Label90:Ret3.为了使程序的结构更加清晰,子程序的命名要尽量能显示出相互间的调用关系。由 main 主循环中直接调用的程序,要以“mn_”作为标号的开头,下面仅列出一些常用的子程序名称,其它类似情况可同样处理。mn_app ;系统应用程序mn_intgnd ;中断与主程序之间的界面子程序mn_key ;按键扫描子程序mn_lcd ;LCD 显示子程序mn_led ;LED 显示子程序mn_tone ;声音处理子程序mn_epp ;EEPROM 读写操作

25、mn_bio ;基本输入/输出控制mn_adc ;ADC 输入及处理mn_debug ;debug 处理程序4.程序的几个常用入口地址命名如下:复位入口: reset中断入口: isr主程序入口: main例如:org 0jmp resetorg 8jmp sr ;ISR(Interrupt Service Routine)org 10;有效程序开始地址reset:;进入主程序前的一些准备工作(预处理)premain:;主程序循环圈main:Jmp main八、文件名的命名规则及文件分割1.在一个项目中要包括两种文件:源文件和头文件。源文件是程序体,扩展名为 “ .asm ”,头文件包括了变量

26、、常量、宏命令的定义,扩展名为 ”.inc”。2.头文件的命名头文件用三个不同的文件来分别定义常量、变量、宏命令,其命名方法如下:常量定义文件: xxx_equ.inc变量定义文件: xxx_ram.inc宏命令定义文件: xxx_macro.inc其中,xxx 表示项目的名称。例如:作一个电话机的完整程序,头文件可如下定义:常量定义文件: phone_equ.inc变量定义文件: phone_ram.inc宏命令定义文件: phone_macro.inc3.源文件分为主文件、子文件。主文件包括了项目的主程序,它描述了芯片信息、CODEOPTION 信息及项目包含的其它子文件模块。子文件是由各

27、个子程序模块组成,功能相近的子程序要放在一个文件中, 文件名可以用“项目名模块功能的缩写扩展名”表示。下面列举一些常用的文件名:主程序文件: xxx_main.asm常用的子文件定义:中断服务程序模块: xxx_int.asm进程处理模块: xxx_pro.asm系统处理程序: xxx_sys.asm按键处理模块: xxx_key.asmLCD显示模块: xxx_lcd.asm其中,xxx 表示项目的名称。九、标准程序模块常用功能模块尽量采用附件提供的标准程序,如果无法使用标准的程序模块, 那么所编写的程序一定要符合规范要求。所提供的标准程序如下,详细的源代码在附录中。1. mn_key ;单

28、键扫描子程序2. mn_mulkey ;多键处理子程序3. mn_tone ;声音处理子程序4. mn_lcd ;LCD 显示子程序5. mn_i2c ;I2C 操作子程序6. mn_sio ;SIO 操作子程序7. mn_1wire ;单总线操作子程序8. mn_uart ;UART 子程序9. wr_fifo ;写 FIFO10. rd_fifo ;读 FIFO11. ram2ram ;RAM 到 RAM 的数据传递12. rom2ram ;ROM 到 RAM 的数据传递13. math ;基本运算程序实例说明1.初始化1)当程序上电复位时, 一个完整的用户寄存器初始化或清零动作是非常重要

29、的, 否则容易造成程序执行的不确定性。例如:pre_clrRAM: b0mov y,#0 ;清 RAM bank0 b0mov z,#48: Clr yz decms z jmp b clr yz ret2) 系统寄存器必须进行初始化,比如说 I/O 口方向和输出电平等。需要特别说明的是输出口的初始化必须按照下列顺序来处理:(1) 设定相应 I/O 口输出高低电平(2) 将相应 I/O 口为输出口如此可确保 MCU 的 I/O 口从输入模式转为输出模式时不会有脉冲的存在。 而在 I/O 口控制频繁变化(如通信)时更要引起注意。例如:(3) mov a,# 11111111b;如果 p1.0 和 p1.1 原来为输入高电平, 当直接切换为输出方式时会有高电平脉冲的输出,而这不是所希望的。 b0mov p2m,a mov a,# 11111100b b0mov p2,a (4) mov a,#00001100b b0mov p2,a;这样处理 p1.0 和 p1.1 就避免了高电平脉冲的输出 mov a,#11111111b ; b0mov p2m,a开机时后IO toggle的作法:利用暂时没有用到的IO 做 toggle 可有效观察以下几点1) 系统是否正常开机2) 是否发生 reset or watchdog reset 现象3)

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

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