在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栏是不会报错的。