ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

基于通用定时器的PWM波形生成

2022-07-07 22:00:43  阅读:143  来源: 互联网

标签:ARR 定时器 波形 TIM4 TIMx TIM GPIO PWM


今天终于写到PWM了,关于PWM是什么我这里不再赘述,下面我们来看看通用定时器的PWM模式吧!
脉冲宽度调制模式可以产生一个由TIMx_ARR寄存器确定频率、由TIMx_CCRx寄存器确定占空比的信号。ARR是啥?可以简单记为从0数到ARR(向上计数)或从ARR数到0(向下计数),我们的TIM是16位的,所以ARR取值范围是0~65535。CCR则是当CNT(计数器的值)小于CCR是为1或者0,具体取决于PWM模式和输出极性。
我们再仔细看看输出模式,有边沿对齐和中央对齐,用的便是计数器的向上计数、向下计数和中央对齐模式。
image

上图是下图为TIMx_ARR=8时边沿对齐的向上计数的PWM波形实例。大家看各个CCR配置下的OCXREF即可。在这个模式中,有效电平是从复位后立刻生效的,到CNT不再小于CCR为止,应该很好理解吧。注意,在向下计数模式中产生无法占空比为0的波形。


image
image

上图给出了一些中央对齐的PWM波形的例子

  • TIMx_ARR=8
  • PWM模式1
  • TIMx_CR1寄存器中的CMS=01,在中央对齐模式1时,当计数器向下计数时设置比较标志。

使用中央对齐模式的提示:

  • 进入中央对齐模式时,使用当前的向上/向下计数配置;这就意味着计数器向上还是向下计数取决于TIMx_CR1寄存器中DIR位的当前值。此外,软件不能同时修改DIR和CMS位。
  • 不推荐当运行在中央对齐模式时改写计数器,因为这会产生不可预知的结果。特别地:
    • 如果写入计数器的值大于自动重加载的值(TIMx_CNT>TIMx_ARR),则方向不会被更新。例如,如果计数器正在向上计数,它就会继续向上计数。
    • 如果将0或者TIMx_ARR的值写入计数器,方向被更新,但不产生更新事件UEV。
  • 使用中央对齐模式最保险的方法,就是在启动计数器之前产生一个软件更新(设置TIMx_EGR 位中的UG位),不要在计数进行过程中修改计数器的值。

下面就是编程环节了

先想想我们需要配置一些什么东西?我们要输出波形到逻辑分析仪就要配置GPIO,有时候还得重映射就要配置AFIO,PWM功能要配置时钟和PWM的两个结构体,一个是ARR和CCR,还有一个是输出信号的模式的配置。下面我们就开始吧!

点击查看代码
void TIM4_CH1_PWM_Init(u16 per,u16 psc)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_OCInitTypeDef TIM_OCInitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	
	/* 开启时钟 */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	
	/*  配置GPIO的模式和IO口 */
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_12;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
	GPIO_Init(GPIOD,&GPIO_InitStructure);
	
	GPIO_PinRemapConfig(GPIO_Remap_TIM4,ENABLE);//改变指定管脚的映射	
	
	TIM_TimeBaseInitStructure.TIM_Period=per;   //自动装载值
	TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //分频系数
	TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //设置向上计数模式
	TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStructure);	
	
	TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;
	TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
	TIM_OC1Init(TIM4,&TIM_OCInitStructure); //输出比较通道1初始化
	
	TIM_OC1PreloadConfig(TIM4,TIM_OCPreload_Enable); //使能TIMx在 CCR1 上的预装载寄存器
	TIM_ARRPreloadConfig(TIM4,ENABLE);//使能预装载寄存器
	
	TIM_Cmd(TIM4,ENABLE); //使能定时器

重映射了为什么是这个引脚呢?这就要去看中文参考手册的8.3.7定时器复用功能重映射章节了

下面是主函数的内容

点击查看代码
int main()
{
	u16 i=0;  
	u8 fx=0;
	SysTick_Init(72);
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  //中断优先级分组 分2组
	LED_Init();
	TIM4_CH1_PWM_Init(500,72-1); //频率是2Kh
	
	while(1)
	{
		
		if(fx==0)
		{
			i++;
			if(i==300)
			{
				fx=1;
			}
		}
		else
		{
			i--;
			if(i==0)
			{
				fx=0;
			}
		}
		TIM_SetCompare1(TIM4,i);  //i值最大可以取499,因为ARR最大值是499.
		LED1=!LED1;
		delay_ms(100);	
	}
}

切记,在更换输出通道或定时器时一点要更改想要的函数以及变量,例如
TIM_SetCompare1(TIM4,i);
在换为TIM3,CH2时应该为
TIM_SetCompare2(TIM3,i);
其他的函数如上设置就可以了。

标签:ARR,定时器,波形,TIM4,TIMx,TIM,GPIO,PWM
来源: https://www.cnblogs.com/CottonTAT/p/16456282.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有