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。

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

    关注

    5186

    文章

    20159

    浏览量

    328999
  • 函数
    +关注

    关注

    3

    文章

    4406

    浏览量

    66855
  • 工程
    +关注

    关注

    0

    文章

    168

    浏览量

    29681

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

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

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    CW32嵌入式软件开发的必备知识

    嵌入式系统中最常用的编程语言,因为它们提供了直接访问硬件的能力,并且代码执行效率高。 了解汇编语言,用于编写底层驱动、中断处理程序以及性能要求极高的代码段。 对其他编程语言如Pytho
    发表于 11-28 07:48

    嵌入式开发的关键点介绍

    嵌入式开发的关键点: 1. 硬件限制: 嵌入式系统通常具有严格的硬件限制,例如处理器速度、内存和存储容量等。因此,嵌入式开发需要考虑这些限制,并编写高效的
    发表于 11-13 08:12

    嵌入式达到什么水平才能就业?

    工具定位问题具备嵌入式软件模块化设计能力:能按功能划分代码模块,编写规范的头文件与源文件,实现模块间低耦合调用会使用Git 进行版本管理:能提交代码
    发表于 09-15 10:20

    嵌入式工程师为什么要学QT?

    受限的环境。 Qt的实现主要是采用p-impl手法,实现接口与实现分离,它有很好的消息循环机制,有助于在资源受限的嵌入式设备上运行。 提升代码质量 Qt的设计理念和架构可以帮助嵌入式工程师
    发表于 08-14 15:15

    入行嵌入式应该怎么准备?

    知识: 一、C/C++编程C/C++是嵌入式系统开发中最常用的编程语言。熟练掌握C/C++语言将使你能够理解和编写底层驱动程序、操作系统以及与硬件交互的代码。对于嵌入式系统来说,效率
    发表于 08-06 10:34

    Linux嵌入式和单片机嵌入式的区别?

    Linux嵌入式与单片机嵌入式在多个方面存在显著的区别,以下是详细的比较和归纳: 一、基本概念 1. Linux嵌入式: 定义:将Linux操作系统运行在嵌入式设备上的一种配置。
    发表于 06-20 09:46

    飞凌嵌入式「2025嵌入式及边缘AI技术论坛」议程公布

    4月22日,飞凌嵌入式“2025嵌入式及边缘AI技术论坛”将在深圳举行,论坛以“新生态,智未来”为主题,旨在汇聚行业智慧,探讨嵌入式技术与边缘AI的深度融合与创新应用。
    的头像 发表于 04-02 15:12 1075次阅读
    飞凌<b class='flag-5'>嵌入式</b>「2025<b class='flag-5'>嵌入式</b>及边缘AI技术论坛」议程公布

    想在嵌入式领域高薪就业?先迈过这些人才门槛!

    嵌入式开发的世界,如今正经历着一场变革,同时也暴露出诸多问题。现在,会编写嵌入式程序的人随处可见,树莓派、Arduino 等开发板的出现,让嵌入式编程变得轻而易举,就连软件工程师也能轻
    的头像 发表于 03-20 10:42 775次阅读
    想在<b class='flag-5'>嵌入式</b>领域高薪就业?先迈过这些人才门槛!

    嵌入式教育科普|GPIO接口全面解析

    在现代科技领域,嵌入式系统接口作为信息交互的核心载体,发挥着至关重要的作用,各类接口通过预定义的通信协议与标准化规范,可以实现设备间的精准数据传输与智能控制。 作为嵌入式开发的技术基础,接口
    的头像 发表于 03-05 11:11 2759次阅读
    <b class='flag-5'>嵌入式</b>教育科普|GPIO接口全面解析

    代码+案例+生态:武汉芯源半导体CW32嵌入式开发实战正式出版

    ,都能从中找到有价值的信息。 对于初学者而言,本书犹如一位耐心的导师,通过通俗易懂的语言和丰富的实例代码,引导他们逐步了解嵌入式开发的基本概念和流程,掌握 CW32 单片机的开发环境搭建、编程基础以及
    发表于 03-03 15:14

    嵌入式系统中的代码优化与压缩技术

    。开发人员在编写代码时,应注重代码的模块化和复用性,避免不必要的重复代码编写嵌入式系统中的
    发表于 02-26 15:00

    如何提高嵌入式代码质量?

    的情况下也必须保持稳定的性能。 3. 硬件依赖:嵌入式软件紧密依赖硬件平台,需要充分理解硬件特性才能编写高效且稳定的代码。 了解这些特点有助于开发人员在编写
    发表于 01-15 10:48

    嵌入式主板的概述与发展

    随着科技的迅猛发展,嵌入式系统在现代电子产品中扮演着越来越重要的角色。嵌入式主板作为嵌入式系统的核心组件之一,承担着控制、处理和通讯等多种功能。本文将对嵌入式主板的基本概念、构成部分、
    的头像 发表于 01-13 16:30 1187次阅读
    <b class='flag-5'>嵌入式</b>主板的概述与发展

    新手怎么学嵌入式?

    的基础上增加了面向对象编程的特性,有助于编写更复杂的嵌入式程序。 3. 学习硬件知识 嵌入式技术与硬件紧密相关,因此你需要了解一些基本的硬件知识。比如微控制器(MCU)、微处理器(MPU)的工作原理,了解
    发表于 12-12 10:51

    什么是嵌入式人工智能

    嵌入式人工智能是指将人工智能技术应用于嵌入式系统中的一种技术。嵌入式系统是嵌入到其他设备或系统中的计算机系统,通常用于控制、监测或执行特定任务,如智能手机、智能家居设备、智能汽车等中的
    的头像 发表于 12-11 09:23 1524次阅读
    什么是<b class='flag-5'>嵌入式</b>人工智能