zoukankan      html  css  js  c++  java
  • Doxygen生成美丽注释文档(1):初体验

    Chapter 1 - 准备工作 (Windows环境)

    1.1 程序包下载

    1. Doxygen

      * 源码: git clone https://github.com/doxygen/doxygen.git

      * GUI版本:点击下载

      * 便携压缩包版本:下载 32位版本 64位版本

    2. HTML Help Workshop

      用于生成CHM文件,便于传播和查看。

      Htmlhelp.ex

    3. Graphviz

      用于绘制DOT语言标本描述的图形。Doxygen 使用 graphviz 自动生成类之间和文件之间的调用关系图。

      * 源码: graphviz.tar.gz

      * graphviz-2.38.msi

      * graphviz-2.38.zip

    4. Sublime + DoxyDoxygen 插件

      * Sublime Text 3 Windows 64 bit 3176.exe

      * 便携版 x64 3176.zip

    1.2 安装教程

    Chapter 2 - 初尝 Doxygen

    2.1 为源代码生成文档大致分为两个步骤:

    1. 为源代码编写符合 doxygen 要求的注释

    2. 使用 doxygenwizard 生成文档

    2.2 编写 Doxygen 注释

    /**< 标准输入输出头文件 */
    #include <stdio.h>
    
    /**
     * @brief      { Calculate the sum of two doubles }
     *
     * This function will return the sum of two doubles
     *
     * @param[in]  a     { the first number }
     * @param[in]  b     { the second number }
     *
     * @return  double   {  the sum of a and b  }
     */
    double add(double a,double b)
    {
    
        return a+b;
    }
    
    /**
     * @brief      { Calculate the different of two doubles }
     * 
     * This function will return the different of two doubles
     * 
     * @param[in]  a     { the first number }
     * @param[in]  b     { the second number }
     *
     * @return  double   { the different of a and b }
     */
    double subtract(double a,double b)
    {
        return a-b;
    }
    
    /**
     * @brief      { Calculate the product of two doubles }
     * 
     * This function will return the product of two doubles
     *
     * @param[in]  a     { the first number }
     * @param[in]  b     { the second number }
     *
     * @return  double   { the product of a and b }
     */
    double multiply(double a,double b)
    {
        return a*b;
    }
    
    /**
     * @brief      { Calculate the quotient of two doubles }
     * 
     * This function will return the quotient of two doubles
     * 
     * @param[in]  a     { the first number }
     * @param[in]  b     { the second number }
     *
     * @return  double   { the quotient of a and b }
     */
    double divide(double a,double b)
    {
        return a/b;
    }
    
    /**
     * @brief      { This is the main function }
     *
     * This function is the main function.
     * It will print something in the screen.
     *
     * @return  int   { The exit code. }
     */
    int main(void)
    {
        int a = 5,b = 6;
        printf("%lf
    ",add(a,b));
        printf("%lf
    ",subtract(a,b));
        printf("%lf
    ",multiply(a,b));
        printf("%lf
    ",divide(a,b));
    
        return 0;
    }
    

    Doxygen 命令规范文档:官网

    2.3 使用 Doxygen 生成文档

    步骤:

    1. 打开 doxywizard
    2. 设置工作目录、项目名称、源文件目录、生成文档的目录等
    3. 设置注释抽取的模式、语言种类
    4. 设置输出格式
    5. 设置如何输出图表
    6. 生成文档

    Chapter 3. Doxygen 书写规则

    此章节参考高明飞博客,原文地址

    注释和文档的程序的组成部分,使用 Doxygen 可以将程序中特定格式的注释提取出来,生成参考文档。这样只要在编程的时候遵循特定的格式书写注释,程序编好后文档也就自然而成了。这无疑减少了单独写文档所要花费的时间。

    Doxygen 支持的语言有很多,常用的有C/C++JavaPython等,可以生成文档格式有HTML、CHM和Latex格式等。

    上文中我们已经使用了Doxygen做了一下演示。本章节主要以STM32系列单片机的标准库的程序注释为例进行分析。

    3.1 定义功能模块

    STM32F0xx_StdPeriph_Driver是按照功能模块进行组织的,每个功能模块有其对应的头文件和源文件。功能模块列表如下:

    为了让Doxygen能正确提前模块定义,需要添加模块定义注释。在文件中加入:

    /**
     * @addtogroup ADC
     * @brief ADC driver modules
     * @{
     */
    
    // 程序代码
    
    /**
     * @}
     */
    

    使用@brief对本模块的主要功能进行说明,如需进行更详细的说明,可使用@details

    3.2 定义宏定义子模块

    定义了功能模块后,一般还将宏定义单独定义为一个子模块,宏定义一般放在头文件中,加入以下注释:

    /**
     * @defgroup ADC_Exported_Constants
     * @{
     */
    
    /**
     * @defgroup ADC_JitterOff
     * @{
     */
    #define ADC_JitterOff_PCLKDiv2    ADC_CFGR2_JITOFFDIV2
    #define ADC_JitterOff_PCLKDiv4  ADC_CFGR2_JITOFFDIV4
    
    #define IS_ADC_JITTEROFF(JITTEROFF) (((JITTEROFF) & 0x3FFFFFFF) == (uint32_t)RESET)
    
    /**
     * @}
     */
    
    /**
     * @defgroup ADC_Resolution
     * @{
     */
    #define ADC_Resolution_12b    ((uint32_t)0x00000000)
    #define ADC_Resolution_10b    ADC_CFGR1_RES_0
    #define ADC_Resolution_8b    ADC_CFGR1_RES_1
    #define ADC_Resolution_6b    ADC_CFGR1_RES
    
    #define IS_ADC_RESOLUTION(RESOLUTION)    (((RESOLUTION) == ADC_Resolution_12b) || 
                                             ((RESOLUTION) == ADC_Resolution_10b) || 
                                             ((RESOLUTION) == ADC_Resolution_8b) || 
                                             ((RESOLUTION) == ADC_Resolution_6b))
    
    /**
     * @}
     */
    
    /**
     * @}
     */
    

    以上代码段中定义了一个名为ADC_Exported_Constants的模块,此模块中包含了ADC模块中所有的宏定义。

    ADC_Exported_Constants模块中,又有若干个子模块,如ADC_JitterOffADC_Resolution等。

    这样组织代码可以让大量的宏定义结构更为清晰,而且有利于在其他地方进行交叉引用。

    3.3 定义函数子模块

    与宏定义子模块类似,也可以将函数定义为一个子模块,并且按功能进行进一步分组归类。

    函数的定义与注释说明一般都全部放在源文件中,头文件中仅简单的进行函数声明。在源文件中加入以下注释:

    /**
     * @defgroup ADC_Private_Functions
     * @{
     */
    
    /**
     * @defgroup ADC_Group1 Initialization and Configuration functions
     * @brief Initialization and Configuration functions
     *
     * @{
     */
    
    void ADC_DeInit(ADC_TypeDef* ADCx){}
    void ADC_Init(ADC_TypeDef* ADCx,ADC_InitTypeDef* ADC_InitStruct){}
    void ADC_StructInit(ADC_InitTypeDef* ADC_InitStruct){}
    /**
     * @}
     */
    
    /**
     * @defgroup ADC_Group2 Power saving functions
     * @brief      Power saving function
     * @{
     */
    void ADC_AutoPowerOffCmd(ADC_TypeDef* ADCx,FunctionalState NewState){}
    void ADC_WaitModeCmd(ADC_TypeDef* ADCx,FunctionalState NewState){}
    /**
     * @}
     */
    
    /**
     * @}
     */
    

    以上代码在实际代码的基础上进行了精简,仅保留了进行模块定义的基本结构。代码段中定义了一个名为ADC_Private_Functions的模块,此模块中包含了所有的函数定义,并且各函数按用途进行了分组,分为若干个子模块,如Initialzation and Configuration FunctionsPower saving functions等。

    3.4 结构体注释说明

    对于结构体,一般使用如下形式的注释:

    /** 
      * @brief  ADC Init structure definition
      */
    typedef struct
    {
      /*!< Selects the resolution of the conversion.
           This parameter can be a value of @ref ADC_Resolution */
      uint32_t ADC_Resolution;                  
    
      /*!< Specifies whether the conversion is performed in
           Continuous or Single mode.
           This parameter can be set to ENABLE or DISABLE. */
      FunctionalState ADC_ContinuousConvMode;   
    
      /*!< Selects the external trigger Edge and enables the
           trigger of a regular group. This parameter can be a value
           of @ref ADC_external_trigger_edge_conversion */
      uint32_t ADC_ExternalTrigConvEdge;        
    
      /*!< Defines the external trigger used to start the analog
           to digital conversion of regular channels. This parameter
           can be a value of @ref ADC_external_trigger_sources_for_channels_conversion */
      uint32_t ADC_ExternalTrigConv;            
    
      /*!< Specifies whether the ADC data alignment is left or right.
           This parameter can be a value of @ref ADC_data_align */
      uint32_t ADC_DataAlign;                   
    
      /*!< Specifies in which direction the channels will be scanned
           in the sequence. 
           This parameter can be a value of @ref ADC_Scan_Direction */
      uint32_t  ADC_ScanDirection;              
    }ADC_InitTypeDef;
    

    此代码段中对ADC_InitTypeDef这个结构体进行了较为详尽的注释,开头使用@brief说明此结构体的主要功能,之后对结构体中每个成员的意义进行了注释。使用/*!< Comment */这样的语法表示此注释对应的是注释前面的语句,这样可以使代码的排版更为美观。

    另外,注意到其中@ref标签的使用,这代表交叉应用,如@ref ADC_Resolution,实际会生成一个超链接指向之前定义的ADC_Resolution模块。这里的交叉引用可以是模块名、函数名、结构体等。

    3.5 枚举注释说明

    枚举的注释形式与结构体完全相同,可参考以上示例。

    3.6 函数注释说明

    函数的注释说明一般放在源文件中,头文件和源文件中最好不要重复添加注释,否则生成文档会有重复

    函数的注释一般使用以下的形式:

    /**
      * @brief  Enables or disables the ADC DMA request after last transfer (Single-ADC mode)
      * @param  ADCx: where x can be 1 to select the ADC1 peripheral.
      * @param  ADC_DMARequestMode: the ADC channel to configure.
      *          This parameter can be one of the following values:
      *            @arg ADC_DMAMode_OneShot: DMA One Shot Mode
      *            @arg ADC_DMAMode_Circular: DMA Circular Mode
      * @retval None
      */
    void ADC_DMARequestModeConfig(ADC_TypeDef* ADCx, uint32_t ADC_DMARequestMode){}
    
    /**
      * @brief  Active the Calibration operation for the selected ADC.
      * @note   The Calibration can be initiated only when ADC is still in the
      *         reset configuration (ADEN must be equal to 0).
      * @param  ADCx: where x can be 1 to select the ADC1 peripheral.
      * @retval ADC Calibration factor
      */
    uint32_t ADC_GetCalibrationFactor(ADC_TypeDef* ADCx){}
    
    • 使用@brief简要说明函数的作用;
    • 使用@param说明输入参数,若输入参数是有限的几个值,可用@arg进行列举;
    • 使用@retval说明函数的返回值,另外,一些需要特别注意的地方可以使用@note@warning进行说明。

    3.7 文件头

    每个文件的开头部分一般都需要添加一个对此文件的说明,可使用如下格式:

    /**
      **************************************************************
      * @file Example.c
      * @author 作者
      * @version V1.0 版本号
      * @date 2015-11-13
      *
      * @brief 程序的简要说明
      *
      * @details
      * @verbatim
      * 程序的详细说明。
      *
      * 修改记录:
      * 2015-11-13 :
      *   - 修改记录
      *
      * @endverbatim
      ***************************************************************
      */
    

    @verbatim@endverbatim会按原样逐行输出,如果不用标签标注出来的文本内容会被忽略掉。

    另外,使用@todo@bug标签列出待办事项和BUG,Doxygen会在生成文档时候自动汇总为Todo与Bug列表。

  • 相关阅读:
    Luogu P1004 方格取数
    Luogu P1896 [SCOI2005]互不侵犯
    Luogu P1879 [USACO06NOV]玉米田Corn Fields 【状压dp模板】
    高精度模板(结构体)
    【模板】快读
    vue input框type=number 保留两位小数自定义组件
    elementui表格表头合并
    将excle表中得数据生成insert语句插入到数据库中
    数据库基本语法
    ztree 数组和树结构互转算法
  • 原文地址:https://www.cnblogs.com/yqmcu/p/10090821.html
Copyright © 2011-2022 走看看