stm32学习笔记-PWM

文章目录

  • 一、神兵:PWM基本知识
  • 二、利用stm32定时器实现PWM
    • 具体原理
    • stm32中PWM的相关配置
    • PWM输出管脚
  • 三、使用PWM实现呼吸灯。
    • 周期,占空比计算公式
    • 编程思路
    • 代码

一、神兵:PWM基本知识

抄自百度的定义:
Pulse Width Modulation 就是通常所说的PWM,译为脉冲宽度调制,简称脉宽调制。也就占空比。
脉冲宽度调制(PWM)是利用微处理器的数字信号对模拟电路进行控制的一种非常有效的技术。
PWM的优点:

  • 从处理器到被控系统信号都是数字形式的,无需进行数模转换。
  • 对噪声抵抗能力的增强.

总之,PWM既经济、节约空间、抗噪性能强,是一种值得广大工程师在许多设计应用中使用的有效技术。
提问:
由于计算机不能输出模拟电压,只能输出0 或5V 的的数字电压值。需要输出模拟电压时,怎么办?如需要输出一个 ,3.3V的电压 或者 2.7V的电压,怎么办?
这时请出我们的神兵利器:PWM
电压换算原理:
输出电压值计算公式:(接通时间/脉冲时间)*最大电压值
基本方法:通过改变 (接通时间/脉冲时间) 从而改变输出的电压值。
stm32学习笔记-PWM_第1张图片

  • 例子1:
    (接通时间/脉冲时间) = 3/4
    输出电压 = (接通时间/脉冲时间)*最大电压值 = 3/4 * 5 V = 3.75V
  • 例子2:
    (接通时间/脉冲时间) = 1/2
    输出电压 = (接通时间/脉冲时间)*最大电压值 = 1/2 * 5 V = 2.5V
  • 例子3:
    (接通时间/脉冲时间) = 1/5
    输出电压 = (接通时间/脉冲时间)*最大电压值 = 1/5 * 5 V = 1V

由上图可以看出,PWM有三个基本参数:

  1. 脉冲宽度变化幅度
  2. 脉冲周期
  3. 电压高度(5v)
  4. stm32学习笔记-PWM_第2张图片

二、利用stm32定时器实现PWM

具体原理

由基础知识知道一个PWM的方波的产生,我们需要考虑脉冲的周期、脉冲宽度变化幅度,电压高度。
stm32学习笔记-PWM_第3张图片

  1. 脉冲的周期的控制。
    可以利用定时器来产生脉冲的周期。
    定时器本质上是一个以单位时间为准的计数器,计数值可从0开始累加,也可从一个设定数值递减。每隔一个固定时间计时器的值加1或减1,当加到(或减到)到头时,会产生一个溢出信号,并将计时值清0重新计时。
    计数器计时开始表示周期开始,计数器溢出表示周期结束。 在计时器中设定ARR寄存器的值就可以设定脉冲的周期。
    stm32学习笔记-PWM_第4张图片
  2. 脉冲宽度变化幅度的控制。
    我们可以设定一个值,当计数器的值大于某个值时,就输出高电平(假设计数器值小于这个值时输出低电平),这样我们就实现了控制脉冲的宽度。在stm32中,定时器的CCRx(Capture/Compare Register)寄存器正好可以实现这样的功能。
    stm32学习笔记-PWM_第5张图片
    调整CCRx的值就可以调整输出高电平的比例,实现脉冲宽度的调制。 例如:提高CCRx的值就可以增加一个周期中高电平的比例。降低CCRx的值就可以减少一个周期中高电平的比例。
  3. 电压高度的控制。
    推挽输出就是电压固定为3.3V。不用控制。

相关寄存器:
stm32学习笔记-PWM_第6张图片

stm32中PWM的相关配置

  1. 配置定时器为PWM模式,有两种PWM模式。查看下图。
    stm32学习笔记-PWM_第7张图片
    stm32学习笔记-PWM_第8张图片
  2. 定义PWM模式中的有效电平。

stm32学习笔记-PWM_第9张图片
代码如下:

TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitstrue.TIM_OCMode = TIM_OCMode_ PWM1 ;// PWM模式1:CNT < CCR时输出有效电平
TIM_OCInitstrue . TIM_OCPolarity = TIM_OCPolarity_ High;//设置极性-有效电平为:高电平
TIM_OCInitstrue .TIM_Outputstate = TIM outputstate_Enable;// 输出使能
TIM_OC2Init (TIM3, &TIM_OCInitstrue) ;//TIM3的通道2 PWM 模式设置;前面的OC2表示通道2,TIM3表示定时器3

PWM输出管脚

stm32学习笔记-PWM_第10张图片
通过重映像功能,我们可以在其他管脚输出PWM方波。
stm32学习笔记-PWM_第11张图片
stm32学习笔记-PWM_第12张图片
stm32学习笔记-PWM_第13张图片
stm32学习笔记-PWM_第14张图片

三、使用PWM实现呼吸灯。

周期,占空比计算公式

  1. 周期:
    T=(TIMx_ARR+1)*(TIMx_PSC+1)/TIMxCLK
    其中,TIMxCLK是其时钟频率,若是晶振为8MHz的,一般为72MHz
  2. 占空比:
    (TIMx_CRRx/TIMx_ARR)*100%

编程思路

  1. 开启TIM3,GPIO,AFIO时钟。
  2. 配置TIM3_CH2重映射到PB5上。(由上面的映射表可知)
  3. 配置GPIO。(led1 PB_5管脚需进行重映射,设置为复用推挽输出)
  4. 配置TIM的计数值。(设置TIM3的ARR和PSC,计数模式)
  5. 配置PWM模式。
  6. 使能TIM,PWM的CCR预装载寄存器。
  7. 配置PWM的预装载值。(在主函数中设置)

代码

pwm.h

#ifndef PWM_H
#define PWM_H
#include "stm32f10x.h"

void TIM3_PWM_Init(u16 arr,u16 psc);//注意arr的值要大于CCR的值

#endif

pwm.c

#include "pwm.h"

void TIM3_PWM_Init(u16 arr,u16 psc)
{
	GPIO_InitTypeDef GPIOInitStructure;
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
	TIM_OCInitTypeDef TIM_OCInitStructure;

	//使能时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	
	//重映射
	GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);
	
	//配置GPIO为AFIO
	GPIOInitStructure.GPIO_Pin = GPIO_Pin_5;
	GPIOInitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIOInitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIOInitStructure);
	
	//初始化 TIM3
	TIM_TimeBaseStructure.TIM_Period = arr; //设置在自动重装载周期值
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置预分频值
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; //这个起到滤波的作用,默认0就行
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM 向上计数模式
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
	
	//初始化 TIM3 Channel2 PWM 模式
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择 PWM 模式 2
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性高
	TIM_OC2Init(TIM3, &TIM_OCInitStructure); //初始化外设 TIM3 OC2
	
	//使能TIM,CCR预装载寄存器
	TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能预装载寄存器
	TIM_Cmd(TIM3, ENABLE); //使能 TIM3
}

main.c

#include "stm32f10x.h"
#include "bsp_systick.h"
#include "led.h"
#include "exti.h"
#include "Tool.h"
#include "usart.h"
#include "pwm.h"

u8 wifiConnected = 0;
u8 cloudConnected = 0;
int main(void)
{
	u16 pwmValue=0;
	led_init();
	usart1_init(9600);
	TIM3_PWM_Init(2999,23); //24分频,PWM 频率=72M/24/3000=1000hz,周期为1ms
	
	led1 = 1;
	led2 = 1;
	printf("system start!\n");
	
	while(1)
	{
		SysTick_Delay_ms(1);
		TIM_SetCompare2(TIM3,pwmValue);
		pwmValue++;
		
		//大约3000ms完成一次渐亮
		if(pwmValue>2999)
			pwmValue=0;
	}
}


你可能感兴趣的:(stm32,stm32,嵌入式)