管理员
最后登录1970-1-1
在线时间 小时
注册时间2013-5-3
|
不想看原理可直接在帖子尾部下载工程代码。
以下为说明:
在stm32固件库里有个 断言检测 assert_param功能,就是在库函数开头里常见的对输入参数检测,如下GPIO_Init库函数的源 代码(stm32f4xx_gpio.c):
- void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
- {
- uint32_t pinpos = 0x00, pos = 0x00 , currentpin = 0x00;
- /* Check the parameters */
- assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
- assert_param(IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin));
- assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode));
- assert_param(IS_GPIO_PUPD(GPIO_InitStruct->GPIO_PuPd));
复制代码 这个assert_param是如何实现参数检测呢?
可以看到这个assert_param输入参数为一些 IS_xxxxx 开头的宏,我们可以在库函数的头文件找到定义,
如下代码(stm32f4xx_gpio.h):
- /** @defgroup GPIO_pins_define
- * @{
- */
- #define GPIO_Pin_0 ((uint16_t)0x0001) /* Pin 0 selected */
- #define GPIO_Pin_1 ((uint16_t)0x0002) /* Pin 1 selected */
- #define GPIO_Pin_2 ((uint16_t)0x0004) /* Pin 2 selected */
- #define GPIO_Pin_3 ((uint16_t)0x0008) /* Pin 3 selected */
- #define GPIO_Pin_4 ((uint16_t)0x0010) /* Pin 4 selected */
- #define GPIO_Pin_5 ((uint16_t)0x0020) /* Pin 5 selected */
- #define GPIO_Pin_6 ((uint16_t)0x0040) /* Pin 6 selected */
- #define GPIO_Pin_7 ((uint16_t)0x0080) /* Pin 7 selected */
- #define GPIO_Pin_8 ((uint16_t)0x0100) /* Pin 8 selected */
- #define GPIO_Pin_9 ((uint16_t)0x0200) /* Pin 9 selected */
- #define GPIO_Pin_10 ((uint16_t)0x0400) /* Pin 10 selected */
- #define GPIO_Pin_11 ((uint16_t)0x0800) /* Pin 11 selected */
- #define GPIO_Pin_12 ((uint16_t)0x1000) /* Pin 12 selected */
- #define GPIO_Pin_13 ((uint16_t)0x2000) /* Pin 13 selected */
- #define GPIO_Pin_14 ((uint16_t)0x4000) /* Pin 14 selected */
- #define GPIO_Pin_15 ((uint16_t)0x8000) /* Pin 15 selected */
- #define GPIO_Pin_All ((uint16_t)0xFFFF) /* All pins selected */
- #define GPIO_PIN_MASK ((uint32_t)0x0000FFFF) /* PIN mask for assert test */
- #define IS_GPIO_PIN(PIN) (((PIN) & GPIO_PIN_MASK ) != (uint32_t)0x00)
复制代码 这代码的最后一行即 IS_GPIO_PIN是一个用来判断输入参数是否合法的条件,
例如在这个检测中,IS_GPIO_PIN(0x00)则返回 假 ,
再把IS_GPIO_PIN(0x00) 为假的结果作为参数调用assert_param,即GPIO_Inii库函数的开头部分,
我们查看assert_param的定义,看看会是什么样的结果(stm32f4xx_conf.h):
- /* 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)
- #endif /* USE_FULL_ASSERT */
复制代码 这个assert_param函数分两种情况,
1.当没有定义宏USE_FULL_ASSERT的时候,assert_param为空函数,也就是断言参数检测功能没有作用,什么事都没干
2.当定义了宏USE_FULL_ASSERT的时候,assert_param是一个宏,若输入参数为真时什么也不做,若参数为假时调用assert_failed函数,
而这个assert_failed函数在下面只有一个声明,需要我们去实现,例如我们可以定义这个函数printf信息到串口调试助手,或者点亮一个LED灯提示。
下面给出使用这个断言功能的工程代码,工程代码在帖子的尾部,适用于F429,F1原理类似,可以自己参考来改。
工程的思想:
1.使能断言检测,当输入参数错误触发断言时点亮红色的LED灯。
在stm32f4xx_conf.h使能断言,加入宏USE_FULL_ASSERT 并把assert_failed函数声明改成外部声明,我们将在bsp_led.c文件定义该函数:
- #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())
- /* Exported functions ------------------------------------------------------- */
- extern void assert_failed(void);
- #else
- #define assert_param(expr) ((void)0)
- #endif /* USE_FULL_ASSERT */
复制代码
在bsp_led.c文件定义 assert_faild函数,直接点亮红灯:- void assert_failed()
- {
- LED1_ON;
- }
复制代码
2.先初始化好红色LED灯,并默认为关闭状态
- /**
- * @brief 初始化控制LED的IO
- * @param 无
- * @retval 无
- */
- void LED_GPIO_Config(void)
- {
- /*定义一个GPIO_InitTypeDef类型的结构体*/
- GPIO_InitTypeDef GPIO_InitStructure;
- /*开启LED相关的GPIO外设时钟*/
- RCC_AHB1PeriphClockCmd ( LED1_GPIO_CLK|
- LED2_GPIO_CLK|
- LED3_GPIO_CLK, ENABLE);
- /*选择要控制的GPIO引脚*/
- GPIO_InitStructure.GPIO_Pin = LED1_PIN;
- /*设置引脚模式为输出模式*/
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
-
- /*设置引脚的输出类型为推挽输出*/
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
-
- /*设置引脚为上拉模式*/
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
- /*设置引脚速率为2MHz */
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
- /*调用库函数,使用上面配置的GPIO_InitStructure初始化GPIO*/
- GPIO_Init(LED1_GPIO_PORT, &GPIO_InitStructure);
-
-
- /*关闭RGB灯*/
- LED1_OFF;
-
- //把LED 红灯确认关闭,再初始化LED2,LED2使用错误的参数,
- //初始化LED2时会引起assert fail,触发调用,点亮红灯
-
-
- /*选择要控制的GPIO引脚*/
- GPIO_InitStructure.GPIO_Pin = LED2_PIN;
- GPIO_Init(LED2_GPIO_PORT, &GPIO_InitStructure);
-
- /*选择要控制的GPIO引脚*/
- GPIO_InitStructure.GPIO_Pin = LED3_PIN;
- GPIO_Init(LED3_GPIO_PORT, &GPIO_InitStructure);
-
-
- }
复制代码
3.再次调用GPIO_Init函数时,给它输入一个错误的引脚参数,如0x00,
修改bsp_led.h文件,定义一个GPIO_Pin_16 宏,宏值为0x00,并把原来绿灯的引脚改成GPIO_Pin_16 - #define GPIO_Pin_16 0x0000
- //G 绿色灯
- #define LED2_PIN GPIO_Pin_16
- #define LED2_GPIO_PORT GPIOH
- #define LED2_GPIO_CLK RCC_AHB1Periph_GPIOH
复制代码
4.在main函数调用LED_GPIO_Config(),该函数初始化完红灯后,红灯处于关闭状态,再初始化绿灯时,由于断言检测触发assert_faild导致红灯亮
工程代码:
asserTemplate.zip
(767.94 KB, 下载次数: 32)
|
|