建立Debug调试日志

参考链接:1 ((sizeof(n)+sizeof(int)-1)&~(sizeof(int)-1))

                    2 对C语言中va_list,va_start,va_arg和va_end的一点理解 

                    3 C 库宏 - va_start()

                    4  vsnprintf函数用法

                    5 C,C++宏中#、##和__VA_ARGS__的理解

                    6 C语言中函数参数的省略号

                    7 函数参数带省略号的用法

                   8 调试技巧——宏定义开关和printf

                   9 怎样写参数个数可变的宏

                  10 __VA_ARGS__用法

 

example 1:

main.c

#include 
#include "Debug.h"

int main(int argc, char *argv[])
{
	int data = 999;
    printDebugMsg("TestProgram", "data= %d", data);
	printf("Hello C-Free!\n");
	return 0;
}

Debug.h

#ifndef __DEBUG_H__
#define __DEBUG_H__

#ifdef __cplusplus
	extern "C" {
#endif

#include 
#include 

#define _DEBUG
#ifdef  _DEBUG
	//#define DEBUG_TO_FILE
	#ifdef  DEBUG_TO_FILE
	//调试信息输出到以下文件
	#define DEBUG_FILE "..//tmp//debugmsg.txt" 
	//调试信息的缓冲长度 
	#define DEBUG_BUFFER_MAX    4096
    //将调试信息输出到文件中
	#define printDebugMsg(moduleName, format, ...) {\
	char buffer[DEBUG_BUFFER_MAX+1] = {0};\
	snprintf(buffer, DEBUG_BUFFER_MAX,\
			"[%s] "format" File:%s, Line:%d\n", moduleName, ##__VA_ARGS__, __FILE__, __LINE__);\
	FILE* fd = fopen(DEBUG_FILE, "a");\
	if(fd != NULL){\
		fwrite(buffer, strlen(buffer), 1, fd);\
		fflush(fd);\
		fclose(fd);\
		}\
	}
	#else //#ifndef  DEBUG_TO_FILE
	//将调试信息输出到终端 
	#define printDebugMsg(moduleName, format, ...)\
	                printf("[%s] "format" File:%s, Line:%d\n", moduleName, ##__VA_ARGS__, __FILE__, __LINE__);
 
	#endif //end for #ifdef DEBUG_TO_FILE
#else
	//发行版本,什么也不做 
    #define printDebugMsg(moduleName, format, ...)
#endif //end for #ifdef _DEBUG 



/*--------------------Private Function------------------------*/
extern void printfDebugMsg(const char* format, ...);

#ifdef __cplusplus
	}
#endif


#endif /*__DEBUG_H__*/

/******************* (C) COPYRIGHT 2018  *****END OF FILE****/

Debug.c

#include "Debug.h"

#define DEBUG_BUFFER_MAX    4096

/*
只有支持C99规范的gcc编译器才有__VA_ARGS__这个宏,
如果不是gcc编译器,或者所用的gcc编译器版本不支持__VA_ARGS__宏怎么办
*/

void printfDebugMsg( const char* format, ...)
{
	 char buffer[DEBUG_BUFFER_MAX + 1]={0};
	 va_list arg;
	 va_start (arg, format);
	 vsnprintf(buffer, DEBUG_BUFFER_MAX, format, arg);
	 va_end (arg);
	 printf( "%s", buffer );
}

测试结果:

建立Debug调试日志_第1张图片

example 2:

debug.h

#ifndef __DEBUG_H__
#define __DEBUG_H__

#ifdef __cplusplus
	extern "C" {
#endif

#include 
#include 

typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;

#define _DEBUG
#ifdef  _DEBUG
	//#define DEBUG_TO_FILE
	#ifdef  DEBUG_TO_FILE
	//调试信息输出到以下文件
	#define DEBUG_FILE "..//tmp//debugmsg.txt" 
	//调试信息的缓冲长度 
	#define DEBUG_BUFFER_MAX    4096
    //将调试信息输出到文件中
	#define printDebugMsg(moduleName, format, ...) {\
	char buffer[DEBUG_BUFFER_MAX+1] = {0};\
	snprintf(buffer, DEBUG_BUFFER_MAX,\
			"[%s] "format" File:%s, Line:%d\n", moduleName, ##__VA_ARGS__, __FILE__, __LINE__);\
	FILE* fd = fopen(DEBUG_FILE, "a");\
	if(fd != NULL){\
		fwrite(buffer, strlen(buffer), 1, fd);\
		fflush(fd);\
		fclose(fd);\
		}\
	}
	#else //#ifndef  DEBUG_TO_FILE
	//将调试信息输出到终端 
	#define printDebugMsg(moduleName, format, ...)\
	                printf("[%s] "format" File:%s, Line:%d\n", moduleName, ##__VA_ARGS__, __FILE__, __LINE__);
 
	#endif //end for #ifdef DEBUG_TO_FILE
	//#define DEBUG(...)  printf(__VA_ARGS__)
	//#define DEBUG(format, ...) printf (format, ##__VA_ARGS__) 
	#define DEBUG(format,...) printf("FILE: "__FILE__",LINE: %05d: "format"\n", __LINE__, ##__VA_ARGS__)
	
#else
	//发行版本,什么也不做 
    #define printDebugMsg(moduleName, format, ...)
    //#define DEBUG(...) 
    #define DEBUG(format, ...) 
    
#endif //end for #ifdef _DEBUG 

/* Private define ------------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
#define USE_FULL_ASSERT    
#ifdef  USE_FULL_ASSERT

/**
  * @brief  The assert_param macro is used for function's parameters check.
  * @param  expr: If expr is false, it calls assert_failed function which reports 
  *         the name of the source file and the source line number of the call 
  *         that failed. If expr is true, it returns no value.
  * @retval None
  */
  #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
/* Exported functions ------------------------------------------------------- */
  void assert_failed(uint8_t* file, uint32_t line);
#else
  #define assert_param(expr) ((void)0)
#endif /* USE_FULL_ASSERT */




/*--------------------Private Function------------------------*/
extern void printfDebugMsg(const char* format, ...);

#ifdef __cplusplus
	}
#endif


#endif /*__DEBUG_H__*/

/******************* (C) COPYRIGHT 2018  *****END OF FILE****/

debug.c

#include "Debug.h"

#define DEBUG_BUFFER_MAX    4096




/*
只有支持C99规范的gcc编译器才有__VA_ARGS__这个宏,
如果不是gcc编译器,或者所用的gcc编译器版本不支持__VA_ARGS__宏怎么办
*/

void printfDebugMsg( const char* format, ...)
{
	 char buffer[DEBUG_BUFFER_MAX + 1]={0};
	 va_list arg;
	 va_start (arg, format);
	 vsnprintf(buffer, DEBUG_BUFFER_MAX, format, arg);
	 va_end (arg);
	 printf( "%s", buffer );
}

void assert_failed(uint8_t* file, uint32_t line)
{
	printf("Wrong parameters value: file %s on line %d\r\n", file, line);
	while (1)
	{}
}

main.c

#include 
#include 
#include "Debug.h"



typedef struct
{
	void (*reqCmdCall)(uint8_t);
	//FPGA_ACK_PACKAGE fpgaAck;
} FPGA_REQCMD_ACKDATA;

typedef struct fileName
{
	char min[3];
	char hour[3];
	char date[3];
	char datehourmin[9];
	char Month[3];
	char Year[5];

}FILE_NEME_TypeDef;

FILE_NEME_TypeDef tFileName;

void regCmdCallTest(uint8_t data)
{
	printf("RegCmdCall Test: data = %d\r\n", data);
}

struct tm*  GetCurrentTime(FILE_NEME_TypeDef *INFO)
{
	time_t timep;
	unsigned int Year = 0;
	char str[100]={0};
	char *pstr = &str; 
	struct tm *p;
	time(&timep); //返回自纪元 Epoch(1970-01-01 00:00:00 UTC)起经过的时间,以秒为单位
	Year = 1970+timep/365/24/60/60;
	DEBUG("now Year is %d\r\n", Year);
	DEBUG("now time is %s %s\r\n",__TIME__, __DATE__);
	pstr = ctime(&timep); //返回一个表示当地时间的字符串,当地时间是基于参数 timer
	DEBUG("now time is %s\r\n", pstr);
	p = gmtime(&timep);
	DEBUG("%d\n",p->tm_sec); /*获取当前秒*/
	DEBUG("%d\n",p->tm_min); /*获取当前分*/
	DEBUG("%d\n",8+p->tm_hour);/*获取当前时,这里获取西方的时间,刚好相差八个小时*/
	DEBUG("%d\n",p->tm_mday);/*获取当前月份日数,范围是1-31*/
	DEBUG("%d\n",1+p->tm_mon);/*获取当前月份,范围是0-11,所以要加1*/
	DEBUG("%d\n",1900+p->tm_year);/*获取当前年份,从1900开始,所以要加1900*/
	DEBUG("%d\n",p->tm_yday); /*从今年1月1日算起至今的天数,范围为0-365*/
	itoa(p->tm_min, INFO->min, 10);
	DEBUG("INFO->min is %s: \r\n", INFO->min);
	itoa(p->tm_hour+8, INFO->hour, 10);
	DEBUG("INFO->hour is %s: \r\n", INFO->hour);
	itoa(p->tm_mday, INFO->date, 10);
	DEBUG("INFO->date is %s: \r\n", INFO->date);
	itoa(p->tm_mday*10000 + (p->tm_hour+8)*100 + (p->tm_min), INFO->datehourmin, 10);
	DEBUG("INFO->datehourmin is %s: \r\n", INFO->datehourmin);
	
	itoa(p->tm_mon+1, INFO->Month, 10);
	DEBUG("INFO->Month is %s: \r\n", INFO->Month);
	itoa(p->tm_year+1900, INFO->Year, 10);
	DEBUG("INFO->Year is %s: \r\n", INFO->Year);
	return p;
}

char* CreateLogmsgFilePath(FILE_NEME_TypeDef *INFO, char** pPath)
{
    int index = 0, len = 0;
	char path[100] = {"\0"};
	char temp[20] = {"\0"};
	GetCurrentTime(&tFileName);
    strcpy(temp,  "..\\msglog\\");
    index = strlen(temp);
    memcpy(path, temp, index);
    memcpy(path+index, tFileName.Year, strlen(tFileName.Year));
    index += strlen(tFileName.Year);
    memcpy(path+index, "\\", strlen("\\"));
    index += strlen("\\");
    memcpy(path+index, tFileName.Month, strlen(tFileName.Month));
    index += strlen(tFileName.Month);
    memcpy(path+index, "\\debugmsg", strlen("\\debugmsg"));
    index += strlen("\\debugmsg");
    memcpy(path+index, tFileName.datehourmin, strlen(tFileName.datehourmin));
    index += strlen(tFileName.datehourmin);
    memcpy(path+index, ".txt", strlen(".txt"));
    index += strlen(".txt");
    memcpy(*pPath, path, index+1);
    DEBUG("path = %s\r\n", path);
    DEBUG("pPath = %s\r\n", *pPath);
    return path;
}


/*
小端转大端 
*/		
void endianConvert(void* mem, unsigned char len)
{
	uint8_t* p = mem;
	uint8_t i;
	uint8_t temp;

	for (i=0; i

 

你可能感兴趣的:(C++,STM32)