基于STM32配置PWM的输出和相关GPIO口的配置(有关重映像问题解答)

使用STM32定时器进行PWM的配置有以下几个步骤,以下是参考例差可以作为历程参考。

/******************************************************************************************************************************
*使用PWM来实现对电机的控制,实现开环的速度控制
*
*使用四个直流电机 motor1:     motor2:     
*                motor3:     motor4:
*
cnt = 0 对应占空比0

TIM3:(部分重映像)
CH1:PB4
CH2:PB5
CH3:PB0
CH4:PB1

TIM4:
CH1:PB6
CH2:PB7
CH3:PB8
CH4:PB9
*******************************************************************************************************************************/
void TIM_PWM_Init(void)
{
	//设置变量
	GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
	TIM_OCInitTypeDef TIM_OCInitStructure; 
	
	//使能时钟
	RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM3 | RCC_APB1Periph_TIM4 , ENABLE);
	RCC_APB2PeriphClockCmd(  RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
	GPIO_PinRemapConfig( GPIO_PartialRemap_TIM3 , ENABLE);//使定时器TIM4进行部分重映像操作
	//GPIO_PinRemapConfig(GPIO_Remap_TIM4,ENABLE);
	 
	
	TIM_TimeBaseStructure.TIM_Period = 899;
	TIM_TimeBaseStructure.TIM_Prescaler = 0;
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseStructure.TIM_ClockDivision = 0;
	TIM_TimeBaseInit(TIM3 , &TIM_TimeBaseStructure);
	TIM_TimeBaseInit(TIM4 , &TIM_TimeBaseStructure);
	
	//端口复用
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 ;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 	
	GPIO_Init(GPIOB, &GPIO_InitStructure);   
	
	
	//PB4:TIM3_CH1
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
	TIM_OCInitStructure.TIM_Pulse = 0;
	TIM_OC1Init(TIM3 , &TIM_OCInitStructure);
	TIM_OC1PreloadConfig(TIM3 , TIM_OCPreload_Enable);
	
	//PB5:TIM3_CH2
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
	TIM_OCInitStructure.TIM_Pulse = 450;
	TIM_OC2Init(TIM3 , &TIM_OCInitStructure);
	TIM_OC2PreloadConfig(TIM3 , TIM_OCPreload_Enable);
	
	//PB0:TIM3_CH3
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
	TIM_OCInitStructure.TIM_Pulse = 0;
	TIM_OC3Init(TIM3 , &TIM_OCInitStructure);
	TIM_OC3PreloadConfig(TIM3 , TIM_OCPreload_Enable);
	
	//PB1:TIM3_CH4 
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
	TIM_OCInitStructure.TIM_Pulse = 0;
	TIM_OC4Init(TIM3 , &TIM_OCInitStructure);
	TIM_OC4PreloadConfig(TIM3 , TIM_OCPreload_Enable);
	
	
//	
	//PB6:TIM4_CH1
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
	TIM_OCInitStructure.TIM_Pulse = 900;
	TIM_OC1Init(TIM4 , &TIM_OCInitStructure);
	TIM_OC1PreloadConfig(TIM4 , TIM_OCPreload_Enable);
	
	//PB7:TIM4_CH2
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
	TIM_OCInitStructure.TIM_Pulse = 900;
	TIM_OC2Init(TIM4 , &TIM_OCInitStructure);
	TIM_OC2PreloadConfig(TIM4 , TIM_OCPreload_Enable);
	
	//PB8:TIM4_CH3
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
	TIM_OCInitStructure.TIM_Pulse = 0;
	TIM_OC3Init(TIM4 , &TIM_OCInitStructure);
	TIM_OC3PreloadConfig(TIM4 , TIM_OCPreload_Enable);
	
	//PB9:TIM4_CH4
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
	TIM_OCInitStructure.TIM_Pulse = 900;
	TIM_OC4Init(TIM4 , &TIM_OCInitStructure);
	TIM_OC4PreloadConfig(TIM4 , TIM_OCPreload_Enable);

	TIM_Cmd(TIM3, ENABLE);
	TIM_Cmd(TIM4, ENABLE);
}

在上述PWM初始化函数中使用定时器TIM3和TIM4来输出PWM波,其中为了更好的应用IO口的布局等等TIM3进行了部分重映像的操作,这意味着部分引脚可以使用重映像的操作使之拥有另外的功能,即让TIM4本来该复用的引脚重映像到了其他引脚上。这个时候我们就需要查找相关的参考手册来对比引脚关系。如我使用的STM32F103。

通过表格我们就可以知道我想要使用PB4和PB5作为PWM的输出引脚,所以对TIM3使用了部分重映像的功能,实现这个功能的代码是:

GPIO_PinRemapConfig( GPIO_PartialRemap_TIM3 , ENABLE);//使定时器TIM3进行部分重映像操作

     这里有一个值得注意的地方,若是其他的功能引脚需要复用IO口,同样也是需要相同的方法来对该外设进行部分重映像或完全重映像(若是没有重映象则不需要),而需要重映像对象则可以在库函数中找到。如我需要使用PD8和PD9作为USART3的TXD和RXD引脚则需要完全重映像USART3:

	RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART3, ENABLE );     /* 使能USART1,GPIOA时钟 */
	GPIO_PinRemapConfig(GPIO_FullRemap_USART3,ENABLE);    //完全重映像USART3,使用PD8和PD9作为USART3的TXD和RXD引脚

除了重映像的问题其余就是以下几个步骤:

(1)使能时钟        

(2)配置GPIO口  pin、speed、mode等,其中mode需选择为GPIO_Mode_AF_PP复用输出。

(3)配置基本的定时器参数,

typedef struct
{
  uint16_t TIM_Prescaler;         /*!< Specifies the prescaler value used to divide the TIM clock.
                                       This parameter can be a number between 0x0000 and 0xFFFF */

  uint16_t TIM_CounterMode;       /*!< Specifies the counter mode.
                                       This parameter can be a value of @ref TIM_Counter_Mode */

  uint16_t TIM_Period;            /*!< Specifies the period value to be loaded into the active
                                       Auto-Reload Register at the next update event.
                                       This parameter must be a number between 0x0000 and 0xFFFF.  */ 

  uint16_t TIM_ClockDivision;     /*!< Specifies the clock division.
                                      This parameter can be a value of @ref TIM_Clock_Division_CKD */

  uint8_t TIM_RepetitionCounter;  /*!< Specifies the repetition counter value. Each time the RCR downcounter
                                       reaches zero, an update event is generated and counting restarts
                                       from the RCR value (N).
                                       This means in PWM mode that (N+1) corresponds to:
                                          - the number of PWM periods in edge-aligned mode
                                          - the number of half PWM period in center-aligned mode
                                       This parameter must be a number between 0x00 and 0xFF. 
                                       @note This parameter is valid only for TIM1 and TIM8. */
} TIM_TimeBaseInitTypeDef;

TIM_Prescaler:定时器分频系数psc,对时钟频率进行分频;

TIM_CounterMode:计数模式,向上计数或是向下计数

TIM_Period:时钟周期

TIM_ClockDivision:时钟分频。(设置为0即可)

(4)配置定时器的输出参数:

	//PB4:TIM3_CH1 TIM3通道1
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//PWM1输出模式
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
	TIM_OCInitStructure.TIM_Pulse = 0;//cnt捕获值,和占空比有关
	TIM_OC1Init(TIM3 , &TIM_OCInitStructure);
	TIM_OC1PreloadConfig(TIM3 , TIM_OCPreload_Enable);

PWM的占空比为n = pul/arr

PWM的周期计算为 T = psc/72M(f103的时钟频率)*arr 如arr=1000,psc=7200,arr=1000则可计算PWM周期为T=7200/72000000*1000=0.1s f=1/T=10HZ

(5)使能TIM定时器

    TIM_Cmd(TIM3, ENABLE);
	TIM_Cmd(TIM4, ENABLE);
	TIM_Cmd(TIM2, ENABLE);

这就是初始化PWM的整个流程,希望可以帮助到你。

  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晨荼荼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值