stm32 笔记 PWM及HAL库应用

本文介绍STM32微控制器中PWM的工作原理和配置方法,详细解析了如何通过定时器产生PWM信号,并提供了完整的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

stm32 PWM原理

 STM32 使用一个定时器作为 PWM 输出,在上图中,ARR 即为重装载值。在计数器的值大于CRRx的值并且小于 ARR 之间,即区分高低电平。输出在图中分别有 ① 和 ② 两种情况.

分别为:

①CRR 和 ARR 区间为低电平。

②CRR 和 ARR 区间为高电平。

设置输出方式

有两个配置可以配置输出方式:

PWM 模式 1–– 在递增计数模式下,只要 TIMx_CNT<TIMx_CCR1,通道 1 便为有效状态,否则为无效状态。在递减计数模式下,只要 TIMx_CNT>TIMx_CCR1,通道 1 便为无效状态,否则为有效状态。

PWM 模式 2–– 在递增计数模式下,只要 TIMx_CNT<TIMx_CCR1,通道 1 便为无效状态,否则为有效状态。在递减计数模式下,只要 TIMx_CNT>TIMx_CCR1,通道 1 便为有效状态,否则为无效状态。

TIMx_CNT即为当前计数值

其中 PWM 模式 1 和模式 2 完全相反。

 除了设置PWM模式之外,还可以设置 CERR:CC1P 位,置 0 高电平有效,置 1 低电平有效。

 例:

如果设置为 PWM1 模式,CC1P 设置为 0,即为:①波形

如果设置为 PWM1 模式,CC1P 设置为 1,即为:②波形

 初始化 PWM

TIM_HandleTypeDef TIM3_Handler;         //定时器3PWM句柄 
TIM_OC_InitTypeDef TIM3_CH4Handler;	    //定时器3通道4句柄

void TIM3_PWM_Init()
{ 
    TIM3_Handler.Instance=TIM3;            //定时器3
    TIM3_Handler.Init.Prescaler=90-1;       //定时器分频
    TIM3_Handler.Init.CounterMode=TIM_COUNTERMODE_UP;//向上计数模式
    TIM3_Handler.Init.Period=500-1;          //自动重装载值
    HAL_TIM_PWM_Init(&TIM3_Handler);       //初始化PWM
    
    TIM3_CH4Handler.OCMode=TIM_OCMODE_PWM1; //模式选择PWM1
    TIM3_CH4Handler.Pulse=250;            //设置默认占空比
    TIM3_CH4Handler.OCPolarity=TIM_OCPOLARITY_LOW; //输出比较极性为低  cc1p为0
    
    HAL_TIM_PWM_ConfigChannel(&TIM3_Handler,&TIM3_CH4Handler,TIM_CHANNEL_4);//配置TIM3通道4
    HAL_TIM_PWM_Start(&TIM3_Handler,TIM_CHANNEL_4);//开启PWM通道4
}

 在上边我们设置了 90分频(Prescaler),我当前机器设置的是 90mhz,90 分频后即为 1mhz 即一秒计数 1000 次,重装载值 (Period)设置为 500。也就说,对于当前 PWM 周期为 500ms。

在之后,我们设置了 TIM3_CH4Handler.Pulse=250; 这即是默认的输出占空比。

输出波形如图所示:

 

设置 GPIO 状态

在芯片手册中,我们发现 PB1 可以被复用为 TIM3,于是做出如下设置: 

void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
    GPIO_InitTypeDef GPIO_Initure;
	__HAL_RCC_TIM3_CLK_ENABLE();			//使能定时器3
    __HAL_RCC_GPIOB_CLK_ENABLE();			//开启GPIOB时钟
	
    GPIO_Initure.Pin=GPIO_PIN_1;           	//PB1
    GPIO_Initure.Mode=GPIO_MODE_AF_PP;  	//复用推挽输出
    GPIO_Initure.Pull=GPIO_PULLUP;          //上拉
    GPIO_Initure.Speed=GPIO_SPEED_HIGH;     //高速
	GPIO_Initure.Alternate= GPIO_AF2_TIM3;	//PB1复用为TIM3_CH4
    HAL_GPIO_Init(GPIOB,&GPIO_Initure);
}

 我们想让 PB1 输出 PWM 波,需要开启时钟这些常规配置。并且需要使用GPIO_Initure.Alternate= GPIO_AF2_TIM3; 使 PB1 复用成 TIM3。这样才可以输出 PWM 波。

编写设置 PWM 值函数

因为我们刚才在初始化的时候用了:

HAL_TIM_PWM_ConfigChannel(&TIM3_Handler,&TIM3_CH4Handler,TIM_CHANNEL_4)

HAL_TIM_PWM_Start(&TIM3_Handler,TIM_CHANNEL_4)

均是 CHANNEL_4 使用了通道4。

//设置TIM通道4的占空比
//compare:比较值
void TIM_SetTIM3Compare4(u32 compare)
{
	TIM3->CCR4=compare; 
}

全部代码

#include "sys.h"
#include "delay.h"

TIM_HandleTypeDef TIM3_Handler;         //定时器3PWM句柄 
TIM_OC_InitTypeDef TIM3_CH4Handler;	    //定时器3通道4句柄

void TIM3_PWM_Init()
{ 
    TIM3_Handler.Instance=TIM3;            //定时器3
    TIM3_Handler.Init.Prescaler=90-1;       //定时器分频
    TIM3_Handler.Init.CounterMode=TIM_COUNTERMODE_UP;//向上计数模式
    TIM3_Handler.Init.Period=500-1;          //自动重装载值
    HAL_TIM_PWM_Init(&TIM3_Handler);       //初始化PWM
    
    TIM3_CH4Handler.OCMode=TIM_OCMODE_PWM1; //模式选择PWM1
    TIM3_CH4Handler.Pulse=250;            //设置比较值,此值用来确定占空比,默认比较值为自动重装载值的一半,即占空比为50%
    TIM3_CH4Handler.OCPolarity=TIM_OCPOLARITY_LOW; //输出比较极性为低  cc1p为0
    HAL_TIM_PWM_ConfigChannel(&TIM3_Handler,&TIM3_CH4Handler,TIM_CHANNEL_4);//配置TIM3通道4
	
    HAL_TIM_PWM_Start(&TIM3_Handler,TIM_CHANNEL_4);//开启PWM通道4
}

void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
    GPIO_InitTypeDef GPIO_Initure;
	__HAL_RCC_TIM3_CLK_ENABLE();			//使能定时器3
    __HAL_RCC_GPIOB_CLK_ENABLE();			//开启GPIOB时钟
	
    GPIO_Initure.Pin=GPIO_PIN_1;           	//PB1
    GPIO_Initure.Mode=GPIO_MODE_AF_PP;  	//复用推挽输出
    GPIO_Initure.Pull=GPIO_PULLUP;          //上拉
    GPIO_Initure.Speed=GPIO_SPEED_HIGH;     //高速
	GPIO_Initure.Alternate= GPIO_AF2_TIM3;	//PB1复用为TIM3_CH4
    HAL_GPIO_Init(GPIOB,&GPIO_Initure);
}

//设置TIM通道4的占空比
//compare:比较值
void TIM_SetTIM3Compare4(u32 compare)
{
	TIM3->CCR4=compare; //因为使用了通道4,所以需要修改 CCR4 寄存器
}

int main(void)
{
	GPIO_InitTypeDef GPIO_Initure;
	
    HAL_Init();                     //初始化HAL库    
    Stm32_Clock_Init(360,25,2,8);   //设置时钟,180Mhz
	
	TIM3_PWM_Init();
	
	while(1){
		TIM_SetTIM3Compare4(0);	//因为使用了 PWM模式1 以及cc1p0 所以设置0是最暗 设置500是最亮
	}
}

### STM32 PWM HAL 使用教程 #### 初始化定时器并配置PWM功能 为了在STM32上通过HAL实现PWM输出,首先需要初始化一个定时器,并将其配置为PWM模式。这通常涉及到设置定时器的周期和脉冲宽度来控制占空比。 ```c // 定义定时器句柄结构体变量 TIM_HandleTypeDef htim3; void MX_TIM3_Init(void) { __HAL_RCC_TIM3_CLK_ENABLE(); // 启用定时器时钟 // 配置定时器参数 htim3.Instance = TIM3; htim3.Init.Prescaler = 79; // 设置预分频值 htim3.Init.CounterMode = TIM_COUNTERMODE_UP; // 计数方向向上 htim3.Init.Period = 999; // 自动重装载值 htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; if (HAL_TIM_PWM_Init(&htim3) != HAL_OK) { Error_Handler(); } } ``` 上述代码片段展示了如何创建`TIM_HandleTypeDef`类型的对象以及怎样调用`HAL_TIM_PWM_Init()`来进行初始化操作[^1]。 #### 创建PWM通道 接下来要做的就是指定哪个GPIO引脚作为PWM信号输出端口,并关联到相应的定时器通道上去: ```c __HAL_AFIO_REMAP_TIM3_PARTIAL(); GPIO_InitStruct.Pin = GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); // 将定时器通道映射至对应的GPIO引脚 sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; if (HAL_TIM_OC_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK){ Error_Handler(); } if (HAL_TIM_OC_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_2) != HAL_OK){ Error_Handler(); } if (HAL_TIM_OC_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_3) != HAL_OK){ Error_Handler(); } if (HAL_TIM_OC_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_4) != HAL_OK){ Error_Handler(); } ``` 这里定义了一个名为`sConfigOC`的对象用来保存有关PWM模式的具体设定,比如选择工作于PWM模式1(`TIM_OCMODE_PWM1`)并且指定了高电平有效极性(`TIM_OCPOLARITY_HIGH`). 接着分别针对四个可能存在的硬件通道执行了相同的配置过程[^2]. #### 开启PWM输出 最后一步则是实际开启PWM波形的发生: ```c if(HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_ALL)!= HAL_OK){ Error_Handler(); } ``` 这段简单的语句会激活之前所选中的所有通道上的PWM输出。值得注意的是,在某些情况下还可以单独启用某个特定的通道而不是全部一起打开;此时只需替换掉宏定义`TIM_CHANNEL_ALL`, 改成具体想要使用的那个编号即可.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值