嵌入式编程规范及注意事项

嵌入式系统已经在各行各业中得到了广泛的应用,随着人们的生活向信息化,智能化的发展,嵌入式技术将彻底融入到我们的生活,在我们的生活当中扮演越来越重要的角色。对于嵌入式系统来讲,嵌入式软件相当于嵌入式系统的灵魂,整个嵌入式系统如何工作,都是由嵌入式软件来控制的。如何编写高质量,高效率的嵌入式软件在实际项目开发过程中变的越来越重要。本文针对嵌入式软件的特点,从嵌入式软件编程规范和注意事项2个方面来阐述如何编写高质量的嵌入式软件。

一、 嵌入式编程规范

我们在公司进行嵌入式项目开发的时候,并不是你一个人在单打独斗,通常是一个团队在一起战斗。很多人在一起共同完成一个嵌入式项目,通常是每个成员,每个小组完成整个项目中的一个或几个模块。我们编写的代码首先是给人看的,其次才是给机器执行的,这就要求我们团队中的每个人在编写软件的时候,要遵循统一的编程规范和编码风格,提高代码的可读性和可维护性,方便团队成员之间的沟通和交流。在实际项目开发过程中,遵循统一的编程规范相当重要,同学们一定要引起足够的重视,下面我就从代码排版,代码注释,标识符命名,代码可读性和函数设计几个方面来讲解比较通用的嵌入式软件编程规范。

1. 代码排版

1) 程序块要采用缩进风格编写, 缩进的空格数为4个或一个TAB键,设置TAB键为

4个空格.

例如:

int main(int argc, char *argv[])

{

int a=900; //缩进4个空格

}

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

例如:

if (!valid_ni(ni))

{

... // program code

}

//相对独立的程序块之间加空行

repssn_ind = ssn_data[index].repssn_index;

repssn_ni = ssn_data[index].ni;

3) 较长的语句( >80字符)要分成多行书写, 长表达式要在低优先级操作符处划

分新行,操作符放在新行之首, 划分出的新行要进行适当的缩进, 使排版整齐,

语句可读。

例如:

perm_count_msg.head.len = NO7_TO_STAT_PERM_COUNT_LEN

+ STAT_SIZE_PER_FRAM * sizeof( _UL );

4) 不允许把多个短语句写在一行中,即一行只写一条语句。

例如:

rect.length = 0;

rect.width = 0;

5) if、 for、 do、 while、 case、 switch、 default等语句自占一行,且if、 for、do、

while等语句的执行语句部分无论多少都要加括号{}。

例如:

if (pUserCR == NULL) //if语句单独占一行

{ //执行语句只有1条也要加{}

return;

}

6) 程序块的分界符(如C/C++语言的大括号‘ {’和‘ }’)应各独占一行并且位

于同一列, 同时与引用它们的语句左对齐。 在函数体的开始、 类的定义、 结

构的定义、 枚举的定义以及if、 for、 do、 while、 switch、 case语句中的

程序都要采用如上的缩进方式.

例如:

for (...)

{ //{}单独占一行,与for左对齐

... // program code

}

void example_fun(void)

{

... // program code

}

2. 代码注释

1) 注释的原则是有助于对程序的阅读理解,在该加的地方都加了,注释不宜太多也不

能太少, 注释语言必须准确、易懂、简洁,防止注释的二义性.

2) 说明性文件(如头文件.h文件)头部应进行注释, 注释必须列出:版权说明、版本

号、生成日期、作者、内容、功能、 修改日志等, 头文件的注释中还应有函数功能

简要说明。

例如:

Copyright (C), 2004-2018, 华清远见教育集团.

File name: // 文件名

Author: Version: Date: // 作者、版本及完成日期

Description: // 用于详细说明此程序文件完成的主要功能,与其他模块

// 或函数的接口,输出值、取值范围、含义及参数间的控

// 制、顺序、独立或依赖等关系

Function List: // 主要函数列表,每条记录应包括函数名及功能简要说明

1. ....

History: // 修改历史记录列表,每条修改记录应包括修改日期、修改

// 者及修改内容简述

1. Date:

Author:

Modification:

2. ...

3) 源文件头部应进行注释, 列出: 版权说明、 版本号、 生成日期、 作者、 模块目的/功能、主要函数及其功能、 修改日志等.

例如:

Copyright (C), 1988-2018, 华清远见教育集团.

FileName: test.cpp

Author: Version : Date:

Description: // 模块描述

Function List: // 主要函数及其功能

1. -------

History: // 历史修改记录

David 96/10/12 1.0 build this moudle

4) 函数头部应进行注释,列出函数的功能、输入参数、输出参数、返回值等。

例如:

Function: // 函数名称

Description: // 函数功能、性能等的描述

Input: // 输入参数说明,包括每个参数的作用、取值说明及参数间关系。

Output: // 对输出参数的说明。

Return: // 函数返回值的说明

Others: // 其它说明

5) 边写代码边注释, 修改代码同时修改相应的注释, 以保证注释与代码的一致

性。 不再有用的注释要删除。

6) 注释应与其描述的代码相近, 对代码的注释应放在其上方或右方(对单条语句

的注释)相邻位置, 不可放在下面,如放于上方则需与其上面的代码用空行隔开。

3. 标识符命名

1) 标识符的命名要清晰、 明了, 有明确含义, 同时使用完整的单词或大家基本

可以理解的缩写,避免使人产生误解.

2) 对于变量命名,禁止取单个字符(如i、 j、 k...) ,建议除了要有具体含义外,

还能表明其变量类型。建议在变量前面加前缀 g表示全局变量,m表示形式参数.

例如: int gCount = 0;

3) 命名规范必须与所使用的系统风格保持一致,并在同一项目中统一,比如采用

UNIX的全小写加下划线的风格或大小写混排的方式, 不要同时使用大小写与下

划线混排的方式。

例如: char total_score =0;

4) 函数名应准确描述函数的功能,使用动宾词组为执行某操作的函数命名。

例如:

int input_record( void )

unsigned char get_current_color( void )

5) 除非必要,不要用数字或较奇怪的字符来定义标识符

6) 用正确的反义词组命名具有互斥意义的变量或相反动作的函数等

4. 代码可读性

1) 注意运算符的优先级,并用括号明确表达式的操作顺序,避免使用默认优先级

例如:不要这样写: word = high << 8 | low

而应该写成如下这样: word = (high << 8) | low

2) 避免使用不易理解的数字, 用有意义的标识来替代。 涉及物理状态或者含有物理意

义的常量,不应直接使用数字,必须用有意义的枚举或宏来代替.

例如:

#define TRUNK_IDLE 0

#define TRUNK_BUSY 1

if (Trunk[index].trunk_state == TRUNK_IDLE)

{

Trunk[index].trunk_state = TRUNK_BUSY;

... // program code

}

3) 不要使用难懂的技巧性很高的语句,除非很有必要时.

例如: 不要使用类似这样的难懂的语句 *stat_poi++ += 1; 应该分成多个语句

书写,增强代码可读性.

二、嵌入式编程中的注意事项

嵌入式软件开发和普通软件编程相比,有一些自己的特点,下面从嵌入式软件架构,中断编程,寄存器配置,浮点运算等几个方面来讲解嵌入式编程中的注意事项.

1. 嵌入式系统的软件架构

一个大型的嵌入式软件往往需要根据功能的不同划分成多个软件功能模块。

1) 模块即是一个.c文件和一个.h文件的结合,头文件(.h)中是对于该模块接口的声明;

2) 某模块提供给其它模块调用的外部函数及数据需在.h中文件中冠以extern关键字

声明;

3) 模块内的函数和全局变量需在.c文件开头冠以static关键字声明;

4) 永远不要在.h文件中定义变量!定义变量和声明变量的区别在于定义会产生内存分

配的操作,是汇编阶段的概念;而声明则只是告诉包含该声明的模块在连接阶段从

其它模块寻找外部函数和变量

2. 中断编程

中断是嵌入式系统中重要的组成部分,但是在标准C中不包含中断。 许多编译开发商在标准C上增加了对中断的支持,提供新的关键字用于标示中断服务程序. 类似于__interrupt、#program interrupt等。当一个函数被定义为中断服务处理程序的时候,编译器会自动为该函数增加中断服务程序所需要的中断现场入栈和出栈代码。

中断服务程序需要满足如下要求:

1) 不能有返回值;

2) 不能向中断服务处理程序传递参数;

3) 中断服务处理程序应该尽可能的短小精悍,不要包含耗时的代码

3. 寄存器配置

嵌入式软件是面向硬件底层的软件,我们在对硬件进行编程时,通常是通过配置硬件相关的寄存器来实现的。在配置寄存器时,通常我们只需要配置寄存器的1位或几位,对于其他不需要配置的位,我们要保持不变,不要更改我们不需要配置的位。

例如:我们希望配置寄存器的 GPIOADAT 的第 1位 为 1

我们不能这样写成这样:

GPIOADAT = 0x02; //将其他位设置为 0

而应该写成这样:

GPIOADAT |= 0x02; //保证其他位不变

4. 浮点运算

大多数低档次的单片机都是不支持浮点运算的,因此在实际使用过程中也很少用到,因此为了降低成本,一般都去掉了浮点运算模块,这就带来了一个问题,如果万一要用到浮点运算怎么办?我们可以采用的是“定点”的方法来解决这个问题,就是直接放大10的N次方倍进行整数的计算,可以得出近似值,因此为了不增加不必要的麻烦,应该总是尽量避免使用浮点运算,一般情况也是可以避免的。

5. volatile 关键字的使用

嵌入式开发过程中,在定义硬件寄存器的时候,需要使用volatile关键字。 volatile提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。 如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值。

例如: #define GPIO_DATA (*(volatile unsigned int *)0x90002000)

以上就是我今天要给同学们讲解的嵌入式软件编程规范和注意事项,希望同学们在实际的嵌入式项目开发过程中严格遵循嵌入式软件编程规范和注意事项,开发出高质量,稳定,可靠,维护性高的嵌入式软件。

嵌入式物联网需要学的东西真的非常多,千万不要学错了路线和内容,导致工资要不上去!

无偿分享大家一个资料包,差不多150多G。里面学习内容、面经、项目都比较新也比较全!某鱼上买估计至少要好几十。(点击找小助理领取)

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
编辑推荐 本书主要特点: 分为原理篇和应用篇,原理与实践相结合,两篇相对独立,又紧密联系。 原理篇以分析源码为特色,深入浅出地介绍RTOS的基本概念以及Small RTOS51的工作原理。 应用篇以DP-51单片综合仿真实验仪为硬件平台,通过对单片机常用和热门外围器件实用驱动程序的分析,详细介绍基于Small RTOS51的编程方法,以及如何为这些外围器件编写中间件,并给出一个完整的例子,让读者全面掌握基于Small RTOS51的编程方法,体会了RTOS下编程的优点。 内容简介 Small RTOS51是为51系列单片机而编写的。它是完全免费的、源代码公开的多任务实时操作系统。它可在无任何外部数据存储器的单片80C51系统上运行,并且是可移植的。全书分两部分。第一部分为基础篇,介绍Small RTOS51和一些基本概念,并详细分析Small RTOS51的工作原理。第二部分为应用篇,给出部分常用硬件在Small RTOS51下驱动程序的源代码。这些源代码在DP—51单片机仿真实验仪上全部调试通过,且只要经过很少的改动,或是不改动,就可以在其他环境下使用。应用篇还通过对这些源代码的分析,让读者理解基于RTOS的编程方法,并给出完整的例子让读者全面掌握基于RTOS的编程方法。 本书可以作为高等院校相关专业的课程教材、实验参考资料或课外读物,对嵌入工应用开发人员也有重要的参考价值。 目录 第一部分 原理篇 第0章 绪论 第1章 Small RTOS51简介 1.1 Small RTOS51的特点 1.2 Small RTOS51的运行条件 1.3 Small RTOS51的存储器需求 1.4 Small RTOS51的任务堆栈的计算 1.5 关于可重入功能 1.6 关于C51的库函数 1.7 关于51系列单片机派生类型的多数据指针和数学单元 1.8 关于51系列单片机的寄存器段 1.9 关于局部变量 第2章 基本概念 2.1 嵌入式系统 2.2 实时系统 2.3 前、后台系统 2.4 操作系统 2.5 实时操作系统 2.6 代码的临界区 2.7 资源 2.8 共享资源 2.9 任务 2.10 任务切换 2.11 内核 2.12 调度 2.13 非占先式内核 2.14 占先式内核 2.15 可重入性 2.16 任务优先级 2.17 信号量 2.18 死锁 2.19 消息队列 2.20 中断 2.21 时钟节拍 第3章 一个简单的例子 3.1 Small RTOS51的安装及目录结构 3.2 例子简介 3.3 Config、h、Os_cfg、h和Os_cpu.h 3.4 与编程器无关的数据类型 3.5 OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL() 3.6 main()函数 3.7 建立任务 3.8 删除任务 3.9 用户任务 3.10 软非屏蔽中断 3.11 中断服务程序的编写 3.12 Os_cpu.h可改变的其他内容 3.13 Small RTOS51的其他注意事项 第4章 任务管理—核心的核心 4.1 临界区 4.2 任务 4.3 任务状态 4.4 与任务相关的数据结构 4.5 任务调度 4.6 Small RTOS51中的中断处理 4.7 时钟节拍 4.8 Small RTOS51初始化和启动 4.9 建立任务 4.10 任务堆栈 4.11 删除任务 4.12 时间服务及任务的挂起和恢复 4.13 获取当前Small RTOS51的版本号 4.14 OSInt…()函数 第5章 如何切换任务 5.1 CPU可以执行多个任务的原因 5.2 CPU怎样运行才能执行多个任务 5.3 何时进行任务切换 5.4 Small RTOS51任务切换时的程序框图 5.5 数组OSTsakStackBotton[]和Small RTOS51的堆栈结构 5.6 变量OSFastSwap 5.7 常量数值OSMapTb[] 5.8 软非屏蔽中断的堆栈SP2[] 5.9 中断切换函数OSIntCtxSw()OSIntCtxSw() 5.10 任务主动放弃CPU-OS_TASK_SW() 5.11 堆栈变换函数C_OSCtxSw() 5.12 恢复新任务环境LoadCtx() 5.13 优先级最低的任务OSIdle() 5.14 Small RTOS51初始化函数OSStart() 5.15 系统时钟节拍中断OSTickISR() 第6章 任务之间的通信和同步之信号量 6.1 概述 6.2 使Keil C51函数具有重入性的特殊方法 6.3 数据结构 6.4 IN_OS_SEM_CHK宏及相关代码 6.5 初始化一个信号量 6.6 等待一个信号量 6.7 发送一个信号量 6.8 无等待地请求一

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值