##__VA_ARGS__的作用,printf函数在格式化输出时,需要重定向char putchar(char c);改成串口输出
/* stm32f103 寄存器操作 重定向putchar */
char putchar(char ch)
{
while((USART1->SR&0X40)==0);//循环发送,直到发送完毕
USART1->DR = (u8) ch;
return c;
}
不需要将log保存在日志文件中
#define LOG_ERROR(fmt, ...) printf("[ERROR] <%s()>%d"fmt"\n", __func__, __LINE__, ##__VA_ARGS__)
#define LOG_WARN(fmt, ...) printf("[WARN] <%s()>%d"fmt"\n", __func__, __LINE__, ##__VA_ARGS__)
#define LOG_INFO(fmt, ...) printf("[INFO] <%s()>%d"fmt"\n", __func__, __LINE__, ##__VA_ARGS__)
#define LOG_DEBUG(fmt, ...) printf("[DEBUG] <%s()>%d"fmt"\n", __func__, __LINE__, ##__VA_ARGS__)
需要将log保存在日志文件中
#ifndef __DEBUG_H_
#define __DEBUG_H_
typedef enum {
LOG_ERROR,
LOG_WARN,
LOG_INFO,
LOG_DEBUG,
LOG_MAX,
} LogLevel;
#define PRINT_LEVEL LOG_MAX /* 默认调试级别 */
#define NameLevel(name) (#name)
int LogPrint(LogLevel level, const char *fmt, ...);
#define M_LOG(level, fmt, ...) \
do { \
LogPrint(level, "<%s() ln:%d> " fmt "\r\n", __FUNCTION__, __LINE__, ##__VA_ARGS__); \
} while (0)
#define M_LOG_ERROR(fmt, ...) M_LOG(LOG_ERROR, fmt, ##__VA_ARGS__)
#define M_LOG_WARN(fmt, ...) M_LOG(LOG_WARN, fmt, ##__VA_ARGS__)
#define M_LOG_INFO(fmt, ...) M_LOG(LOG_INFO, fmt, ##__VA_ARGS__)
#define M_LOG_DEBUG(fmt, ...) M_LOG(LOG_DEBUG, fmt, ##__VA_ARGS__)
#endif // !__DEBUG_H_
#include "debug.h"
#include <stdio.h>
#include <stdarg.h>
const char *g_levelInfo[LOG_MAX] = {
[LOG_ERROR] = "ERROR",
[LOG_WARN] = "WARN",
[LOG_INFO] = "INFO",
[LOG_DEBUG] = "DEBUG",
};
/* 这个通常用于将log保存在日志文件中,可以通过snprintf函数从格式化参数中获取数据 */
int LogPrint(LogLevel level, const char* fmt, ...)
{
va_list valist;
if ((level > LOG_MAX) || (level < LOG_ERROR) || (fmt== NULL)) {
printf("[LOG_IGNORE]: log input para invaild\n");
return -1;
}
if (level > PRINT_LEVEL) {
return 0;
}
va_start(valist, fmt);
printf("[%s] ", g_levelInfo[level]);
vprintf(fmt, valist);
va_end(valist);
return 0;
}