STM32 中的 assert_param 函数

发布者:SparklingDreams最新更新时间:2016-06-13 来源: eefocus关键字:STM32  assert_param  函数 手机看文章 扫描二维码
随时随地手机看文章
我们在学STM32的时候函数assert_param出现的几率非常大,上网搜索一下,网上一般解释断言机制,做为程序开发调试阶段时使用。下面我就谈一下我对这些应用的看法,学习东西抱着知其然也要知其所以然。

4 断言机制函数assert_param
我们在分析库函数的时候,几乎每一个函数的原型有这个函数assert_param();下面以assert_param(IS_GPIO_ALL_PERIPH(GPIOx));为例说一下我的理解,函数的参数IS_GPIO_ALL_PERIPH(GPIOx),我们可以寻找到原型
#define IS_GPIO_ALL_PERIPH(PERIPH) (((*(uint32_t*)&(PERIPH)) == GPIOA_BASE)|| \
((*(uint32_t*)&(PERIPH)) == GPIOB_BASE) || \
((*(uint32_t*)&(PERIPH)) == GPIOC_BASE) || \
((*(uint32_t*)&(PERIPH)) == GPIOD_BASE) || \
((*(uint32_t*)&(PERIPH)) == GPIOE_BASE) || \
((*(uint32_t*)&(PERIPH)) == GPIOF_BASE) || \
((*(uint32_t*)&(PERIPH)) == GPIOG_BASE))
这个宏定义的作用就是检查参数PERIPH,判断参数PERIPH是否为GPIOX(A...G)基址中的一个,只要有一个为真则其值为真,否则为假,不用多说,这是C语言中基本的逻辑运算。当然这个库函数也用的很有意思,看:首先对PERIPH进行取址,也就是求地址,&PERIPH,然后对这个地址强制转化为32位的指针,即前面加(uint32_t *),然后通过*进行访问这个地址(指针)中的内容。不多说了,看几遍就能明白。
下面我们再回到assert_param这个函数,这个函数是哪里的呢?在stm32f10x_conf.h寻找到原型如下:
#ifdef USE_FULL_ASSERT

#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t*)__FILE__, __LINE__))
void assert_failed(uint8_t* file, uint32_t line);
#else
#define assert_param(expr) ((void)0)
#endif 
这是一个预编译文件,若是定义了USE_FULL_ASSERT这个文件,则执行后面的文件,我们在程序中一般都没什么定义,即执行后面这个语句((void)0),这个语句不用多想,没有定义USE_FULL_ASSERT就是什么也不执行。说的明白点,对上面的那个语句IS_GPIO_ALL_PERIPH(GPIOx)不执行任何操作。
若是定义了USE_FULL_ASSERT它,我们调用这个函数assert_param时,及对参数IS_GPIO_ALL_PERIPH(GPIOx)的正确性进行检查,通过一个C语言中的双目运算符来判断,若是返回1,执行语句(void)0,跟上面一样,若是返回0,则执行后面的函数assert_failed((uint8_t *)__FILE__,__LINE__),函数的作用在库函数中有解释,用来指示出错的行数和文件。注意:__FILE__,__LINE__是标准库函数中的宏定义!切记
void assert_failed(uint8_t* file, uint32_t line);刚开始没看明白为什么加在这里,仔细一想是在头文件的函数声明。至于函数实体呢?我们从官方文件的模板中main.c中可以找到。如下:
void assert_failed(u8* file, u32 line) 
{ /* User can add his own implementation to report the file name and linenumber, 
ex: printf("Wrong parameters value: file %s on line %d\r\n", file,line) */ 
/* Infinite loop */ 
while (1) { } 
} 英文注释也说明了怎么应用,通过输入参数来确定位置,最简单的方法就是串口打印了,这个函数的主要思想是在输入参数有问题的时候,但是有编译不出来,它可以帮你检查参数的有效性,好处不必多言,自己领悟就行。
继续说明如下: assert_param是怎样包含进去的呢?我们在stm32f10x_conf.h这个头文件中定义的函数声明还是宏定义,怎么在其它文件中都能应用呢?也很多网上朋友在刚开始学习的时候都遇到编译不过去的问题出现,最后通过在文件中添加USE_STDPERIPH_DRIVER来解决的:STM32 中的 assert_param 函数

 

我们可以在整个工程中进行搜索USE_STDPERIPH_DRIVER,通过头文件可以看出,是使用标准外设文件。在stm32f10x.h文件中我们可以搜索到如下情况:
#if !defined USE_STDPERIPH_DRIVER
/
* @brief Comment the line below if you will not use the peripherals drivers.
In this case, these drivers will not be included and the application code will 
be based on direct access to peripherals registers 
*/
#define USE_STDPERIPH_DRIVER
#endif

#ifdef USE_STDPERIPH_DRIVER
#include "stm32f10x_conf.h"
#endif
可以很容易看出来,我们不在那里添加,这个头文件中也给我们设置了开关,只要把第一个的注释去掉,就不用在配置中添加USE_STDPERIPH_DRIVER了,在第二个文件中我们可以知道怎样包含这个控制开关文件了,。我们也明白为什么我们在写程序的时候只要包含stm32f10x.h就能很容易的包含所有的文件文件了吧,我们只要在stm32f10x_conf.h配置一下就能包含所需要的库文件了。
通过以上可以看出,通过头文件的相互包含,来控制外设以及调试文件的调用,这样我们理清思路,理解起来就好多了。当然在学习中可能有些C语言问题还没有理解透彻,多上网搜一下,或者多看书,很快就搞明白的。

 

 

PS 2:

       

STM32中assert_param的使用
在STM32的固件库和提供的例程中,到处都可以见到assert_param()的使用。如果打开任何一个例程中的stm32f10x_conf.h文件,就可以看到实际上assert_param是一个宏定义;
在固件库中,它的作用就是检测传递给函数的参数是否是有效的参数。
所谓有效的参数是指满足规定范围的参数,比如某个参数的取值范围只能是小于3的正整数,如果给出的参数大于3,
则这个assert_param()可以在运行的程序调用到这个函数时报告错误,使程序员可以及时发现错误,而不必等到程序运行结果的错误而大费周折。

 

这是一种常见的软件技术,可以在调试阶段帮助程序员快速地排除那些明显的错误。

它确实在程序的运行上牺牲了效率(但只是在调试阶段),但在项目的开发上却帮助你提高了效率。

当你的项目开发成功,使用release模式编译之后,或在stm32f10x_conf.h文件中注释掉对USE_FULL_ASSERT的宏定义,所有的assert_param()检验都消失了,不会影响最终程序的运行效率。

#define assert_param(expr) ((expr) ? (void)0 : assert_failed((u8 *)__FILE__, __LINE__))
。。。

assert_param(IS_ADC_ALL_PERIPH(ADCx));
。。。

在执行assert_param()的检验时,如果发现参数出错,它会调用函数assert_failed()向程序员报告错误,在任何一个例程中的main.c中都有这个函数的模板,如下:

void assert_failed(uint8_t* file, uint32_t line)
{


while (1)
{}
}

你可以按照自己使用的环境需求,添加适当的语句输出错误的信息提示,或修改这个函数做出适当的错误处理。

1、STM32F10xD.LIB是DEBUG模式的库库文件。
2、STM32F10xR.LIB是Release模式的库库文件。
3、要选择DEBUG和RELEASE模式,需要修改stm32f10x_conf.h的内容。
    #define DEBUG 表示DEBUG模式,把该语句注释掉,则为RELEASE模式。
4、要选择DEBUG和RELEASE模式,也可以在Options,C/C++,Define里填入DEBUG的预定义。
    这样,就不需要修改stm32f10x_conf.h的内容。
5、如果把库加入项目,则不需要将ST的库源文件加入项目,比较方便。
    但是,库的选择要和DEBUG预定义对应

关键字:STM32  assert_param  函数 引用地址:STM32 中的 assert_param 函数

上一篇:位带操作在stm32中的C语言实现
下一篇:关于STM32中CAN1_RX0_IRQn和CAN1_RX1_IRQn的使用

推荐阅读最新更新时间:2024-03-16 14:57

ST-LINK V2 无法下载程序相关问题
1.两种STLINK 2.针对第一款ST-LINK connection error 和 No ST-LINK connected 其实并没有那么多的麻烦 只需要检查这几点 检查连线是否正确 检查驱动是否安装 更新下ST-LINK固件版本 不要使用拓展坞(分线器) 开发板一定要先独立供电后,再将ST-LINK插到电脑端 3.针对第二款ST-LINK相关问题 正常现象 2.不正常现象 这种情况建议换台电脑试一下,指示灯不亮的情况下很大可能ST-LINK已损坏,一直闪烁时估计是内部电路出现了问题。 大部分情况下,损坏的原因是ST-LINK单独长时间供电导致的,要避免这种情况的发生。 4.安装驱动
[单片机]
ST-LINK V2 无法下载程序相关问题
函数多一个参数导致指针内容发送变化(未知异常)
开发环境 单片机:PIC18F45K80 IDE: MPLAB X IDE 未知异常 char * str 与 char str 差异导致? //输出正常 int strcmp_new(unsigned char *src) { putch(*(src)); putch(*(src+1)); putch(*(src+2)); putch(*(src+3)); } char arr = ; char* rxdata=arr; strcmp_new(rxdata); //输出正常 31323334 strcmp_new(arr); //输出正常 31323334
[单片机]
stm32基础实验1
一、GPIO基础 4种输入模式: 浮空、上拉、下拉、模拟输入 4种输出模式: 开漏输出 开漏复用功能 推挽式输出 推挽式复用功能 3种最大输出速度:2MHZ,10MHz,50MHz 其中 推挽输出:可以输出强高低电平,连接数字器件 开漏输出:只可以输出强低电平,高电平得靠外部电阻拉高。输出端相当于三极管的集电极. 要得到高电平状态需要上拉电阻才行. 适合于做电流型的驱动,其吸收电流的能力相对强(一般20ma以内) 二、 跑马灯code GPIO输出:推挽输出 实现步骤: 1)使能IO口时钟。调用函数RCC_APB2PeriphColckCmd(); 不同的IO组,调用的时钟
[单片机]
<font color='red'>stm32</font>基础实验1
STM32定时器编码器模式计算减速电机AB相脉冲个数
STM32定时器编码器模式计算减速电机AB相脉冲个数,通过 AB相脉冲的上升沿和下降沿触发,然后计数器加一,那么如果检测到一个周期,有AB两相,两个上升沿两个下降沿的话,计数器就会四个 加一 。 #ifndef __TIMER_H #define __TIMER_H #include sys.h void TIM3_Int_Init(u16 arr,u16 psc); void TIM8_Encoder_Init(u16 arr,u16 psc) ; void Frequent(void) ; #endif #include timer.h #include led.h #include delay.h #includ
[单片机]
<font color='red'>STM32</font>定时器编码器模式计算减速电机AB相脉冲个数
STM32使用过程中的踩坑记录
1. 中断函数不要随意使用prinf()函数 记调试步进电机加速减速过程的一次大坑。 2. 使用HAL库的时候不要在中断中使用HAL_Delay()函数 HAL库的HAL_Delay()函数是通过Systick定时器的1ms中断实现的,一般情况下Systick定时器的优先级设置为最低,因此在更高优先级的中断触发后导致HAL_Delay()函数uwtick值无法更新,因此程序会卡死在HAL_Delay()函数中。 3.注意STM32库在配置串口字长时是包含校验位的字长,而一般上位机配置的串口字长是不包含校验位的。 这点在配置使用校验时是非常重要的,如果配置出错会导致通讯不正常。 4.使用不同的开发板的时候一定要注意不同板
[单片机]
<font color='red'>STM32</font>使用过程中的踩坑记录
STM32的DMA基本原理及实现过程
1、什么是DMA DMA全称是Direct Memory Access,即是直接存储器访问。 DMA 传输方式无需 CPU 直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为 RAM 与 I/O 设备开辟一条直接传送数据的通路,能使CPU的效率大为提高。 2、DMA特性 ● STM32F1有12个独立的可配置的通道(请求):DMA1有7个通道,DMA2有5个通道 ● 每个通道都直接连接专用的硬件DMA请求,每个通道都同样支持软件触发。可通过软件来配置。 ● 在同一个DMA模块上,多个请求间的优先权可以通过软件编程设置(共有四级:很高、高、 中等和低),优先权设置相等时由硬件决定(请求0优先于请
[单片机]
<font color='red'>STM32</font>的DMA基本原理及实现过程
STM32之USART配置
//USART void UART2_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; USART_ClockInitTypeDef USART_ClockInitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_5
[单片机]
ST 最新STM32 Primer开发工具可玩Maze和Breakout
完整、独立、预编程的评估工具套件,既有充满趣味性的功能介绍,又有严肃的开发工具,可以链接到在线开发社区 中国,2007年10月15日 — 意法半导体(纽约证券交易所代码:STM)今天推出了一套价格低廉的开发工具,这款代号为STM32 Primer开发工具是一套完整的学习与娱乐相结合的趣味性应用开发工具,用于ST的STM32系列基于具有突破性的ARM Cortex-M3内核的闪存微控制器。这套工具包含一个创新的用户界面、多个游戏和向新用户介绍该系列产品的产品入门功能,以及用于高级开发和编程的Raisonance软件工具。 STM32 Primer是一个手持评估开发工具,力图通过简单和有趣的介绍,让用户了解STM32的强大功能。紧
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved