• 单片机之从C语言基础到专家编程 - 4 C语言基础 - 4.11函数


    在单片机开发中,一般使用C语言进行编程,C语言提供了一种结构化的编程方法,能有效地管理和控制硬件资源。函数是C语言中的一个基本构建块,它允许开发者将程序分解成更小、更易于管理的部分。

    1 函数的基本概念
    1)定义

    函数是一段执行特定任务的代码块,它可以接受输入(称为参数),并可以返回一个结果。函数的主要目的是提高代码的可重用性和模块性。

    2)声明

    函数在使用前必须被声明。声明通常包括函数的返回类型、函数名和参数列表。这告诉编译器函数的存在,其具体实现可以在别处。

    和变量类似,一般在源文件中对函数进行定义,在头文件中对需要对外提供的函数进行声明,如某函数不需要对外提供,但又需要在其他函数中提前使用,请在源文件头部对函数进行声明。

    3)调用

    当需要执行函数中的代码时,会进行函数调用。调用函数时,需要按照声明时的参数列表提供相应的参数。

    4)参数

    函数可以有参数,这些参数为函数提供了执行操作所需的数据。参数在函数调用时指定,并在函数执行期间使用。为了编译器的兼容性,如果函数没有参数,也最好将参数类型设为void。

    5)返回类型

    函数可以有一个返回类型,指定了函数执行完成后返回给调用者的数据类型。如果函数不返回任何值,则其返回类型为void

    2 函数在单片机开发中的应用

    在STM32等单片机开发中,函数的使用非常广泛,例如:

    1)标准库函数

    STM32提供了一套标准库,里面提供了单片机底层硬件的访问和控制,如GPIO、FLASH、IIC、USART等,如在stm32f10x_gpio中,GPIO_SetBits用于将某GPIO口的引脚电平拉高(置1,输出高电平),GPIO_ResetBits用于将某GPIO口的引脚电平拉低(置0,输出低电平)。

    2)硬件抽象层(HAL)函数

    STM32提供了一套硬件抽象层库,这些库的函数简化了对底层硬件的访问和控制。例如,HAL_GPIO_TogglePin()函数用于切换GPIO引脚的状态。

    3)中断服务例程(ISR)

    中断服务例程是特殊的函数,用于响应硬件中断。例如,当外部设备(如按钮)生成中断信号时,相应的ISR会被执行,以处理该中断。

    4)用户定义函数

    开发者可以定义自己的函数来执行特定的任务,比如数据处理、通信协议的实现等。这些函数增加了代码的模块性和可读性。

    5)回调函数

    在某些异步操作中,可以使用回调函数来处理完成后的事件。例如,在完成异步串行通信后,可以通过回调函数来处理接收到的数据。

    3 函数的好处
    1)可重用性

    通过函数,可以将常用的代码封装起来,以便在多个地方重用,减少代码冗余。

    2)模块化

    函数允许开发者将复杂的程序分解成更小的、易于管理的单元,每个单元执行特定的任务。

    3)易于维护

    当程序逻辑需要更改或修复时,有了函数划分,开发者只需关注与问题相关的部分,而不必梳理整个程序代码。

    4 函数的语法结构

    返回类型 函数名(参数声明)

    {

    ​ 函数体;

    }

    返回类型:void、char、unsigned char、int、unsigned int、float、double、uint8_t、uint16_t、uint32_t等

    函数名:由英文字母、数字、下划线组成。函数名的起始位只能为字母或下划线

    参数声明:可以是多个参数或void

    函数体:由多个语句或代码段组成。

    5 函数的使用举例
    1)标准库函数的使用
    #include "stm32f10x.h"
    #include "stdbool.h"
    
    #define LED_DEBUG_PORT				GPIOA
    #define LED_DEBUG_PIN				GPIO_Pin_10
    
    void LED_DebugSetOn(void) 
    {
    	GPIO_SetBits(LED_DEBUG_PORT , LED_DEBUG_PIN);			// 打开
    }
    
    void LED_DebugSetOff(void) 
    {
    	GPIO_ResetBits(LED_DEBUG_PORT , LED_DEBUG_PIN);			// 关闭
    }
    
    void LED_DebugSet(bool value) 
    {
    	if(value == false)
    	{
    		GPIO_ResetBits(LED_DEBUG_PORT , LED_DEBUG_PIN);			// 关闭
    	}	
    	else
    	{
    		GPIO_SetBits(LED_DEBUG_PORT, LED_DEBUG_PIN);			// 点亮
    	}	
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    2)自定义函数的使用

    void DELAY_1us(void)
    {
    	uint32_t ticks;
    	
    	//MCU执行1us所走的时钟步数
    	ticks = (SystemCoreClock / 1000000);
    	//非精确延时等待
    	while (ticks--);
    }
    
    void DELAY_Nus(uint16_t nus)
    {
    	 while(nus--)
    	 {
    		  DELAY_1us();
    	 }
    }
    
    void DELAY_1ms(void)
    {
    	for (int i = 0;i < 1000; i++)
    	{
    		  DELAY_1us();
    	}
    }
     
    void DELAY_Nms(uint16_t nms)
    {
    	 while(nms--)
    	 {
    		  DELAY_1ms();
    	 }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
  • 相关阅读:
    华为云云耀云服务器L实例评测|云耀云服务器L实例部署Bolo开源个人博客
    left join时筛选条件对查询结果的
    【操作系统学习笔记】文件管理3.5
    学信息系统项目管理师第4版系列23_成本管理
    (208)Verilog HDL:时钟双沿触发器
    Git面试题整理(实操)
    一个霸占程序员休息时间的 APP
    linux x64 下的redis安装
    使用SSM为学校医务室开发一套管理系统
    Dubbo基于注解方式的配置
  • 原文地址:https://blog.csdn.net/fancyang/article/details/136791512