学习笔记:stm32定时器翻转模式实现同一个定时器不同通道不同频率占空比输出

STM32定时器输出pwm输出比较模式与PWM模式区别

一:PWM模式:

在这里插入图片描述
pwm模式就是最简单的输出pwm的方法,通过配置定时器的ARR寄存器来确定输出的频率,配置比较寄存器(CRR)来控制pwm的占空比,当CNT小于CRR输出一种电平,当CNT介于CRR与ARR之间时输出另一种电平。
但是由于四个通道使用一个定时器,ARR值一更改,四个通道都更改,所以无法使不同通道输出不同频率。

二:输出比较模式

在这里插入图片描述
输出比较模式就是当CNT达到CRR值时,翻转输出的电平,我们可以利用这一特性,实现不同通道输出不同频率,因为每一个通道均有自己的CRR。

(1)实现原理:

我们将ARR设置成一个值Y,令最初的CRR值为X,当CNT加载到X时,我们开启一个中断,在中断中,我们更改X的值,这样就可以实现频率与占空比控制。
在这里插入图片描述 由图可知,我们更改CRR值可以实现在一个ARR内,输出多个周期的方波,且只要**(CRR1+CRR2)N=ARR+1* ,(N为正整数)我们就可以实现稳定的pwm输出。
例如令ARR=65535,CRR1=4915,CRR2=3277,(CRR3与CRR4与前面重复就可,理解简单不在赘述)所以经过一个周期需要计数8192下,我们只需要将定时器时钟(72MHZ)进行8分频,就可以实现1KHZ,60%占空比的波形输出。

当我们的ARR设置不是65535时,我们需要在中断服务函数中判断读取到的CRR的值,若CRR的值大于ARR值,则令CRR=0,则可继续实现功能

例如:

u16 oc2crr1=3600;
u16 oc2crr2=900;
_Bool oc2_sta=0;
void TIM3_IRQHandler(void)
{
	u16 capture=0;
	u16 capture2=0;
	
  if(TIM_GetITStatus(TIM3,TIM_IT_CC1)!=RESET)
  {
    TIM_ClearITPendingBit(TIM3,TIM_IT_CC1);
		capture=TIM_GetCapture1(TIM3);
		if(capture>=9000)
		{
     capture=0;
   }
		if(oc1_sta==0)
		{
      TIM_SetCompare1(TIM3,capture+oc1crr2);
			oc1_sta=1;
    }
		else
		{
       TIM_SetCompare1(TIM3,capture+oc1crr1);
			 oc1_sta=0;
    }
  }
	 if(TIM_GetITStatus(TIM3,TIM_IT_CC2)!=RESET)
  {
    TIM_ClearITPendingBit(TIM3,TIM_IT_CC2);
		capture2=TIM_GetCapture2(TIM3);//读当前CRR值
		if(capture2>=9000)//判断crr值是否大于ARR
		{
     capture2   =0;
   }
		if(oc2_sta==0)
		{
      TIM_SetCompare2(TIM3,capture2+oc2crr2);
			oc2_sta=1;
    }
		else
		{
       TIM_SetCompare2(TIM3,capture2+oc2crr1);
			 oc2_sta=0;
    }
  }
}

main

  time3_initer(9000,7);//arr为9000;
补充说明:

简单函数介绍
1.更改CRR值的函数

TIM_SetCompare2();//设置TIM3的通道2CRR值

2.读取当前CRR值的函数

TIM_GetCapture2(TIM3);//读取通道2的TIM3CRR值

(2)代码实现

1.配置时钟:开启GPIO和定时器时钟

   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);

2.配置gpio

      GPIO_InitTypeDef GPIO_InitTypestu;
     GPIO_InitTypestu.GPIO_Mode=GPIO_Mode_AF_PP;
	 GPIO_InitTypestu.GPIO_Pin=GPIO_Pin_6;
	 GPIO_InitTypestu.GPIO_Speed=GPIO_Speed_10MHz;
	 GPIO_Init(GPIOA,&GPIO_InitTypestu);
	 GPIO_InitTypestu.GPIO_Pin=GPIO_Pin_7;
	 GPIO_Init(GPIOA,&GPIO_InitTypestu);

3.配置定时器

   TIM_TimeBaseInitTypeDef TIM_TimeBaseInitTypestu;
    TIM_TimeBaseInitTypestu.TIM_ClockDivision=TIM_CKD_DIV1;
	 TIM_TimeBaseInitTypestu.TIM_CounterMode=TIM_CounterMode_Up;
	 TIM_TimeBaseInitTypestu.TIM_Period=arr;
	 TIM_TimeBaseInitTypestu.TIM_Prescaler=psc;
	 TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitTypestu);

4,.配置通道:注意要关闭 TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Disable);

      TIM_OCInitTypeDef TIM_OCInitTypeSTU;
	 TIM_OCInitTypeDef TIM_OCInitTypeSSS;
     TIM_OCInitTypeSTU.TIM_OCMode=TIM_OCMode_Toggle;
	 TIM_OCInitTypeSTU.TIM_OCPolarity=TIM_OCPolarity_Low;
	 TIM_OCInitTypeSTU.TIM_OutputState=TIM_OutputState_Enable;
	 TIM_OCInitTypeSTU.TIM_Pulse=oc1crr1;
	 TIM_OC1Init(TIM3,&TIM_OCInitTypeSTU);
	 TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Disable);
	 
	 TIM_OCInitTypeSSS.TIM_OCMode=TIM_OCMode_Toggle;
	 TIM_OCInitTypeSSS.TIM_OCPolarity=TIM_OCPolarity_Low;//如果使用HIGH那么占空比计算应该相反,CRR1=3277,CRR2=4915
	 TIM_OCInitTypeSSS.TIM_OutputState=TIM_OutputState_Enable;
	 TIM_OCInitTypeSSS.TIM_Pulse=oc2crr1;
	 TIM_OC2Init(TIM3,&TIM_OCInitTypeSSS);
	 TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Disable);

5.开启中断

	 NVIC_InitTypeDST.NVIC_IRQChannel=TIM3_IRQn;
	 NVIC_InitTypeDST.NVIC_IRQChannelCmd=ENABLE;
	 NVIC_InitTypeDST.NVIC_IRQChannelPreemptionPriority=1;
	 NVIC_InitTypeDST.NVIC_IRQChannelSubPriority=1;
	 NVIC_Init(&NVIC_InitTypeDST);
	 TIM_ITConfig(TIM3,TIM_IT_CC1|TIM_IT_CC2,ENABLE);

6.使能

TIM_Cmd(TIM3,ENABLE);

7:配置中断服务函数:记得清除标志位

u16 oc1crr1=4915;
u16 oc1crr2=3271;
_Bool oc1_sta=0;

u16 oc2crr1=3277;
u16 oc2crr2=819;
_Bool oc2_sta=0;
void TIM3_IRQHandler(void)
{
	u16 capture=0;
	u16 capture2=0;
	
  if(TIM_GetITStatus(TIM3,TIM_IT_CC1)!=RESET)
  {
    TIM_ClearITPendingBit(TIM3,TIM_IT_CC1);//要清楚标志位 切记
		capture=TIM_GetCapture1(TIM3);
		if(oc1_sta==0)
		{
      TIM_SetCompare1(TIM3,capture+oc1crr2);
			oc1_sta=1;
    }
		else
		{
       TIM_SetCompare1(TIM3,capture+oc1crr1);
			 oc1_sta=0;
    }
  }
	 if(TIM_GetITStatus(TIM3,TIM_IT_CC2)!=RESET)
  {
    TIM_ClearITPendingBit(TIM3,TIM_IT_CC2);
		capture2=TIM_GetCapture2(TIM3);
		if(oc2_sta==0)
		{
      TIM_SetCompare2(TIM3,capture2+oc2crr2);
			oc2_sta=1;
    }
		else
		{
       TIM_SetCompare2(TIM3,capture2+oc2crr1);
			 oc2_sta=0;
    }
  }
}
	

(3)完整代码

a.time.c
#include "time.h"
u16 oc1crr1=4915;
u16 oc1crr2=3271;
_Bool oc1_sta=0;

u16 oc2crr1=3277;
u16 oc2crr2=819;
_Bool oc2_sta=0;

void time3_initer(u16 arr,u16 psc)
{
	 GPIO_InitTypeDef GPIO_InitTypestu;
	 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitTypestu;
	 NVIC_InitTypeDef NVIC_InitTypeDST;
	 TIM_OCInitTypeDef TIM_OCInitTypeSTU;
	 TIM_OCInitTypeDef TIM_OCInitTypeSSS;
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
   
	 GPIO_InitTypestu.GPIO_Mode=GPIO_Mode_AF_PP;
	 GPIO_InitTypestu.GPIO_Pin=GPIO_Pin_6;
	 GPIO_InitTypestu.GPIO_Speed=GPIO_Speed_10MHz;
	 GPIO_Init(GPIOA,&GPIO_InitTypestu);
	 GPIO_InitTypestu.GPIO_Pin=GPIO_Pin_7;
	 GPIO_Init(GPIOA,&GPIO_InitTypestu);
	
	 TIM_TimeBaseInitTypestu.TIM_ClockDivision=TIM_CKD_DIV1;
	 TIM_TimeBaseInitTypestu.TIM_CounterMode=TIM_CounterMode_Up;
	 TIM_TimeBaseInitTypestu.TIM_Period=arr;
	 TIM_TimeBaseInitTypestu.TIM_Prescaler=psc;
	 TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitTypestu);
	
	
	 NVIC_InitTypeDST.NVIC_IRQChannel=TIM3_IRQn;
	 NVIC_InitTypeDST.NVIC_IRQChannelCmd=ENABLE;
	 NVIC_InitTypeDST.NVIC_IRQChannelPreemptionPriority=1;
	 NVIC_InitTypeDST.NVIC_IRQChannelSubPriority=1;
	 NVIC_Init(&NVIC_InitTypeDST);
	 
	 TIM_OCInitTypeSTU.TIM_OCMode=TIM_OCMode_Toggle;
	 TIM_OCInitTypeSTU.TIM_OCPolarity=TIM_OCPolarity_Low;
	 TIM_OCInitTypeSTU.TIM_OutputState=TIM_OutputState_Enable;
	 TIM_OCInitTypeSTU.TIM_Pulse=oc1crr1;
	 TIM_OC1Init(TIM3,&TIM_OCInitTypeSTU);
	 TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Disable);
	 
	 TIM_OCInitTypeSSS.TIM_OCMode=TIM_OCMode_Toggle;
	 TIM_OCInitTypeSSS.TIM_OCPolarity=TIM_OCPolarity_Low;
	 TIM_OCInitTypeSSS.TIM_OutputState=TIM_OutputState_Enable;
	 TIM_OCInitTypeSSS.TIM_Pulse=oc2crr1;
	 TIM_OC2Init(TIM3,&TIM_OCInitTypeSSS);
	 TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Disable);
	 
	 TIM_Cmd(TIM3,ENABLE);
	 
	 TIM_ITConfig(TIM3,TIM_IT_CC1|TIM_IT_CC2,ENABLE);
}


void TIM3_IRQHandler(void)
{
	u16 capture=0;
	u16 capture2=0;
	
  if(TIM_GetITStatus(TIM3,TIM_IT_CC1)!=RESET)
  {
    TIM_ClearITPendingBit(TIM3,TIM_IT_CC1);
		capture=TIM_GetCapture1(TIM3);
		if(oc1_sta==0)
		{
      TIM_SetCompare1(TIM3,capture+oc1crr2);
			oc1_sta=1;
    }
		else
		{
       TIM_SetCompare1(TIM3,capture+oc1crr1);
			 oc1_sta=0;
    }
  }
	 if(TIM_GetITStatus(TIM3,TIM_IT_CC2)!=RESET)
  {
    TIM_ClearITPendingBit(TIM3,TIM_IT_CC2);
		capture2=TIM_GetCapture2(TIM3);
		if(oc2_sta==0)
		{
      TIM_SetCompare2(TIM3,capture2+oc2crr2);
			oc2_sta=1;
    }
		else
		{
       TIM_SetCompare2(TIM3,capture2+oc2crr1);
			 oc2_sta=0;
    }
  }
}
	
	
b.time.h
#ifndef __TIME_H
#define __TIME_H
#include "stm32f10x.h"

void time3_initer(u16 arr,u16 psc);

#endif
c.main.c
#include "time.h"
#include "stm32f10x.h"
int main(void)
{
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
  time3_initer(65535,7);
  
	while(1)
	{

  }
}

  • 8
    点赞
  • 85
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值