但当一个项目软件代码多了以后,尤其是分了很多模块后,这样打印就不方便了,因为有时我只想看本模块的打印的信息,而又不想被其他模块信息干扰,怎么办呢?
一种简单直观的方法是为本模块单独写一个打印信息的函数来调用。然而当模块很多时,这样做就效率就不高了,并显得冗余。下面介绍我设计的一个可配置的模块打印信息的方法(此适用于裸机程序) 。
在此我单独写了一个 debug 模块,包含 debug.c 和 debug.h 两文件,.c 定义了所要调用打印信息函数等,.h 可配置,以方便地选择性打印你需要的模块信息。
如我一个工程中包含有系统模块、温度检测模块、电机控制模块,则首先在 debug.c 中定义如下字符串数组
- char *DEBUG_MODULE_MSG[] =
- {
- "NOTHING",
- "SYS",
- "TEMP",
- "MOTOR",
- };
复制代码
在.h 中作如下定义 - #if 1
- #define SYS_DEBUG
- #define TEMP_DEBUG
- #define MOTOR_DEBUG
- #endif
- //-------
- #ifdef SYS_DEBUG
- #define SYS (1<<0)
- #else
- #define SYS 0
- #endif
- //-------
- #ifdef TEMP_DEBUG
- #define TEMP (1<<1)
- #else
- #define TEMP 0
- #endif
- //-------
- #ifdef MOTOR_DEBUG
- #define MOTOR (1<<2)
- #else
- #define MOTOR 0
- #endif
- #define DEBUG_MODULE_NUM 3
- //-------
复制代码
其中通过最上面几个宏定义你就可以选择性地打印需要的模块的调试信息,不要打印的直接屏蔽掉就好了,如果再增加模块,只需再多定义一个宏,然把模块数量增加,并在字符串数组里依次添加此模块要打印出名称。
下面介绍如何对以上配置进行解析并按要求打印出来,在.c 里如下实现代码
- /**
- * @brief 检测询要打印的模块
- * @param module: 宏定义模块名
- * @retval 对应模块字符串偏移量
- */
- static u16 check_debug_sw(u module)
- {
- u16 i ;
-
- if (0 == module)
- {
- return 0;
- }
- else
- {
- for (i = 0; i < DEBUG_MODULE_NUM ; i++)
- {
- if (module & (1 << i))
- {
- return (i + 1);
- }
- }
- }
-
- return 0;
- }
复制代码
此函数用于检测要打印的模块是否开启,如开启则返回模块对应的偏移量,以方便打印字符串数组中对应的模块名,若没找到,则返回 0。
下面就是调试信息打印函数了,其实只需模仿 printf 函数的实现,并作简单的修改就可实现模块化打印。如下
- /**
- * @brief 可进行模块选择的可变参数的打印调试函数
- * @param module: 宏定义模块名 ...
- * @retval None
- */
- void Debug_Msg_Module_Printf(u16 module, char *fmt, ...)
- {
- va_list ap;
- char *p = NULL , *sval = NULL;
- int ival;
- unsigned uval;
- double dval;
- u16 flag = 0 ;
-
- if (0 != (flag = check_debug_sw(module)))
- {
- printf("[ %s ]", DEBUG_MODULE_MSG[flag]);
- va_start(ap, fmt);
-
- for (p = fmt; *p; p++)
- {
- if (*p != '%')
- {
- putchar(*p);
- continue;
- }
-
- switch (*++p)
- {
- case 'd':
- case 'i':
- ival = va_arg(ap, int);
- printf("%d", ival);
- break;
-
- case 'c':
- ival = va_arg(ap, int);
- putchar(ival);
- break;
-
- case 'u':
- uval = va_arg(ap, unsigned);
- printf("%u", uval);
- break;
-
- case 'x':
- uval = va_arg(ap, unsigned);
- printf("%x", uval);
- break;
-
- case 'X':
- uval = va_arg(ap, unsigned);
- printf("%X", uval);
- break;
-
- case 'o':
- uval = va_arg(ap, unsigned);
- printf("%o", uval);
- break;
-
- case 'e':
- dval = va_arg(ap, double);
- printf("%e", dval);
- break;
-
- case 'f':
- dval = va_arg(ap, double);
- printf("%f", dval);
- break;
-
- case 'g':
- dval = va_arg(ap, double);
- printf("%g", dval);
- break;
-
- case 's':
- for (sval = va_arg(ap, char *); *sval; sval++)
- {
- putchar(*sval);
- }
-
- break;
-
- default :
- putchar(*p);
- break;
- }
- }
-
- va_end(ap);
- }
- }
复制代码
至此,模块化信息打印方法就实现了。
要进行打印信息调试,如温度检测模块可以如下调用
- Debug_Msg_Module_Printf(TEMP,"Temp is %d \n",temp);
复制代码电机控制模块可如此调用:
- Debug_Msg_Module_Printf(MOTOR,"Motor Running \n");
- Debug_Msg_Module_Printf(MOTOR,"Motor Stopped \n");
复制代码
如若要屏蔽掉所有的电机模块打印消息,只需要.h 文件中作如下修改: - #if 1
- #define SYS_DEBUG
- #define TEMP_DEBUG
- //#define MOTOR_DEBUG //注释掉此行宏定义
- #endif
复制代码
转载自:以太快跑 |