0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

嵌入式代码之编写规范

GReq_mcu168 来源:工程师李察 2019-04-26 15:21 次阅读

嵌入式代码编码规范,用于规范自己的代码,增强可读性,非标准规范。最好能强制自己形成良好的编码风格,有利于开发大规模程序而不显得杂乱。参考STM32固件库编码风格和FreeRTOS编码风格。

一、工程文件组织结构

新建工程文件应包含以下全部或部分文件夹:

usrSrc:用户源文件,用来存放.c文件和其他的源文件。main.c应放在这里。

usrInc:用户头文件,用来存放.h文件。

usrDoc:用户说明文档,用来存放用户在开发过程中书写的文档,一般为.txt格式。例如Readme.txt,指令说明等。

Src:引用库的源文件。

Inc:应用库的头文件。

Lib:引用的库文件。

一个工程一定要包含一个main.c文件,只用来存放main函数。其余函数的定义应在相应的.c文件中,声明在相应的.h文件中。

So can you help to prepare our suggest contents display in the page (e.g. tools intro, feature, which videos, which documents etc) to us first? We will then further discuss with Infineon if anything need to change / add.

二、源文件

文件头,文件的简介

/************************************************************************* * Copyright (c) 2018, Xiaodan * All rights reserved. * * File name : USB_Ctrl.c * Brief : USB API source code. * Introduce the main function or content of this document briefly. * Revision : 1.01 * Author : Xiaodan * Date : 2018.11.06 * Update : Introduce the difference from previous version.*************************************************************************/

必要的注释和说明

源文件应该只包含它自己的头文件,其他的头文件在他自己的头文件中包含。

源文件中只声明局部函数,全局函数在头文件中声明。

全局变量在相应的源文件中定义,在头文件中用extern声明。

类型定义在头文件中定义。

/* Includes -----------------------------------------------------------*//*only include it's own header file, the others header file included by USB_Ctrl.h*/#include "USB_Ctrl.h"/* Declaration --------------------------------------------------------*//*here are the local function declare, global fuction declare in header file.*/void delay( uint32_t n);/* Global variable ----------------------------------------------------*/

函数头

/****************************************************** * Brief : Delay n ms * Parameter : * n: the number of delay microsecond. * Return : None.*******************************************************/void delay( uint32_t n){for( i=0; i<110; i++) ;}

三、头文件

文件头,文件的简介

/************************************************************************* - Copyright (c) 2018, Xiaodan - All rights reserved. - - File name : USB_Ctrl.h - Brief : The header file of USB_Ctrl.c. - Revision : 1.01 - Author : Xiaodan - Date : 2018.11.06 - Update : Introduce the difference from previous version.*************************************************************************/

必要的注释和声明

/* Includes -----------------------------------------------------------*//* Define -------------------------------------------------------------*//* Typedef ------------------------------------------------------------*/typedef unsigned int apiStatus; //api return code/* Enume --------------------------------------------------------------*//* Extern -------------------------------------------------------------*//* Declaration --------------------------------------------------------*/

四、命名规则

参考FreeRTOS命名规则,MISRA C规范。

定义变量时尽量使用uint8_t 、uint16_t 、uint32_t等。头文件为stdint.h。

typedef signed char int8_t;typedef short int16_t;typedef int int32_t;typedef long long int64_t;typedef unsigned char uint8_t;typedef unsigned short uint16_t;typedef unsigned int uint32_t;typedef unsigned long long uint64_t;

uint32_t类型的变量使用前缀ul,这里’u’表示’unsigned’,’l’表示’long’

uint16_t类型的变量使用前缀us,这里’u’表示’unsigned’,’s’表示’short’

uint8_t类型的变量使用前缀uc,这里’u’表示’unsigned’,’c’表示’char’

枚举类型变量使用前缀e

指针类型变量在类型基础上附加前缀p,比如指向uint16_t的指针变量前缀为pus

与MISRA指南一致,char类型变量仅被允许保存ASCII字符,前缀为c

与MISRA指南一致,char *类型变量仅允许指向ASCII字符串,前缀为pc

宏定义全部使用大写,两个单词之间用下划线隔开。

具有文件作用域的对象尽量声名为static的。

全局变量加前缀’g_’。整个工程都可以用的变量,不局限于文件作用域。

五、代码风格

缩进:缩进使用制表符,一个制表符等于4个空格。

注释:注释单行不超过80列,特殊情况除外。

布局:源代码应被设计成尽可能的易于查看和阅读。

下面的代码片中,第一部分展示文件布局,第二部分展示C代码设计格式。

/* #defines, 在合理的位置添加括号. */#define A_DEFINITION ( 1 )/* * 随后是Static (文件内部的)函数原型, * 如果注释有多行,参照本条注释风格---每一行都以’*’起始. */static void prvAFunction( uint32_t ulParameter );/* 文件作用域变量(本文件内部使用),要在函数体定义之前. */static BaseType_t xMyVariable./* 每一个函数的结束都有一行破折号,破折号与下面的第一个函数之间留一行空白。*//*-----------------------------------------------------------*/void vAFunction( void ){/* 函数体在此定义,注意要用大括号括住 */}/*-----------------------------------------------------------*/static UBaseType_t prvNextFunction( void ){/* 函数体在此定义. */}/*-----------------------------------------------------------*//* * 函数名字总是占一行,包括返回类型。左括号之前没有空格左括号之后有一个空格, * 每个参数后面有一个空格,参数的命名应该具有一定的描述性. */void vAnExampleFunction( long lParameter1, unsigned short usParameter2 ){/* 变量声明没有缩进. */uint8_t ucByte;/* 代码要对齐. 大括号占独自一行. */for( ucByte = 0U; ucByte < fileBUFFER_LENGTH; ucByte++ ) {/* 这里再次缩进. */ }}/* * for、while、do、if结构具有相似的模式。这些关键字和左括号之间没有空格。 * 左括号之后有一个空格,右括号前面也有一个空格,每个分号后面有一个空格。 * 每个运算符的前后各一个空格。使用圆括号明确运算符的优先级。不允许有0 * 以外的数字(魔鬼数)出现,必要时将这些数字换成能表示出数字含义的常量或 * 宏定义。 */for( ucByte = 0U; ucByte < fileBUFFER_LENGTH; ucByte++ ){}while( ucByte < fileBUFFER_LENGTH ){}/* * 由于运算符优先级的复杂性,我们不能相信自己对运算符优先级时刻保持警惕 * 并能正确的使用,因此对于多个表达式运算时,使用括号明确优先级顺序 */if( ( ucByte < fileBUFFER_LENGTH ) && ( ucByte != 0U ) ){ ulResult = ( ( ulValue1 + ulValue2 ) - ulValue3 ) * ulValue4;}/* 条件表达式也要像其它代码那样对齐。*/#if( configUSE_TRACE_FACILITY == 1 ){/* 向TCB增加一个用于跟踪的计数器. */ pxNewTCB->uxTCBNumber = uxTaskNumber;}#endif/*方括号前后各留一个空格*/ucBuffer[ 0 ] = 0U;ucBuffer[ fileBUFFER_LENGTH - 1U ] = 0U;

六、编程思想

将特定功能的代码封装成函数。

七、C语言编程规则

参考MISRA

Rule1:不得使用三元操作符(? : )。

Rule2:不得残留被注释掉的废代码。

Rule3:所有标识符不超过31字符。

Rule4:不同名空间中的变量名不得相同。

例如:

typedef struct MyStruct {... } MyStruct; (违规) struct Person { char* name; ...};char name[32]; (违规)

Rule5: 不得使用char, int, float, double, long等基本类型,应该用stdint.h中定义的类型显示表示类型的大小,如uint16_t、int32_t等。

Rule6:禁止使用八进制数。(因为086U这样的常数很容易引起误解)。

Rule7:不得定义与外部作用域中某个标识符同名的对象,以避免遮盖外部作用域中的标识符。

Rule8:具有文件作用域的对象尽量声名为static的。

Rule9:自动对象(栈对象)使用前必须赋初值。

Rule10:操作符&&和||的右侧表达式不得具有副作用(side-effect)。

也就是说,象 if (x == 20 && ++y == 19)这样的表达式被禁止。

Rule11:不得对有符号数施加位操作,例如 1 << 4 将被禁止,必须写 1UL << 4。

Rule12:不得对有副作用的表达式施加sizeof操作符。

Rule13:除了循环控制语句,不得使用逗号表达式。

Rule14:不得显式判断浮点数的相等性和不等性。

Rule15:不得遗留“永远不会用到”的代码。

Rule16:除了switch语句,不得使用标号(label)。

Rule17:不得使用goto。

Rule18:不得使用continue。

Rule19:除了switch语句,不得使用break

Rule20:if, else if, else, while, do..while, for语句块必须使用{}括起。

Rule21:循环计数器的值不得在循环体内修改。

Rule22:禁止任何直接和间接的递归函数调用。

Rule23:不应该使用#undef。

Rule24:不得将宏作为参数传给宏函数。

Rule25:在一个宏定义中,#或##符号只能出现一次。

Rule26:禁止指针运算(代之以数组下标运算)。

Rule27:禁止超过两级的指针。

Rule28:禁止使用指向函数的非常量指针。

Rule29:禁止使用setjmp, longjmp。

Rule30:禁止使用atoi, atof, atol。(这个我很赞成,建议使用strtol, strtod等函数)

Rule31:禁止使用abort, exit, getenv。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 嵌入式
    +关注

    关注

    4981

    文章

    18281

    浏览量

    288423
  • 函数
    +关注

    关注

    3

    文章

    3868

    浏览量

    61308
  • 工程
    +关注

    关注

    0

    文章

    165

    浏览量

    27566

原文标题:如何增强代码的可读性?嵌入式代码之编写规范

文章出处:【微信号:mcu168,微信公众号:硬件攻城狮】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    如何成为一名嵌入式C语言高手?

    相关教材、参加在线课程或者参考编程书籍来系统地学习C语言的基础知识,并通过编写简单的程序进行实践。 二、深入了解嵌入式系统的硬件架构和工作原理嵌入式系统通常包含微控制器或微处理器等硬件设备,了解这些设备
    发表于 04-07 16:03

    如何成为一名嵌入式C语言高手?

    相关教材、参加在线课程或者参考编程书籍来系统地学习C语言的基础知识,并通过编写简单的程序进行实践。 二、深入了解嵌入式系统的硬件架构和工作原理嵌入式系统通常包含微控制器或微处理器等硬件设备,了解这些设备
    发表于 03-25 14:12

    嵌入式工程师需要掌握哪些技术?

    一些必要的技术能力是至关重要的。在本篇中,我们将讨论入行嵌入式所必须的技术能力。 1.C/C++编程能力:C/C++是嵌入式系统开发中最常用的编程语言。熟练掌握C/C++语言将使你能够理解和编写底层
    发表于 03-04 16:38

    嵌入式学习步骤

    语言编写。但是,有些嵌入式系统也使用其他编程语言,例如Python或Java。 (3).了解硬件:深入了解您要控制的硬件设备的功能和特性。您需要了解嵌入式系统的处理器、内存、I/O端口、传感器和其他
    发表于 02-02 15:24

    嵌入式自学好书推荐

    令、编辑器VI、编译器GCC、调试器GDB以及Make项目管理工具、Shell和Makefile脚本编写等知识,并搭建嵌入式开发环境。推荐书籍:《Linux从入门到精通》。 无论从就业市场还是技术发展的角度来看,嵌入式都是一个
    发表于 01-11 15:13

    嵌入式开发学习的十三法则分享

    的“ 初始敏感性” 对于其“ 最终计算结果” 的影响就变得微乎其微了。 二、实时性法则 嵌入式系统的计算结果,不仅依赖于系统的逻辑运算正确性,而且也依赖于这个运算结果的计算时间。 三、资源
    发表于 12-21 06:32

    嵌入式硬件和软件哪个好?

    嵌入式硬件和软件哪个好? 嵌入式软硬件工程师哪个更有前途呢?一起来看看。 嵌入式是分为软硬件工程师的,首先我们先来看看嵌入式硬件工程师吧! 嵌入式
    发表于 12-05 15:17

    如何成为一名优秀的嵌入式工程师?

    使用调试器、打印调试信息、分析日志等。 7.关注代码质量和可维护性:作为嵌入式工程师,你需要编写高质量、可维护的代码。这意味着你需要遵循良好的编程习惯,如使用适当的命名
    发表于 11-07 15:36

    嵌入式程序基于源代码仿真调试

    前面一课设计了51单片机最小系统电路,使用51单片机的I/O口控制发光二极管的状态,并装载运行了使用keil编写嵌入式程序。本次实验应用proteus结合keil对嵌入式C程序进行源代码
    的头像 发表于 11-01 09:24 570次阅读
    <b class='flag-5'>嵌入式</b>程序基于源<b class='flag-5'>代码</b>仿真调试

    什么是嵌入式Linux?

    什么是嵌入式Linux? 对于很多电气、电信、通信专业的同学来说,对口专业就业方向主要有软、硬件两个方向。无论是对于学生还是就业而言,软硬件的开发学习,嵌入式物联网在近年来无疑是一个摆在面前
    发表于 10-11 13:47

    嵌入式Linux应用开发的完全手册

    嵌入式Linux在嵌入式领域发展迅速、需求旺盛,但是嵌入式Linux 的入门很难。初学者多是自己琢磨,效率不高。学习过程中碰到的问题千奇百怪,解决后却往往发现是极其低级的错误,以作者为例,初学时在
    发表于 09-25 07:12

    嵌入式软件好还是硬件好?

    嵌入式软硬件工程师哪个更有前途呢?一起来看看。 嵌入式是分为软硬件工程师的,首先我们先来看看嵌入式硬件工程师吧! 嵌入式硬件开发工程师主要编写
    发表于 09-18 15:31

    FPGA的Verilog代码编写规范

      注:以R起头的是对编写Verilog代码的IP设计者所做的强制性规定,以G起头的条款是建议采用的规范。每个设计者遵守本规范可锻炼命名规范
    的头像 发表于 08-15 16:23 1219次阅读

    Arm® 嵌入式跟踪路由器体系结构规范

    控制器(TMC)。这可以采取多种形式,其中嵌入式跟踪路由器(ETR)。ETR的功能是将格式化的跟踪写入内存中的缓冲区。在 效果,是连接痕迹和记忆的桥梁。 本规范描述了ETR架构,它对以下两种情况
    发表于 08-02 10:10

    如何通过AT命令为esp8266编写嵌入式c代码

    大家好, 我正在尝试通过 AT 命令为 esp8266 编写嵌入式 c 代码。 在 esp8266 中刷入 AT 命令固件。通过 rx 和 tx 与 arduino mega 引脚 18-19 连接
    发表于 05-19 11:03