【无标题】

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

深入了解STM32定时器原理,掌握脉宽调制pwm生成方法。

一. 使用STM32F103的 Tim2~Tim5其一定时器的某一个通道pin(与GPIOx管脚复用,见下图),连接一个LED,用定时器计数方式,控制LED以2s的频率周期性地亮-灭。

二. 接上,采用定时器pwm模式,让 LED 以呼吸灯方式渐亮渐灭,周期为1~2秒,自己调整到一个满意效果。使用Keil虚拟示波器,观察 pwm输出波形。

三. 再接上,采用定时器的另外一个通道,编程采集上面的pwm输出信号,获得其周期和脉宽,并重定向输出到串口显示。

一、介绍

 脉冲宽度调制(PWM),是英文 “Pulse Width Modulation”的缩写,简 称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种 非常有效的技术。简单一点,就是对脉冲宽度的控制。 STM32 的定时器除了 TIM6 和 7 。其他的定时器都可以用来产生 PWM 输出。其 中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出。而通用定时 器也能同时产生多达 4路的 PWM 输出,这样, STM32 最多可以同时产生 30 路48 PWM 输出。
 输出比较:当计数器CNT的值和比较器CCR(Capture Compare Register)的值相等的时候,输出信号的极性就会改变。例如翻转极性,拉高极性,或者拉低极性。直到CNT的值等于ARR的值时,再次发生跳变。此时一个周期完整结束。
例如 psc配置71,period(ARR)配置999。也就是我们之前的1ms计一次。那么CCR的值配置为200。
假设最开始是高电平,每次CNT+1,加到200的时候,电平翻转,再走完剩下的800,电平再次翻转。实现百分之20占空比的方波。

在这里插入图片描述

二、接上,采用定时器pwm模式,让 LED 以呼吸灯方式渐亮渐灭,周期为1~2秒,自己调整到一个满意效果。使用Keil虚拟示波器,观察 pwm输出波形。再接上,采用定时器的另外一个通道,编程采集上面的pwm输出信号,获得其周期和脉宽,并重定向输出到串口显示。

代码如下:

void TIM4_PWM_Init(u16 arr,u16 psc)
{  
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;
	
 
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);	//使能定时器4时钟
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO , ENABLE);  //使能GPIO外设和AFIO复用功能模块时钟
	
 
 
   //设置该引脚为复用输出功能,输出TIM4 CH2的PWM脉冲波形	GPIOB.7
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; //TIM4_CH2
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO
	
 
   //初始化TIM4
	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
	
	//初始化TIM4 Channel 2 PWM模式	 
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
 	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性:TIM输出比较极性低
	TIM_OC2Init(TIM4, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM4 OC2
 
	TIM_CtrlPWMOutputs(TIM4,ENABLE);	
 
	TIM_OC2PreloadConfig(TIM4, TIM_OCPreload_Enable);  //使能TIM4在CCR2上的预装载寄存器
 
	TIM_ARRPreloadConfig(TIM4, ENABLE); 
 
	TIM_Cmd(TIM4, ENABLE);  //使能TIM4
	
 
}

在这里插入图片描述
完整配置代码:

void TIM3_Init(int psc,int arr)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	TIM_TimeBaseStructure.TIM_Period = arr;
	TIM_TimeBaseStructure.TIM_Prescaler =psc; 
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; 
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); 
	//设置PWM模式2
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; 
	//设置PWM输出使能
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	//设置脉冲(CCP)的值
	TIM_OCInitStructure.TIM_Pulse = 500; 
	//设置PWM输出极性
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
	//初始化TIM3输出结构体
	TIM_OC3Init(TIM3, &TIM_OCInitStructure);  
	TIM_OC4Init(TIM3, &TIM_OCInitStructure);  
	//使能通道3的预装载寄存器
	TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);  
	//使能通道4的预装载寄存器
	TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);  
	TIM_Cmd(TIM3, ENABLE); 
}

在这里插入图片描述
在这里插入图片描述
PWM控制颜色的亮度:

首先由于小灯泡是置低电平触发,所以我们先把初始化配置里的输出极性改为Low
主函数设置延时:
while (1)
{
for(i=0;i<100;i+=5)
{
TIM_SetCompare3(TIM3,i);
Delay(0xFFFFF);
}
for(i=100;i>0;i-=5)
{
TIM_SetCompare3(TIM3,i);
Delay(0xFFFFF);
}
}

中断代码:
//…省略全局变量…
void TIM4_IRQHandler(void)
{
//清除标志位
TIM_ClearITPendingBit(TIM4, TIM_IT_CC1);
//获取通道1和2的值
IC1Value = TIM_GetCapture1(TIM4);
IC2Value = TIM_GetCapture2(TIM4);
if (IC1Value != 0)
{
DutyCycle = (float)((IC2Value+1) * 100) / (IC1Value+1);
//这里的72就是刚刚输入捕获那边配置的分频数,如果配置的是36-1就要除36-1
Frequency = (SystemCoreClock/72-1)/(float)(IC1Value+1);
}
else
{
DutyCycle = 0;
Frequency = 0;
}
}

总结

结构体参数中Period是计数周期,即ARR;Prescaler是预分频器的值,即PSC;注意在配置参数时不要超出0~65535的范围;
预分频给少点,自动重装给多点,就是以高频率计比较多的数;预分频给多点,自动重装给少点,就是以高频率计比较少的数;两种方法的定时效果一致。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值