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 定时器基本时基配置
- 定义结构体
使用TIM_TimeBaseInitTypeDef
类型定义结构体变量,用于存储定时器基本时基配置参数。c
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- 使能定时器时钟
需根据定时器所在的 APB 总线,使用RCC_APBxPeriphClockCmd
函数使能对应时钟。例如,若定时器在 APB2 总线上,则:c
RCC_APB2PeriphClockCmd(对应时钟, ENABLE);
- 设置基本时基参数
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_DIV1
、TIM_CKD_DIV2
、TIM_CKD_DIV4
等,数值越高过滤效果越好,在编码器应用中一般不使用 。countermode
:计数方式,默认使用向上计数TIM_CounterMode_Up
,也可选择向下计数TIM_CounterMode_Down
。
- 绑定配置
将配置好的结构体应用到对应的定时器,完成基本时基配置。c
TIM_TimeBaseInit(定时器实例, &TIM_TimeBaseStructure);
例如,若使用
TIM3
,则为TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
3.2 定时器输出比较(OC)配置
- 定义结构体
使用TIM_OCInitTypeDef
类型定义结构体变量,用于存储输出比较配置参数。c
TIM_OCInitTypeDef TIM_OCInitStructure;
- 使能定时器时钟
与基本时基配置相同,根据定时器所在总线使能时钟。c
RCC_APB2PeriphClockCmd(对应时钟, ENABLE);
- 设置输出比较参数
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
表示当计数器值小于比较值时输出高电平。
- 绑定配置到定时器通道
根据所需通道,将配置绑定到对应定时器实例的通道上。例如,将配置绑定到TIM3
的通道 1:c
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
一个定时器通常可以输出 4 个通道(
OC1
、OC2
、OC3
、OC4
),可分别进行配置。
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);
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
- 这个函数调用是用于使能定时器
TIM3
的更新中断(TIM_IT_Update
)。在 STM32 的定时器中,更新事件会在计数器溢出(向上计数模式下计数值达到自动重装载值)、下溢(向下计数模式下计数值减为 0)等情况下发生。通过调用TIM_ITConfig
函数并传入ENABLE
参数,就开启了定时器TIM3
发生更新事件时产生中断的功能。
NVIC_InitTypeDef NVIC_InitStructure;
- 这行代码定义了一个
NVIC_InitTypeDef
类型的结构体变量NVIC_InitStructure
,该结构体用于存储中断向量控制器(NVIC)的初始化配置参数。
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
- 这行代码设置了
NVIC_InitStructure
结构体中的NVIC_IRQChannel
成员,将其赋值为TIM3_IRQn
。TIM3_IRQn
是一个枚举值,表示定时器TIM3
对应的中断通道,这一步是告诉 NVIC 要配置哪个中断源的相关参数。
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
- 这里设置了中断通道的抢占优先级(Preemption Priority)为 0。在 NVIC 中,抢占优先级用于确定当多个中断同时发生时,哪个中断具有更高的优先级从而优先得到响应。数值越小,优先级越高。
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
- 这行代码设置了中断通道的子优先级(Sub Priority)为 1。当两个中断具有相同的抢占优先级时,子优先级用于进一步区分它们的优先级顺序。同样,数值越小,优先级越高。
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- 此代码设置了
NVIC_InitStructure
结构体中的NVIC_IRQChannelCmd
成员为ENABLE
,表示使能TIM3
对应的中断通道。即允许该中断通道产生的中断请求能够被 NVIC 处理。
NVIC_Init(&NVIC_InitStructure);
- 最后调用
NVIC_Init
函数,并传入NVIC_InitStructure
结构体的指针。这个函数根据结构体中设置的参数对 NVIC 进行初始化配置,完成定时器TIM3
中断在 NVIC 中的相关设置,使得当TIM3
产生更新中断时,系统能够正确响应并执行相应的中断服务函数。
第二天:stm32学习笔记(GPIO,TIM_TIME定时器,TIM_OC比较器,NVIC中断)
于 2025-04-20 19:27:58 首次发布