一、assert_param是什麼
assert_param是STM32固件庫中的函數,用於檢查傳入的參數是否合法。該函數的原型為assert_param(),在代碼中使用時通常會被宏定義為以下形式:
#define assert_param(expr) ((void)0)
由此可見,如果表達式expr為真,則assert_param()函數不做任何操作,否則程序將進入死循環,表示傳入的參數不合法。
二、assert_param的作用
在程序開發過程中,我們經常需要在函數中檢查傳入的參數是否合法。例如,在初始化GPIO口之前,需要檢查GPIO口是否已經被使能,在設置ADC採樣率之前,需要檢查採樣率是否符合ADC的要求。這些參數的檢查需要花費大量的時間和精力,而assert_param函數正是為了解決這個問題而存在的。
assert_param函數能夠大大簡化參數檢查的工作,同時能夠提高代碼的可讀性和可維護性。使用assert_param函數,可以避免程序在使用不合法的參數時崩潰,提高了程序的穩定性和安全性。
三、assert_param的使用
assert_param函數通常用於STM32的固件庫中,我們可以在我們的代碼中使用這個函數來檢查傳入的參數是否合法。assert_param函數通常有如下幾個步驟:
第一步,定義assert_param()函數:
#define assert_param(expr) ((void)0)
第二步,根據表達式,判斷參數是否合法:
if(expr) { // do nothing } else { assert_param_failed(file, line); }
第三步,當參數不合法時,調用assert_param_failed()函數:
void assert_param_failed(uint8_t *file, uint32_t line) { // 程序運行到這裡表示執行了不合法的操作,需要進行相應的處理 while (1) { // 程序進入死循環 } }
在使用assert_param函數時,需要注意以下幾點:
1、assert_param函數僅用於檢查傳入的參數是否合法,不作為程序中斷或調試的依據;
2、在使用assert_param函數時,需要確保被檢查的參數已經被正確初始化,否則可能會出現錯誤的判斷結果;
3、在使用assert_param函數時,需要確保被檢查的參數不會修改被編譯器優化掉,否則可能會導致assert_param函數失效。
四、assert_param的示例代碼
下面是一個使用assert_param函數的示例程序,該程序功能是通過LM35傳感器採集環境溫度,並將溫度值通過串口輸出:
#include "stm32f10x.h" #include "stdio.h" #define assert_param(expr) ((void)0) USART_InitTypeDef USART_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; ADC_InitTypeDef ADC_InitStructure; void delay_ms(unsigned long n) { unsigned long i; for(i=0;i<n;i++); } void USARTx_SendChar(USART_TypeDef *USARTx, char Data) { while (USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET); USART_SendData(USARTx, Data); } void USARTx_SendString(USART_TypeDef *USARTx, char *str) { while(*str != '\0') { USARTx_SendChar(USARTx, *str); str++; } } int main(void) { float temp = 0.0; char buffer[50] = {0}; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = 115200; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No ; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Tx; USART_Init(USART1, &USART_InitStructure); USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); USART_Cmd(USART1, ENABLE); ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel = 1; ADC_Init(ADC1, &ADC_InitStructure); ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5); ADC_Cmd(ADC1, ENABLE); delay_ms(10); ADC_SoftwareStartConvCmd(ADC1, ENABLE); while (1) { while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); temp = (float)ADC_GetConversionValue(ADC1)*3.3/4096*1000/10; sprintf(buffer, "Temperature = %.2f\r\n", temp); USARTx_SendString(USART1, buffer); delay_ms(1000); } }
在上述代碼中,我們使用assert_param函數來檢查串口和ADC的初始化參數是否合法:
USART_Init(USART1, &USART_InitStructure); ADC_Init(ADC1, &ADC_InitStructure);
這裡需要注意的是,在使用assert_param函數時,需要先定義一個常量,以便在assert_param_failed()函數中使用:
#define FILE_NAME __FILE__
assert_param_failed()函數的代碼如下:
void assert_param_failed(uint8_t *file, uint32_t line) { char buffer[50] = {0}; sprintf(buffer, "assert_param_failed - file %s, line %d\r\n", file, line); USARTx_SendString(USART1, buffer); while (1) { // 程序進入死循環 } }
在上述代碼中,我們使用串口將錯誤信息輸出,以方便我們進行調試和錯誤定位。
原創文章,作者:HMNM,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/145712.html