第二天:stm32学习笔记(GPIO,TIM_TIME定时器,TIM_OC比较器,NVIC中断)


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);

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

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

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

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

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值