http://www.360doc.com/content/12/0904/23/348183_234335793.shtml
STM32的函数ssert_param(IS_GPIO_ALL_PERIPH(GPIOx));
             
 
我们在学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 line number, 
   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来解决的:

我们可以在整个工程中进行搜索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语言问题还没有理解透彻,多上网搜一下,或者多看书,很快就搞明白的。

STM32的函数ssert_param(IS_GPIO_ALL_PERIPH(GPIOx));相关推荐

  1. stm32系列单片机编程中的IS_GPIO_ALL_PERIPH(GPIOx)的解释说明

    转载 链接 https://wenku.baidu.com/view/e473ed03677d27284b73f242336c1eb91b373372.html?_wkts_=167756636111 ...

  2. STM32延时函数的四种方法:普通延时(2种)、SysTick 定时器延时(2种)

    STM32延时函数的三种方法:普通延时.SysTick 定时器延时(1.中断方式:2.非中断方式) 单片机编程过程中经常用到延时函数,最常用的莫过于微秒级延时delay_us( )和毫秒级delay_ ...

  3. 6.STM32外设函数分类

    STM32外设函数分类如下:

  4. STM32延时函数的四种方法

    目录 1.普通延时 2.定时器中断 3.查询定时器 4.汇编指令 单片机编程过程中经常用到延时函数,最常用的莫过于微秒级延时delay_us()和毫秒级delay_ms().本文基于STM32F207 ...

  5. 基于STM32的函数信号发生器设计(下:软件设计)

    转载请注明出处:http://blog.csdn.net/sctu_vroy/article/details/46279817 下篇将介绍整个STM32函数信号发生器系统软件设计部分,将着重介绍设计逻 ...

  6. 基于STM32的函数信号发生器设计(上:硬件设计)

    转载请注明出处:http://blog.csdn.net/sctu_vroy/article/details/45888277 大三初学STM32时做的点东西,现在拿出来和大家分享一下~ 这是一款基于 ...

  7. linux 信号发生器,用STM32实现函数信号发生器

    自己慢慢看,,,, [mw_shl_code=c,true]#ifndef __BSP_WAVEMAKER_H #define __BSP_WAVEMAKER_H #include "stm ...

  8. CubeMX STM32 常用函数HAL库

    初始化函数: HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); 读取输入电平函数: HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_3): 设置 ...

  9. STM32 f_getfree函数读取sd卡一直不返回的解决方法

    使用FatFs f_getfree函数当复位sd卡给的空闲时钟不够会卡住在这里: 解决方法:在原先的8个时钟下,再提供额外的8个时钟. 结果如下:f_getfree每次都能获取成功.

  10. STM32 SystemCoreClockUpdate()函数详解

    SystemCoreClockUpdate()作用:用来更新 SystemCoreClock 变量,在时钟配置完成之后,需要调用这个函数来更新 SystemCoreClock 变量: 默认情况下:Sy ...

最新文章

  1. Python忽略warning警告错误
  2. AAAI | 深度生成模型—NEVAE
  3. delphi SAP
  4. Notepadd++主题推荐
  5. Linux环境下虚拟环境virtualenv安装和使用(转)
  6. Runtime底层原理--Runtime简介、函数注释
  7. 减一天 日期函数_一文掌握excel中的日期函数
  8. hpm1216nfh驱动程序_惠普M1216nfh驱动下载
  9. 数据库索引介绍及使用
  10. 不让editText自动获取焦点
  11. 产业分析:东方甄选vs罗永浩直播间
  12. WPE1.3C的详细使用教程
  13. Tensorflow概念详解
  14. Inkscape制作logo
  15. 使用Maxima求解常微分方程~
  16. 油溶性CdSeTe/ZnS量子点(以CdSeTe为核心,ZnS为壳层)
  17. 解答2020国庆节建模竞赛题(第2赛季第18轮)
  18. Ear Clipping算法简介
  19. 从Flash到MP4,爱奇艺奇秀直播礼物特效精进之路
  20. 英文文本分词之工具NLTK

热门文章

  1. zabbix 清理历史数据
  2. 【Python】ID3算法的实现
  3. adb安装apk文件时的常见的错误及解决方法
  4. solidworks做运动学分析Motion(牛头刨床为例)机械原理课设(详细)
  5. win10系统问题记录(一):解决D/E盘根目录出现的msdia80.dll文件
  6. 2020年被“冰封”的猫眼、淘票票、大麦们,还能看见春天吗?
  7. java计算机毕业设计济南旅游网站源码+mysql数据库+系统+lw文档+部署
  8. Linux复制文件到某路径并重命名
  9. 第1节 中华人民共和国网络安全法
  10. 【Java面试】Java面试简历—轻松月薪过w(附赠最全简历模板)