新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > STM32 printf函數詳解

        STM32 printf函數詳解

        作者: 時間:2016-11-21 來源:網絡 收藏
        本實驗所用的硬件:STM32F103RTB6

        實驗所用的晶振: 8M

        本文引用地址:http://www.104case.com/article/201611/319241.htm

        實驗所用的ST官方庫:3.5版

        C語言中的標準庫中所用的標準輸出函數,默認的輸出設備是顯示器,要實現串口或LCD的輸出,必須重新定義標準庫函數里與輸出函數相關的函數。

        1.下面首先介紹怎么根據官方3.5庫里面的標準例程“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

        上邊用紅色字體標記出來的,表示是要修改的,首先#include "stm32_eval.h"是官方提供的測試板上的頭文件,而咱們要移植到自己的實驗板上,所以不能用,負責編譯肯定出錯誤,在這里直接屏蔽就行了。STM_EVAL_COMInit(COM1, &USART_InitStructure);這個函數是官方為測試板寫的一個標準初始化串口的函數,所以咱們也不能用,當然你可以把這個函數復制到自己的main函數里,加以修改,這樣配置起串口也就相對方便了,在這里咱們就不這樣做了。因為咱們是自己新建工程,所以不能調用官方測試板的初始化串口的函數,所以必須重新寫一個函數,按下面的方法進行:

        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);

        這是標準例程里的,它實現了串口的初始化,下邊是我自己寫的函數,也是初始化串口,所以用下面的函數替換上面的函數就ok了,函數為:

        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)這兩個函數的修改,其中EVAL_COM1是官方為自己的測試板寫的庫函數定義的USART1,所以這里咱們直接用USATT1替換EVAL_COM1就行了,做完這些后編譯整個工程,整個工程就可以編譯過去了,不會出現錯誤,接下來的任務就是下載到實驗板上做測試了。

        2.下載到自己的實驗板上,做測試

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



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

        3.對標準printf函數的修改如下:

        //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;
        }

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

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



        關鍵詞: STM32printf函

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 迭部县| 武平县| 环江| 金沙县| 大埔区| 贵德县| 象州县| 尉氏县| 平陆县| 彭山县| 大石桥市| 曲松县| 兴和县| 永康市| 临桂县| 综艺| 呼伦贝尔市| 贵阳市| 翼城县| 中阳县| 车险| 福海县| 赞皇县| 民丰县| 若尔盖县| 罗田县| 安泽县| 吉木乃县| 开阳县| 新沂市| 台湾省| 惠东县| 平乡县| 阳朔县| 紫云| 淮安市| 河源市| 兴仁县| 突泉县| 横峰县| 天峨县|