assert_param函數詳解

一、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

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
HMNM的頭像HMNM
上一篇 2024-10-27 23:52
下一篇 2024-10-27 23:52

相關推薦

  • Python中引入上一級目錄中函數

    Python中經常需要調用其他文件夾中的模塊或函數,其中一個常見的操作是引入上一級目錄中的函數。在此,我們將從多個角度詳細解釋如何在Python中引入上一級目錄的函數。 一、加入環…

    編程 2025-04-29
  • Python中capitalize函數的使用

    在Python的字符串操作中,capitalize函數常常被用到,這個函數可以使字符串中的第一個單詞首字母大寫,其餘字母小寫。在本文中,我們將從以下幾個方面對capitalize函…

    編程 2025-04-29
  • Python中set函數的作用

    Python中set函數是一個有用的數據類型,可以被用於許多編程場景中。在這篇文章中,我們將學習Python中set函數的多個方面,從而深入了解這個函數在Python中的用途。 一…

    編程 2025-04-29
  • 三角函數用英語怎麼說

    三角函數,即三角比函數,是指在一個銳角三角形中某一角的對邊、鄰邊之比。在數學中,三角函數包括正弦、餘弦、正切等,它們在數學、物理、工程和計算機等領域都得到了廣泛的應用。 一、正弦函…

    編程 2025-04-29
  • 單片機打印函數

    單片機打印是指通過串口或並口將一些數據打印到終端設備上。在單片機應用中,打印非常重要。正確的打印數據可以讓我們知道單片機運行的狀態,方便我們進行調試;錯誤的打印數據可以幫助我們快速…

    編程 2025-04-29
  • Python3定義函數參數類型

    Python是一門動態類型語言,不需要在定義變量時顯示的指定變量類型,但是Python3中提供了函數參數類型的聲明功能,在函數定義時明確定義參數類型。在函數的形參後面加上冒號(:)…

    編程 2025-04-29
  • Python定義函數判斷奇偶數

    本文將從多個方面詳細闡述Python定義函數判斷奇偶數的方法,並提供完整的代碼示例。 一、初步了解Python函數 在介紹Python如何定義函數判斷奇偶數之前,我們先來了解一下P…

    編程 2025-04-29
  • Python實現計算階乘的函數

    本文將介紹如何使用Python定義函數fact(n),計算n的階乘。 一、什麼是階乘 階乘指從1乘到指定數之間所有整數的乘積。如:5! = 5 * 4 * 3 * 2 * 1 = …

    編程 2025-04-29
  • Python函數名稱相同參數不同:多態

    Python是一門面向對象的編程語言,它強烈支持多態性 一、什麼是多態多態是面向對象三大特性中的一種,它指的是:相同的函數名稱可以有不同的實現方式。也就是說,不同的對象調用同名方法…

    編程 2025-04-29
  • 分段函數Python

    本文將從以下幾個方面詳細闡述Python中的分段函數,包括函數基本定義、調用示例、圖像繪製、函數優化和應用實例。 一、函數基本定義 分段函數又稱為條件函數,指一條直線段或曲線段,由…

    編程 2025-04-29

發表回復

登錄後才能評論