1. 程式人生 > >STM32輸出除錯資訊-printf重定向到串列埠

STM32輸出除錯資訊-printf重定向到串列埠

在STM32除錯過程中常常需要將除錯資訊輸出到串列埠,然後通過串列埠助手檢視輸出的除錯資訊。一般來說,串列埠輸出的是指定長度的十六進位制位元組,對於想列印的除錯資訊來

說,略顯靈活性不足。這時候如果可以將printf重定向到串列埠輸出,則能很好的解決這個問題。

關於printf重定向的方法有很多種,這裡只討論一種我認為相對簡單實用的方法。其主要方法步驟如下:

1、配置STM32的串列埠,確保STM32能輸出資料到串列埠除錯助手。

void USART5_Init(void)
{
	USART_InitTypeDef USART_InitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC |RCC_APB2Periph_GPIOD |RCC_APB2Periph_AFIO , ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE);

	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOC, &GPIO_InitStructure);

	// Configure the USART1_Rx as input floating
	GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IN_FLOATING ;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
	GPIO_Init(GPIOD, &GPIO_InitStructure);

	NVIC_InitStructure.NVIC_IRQChannel = UART5_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

	USART_InitStructure.USART_BaudRate = 115200;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

	USART_ITConfig(UART5, USART_IT_RXNE, ENABLE); //Enable rx enable, 
    USART_ClearFlag(UART5, USART_IT_RXNE);
	/* Configure the USARTx */ 
	USART_Init(UART5, &USART_InitStructure);
	/* Enable the USARTx */
	USART_Cmd(UART5, ENABLE);
}
2、新增printf標頭檔案#include <stdio.h>

3、點選Keil中小魔術棒Target頁勾選Use MicroLIB。

:這個步驟必須有,否則程式碼編譯通過後,進行模擬時會卡住,進入不了Main函式。printf、malloc等標準庫函式在工程建立時,不勾選Use MicroLIB就會引起這類問題。

至此,就可以通過printf列印除錯資訊到串列埠助手了。

接下來關於輸出除錯資訊再補充兩點。

1、printf輸出指定長度的字串。

格式為printf("%.*s\n",strlen,str);

        printf("指定長度字串:%.*s\n",strlen,str);	//列印指令長度位元組串
2、列印十六進位制資料。

當我們使用串列埠除錯助手檢視輸出資訊,如果我們檢視的資料是十六進位制型別,我們會勾選除錯助手中的Hex顯示選項。這時當資料量很大時,我們可能需要附加一些可見字元的說明,比如英文或者中文,這時在Hex顯示下,這些字元辨識度比較低,甚至是亂碼,printf輔助列印除錯資訊目的作用不大。這裡可以選擇一種方法,電腦串列埠助手不勾選Hex選項,而將要顯示的十六進位制資料轉為可見的ASCII碼格式。

如下為指定長度的十六進位制資料轉化為字串的函式:

/**********************************************************
*函式功能:將十六進位制資料轉為字串格式
*參    數:In,十六進位制資料;Len十六進位制資料長度
*          Out,輸出字串
*返 回 值:無
**********************************************************/
void HexToString(char *Out,char *In,char Len){
	long i;
	char Temp;
	for(i=0;i<Len;i++)	{
		Temp = In[i]>>4;
		if(Temp>9)Out[2*i] = Temp + 'A' - 10;
		else Out[2*i] = Temp + '0';
		Temp = In[i] & 0x0F;
		if(Temp>9)Out[2*i+1] = Temp + 'A' - 10;
		else Out[2*i+1] = Temp + '0';
	}
	Out[2*i] = 0;
}

此時再呼叫printf即可打印出清晰的除錯資訊:

HexToString(DebugData,(char *)buffer,bufferlen);
	printf("NTP傳送:\n%s\r\n",DebugData);

以上步驟根據除錯成功後的結果總結。