<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > STM32 中的 assert_param 函數

STM32 中的 assert_param 函數

作者: 時(shí)間:2016-11-19 來(lái)源:網(wǎng)絡(luò ) 收藏
我們在學(xué)STM32的時(shí)候函數assert_param出現的幾率非常大,上網(wǎng)搜索一下,網(wǎng)上一般解釋斷言機制,做為程序開(kāi)發(fā)調試階段時(shí)使用。下面我就談一下我對這些應用的看法,學(xué)習東西抱著(zhù)知其然也要知其所以然。

4 斷言機制函數assert_param
我們在分析庫函數的時(shí)候,幾乎每一個(gè)函數的原型有這個(gè)函數assert_param();下面以assert_param(IS_GPIO_ALL_PERIPH(GPIOx));為例說(shuō)一下我的理解,函數的參數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))
這個(gè)宏定義的作用就是檢查參數PERIPH,判斷參數PERIPH是否為GPIOX(A...G)基址中的一個(gè),只要有一個(gè)為真則其值為真,否則為假,不用多說(shuō),這是C語(yǔ)言中基本的邏輯運算。當然這個(gè)庫函數也用的很有意思,看:首先對PERIPH進(jìn)行取址,也就是求地址,&PERIPH,然后對這個(gè)地址強制轉化為32位的指針,即前面加(uint32_t *),然后通過(guò)*進(jìn)行訪(fǎng)問(wèn)這個(gè)地址(指針)中的內容。不多說(shuō)了,看幾遍就能明白。
下面我們再回到assert_param這個(gè)函數,這個(gè)函數是哪里的呢?在stm32f10x_conf.h尋找到原型如下:
#ifdef USE_FULL_ASSERT

本文引用地址:http://dyxdggzs.com/article/201611/318095.htm

#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
這是一個(gè)預編譯文件,若是定義了USE_FULL_ASSERT這個(gè)文件,則執行后面的文件,我們在程序中一般都沒(méi)什么定義,即執行后面這個(gè)語(yǔ)句((void)0),這個(gè)語(yǔ)句不用多想,沒(méi)有定義USE_FULL_ASSERT就是什么也不執行。說(shuō)的明白點(diǎn),對上面的那個(gè)語(yǔ)句IS_GPIO_ALL_PERIPH(GPIOx)不執行任何操作。
若是定義了USE_FULL_ASSERT它,我們調用這個(gè)函數assert_param時(shí),及對參數IS_GPIO_ALL_PERIPH(GPIOx)的正確性進(jìn)行檢查,通過(guò)一個(gè)C語(yǔ)言中的雙目運算符來(lái)判斷,若是返回1,執行語(yǔ)句(void)0,跟上面一樣,若是返回0,則執行后面的函數assert_failed((uint8_t *)__FILE__,__LINE__),函數的作用在庫函數中有解釋?zhuān)脕?lái)指示出錯的行數和文件。注意:__FILE__,__LINE__是標準庫函數中的宏定義!切記
void assert_failed(uint8_t* file, uint32_t line);剛開(kāi)始沒(méi)看明白為什么加在這里,仔細一想是在頭文件的函數聲明。至于函數實(shí)體呢?我們從官方文件的模板中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 %drn", file,line) */
/* Infinite loop */
while (1) { }
} 英文注釋也說(shuō)明了怎么應用,通過(guò)輸入參數來(lái)確定位置,最簡(jiǎn)單的方法就是串口打印了,這個(gè)函數的主要思想是在輸入參數有問(wèn)題的時(shí)候,但是有編譯不出來(lái),它可以幫你檢查參數的有效性,好處不必多言,自己領(lǐng)悟就行。
繼續說(shuō)明如下: assert_param是怎樣包含進(jìn)去的呢?我們在stm32f10x_conf.h這個(gè)頭文件中定義的函數聲明還是宏定義,怎么在其它文件中都能應用呢?也很多網(wǎng)上朋友在剛開(kāi)始學(xué)習的時(shí)候都遇到編譯不過(guò)去的問(wèn)題出現,最后通過(guò)在文件中添加USE_STDPERIPH_DRIVER來(lái)解決的:

我們可以在整個(gè)工程中進(jìn)行搜索USE_STDPERIPH_DRIVER,通過(guò)頭文件可以看出,是使用標準外設文件。在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
可以很容易看出來(lái),我們不在那里添加,這個(gè)頭文件中也給我們設置了開(kāi)關(guān),只要把第一個(gè)的注釋去掉,就不用在配置中添加USE_STDPERIPH_DRIVER了,在第二個(gè)文件中我們可以知道怎樣包含這個(gè)控制開(kāi)關(guān)文件了,。我們也明白為什么我們在寫(xiě)程序的時(shí)候只要包含stm32f10x.h就能很容易的包含所有的文件文件了吧,我們只要在stm32f10x_conf.h配置一下就能包含所需要的庫文件了。
通過(guò)以上可以看出,通過(guò)頭文件的相互包含,來(lái)控制外設以及調試文件的調用,這樣我們理清思路,理解起來(lái)就好多了。當然在學(xué)習中可能有些C語(yǔ)言問(wèn)題還沒(méi)有理解透徹,多上網(wǎng)搜一下,或者多看書(shū),很快就搞明白的。

PS 2:

STM32中assert_param的使用
在STM32的固件庫和提供的例程中,到處都可以見(jiàn)到assert_param()的使用。如果打開(kāi)任何一個(gè)例程中的stm32f10x_conf.h文件,就可以看到實(shí)際上assert_param是一個(gè)宏定義;
在固件庫中,它的作用就是檢測傳遞給函數的參數是否是有效的參數。
所謂有效的參數是指滿(mǎn)足規定范圍的參數,比如某個(gè)參數的取值范圍只能是小于3的正整數,如果給出的參數大于3,
則這個(gè)assert_param()可以在運行的程序調用到這個(gè)函數時(shí)報告錯誤,使程序員可以及時(shí)發(fā)現錯誤,而不必等到程序運行結果的錯誤而大費周折。

這是一種常見(jiàn)的軟件技術(shù),可以在調試階段幫助程序員快速地排除那些明顯的錯誤。

它確實(shí)在程序的運行上犧牲了效率(但只是在調試階段),但在項目的開(kāi)發(fā)上卻幫助你提高了效率。

當你的項目開(kāi)發(fā)成功,使用release模式編譯之后,或在stm32f10x_conf.h文件中注釋掉對USE_FULL_ASSERT的宏定義,所有的assert_param()檢驗都消失了,不會(huì )影響最終程序的運行效率。

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

assert_param(IS_ADC_ALL_PERIPH(ADCx));
。。。

在執行assert_param()的檢驗時(shí),如果發(fā)現參數出錯,它會(huì )調用函數assert_failed()向程序員報告錯誤,在任何一個(gè)例程中的main.c中都有這個(gè)函數的模板,如下:

void assert_failed(uint8_t* file, uint32_t line)
{


while (1)
{}
}

你可以按照自己使用的環(huán)境需求,添加適當的語(yǔ)句輸出錯誤的信息提示,或修改這個(gè)函數做出適當的錯誤處理。

1、STM32F10xD.LIB是DEBUG模式的庫庫文件。
2、STM32F10xR.LIB是Release模式的庫庫文件。
3、要選擇DEBUG和RELEASE模式,需要修改stm32f10x_conf.h的內容。
#define DEBUG 表示DEBUG模式,把該語(yǔ)句注釋掉,則為RELEASE模式。
4、要選擇DEBUG和RELEASE模式,也可以在Options,C/C++,Define里填入DEBUG的預定義。
這樣,就不需要修改stm32f10x_conf.h的內容。
5、如果把庫加入項目,則不需要將ST的庫源文件加入項目,比較方便。
但是,庫的選擇要和DEBUG預定義對應



關(guān)鍵詞: STM32assert_param函

評論


技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>