【摘要】 平時(shí)開(kāi)發(fā)C語(yǔ)言程序時(shí),經(jīng)常需要調(diào)試代碼,C語(yǔ)言有一些宏,可以打印出當(dāng)前的行號(hào)、文件名稱、日期、時(shí)間,對(duì)程序的調(diào)試起到很大的幫助,可以快速定位問(wèn)題。特別是開(kāi)發(fā)單片機(jī)程序時(shí),使用這些宏打印這些信息或者在LCD上顯示程序的編譯日期、時(shí)間,可以知道這個(gè)單片機(jī)上的固件是什么時(shí)候編譯。幫助判斷版本。
一、前言
平時(shí)開(kāi)發(fā)C語(yǔ)言程序時(shí),經(jīng)常需要調(diào)試代碼,C語(yǔ)言有一些宏,可以打印出當(dāng)前的行號(hào)、文件名稱、日期、時(shí)間,對(duì)程序的調(diào)試起到很大的幫助,可以快速定位問(wèn)題。特別是開(kāi)發(fā)單片機(jī)程序時(shí),使用這些宏打印這些信息或者在LCD上顯示程序的編譯日期、時(shí)間,可以知道這個(gè)單片機(jī)上的固件是什么時(shí)候編譯。幫助判斷版本。
ANSIC標(biāo)準(zhǔn)定義了可供C語(yǔ)言使用的預(yù)定義宏:
__LINE__ : 在源代碼中插入當(dāng)前源代碼行號(hào)
__FILE__ : 在源代碼中插入當(dāng)前源代碼文件名
__DATE__ : 在源代碼中插入當(dāng)前編譯日期
__TIME__ : 在源代碼中插入當(dāng)前編譯時(shí)間
其中標(biāo)識(shí)符__LINE__和__FILE__一般用來(lái)調(diào)試程序,打印信息,方便定位錯(cuò)誤。
標(biāo)識(shí)符__DATE__和__TIME__一般可以用來(lái)表示固件的版本,方便了解運(yùn)行的程序是什么時(shí)候的版本。
標(biāo)識(shí)符__LINE__是一個(gè)整數(shù),其他的文件名稱、日期、時(shí)間都是字符串。
二、打印示例
printf("編譯日期與時(shí)間: %s,%s\n", __DATE__,__TIME__);
printf("當(dāng)前所在行號(hào):%d\r\n", __LINE__);
printf("當(dāng)前源文件名稱:%s\r\n", __FILE__);
printf("當(dāng)前固件編譯日期:%s\r\n", __DATE__);
printf("當(dāng)前固件編譯時(shí)間:%s\r\n", __TIME__);
三、C語(yǔ)言封裝快捷Debug
#define DEBUG
#ifdef DEBUG
static int DebugPrintf(const char *format, ...)
{
va_list arg_data;
int count;
va_start(arg_data, format); /* 獲取可變參數(shù)列表 */
fflush(stdout); /* 強(qiáng)制刷新輸出緩沖區(qū) */
count = vfprintf(stderr, format, arg_data); /* 將信息輸出到標(biāo)準(zhǔn)出錯(cuò)流設(shè)備 */
va_end(arg_data); /* 可變參數(shù)列表結(jié)束 */
return count;
}
#else
static inline int DebugPrintf(const char *format, ...)
{
}
#endif
通過(guò)DEBUG這個(gè)宏來(lái)開(kāi)啟是否開(kāi)啟調(diào)試信息打印功能,如果程序穩(wěn)定后,不需要打印調(diào)試信息,就可以將DEBUG的定義取消掉即可。
完整代碼:
#include
#include
#include
#include
#include
#include
#include
using namespace std;
//#define DEBUG
#ifdef DEBUG
static int DebugPrintf(const char *format, ...)
{
va_list arg_data;
int count;
va_start(arg_data, format); /* 獲取可變參數(shù)列表 */
fflush(stdout); /* 強(qiáng)制刷新輸出緩沖區(qū) */
count = vfprintf(stderr, format, arg_data); /* 將信息輸出到標(biāo)準(zhǔn)出錯(cuò)流設(shè)備 */
va_end(arg_data); /* 可變參數(shù)列表結(jié)束 */
return count;
}
#else
static inline int DebugPrintf(const char *format, ...)
{
return 0;
}
#endif
int main()
{
DebugPrintf("編譯日期與時(shí)間: %s,%s\n", __DATE__,__TIME__);
DebugPrintf("當(dāng)前所在行號(hào):%d\r\n", __LINE__);
DebugPrintf("當(dāng)前源文件名稱:%s\r\n", __FILE__);
DebugPrintf("當(dāng)前固件編譯日期:%s\r\n", __DATE__);
DebugPrintf("當(dāng)前固件編譯時(shí)間:%s\r\n", __TIME__);
return 0;
}
四、STM32單片機(jī)上封裝printf函數(shù)
/*
函數(shù)功能: 字符串發(fā)送
*/
void USARTx_StringSend(USART_TypeDef *USARTx,u8 *str)
{
while(*str!='\0')
{
USARTx->DR=*str++;
while(!(USARTx->SR&1<<7)){}
}
}
//printf函數(shù)底層函數(shù)接口
int fputc(int c, FILE* stream)
{
USART1->DR=c;
while(!(USART1->SR&1<<7)){}
return c;
}
/*
函數(shù)功能: 格式化打印函數(shù)
*/
char USART1_PRINTF_BUFF[1024];
void USART1_Printf(char *fmt,...)
{
va_list ap;
/*1. 初始化形參列表*/
va_start(ap,fmt);
/*2. 提取可變形參數(shù)據(jù)*/
vsprintf(USART1_PRINTF_BUFF,fmt,ap);
/*3. 結(jié)束,釋放空間*/
va_end(ap);
/*4. 輸出數(shù)據(jù)到串口1*/
USARTx_StringSend(USART1,(u8*)USART1_PRINTF_BUFF);
//USART1_Printf("%d%s",123,454656);
//int data=va_arg(ap,int);
}
USART1_Printf的用法與printf是一樣的,通過(guò)這個(gè)函數(shù)就可以實(shí)現(xiàn)數(shù)據(jù)打印到任意地方,包括改成存儲(chǔ)到SD卡上。
-
單片機(jī)
+關(guān)注
關(guān)注
6039文章
44579瀏覽量
636453 -
C語(yǔ)言
+關(guān)注
關(guān)注
180文章
7608瀏覽量
137128 -
程序
+關(guān)注
關(guān)注
117文章
3792瀏覽量
81163
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論