在确定STM32各种库中的函数能用什么参数或者该参数对应结构体的成员能赋什么值时,经常会找该函数的定义,然后在定义中找到assert_param(),例如f4标准库中的NVIC_Init():
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)
{
uint8_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F;
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd));
assert_param(IS_NVIC_PREEMPTION_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority));
assert_param(IS_NVIC_SUB_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelSubPriority));
if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE)
{
/* Compute the Corresponding IRQ Priority --------------------------------*/
tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08;
tmppre = (0x4 - tmppriority);
tmpsub = tmpsub >> tmppriority;
tmppriority = NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre;
tmppriority |= (uint8_t)(NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub);
tmppriority = tmppriority << 0x04;
NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority;
/* Enable the Selected IRQ Channels --------------------------------------*/
NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
(uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
}
else
{
/* Disable the Selected IRQ Channels -------------------------------------*/
NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
(uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
}
}
查看这行代码assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd));中IS_FUNCTIONAL_STATE的定义时可以看到
#define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE))
其中DISABLE和ENABLE就是NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)参数结构体中成员NVIC_IRQChannelCmd可以赋的值
当我们查看assert_param的定义时,可以看到
#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)
#endif /* USE_FULL_ASSERT */
想要看懂这段代码要知道“#define 宏名(形参表) 字符串”的用法
在*@param expr后的内容解释了assert_param的作用,简单来讲就是如果启用断言(#ifdef USE_FULL_ASSERT)就看是否满足assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)FILE, LINE))满足就报错,还能交代出错的行
而IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd)在这里就是expr,它宏定义所对应的表达式是(((STATE) == DISABLE) || ((STATE) == ENABLE))这个表达式结合NVIC_IRQChannelCmd的值就能计算出expr,进而代到assert_param来决定是否报错了