你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32 模块化调试技巧

[复制链接]
STMCU小助手 发布时间:2023-2-26 16:22
但当一个项目软件代码多了以后,尤其是分了很多模块后,这样打印就不方便了,因为有时我只想看本模块的打印的信息,而又不想被其他模块信息干扰,怎么办呢?
一种简单直观的方法是为本模块单独写一个打印信息的函数来调用。然而当模块很多时,这样做就效率就不高了,并显得冗余。下面介绍我设计的一个可配置的模块打印信息的方法(此适用于裸机程序) 。

在此我单独写了一个 debug 模块,包含 debug.c 和 debug.h 两文件,.c 定义了所要调用打印信息函数等,.h 可配置,以方便地选择性打印你需要的模块信息。

如我一个工程中包含有系统模块、温度检测模块、电机控制模块,则首先在 debug.c 中定义如下字符串数组
  1. char *DEBUG_MODULE_MSG[] =
  2. {
  3.     "NOTHING",
  4.     "SYS",
  5.     "TEMP",
  6.     "MOTOR",
  7. };
复制代码

在.h 中作如下定义
  1. #if 1
  2. #define SYS_DEBUG
  3. #define TEMP_DEBUG
  4. #define MOTOR_DEBUG
  5. #endif
  6. //-------
  7. #ifdef  SYS_DEBUG
  8. #define SYS   (1<<0)
  9. #else
  10. #define SYS    0
  11. #endif
  12. //-------
  13. #ifdef  TEMP_DEBUG
  14. #define TEMP  (1<<1)
  15. #else
  16. #define TEMP    0
  17. #endif
  18. //-------
  19. #ifdef  MOTOR_DEBUG
  20. #define MOTOR (1<<2)
  21. #else
  22. #define MOTOR 0
  23. #endif
  24. #define DEBUG_MODULE_NUM  3
  25. //-------
复制代码

其中通过最上面几个宏定义你就可以选择性地打印需要的模块的调试信息,不要打印的直接屏蔽掉就好了,如果再增加模块,只需再多定义一个宏,然把模块数量增加,并在字符串数组里依次添加此模块要打印出名称。

下面介绍如何对以上配置进行解析并按要求打印出来,在.c 里如下实现代码
  1. /**
  2.   * @brief  检测询要打印的模块
  3.   * @param  module: 宏定义模块名
  4.   * @retval 对应模块字符串偏移量
  5.   */
  6. static u16 check_debug_sw(u module)  
  7. {
  8.     u16 i ;
  9.    
  10.     if (0 == module)
  11.     {
  12.         return 0;
  13.     }
  14.     else
  15.     {
  16.         for (i = 0; i < DEBUG_MODULE_NUM ; i++)
  17.         {
  18.             if (module & (1 << i))
  19.             {
  20.                 return (i + 1);
  21.             }
  22.         }
  23.     }
  24.    
  25.     return 0;
  26. }
复制代码

此函数用于检测要打印的模块是否开启,如开启则返回模块对应的偏移量,以方便打印字符串数组中对应的模块名,若没找到,则返回 0。

下面就是调试信息打印函数了,其实只需模仿 printf 函数的实现,并作简单的修改就可实现模块化打印。如下
  1. /**
  2.   * @brief  可进行模块选择的可变参数的打印调试函数
  3.   * @param  module: 宏定义模块名  ...
  4.   * @retval None
  5.   */
  6. void Debug_Msg_Module_Printf(u16 module, char *fmt, ...)
  7. {
  8.     va_list ap;
  9.     char *p = NULL , *sval = NULL;
  10.     int  ival;
  11.     unsigned uval;
  12.     double dval;
  13.     u16 flag = 0 ;
  14.    
  15.     if (0 != (flag = check_debug_sw(module)))
  16.     {
  17.         printf("[ %s ]", DEBUG_MODULE_MSG[flag]);
  18.         va_start(ap, fmt);
  19.         
  20.         for (p = fmt; *p; p++)
  21.         {
  22.             if (*p != '%')
  23.             {
  24.                 putchar(*p);
  25.                 continue;
  26.             }
  27.             
  28.             switch (*++p)
  29.             {
  30.                 case 'd':
  31.                 case 'i':
  32.                     ival = va_arg(ap, int);
  33.                     printf("%d", ival);
  34.                     break;
  35.                     
  36.                 case 'c':
  37.                     ival = va_arg(ap, int);
  38.                     putchar(ival);
  39.                     break;
  40.                     
  41.                 case 'u':
  42.                     uval = va_arg(ap, unsigned);
  43.                     printf("%u", uval);
  44.                     break;
  45.                     
  46.                 case 'x':
  47.                     uval = va_arg(ap, unsigned);
  48.                     printf("%x", uval);
  49.                     break;
  50.                     
  51.                 case 'X':
  52.                     uval = va_arg(ap, unsigned);
  53.                     printf("%X", uval);
  54.                     break;
  55.                     
  56.                 case 'o':
  57.                     uval = va_arg(ap, unsigned);
  58.                     printf("%o", uval);
  59.                     break;
  60.                     
  61.                 case 'e':
  62.                     dval = va_arg(ap, double);
  63.                     printf("%e", dval);
  64.                     break;
  65.                     
  66.                 case 'f':
  67.                     dval = va_arg(ap, double);
  68.                     printf("%f", dval);
  69.                     break;
  70.                     
  71.                 case 'g':
  72.                     dval = va_arg(ap, double);
  73.                     printf("%g", dval);
  74.                     break;
  75.                     
  76.                 case 's':
  77.                     for (sval = va_arg(ap, char *); *sval; sval++)
  78.                     {
  79.                         putchar(*sval);
  80.                     }
  81.                     
  82.                     break;
  83.                     
  84.                 default :
  85.                     putchar(*p);
  86.                     break;
  87.             }
  88.         }
  89.         
  90.         va_end(ap);
  91.     }
  92. }
复制代码

至此,模块化信息打印方法就实现了。

要进行打印信息调试,如温度检测模块可以如下调用
  1. Debug_Msg_Module_Printf(TEMP,"Temp is %d \n",temp);
复制代码
电机控制模块可如此调用:
  1. Debug_Msg_Module_Printf(MOTOR,"Motor Running \n");
  2. Debug_Msg_Module_Printf(MOTOR,"Motor Stopped \n");
复制代码

如若要屏蔽掉所有的电机模块打印消息,只需要.h 文件中作如下修改:
  1. #if 1
  2. #define SYS_DEBUG
  3. #define TEMP_DEBUG
  4. //#define MOTOR_DEBUG  //注释掉此行宏定义
  5. #endif
复制代码

转载自:以太快跑
收藏 评论0 发布时间:2023-2-26 16:22

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版