assert_param 函數,斷言

        在STM32的固件庫和提供的例程中,到處都可以見到assert_param()的使用。在固件庫中,它的作用就是檢測傳遞給函數的參數是否是有效的參數。       

        這是一種常見的軟件技術,可以在調試階段幫助程序員快速地排除那些明顯的錯誤。它確實在程序的運行上犧牲了效率(但只是在調試階段),但在項目的開發上卻幫助你提高了效率。

        當你的項目開發成功,使用release模式編譯之後,或在stm32f10x_conf.h文件中註釋掉對USE_FULL_ASSERT的宏定義,所有的assert_param()檢驗都消失了,不會影響最終程序的運行效率。

        assert_param函數在stm32f0xx_conf.h 庫函數中定義:

/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Uncomment the line below to expanse the "assert_param" macro in the
   Standard Peripheral Library drivers code */
/* #define USE_FULL_ASSERT    1 */

/* Exported macro ------------------------------------------------------------*/
#ifdef  USE_FULL_ASSERT

/**
  * @brief  The assert_param macro is used for function's parameters check.
  * @param  expr: If expr is false, it calls assert_failed function which reports
  *         the name of the source file and the source line number of the call
  *         that failed. If expr is true, it returns no value.
  * @retval None
  */
#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
/* Exported functions ------------------------------------------------------- */
void assert_failed(uint8_t* file, uint32_t line);   // 聲明該函數
#else
#define assert_param(expr) ((void)0)                // 把assert_param(expr)定義爲空
#endif /* USE_FULL_ASSERT */

        如果定義USE_FULL_ASSERT,就把 assert_param(expr) 定義爲:  ((expr) ?  (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))  並申明一下assert_failed這個函數。沒定義USE_FULL_ASSERT時即把assert_param(expr)定義爲。 __FILE__和__LINE__是IAR定義的宏,指的是當前的編譯的文件名行數。     

         整個宏作用爲: 如果expr爲真,則什麼也不返回,如果expr爲假,則調用assert_failed()這個出錯程序。

        (條件) ? (條件成立執行部分) :(條件不成立執行部分)

例如:  a=( x>y ? x:y );       // 當x>y爲真時,a=x,當x>y爲假(即y>x)時,a=y。

注意: assert_failed()函數一般在代碼調試時使用,先將頭文件stm32f0xx_conf.h裏面的宏定義/* #define USE_FULL_ASSERT    1 */ 註釋去掉,可以幫助開發者檢查輸入參數無效的錯誤,但由於assert_failed()函數會影響代碼執行效率,在程序release時,需要屏蔽掉,將宏定義USE_FULL_ASSERT註釋即可。

舉例說明:

  assert_param(IS_USART_ALL_PERIPH(USARTx));  

     這句代碼用於檢查參數USARTx是否有效,其中IS_USART_ALL_PERIPH(USARTx)是一個宏定義,如下:

#define IS_USART_ALL_PERIPH(PERIPH) (((PERIPH) == USART1) || \
                                     ((PERIPH) == USART2) || \
                                     ((PERIPH) == USART3) || \
                                     ((PERIPH) == UART4) || \
                                     ((PERIPH) == UART5))

        宏定義的功能是參數USARTx是USART1~USART8其中的一個,表示參數USARTx有效,不返回,否則返回assert_failed函數定義顯示的內容。

       assert_failed函數可以從官方文件的模板中main.c中可以找到

#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 %d\r\n", file, line) */

    /* Infinite loop */
    while (1)
    {

    }
}

        裏面英文註釋也說明了怎麼應用,通過輸入參數來確定位置,最簡單的方法就是串口打印了,這個函數的主要思想是在輸入參數有問題的時候,但是有編譯不出來,它可以幫你檢查參數的有效性。 結果是輸出到串口,用串口調試助手可以看到輸出結果。注意,編譯器Build Output欄是不會報錯的。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章