重定向C庫中stdio檔案中的printf()函式,檔案流-->串列埠USART1
阿新 • • 發佈:2019-01-08
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); }
程式執行前:
程式執行後: