STM32学习进阶笔记:GPIO、TIM定时器与中断管理(第二天学习要点)


1. 总线相关讲解

(看不懂没事,这是个人理解,下面开始是正文)

首先这是 STM32 里面的总线,简单来说,总线关系如下:
总线 AHB 进行分支:

  • –> APB1(低速)
  • –> APB2(高速)
  • 并且每个时钟可以绑定 4 个通道,用于 PWM 输出。输出原理简单来讲,就是先将 GPIO 端口绑定好,再绑定好时钟,然后用 OC(后续会详细讲解)的方法对比输出 PWM。

    需要注意的是:

  • APB2 (1) :时钟 1(即 TIM1)走的线是 APB1;
  • APB1 (2, 3, 4) :时钟 2、3、4 走的线是 APB2(后续会详细讲到,这里先提及)。
  • 2. 每引脚状态设置(GPIO 设置)

    在 STM32 里,几乎每个功能都需要经过以下 4 个步骤才能使用:1. 定义结构体;2. 使能化;3. 设置;4. 绑定。

    2.1 定义结构体

    如果对其他功能的使能化感兴趣,可以查看它们对应的文档。

    这里我们要定义 GPIO(即每个引脚)的结构体。使用什么功能,就定义什么结构体。对于 GPIO 端口设置,定义结构体的方式如下:

    c

    GPIO_InitTypeDef + 你要使用的功能的结构体的名字(这里是对 GPIO 端口设置,结构体名称为 GPIO_InitStructure)
    

    实际定义代码为:

    c

    GPIO_InitTypeDef GPIO_InitStructure;
    
    2.2 使能化(RCC 总线)

    直白来讲,RCC 线是一条控制功能开启关闭的线。

    先讲讲 RCC 与前面的 AHB 数据传输总线的区别:RCC 的主要功能是控制时钟的状态,AHB 线主要用于传输数据。之所以需要 RCC,是因为想要一个引脚输出,必须先开启其时钟,否则无法使用。可以说时钟就像开关,便于管理。

    使能化可以简单理解为:默认状态是关闭的,若要驱动某个功能,就需要将其打开,这个操作就称为使能化。

    代码示例:

    c

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    

    对代码各部分的解释如下:

  • RCC:控制线;
  • APB2:走快速线(也可根据需求选择走慢线 APB1);
  • Periph:外设;
  • Clock:时钟;
  • Cmd:命令的意思。
  • 总结来说,就是在 RCC 总线上通过 APB2 快速线发送时钟命令。

    若大家感兴趣,可以查看相关资源。

    STM32嵌入式开发常用词汇词组及缩写汇总_嵌入式psp是什么意思-CSDN博客

    2.3 设置

    不同的功能定义设置不同,这里讲解的是 GPIO 引脚的设置(共需设置 3 项)。

    因为已经定义了结构体,只需为结构体对应的项赋值即可。若觉得麻烦,也可将其写成函数,虽然代码会长一些,但使用起来更方便。

    代码示例:

    c

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50Hz;
    

    格式为 GPIO_InitStructure.GPIO_ + 你要设置的值,每个项都必须设置,不能遗漏。

    下面详细讲解这三个设置项及可赋予的值:

    2.3.1 PIN(引脚)

    前面的使能化是针对整个 GPIOA 组,而这里要指定 GPIOA 里具体的引脚。除了单独指定引脚,还有两种多选引脚的方式:

  • 使用 “|” 的方式:例如 GPIO_Pin_2 | GPIO_Pin_3,可同时选择多个引脚。
  • 使用 “all” 的方式:如 GPIO_Pin_All,可选取前面使能的 GPIOA 所有引脚。
  • 2.3.2 mode(端口模式)
  • GPIO_Mode_Out_PP:直白来说就是输出,但只能输出高电平和低电平,不能输出 PWM。
  • GPIO_Mode_IN_FLOATING:这是正常不使用时的状态,即浮空状态。
  • GPIO_Mode_IPU:上拉模式,默认成高电平。
  • GPIO_AF_OUT:可用于输出 PWM(注:完整表述可能是 GPIO_Mode_AF_PP 等复用输出模式)。
  • 2.3.3 SPEED(频率)

    这里的 SPEED 指频率,不过代码中的 GPIO_Speed_50Hz 有误,通常是 GPIO_Speed_50MHz 。

    2.4 绑定

    代码示例:

    c

    GPIO_Init(GPIOA, &GPIO_InitStructure);
    

    即 ..._Init(你最开始使能化的那个 GPIO 组,&到这个你定义的结构体),简单来说,就是将对结构体的定义应用到该引脚组。

            case 1: GPIO_SetBits(gpio, pin);输出高电平
            case 0: GPIO_ResetBits;输出低电平

    3. 定时器(TIM)配置

    定时器配置主要分为定时器基本时基配置和输出比较(OC)配置两部分,以下为详细说明:

    3.1 定时器基本时基配置
    1. 定义结构体
      使用 TIM_TimeBaseInitTypeDef 类型定义结构体变量,用于存储定时器基本时基配置参数。

     

    c

    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    

     

    1. 使能定时器时钟
      需根据定时器所在的 APB 总线,使用 RCC_APBxPeriphClockCmd 函数使能对应时钟。例如,若定时器在 APB2 总线上,则:

     

    c

    RCC_APB2PeriphClockCmd(对应时钟, ENABLE);
    

     

    1. 设置基本时基参数

     

    c

    TIM_TimeBaseStructure.TIM_Period = period;
    TIM_TimeBaseStructure.TIM_Prescaler = prescaler; 
    TIM_TimeBaseStructure.TIM_ClockDivision = clockdivision;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;   
    

     

    各参数含义如下:

     

  • period:设置定时周期,如 999 ,用于设定定时器计数到该值时的周期长度。
  • prescaler:预分频器值,取值如 0 或 1 ,用于降低计数器的计数频率 。
  • clockdivision:时钟分频因子,可取值 TIM_CKD_DIV1TIM_CKD_DIV2TIM_CKD_DIV4 等,数值越高过滤效果越好,在编码器应用中一般不使用 。
  • countermode:计数方式,默认使用向上计数 TIM_CounterMode_Up ,也可选择向下计数 TIM_CounterMode_Down 。
  •  

    1. 绑定配置
      将配置好的结构体应用到对应的定时器,完成基本时基配置。

     

    c

    TIM_TimeBaseInit(定时器实例, &TIM_TimeBaseStructure);
    

     

    例如,若使用 TIM3 ,则为 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

    3.2 定时器输出比较(OC)配置
    1. 定义结构体
      使用 TIM_OCInitTypeDef 类型定义结构体变量,用于存储输出比较配置参数。

     

    c

    TIM_OCInitTypeDef TIM_OCInitStructure;
    

     

    1. 使能定时器时钟
      与基本时基配置相同,根据定时器所在总线使能时钟。

     

    c

    RCC_APB2PeriphClockCmd(对应时钟, ENABLE);
    

     

    1. 设置输出比较参数

     

    c

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = pulse;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    

     

    各参数含义如下:

     

  • TIM_OCMode:输出比较模式,如 TIM_OCMode_PWM1 ,用于产生 PWM 信号。
  • TIM_OutputState:输出使能状态,TIM_OutputState_Enable 表示使能输出。
  • TIM_Pulse:比较值,如 500 ,与定时周期 period 共同决定 PWM 信号的占空比 。
  • TIM_OCPolarity:输出极性,TIM_OCPolarity_High 表示当计数器值小于比较值时输出高电平。
  •  

    1. 绑定配置到定时器通道
      根据所需通道,将配置绑定到对应定时器实例的通道上。例如,将配置绑定到 TIM3 的通道 1:

     

    c

    TIM_OC1Init(TIM3, &TIM_OCInitStructure);
    

     

    一个定时器通常可以输出 4 个通道(OC1OC2OC3OC4),可分别进行配置。
    5. 使能定时器
    完成上述配置后,使用 TIM_Cmd 函数使能定时器,让其开始工作。

     

    c

    TIM_Cmd(绑定好的定时器实例, ENABLE);

    这里是定时器NVIC

        TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
        
        NVIC_InitTypeDef NVIC_InitStructure;
    	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;  
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
    1. TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);

    2. 这个函数调用是用于使能定时器 TIM3 的更新中断(TIM_IT_Update)。在 STM32 的定时器中,更新事件会在计数器溢出(向上计数模式下计数值达到自动重装载值)、下溢(向下计数模式下计数值减为 0)等情况下发生。通过调用 TIM_ITConfig 函数并传入 ENABLE 参数,就开启了定时器 TIM3 发生更新事件时产生中断的功能。
    3. NVIC_InitTypeDef NVIC_InitStructure;

    4. 这行代码定义了一个 NVIC_InitTypeDef 类型的结构体变量 NVIC_InitStructure,该结构体用于存储中断向量控制器(NVIC)的初始化配置参数。
    5. NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;

    6. 这行代码设置了 NVIC_InitStructure 结构体中的 NVIC_IRQChannel 成员,将其赋值为 TIM3_IRQnTIM3_IRQn 是一个枚举值,表示定时器 TIM3 对应的中断通道,这一步是告诉 NVIC 要配置哪个中断源的相关参数。
    7. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

    8. 这里设置了中断通道的抢占优先级(Preemption Priority)为 0。在 NVIC 中,抢占优先级用于确定当多个中断同时发生时,哪个中断具有更高的优先级从而优先得到响应。数值越小,优先级越高。
    9. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

    10. 这行代码设置了中断通道的子优先级(Sub Priority)为 1。当两个中断具有相同的抢占优先级时,子优先级用于进一步区分它们的优先级顺序。同样,数值越小,优先级越高。
    11. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    12. 此代码设置了 NVIC_InitStructure 结构体中的 NVIC_IRQChannelCmd 成员为 ENABLE,表示使能 TIM3 对应的中断通道。即允许该中断通道产生的中断请求能够被 NVIC 处理。
    13. NVIC_Init(&NVIC_InitStructure);

    14. 最后调用 NVIC_Init 函数,并传入 NVIC_InitStructure 结构体的指针。这个函数根据结构体中设置的参数对 NVIC 进行初始化配置,完成定时器 TIM3 中断在 NVIC 中的相关设置,使得当 TIM3 产生更新中断时,系统能够正确响应并执行相应的中断服务函数。

    作者:2401_88712943

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32学习进阶笔记:GPIO、TIM定时器与中断管理(第二天学习要点)

    发表回复