1. 程式人生 > >重定向C庫中stdio檔案中的printf()函式,檔案流-->串列埠USART1

重定向C庫中stdio檔案中的printf()函式,檔案流-->串列埠USART1

1、printf()函式:

我們以前在VC6.0中程式設計時,包含include<stdio.h>標頭檔案之後,呼叫printf()函式後可以向控制檯傳輸(列印)一連串字元等。

若要在STM32上也想用printf()函式向指定的裝置上傳輸(列印)一串資料的話,可以“重定向這個C庫(stdio)printf()函式”來實現。

比如將其重定向到USART1上,即:printf()函式要輸出的資料通過串列埠USART1傳送出去,通過串列埠助手可以檢視。

重定向後的優點:可以像在VC6.0裡面使用printf()函式在控制檯輸出資料和控制符之類的一樣,通過串列埠將其傳送,對以後除錯程式帶來很大的便利。

2、對檔案stdio的printf()函式的“重定向”的函式如下:


3、程式例舉:

/**************************************************************************************************
 *	硬體平臺:STM32F103VC
 *	學習重點:呼叫庫函式來實現對USART的操作
 *	實現功能:軟體模擬,實現STM32通過USART1傳送資料
 *	作    者:趙小龍
 **************************************************************************************************/


/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_lib.h"	  //包含了所有的標頭檔案 它是唯一一個使用者需要包括在自己應用中的檔案,起到應用和庫之間介面的作用。
#include "stm32f10x_map.h"
#include <stdio.h>


/*----------------函式宣告部分---------------*/
void delay1ms(int t) ;
void RCC_Configuration(void) ;
void GPIO_Configuration(void) ;
void USART_Configuration(u32 BaudRate) ;

/*******************************************************************************
* Function Name  : int fputc(int ch , FILE *f)
* Description    : 重定向這個C庫(stdio)中printf函式 : 檔案流-->串列埠USART1
* Input          : int ch , FILE *f
* Output         : 將printf函式要列印的字元不是顯示在螢幕上,而是將其通過USART1傳送出去
* Return         : int ch
*******************************************************************************/ 
int fputc(int ch , FILE *f)
{
/*---------------在呼叫本函式對printf函式重定向前,先要對USART1進行配置------------------*/
	//1、將ch送給USART1
	USART_SendData(USART1 , ch) ;

	//2、等待發送完畢
	while( USART_GetFlagStatus(USART1 , USART_FLAG_TC) == RESET ) { ; }
	
	//3、返回ch
	return(ch) ;
}


/* Private functions -----------------------------------------------------------------------------*/ 
/**************************************************************************************************
* Function Name  : main
* Description    : 軟體模擬,從USART1傳送26個大寫的英文字母
* Input          : None
* Output         : None
* Return         : None
****************************************************************************************************/
int main(void)
{

	u8 i,data;	
/*--------配置開啟系統時鐘、配置USART1傳送/接收使用的兩個I/O口、配置USART1---------------------------------------------*/
	RCC_Configuration();
	GPIO_Configuration();
	USART_Configuration(19600);

/*--------傳送一串字元‘A’--‘Z’到USART1的DR-----------------------------------------------------------------------------*/
	data='A';
	for(i=0;i<26;i++)
	{
		printf(" %d:",i+1);
		USART_SendData(USART1, data) ;
		data++ ;
		while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) ;//傳送完成標誌位為1時便是資料傳送完畢,若為0時則應讓程式等待(等待資料傳送傳送完成)
		/*注意:這裡最好不要按照以下形式書寫,否則會出錯,具體原因我暫且還不知道
			u8 status ; 
			status = USART_GetFlagStatus(USART1, USART_FLAG_TC) ;  //將檢視狀態暫存器的函式的返回值賦值給變數status 
			while(status == RESET) ;
		*/
	}

	printf("\n趙小龍好人好運!\n") ; 

}

/*******************************************************************************
* Function Name  : Delay_Ms
* Description    : delay 1 ms.
* Input          : dly (ms)
* Output         : None
* Return         : None
*******************************************************************************/
void delay1ms(int t)
{
	//機器週期T = 1/(72000000/12)s = 1/6000000 s = 1/6 us
	int temp = 6000/4 ;
	while(t--)
	{
		while(temp--)
		{ ; }	
	}

}


/*******************************************************************************
* Function Name  : RCC_Configuration
* Description    : Configures the different system clocks.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void RCC_Configuration(void)
{
	//----------使用外部RC晶振-----------
	RCC_DeInit();			//初始化為預設值
	RCC_HSEConfig(RCC_HSE_ON);	//使能外部的高速時鐘 
	while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);	//等待外部高速時鐘使能就緒
	
	//FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);	//Enable Prefetch Buffer
	//FLASH_SetLatency(FLASH_Latency_2);		//Flash 2 wait state
	
	RCC_HCLKConfig(RCC_SYSCLK_Div1);		//HCLK = SYSCLK
	RCC_PCLK2Config(RCC_HCLK_Div1);			//PCLK2 =  HCLK
	RCC_PCLK1Config(RCC_HCLK_Div2);			//PCLK1 = HCLK/2
	RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9);	//PLLCLK = 8MHZ * 9 =72MHZ
	RCC_PLLCmd(ENABLE);			//Enable PLLCLK

	while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);	//Wait till PLLCLK is ready
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);	//Select PLL as system clock
	while(RCC_GetSYSCLKSource()!=0x08);		//Wait till PLL is used as system clock source
	
	//---------開啟相應外設時鐘--------------------
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);	//使能APB2外設的GPIOA的時鐘	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);	//使能APB2外設的GPIOC的時鐘
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	
	//GPIO_PinRemapConfig(GPIO_Remap_USART1,ENABLE);	 
		 
}

/*******************************************************************************
* Function Name  : GPIO_Configuration
* Description    : 初始化GPIO外設
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/ 
void GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  /* Configure USARTx_Tx as alternate function push-pull */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* Configure USARTx_Rx as input floating */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

}

/*******************************************************************************
* Function Name  : USART_Configuration
* Description    : 初始化串列埠USART1(非同步收發模式)
* Input          : BaudRate (要設定的波特率)
* Output         : None
* Return         : None
*******************************************************************************/ 
void USART_Configuration(u32 BaudRate)
{
//1、定義一個用於初始化USART的結構體
	USART_InitTypeDef USART_InitStructure;
	 
//2、給結構體元素賦值,設定 波特率、資料幀的位數、停止位的位數、奇偶校驗位、硬體流控制位、USART模式(傳送、接收)
	USART_InitStructure.USART_BaudRate = BaudRate; 
	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_Tx | USART_Mode_Rx;  

//3、呼叫函式USART_Init();用上面的結構體值作為引數對USART1進行初始化
	USART_Init(USART1, &USART_InitStructure);

//4、呼叫函式USART_Cmd();對USART1進行使能
	USART_Cmd(USART1, ENABLE);

}



程式執行前:


程式執行後: