新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > STM32 printf函數(shù)詳解

STM32 printf函數(shù)詳解

作者: 時間:2016-11-21 來源:網(wǎng)絡(luò) 收藏
本實(shí)驗(yàn)所用的硬件:STM32F103RTB6

實(shí)驗(yàn)所用的晶振: 8M

本文引用地址:http://m.butianyuan.cn/article/201611/319241.htm

實(shí)驗(yàn)所用的ST官方庫:3.5版

C語言中的標(biāo)準(zhǔn)庫中所用的標(biāo)準(zhǔn)輸出函數(shù),默認(rèn)的輸出設(shè)備是顯示器,要實(shí)現(xiàn)串口或LCD的輸出,必須重新定義標(biāo)準(zhǔn)庫函數(shù)里與輸出函數(shù)相關(guān)的函數(shù)。

1.下面首先介紹怎么根據(jù)官方3.5庫里面的標(biāo)準(zhǔn)例程“printf”修改成自己的“printf”工程:

下邊是官方提供的例程:

//Includes ------------------------------------------------------------------
#include "stm32f10x.h"
#include "stm32_eval.h"
#include

//@addtogroup STM32F10x_StdPeriph_Examples
// @{
//

//@addtogroup USART_Printf
//@{
//

//Private typedef -----------------------------------------------------------
//Private define ------------------------------------------------------------
//Private macro -------------------------------------------------------------
//Private variables ---------------------------------------------------------
USART_InitTypeDef USART_InitStructure;

//Private function prototypes -----------------------------------------------

#ifdef __GNUC__
//With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
// set to Yes) calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif

// Private functions ---------------------------------------------------------


// @brief Main program
//@param None
//@retval None


int main(void)
{
//At this stage the microcontroller clock setting is already configured,
//this is done through SystemInit() function which is called from startup
//file (startup_stm32f10x_xx.s) before to branch to application main.
//To reconfigure the default setting of SystemInit() function, refer to
//system_stm32f10x.c file


//USARTx configured as follow:
// - BaudRate = 115200 baud
// - Word Length = 8 Bits
// - One Stop Bit
// - No parity
// - Hardware flow control disabled (RTS and CTS signals)
// - Receive and transmit enabled
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;

STM_EVAL_COMInit(COM1, &USART_InitStructure);

// Output a message on Hyperterminal using printf function
printf("nrUSART Printf Example: retarget the C library printf function to the USARTnr");

while (1)
{
}
}
// @brief Retargets the C library printf function to the USART.
// @param None
//@retval None
//
PUTCHAR_PROTOTYPE
{
// Place your implementation of fputc here
// e.g. write a character to the USART
USART_SendData(EVAL_COM1, (uint8_t) ch);

// Loop until the end of transmission
while (USART_GetFlagStatus(EVAL_COM1, USART_FLAG_TC) == RESET)
{}

return ch;
}

#ifdef USE_FULL_ASSERT

//@brief Reports the name of the source file and the source line number
// where the assert_param error has occurred.
//@param file: pointer to the source file name
// @param line: assert_param error line source number
// @retval None
//
void assert_failed(uint8_t* file, uint32_t line)
{
//User can add his own implementation to report the file name and line number,
// ex: printf("Wrong parameters value: file %s on line %drn", file, line) */

// Infinite loop */
while (1)
{
}
}

#endif

上邊用紅色字體標(biāo)記出來的,表示是要修改的,首先#include "stm32_eval.h"是官方提供的測試板上的頭文件,而咱們要移植到自己的實(shí)驗(yàn)板上,所以不能用,負(fù)責(zé)編譯肯定出錯誤,在這里直接屏蔽就行了。STM_EVAL_COMInit(COM1, &USART_InitStructure);這個函數(shù)是官方為測試板寫的一個標(biāo)準(zhǔn)初始化串口的函數(shù),所以咱們也不能用,當(dāng)然你可以把這個函數(shù)復(fù)制到自己的main函數(shù)里,加以修改,這樣配置起串口也就相對方便了,在這里咱們就不這樣做了。因?yàn)樵蹅兪亲约盒陆üこ蹋圆荒苷{(diào)用官方測試板的初始化串口的函數(shù),所以必須重新寫一個函數(shù),按下面的方法進(jìn)行:

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;

STM_EVAL_COMInit(COM1, &USART_InitStructure);

這是標(biāo)準(zhǔn)例程里的,它實(shí)現(xiàn)了串口的初始化,下邊是我自己寫的函數(shù),也是初始化串口,所以用下面的函數(shù)替換上面的函數(shù)就ok了,函數(shù)為:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1|RCC_APB2Periph_AFIO, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //推挽輸出-TX
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空輸入-RX
GPIO_Init(GPIOA, &GPIO_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_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);

上面程序就完成了對stm32f103rbt6串口1的初始化。

接下來就是對USART_SendData(EVAL_COM1, (uint8_t) ch),while (USART_GetFlagStatus(EVAL_COM1, USART_FLAG_TC) == RESET)這兩個函數(shù)的修改,其中EVAL_COM1是官方為自己的測試板寫的庫函數(shù)定義的USART1,所以這里咱們直接用USATT1替換EVAL_COM1就行了,做完這些后編譯整個工程,整個工程就可以編譯過去了,不會出現(xiàn)錯誤,接下來的任務(wù)就是下載到實(shí)驗(yàn)板上做測試了。

2.下載到自己的實(shí)驗(yàn)板上,做測試

根據(jù)上面的修改,工程編譯過去了,也沒有出現(xiàn)任何錯誤,但下載到實(shí)驗(yàn)板上后,發(fā)現(xiàn)printf函數(shù)根本打印不出來想要打印出來的信息,后來我把所有的printf函數(shù)都屏蔽了,然后自己調(diào)用USART_SendData()這個函數(shù),看到底是配置有問題還是其他問題,結(jié)果在串口調(diào)試助手里正常的打印出了想要的字符,到這里,大家應(yīng)該都能猜到不是程序的問題,而是軟件的配置問題,經(jīng)過在網(wǎng)上的各種搜索后終于找到了答案。的確是配置問題,打開keil軟件的target



看到上面用紅線標(biāo)出來的位置了吧,默認(rèn)情況下,keil軟件是沒有把Use MicroLIB這個選項(xiàng)勾上的,咱們修改的程序之所以沒有打印出東西,就是應(yīng)該勾上這個選項(xiàng),勾上后,在進(jìn)行一次編譯,然后下載到實(shí)驗(yàn)板上,一切就正確了。

3.對標(biāo)準(zhǔn)printf函數(shù)的修改如下:

//Private function prototypes -----------------------------------------------

#ifdef __GNUC__
// With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
// set to Yes) calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif // __GNUC__


// @brief Retargets the C library printf function to the USART.
//@param None
// @retval None
//
PUTCHAR_PROTOTYPE
{
//Place your implementation of fputc here
// e.g. write a character to the USART
USART_SendData(USART1, (uint8_t) ch);

// Loop until the end of transmission
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
{}

return ch;
}

這一段函數(shù)就是把printf函數(shù)輸出到串口,需要將fputc輸出給串口,也就是重新定義。

以上就是對printf函數(shù)在調(diào)試STM32配置成串口printf函數(shù)的這個過程,希望對大家有所幫助!



關(guān)鍵詞: STM32printf函

評論


技術(shù)專區(qū)

關(guān)閉