【STM32】PWM多通道输出

目标:

1- 把PWM信号的频率改成100KHZ
2- 使用高级定时器1输出4路占空比相同的PWM信号

编程要点:

1.定时器用到的GPIO初始化
2.定时器时基结构体f初始化
3.定时器输出比较结构体初始化

宏定义:

#ifndef _LL_TIM_H
#define _LL_TIM_H

#include "stm32f10x.h"
// 这里我们使用高级控制定时器TIM1

#define            TIM_arr            (10-1)
#define            TIM_psc            (72-1)
#define            TIM_ccr1             5

void TIM1_Init(void);

#endif	

GPIO初始化:


static void TIM1_GPIO_Config(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	//设置该引脚为复用输出功能,输出TIM1 CH1的PWM脉冲波形	GPIOA.8
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; 		//TIM1_CH1
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  	//复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	//设置该引脚为复用输出功能,输出TIM1 CH2的PWM脉冲波形	GPIOA.9
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; 		//TIM1_CH2
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  	//复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	//设置该引脚为复用输出功能,输出TIM1 CH3的PWM脉冲波形	GPIOA.10
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; 		//TIM1_CH3
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  	//复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	//设置该引脚为复用输出功能,输出TIM1 CH4的PWM脉冲波形	GPIOA.11
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; 		//TIM1_CH4
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  	//复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
}

定时器模式配置:

// PWM 信号的频率F = TIM_CLK/{(ARR+1) *(PSC+1)}
// TIM_CLK等于72MHz
// ARR :自动重装载寄存器的值,对应TIM_arr这个宏
// PSC :计数器时钟的分频因子,对应TIM_psc这个宏
// 占空比Duty=CCR/(ARR+1),CCR对应TIM_ccr1这个宏,该测试程序中占空比{ 5/(10-1)}为50%

static void TIM1_Model_Config(void)
{
	// 开启定时器时钟,即内部时钟CK_INT=72M
	 RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
	 
	 /*--------------------时基结构体初始化-------------------------*/
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
	TIM_TimeBaseStructure.TIM_Period=TIM_arr;	
	TIM_TimeBaseStructure.TIM_Prescaler= TIM_psc;	// 驱动CNT计数器的时钟 = Fck_int/(psc+1)
	// 时钟分频因子 ,配置死区时间时需要用到
	TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;	//不分频	
	TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;// 计数器计数模式,设置为向上计数	
	// 重复计数器的值,没用到不用管
	TIM_TimeBaseStructure.TIM_RepetitionCounter=0;	
	TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);// 初始化定时器

	
	/*-------------------------输出比较结构体初始化---------------------------------*/
	TIM_OCInitTypeDef  TIM_OCInitStructure;
	
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;// 配置为PWM模式1
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//比较输出使能
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;// 输出通道电平极性配置
	
	
	TIM_OCInitStructure.TIM_Pulse = TIM_ccr1;// 设置占空比大小
	TIM_OC1Init(TIM1, &TIM_OCInitStructure);
	TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);//使能TIM1在CCR1上的预装载寄存器
	
	//ch2 PWM模式
	TIM_OCInitStructure.TIM_Pulse = TIM_ccr1;// 设置占空比大小
	TIM_OC2Init(TIM1, &TIM_OCInitStructure);
	TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);//使能TIM1在CCR1上的预装载寄存器
	
	//ch3 PWM模式
TIM_OCInitStructure.TIM_Pulse = TIM_ccr1;// 设置占空比大小
	TIM_OC3Init(TIM1, &TIM_OCInitStructure);
	TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable);//使能TIM1在CCR1上的预装载寄存器
	
	//ch4 PWM模式
	TIM_OCInitStructure.TIM_Pulse = TIM_ccr1;// 设置占空比大小
	TIM_OC4Init(TIM1, &TIM_OCInitStructure);
	TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable);//使能TIM1在CCR1上的预装载寄存器
	
	TIM_Cmd(TIM1, ENABLE);	// 使能计数器
	TIM_CtrlPWMOutputs(TIM1, ENABLE);// 主输出使能,当使用的是通用定时器时,这句不需要

}
void TIM1_Init(void)
{
	TIM1_GPIO_Config();
	TIM1_Model_Config();

}

主函数:

int main(void)
{	
  /* 高级定时器初始化 */
	TIM1_Init();
	
  while(1)
	{	
		
	}	
}

下载验证程序中4个通道的占空比设置均为50%

需要注意的地方

// * 【注意】:TIM_TimeBaseInitTypeDef结构体里面有5个成员,TIM6和TIM7的寄存器里面只有
// * TIM_Prescaler和TIM_Period,所以使用TIM6和TIM7的时候只需初始化这两个成员即可,
// * 另外三个成员是通用定时器和高级定时器才有.
// *-----------------------------------------------------------------------------
// *typedef struct
// *{ TIM_Prescaler --------------------------都有
// * TIM_CounterMode ----------------------TIMx,x[6,7]没有,其他都有
// * TIM_Period---------------------------------都有
// * TIM_ClockDivision -----------------------TIMx,x[6,7]没有,其他都有
// * TIM_RepetitionCounter------------------TIMx,x[1,8,15,16,17]才有
// *}TIM_TimeBaseInitTypeDef;
// -----------------------------------------------------------------------------
// /
/**-----------------------------------------------------------------------------------------------
/
/
注意】TIM_CtrlPWMOutputs(TIM1, ENABLE); // 主输出使能,当使用的是通用定时器时,这句不需要
TIM_TimeBaseStructure.TIM_RepetitionCounter=0;//重复计数器,高级控制定时器特有
*/
// * 【注意】:高级控制定时器比通用定时器增加了可编程死区互补输出、重复计数器、带刹车(断路)功能,主要针对工业电机控制方面,通过设置死区时间(由MOS管工艺确定)防止电路短路;

	/*-------------------刹车和死区结构体初始化-------------------*/
	TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
  TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
  TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
  TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;
	// 这里配置的死区时间为152ns
  TIM_BDTRInitStructure.TIM_DeadTime = 11;
  TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable;
	// 当BKIN引脚检测到高电平的时候,输出比较信号被禁止,就好像是刹车一样
  TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;
  TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
  TIM_BDTRConfig(ADVANCE_TIM, &TIM_BDTRInitStructure);

注意】定时器输出频率和占空比问题
1.系统频率(TIM_CLK)设置为72MHz时,F = TIM_CLK/{(ARR+1) *(PSC+1)}
//(为什么要加1,是因为是从0开始计数)
//ARR:0~65535
//PSC:1~65536
2.占空比由CCR和ARR决定 Duty=CCR/(ARR+1)

### STM32 PWM多通道输出配置 对于STM32来说,PWM多通道输出可以通过TIMx定时器的不同通道来实现。每个高级定时器(如 TIM1, TIM8)、通用定时器(如 TIM2-TIM7)都支持多个独立的PWM通道[^1]。 #### 配置要点 为了设置多通道PWM输出,在初始化结构体`TIM_OC_InitTypeDef`中需针对每一个要使用的通道分别设定参数。这些参数包括但不限于脉冲宽度(即占空比),模式选择等。具体而言: - `TIM_Channel`: 定义哪个通道被配置成PWM输出。 - `TIM_Pulse`: 设置比较寄存器值,决定占空比大小。 - `TIM_OCPolarity`: 设定输出极性,高有效还是低有效。 - `TIM_OutputState`: 启用或禁用该通道的输出功能。 #### 示例代码 下面给出一段简单的C语言程序片段用于演示如何在一个定时器上启用两个不同频率和占空比的PWM信号输出: ```c // 初始化定时器并开启时钟 __HAL_RCC_TIM1_CLK_ENABLE(); htim1.Instance = TIM1; htim1.Init.Prescaler = 83; // 假设系统核心频率为84MHz,则此预分频系数使得计数频率约为1MHz htim1.Init.CounterMode = TIM_COUNTERMODE_UP; htim1.Init.Period = 999; // 自由运行至1000个单位时间后重载 if (HAL_TIM_PWM_Init(&htim1) != HAL_OK){ Error_Handler(); // 错误处理函数 } // 配置第一个PWM通道(CH1) sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 500; // 占空比=50% sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.Channel = TIM_CHANNEL_1; if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK){ Error_Handler(); } HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1); // 配置第二个PWM通道(CH2),这里假设需要不同的频率和占空比 sConfigOC.Pulse = 250; // 改变Pulse改变占空比到25% sConfigOC.Channel = TIM_CHANNEL_2; if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2) != HAL_OK){ Error_Handler(); } HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_2); ``` 上述例子展示了如何在同一定时器资源下创建具有不同特性的双路PWM输出[^2]。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值