一、PWM简介
1.定义
脉冲宽度调制(PWM) 是一种数字信号,最常用于控制电路。该信号在预定义的时间和速度中设置为高(5v或3.3v)和低(0v)。通常,我们将PWM的高电平称为1,低电平为0。
2.主要参数
(1)PWM占空比
PWM信号保持高电平的时间百分比称为占空比。如果信号始终为高电平,则它处于100%占空比,如果它始终处于低电平,则占空比为0%。如图1所示,T1为占空比,T为一个PWM周期。
图1 图片来源于网络
(2)PWM的频率
PWM信号的频率决定PWM完成一个周期的速度。STM32的MDK编译器可以选择5MHZ,10MHZ,20MHZ和50MHZ。
二、PWM产生方式
通过STM32控制板,有两种方式能产生PWM,第一是利用普通IO口输出PWM,第二种是利用定时器的PWM的IO口或复用IO口。
1.普通IO口与PWM口
(1)PWM端口
STM32 的定时器除了 TIM6 和 7。其他的定时器都可以用来产生 PWM 输出。其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出。而通用定时器也能同时产生多达 4路的 PWM 输出,这样,STM32 最多可以同时产生 30 路 PWM 输出。
(2)普通IO口
一般能够输出PWM的端口都会在主要功能那一栏出现CHx的标志,而普通定时器没有出现这种标志。如图所示,上面的红框就是普通的定时器,不是专用的PWM端口。
图2 普通IO定时器与PWM定时器
(3)两者区别
1)一般而言,尽量选用PWM口进行PWM输出,因为普通IO口模拟PWM的输出频率越高,进入定时器中断的次数就越快,中断间隔的时间越短,如果再有其他类型的中断也要处理时,会因为中断的优先级嵌套等待响应,影响控制精度,PWM输出误差增大,也会影响其他如ADC等中断处理,甚至会较出现单片机逻辑出错,死机或者跑飞的情况。
2)普通IO也可以输出PWM,只是产生PWM一般用转用芯片(开关电源上用的较多)或者单片机的PWM内置模块如定时器,很小直接用MCU的IO口线直接输出因为那样太耗MCU资源了。
(4)STM32f103c8t6的PWM口
因为自己在用stm32最小系统,因此在此贴出其PWM口配置。
[注]不是所有的芯片都有重映像功能的,STM32f103c8t6这四个定时器就不需要重映像。
详细配置如下:
TIM1_CH1->PA8;
TIM1_CH2->PA9;
TIM1_CH3->PA10;
TIM1_CH4->PA11;
TIM2_CH1->PA0;
TIM2_CH2->PA1;
TIM2_CH3->PA2;
TIM2_CH4->PA3;
TIM3_CH1->PA6;
TIM3_CH2->PA7;
TIM3_CH3->PB0;
TIM3_CH4->PB1;
TIM4_CH1->PB6;
TIM4_CH1->PB7;
TIM4_CH1->PB8;
TIM4_CH1->PB9;
2.普通IO口产生PWM
(1)方法:定时器中断
普通IO口如何产生一个pwm?其实就是通过一个高低电平周期性的变化。这种思想很重要,确定频率就可以确定周期(T=1/f)也就是在一个周期内产生pwm的时间可以确定下来了。
如何改变占空比?确定了时间,高电平的时间不就是想要的占空比么,比如要产生一个频率1khz,占空比为70%的pwm,根据频率我们知道了周期为1ms,产生一个占空比为70%的不就是0.7ms的时间给高电平么,(我们用定时器中断的方式,使0.1ms产生一次中断,计数中断次数,中断处理函数前七次中断都给高电平就ok了。
参考链接:https://blog.csdn.net/m0_51095029/article/details/116426226
代码如下(示例)
//#include "stm32f10x.h"
#include "stdio.h"
#include "usart.h"
#include "tim.h"
#include "led.h"
#include "misc.h"
void TIM2_NVIC(void);
void TIM2_Init(void);
unsigned char ucLed;
unsigned char ucLCK;
int main(void)
{
SysTick_Config(72000); // 定时1ms(HCLK = 72MHz)
TIM2_Init();
TIM2_NVIC();
LED_Init();
while(1)
{
LED_Disp(ucLed);
}
}
//unsigned int count;
//中断服务函数
unsigned int count=0;
unsigned int i;
void TIM2_IRQHandler(void)
{ count++;//计中断次数
if(TIM_GetITStatus(TIM2,TIM_IT_Update) != RESET)
{
if(count%10<i)//i:改变占空比值,这里i为变量,且让占空比一直变化
ucLed =0xff;//高电平
else
ucLed =0;
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
}
}
void TIM2_NVIC(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断分组
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;//设置TIM2中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//抢占优先级为0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//响应优先级为1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能中断源
NVIC_Init(&NVIC_InitStructure);
}
void TIM2_Init(void)//0.1ms定时
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
// RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_TimeBaseInitStruct.TIM_Prescaler = (2-1);//预分屏系数
TIM_TimeBaseInitStruct.TIM_Period = (36000/10)-1;//自动重载计数周期值
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//设置为向上计数方式
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;//时钟分频系数
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);
TIM_ClearFlag(TIM2,TIM_FLAG_Update);//清除中断
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//使能TIM2的更新中断
TIM_Cmd(TIM2, ENABLE);//使能TIM2定时器
}
//此函数必须有
void SysTick_Handler(void)
{
//ucLCK++;
if(ucLCK++%500==0)
{
i++;
if(i==10)
i=0;
}
}
3.PWM口产生PWM
(1)方法:比较匹配+溢出中断
(2)使用前的基本知识
- 寄存器
- 定时器中断相关寄存器:CNT、ARR、PSC、 CR1
(1)计数器当前寄存器CNT
(2)预分频寄存器PSC
(3)自动重装载寄存器PSC
(4)控制寄存器 CR1
- 控制 PWM 的输出寄存器:CCMR1/2、CCER、CCR1~4、BDTR
(1)捕获/比较模式寄存器( TIMx_CCMR1/2)
(2)捕获/比较使能寄存器( TIMx_CCER)
(3)捕获/比较寄存器( TIMx_CCR1~4)
(4)刹车和死区寄存器( TIMx_BDTR)
[注]刹车和死区寄存器( TIMx_BDTR)仅在高级定时器中使用,普通定时器只需要配置前三个寄存器即可。
有关这几个寄存器的学习内容请点击下面的链接
原文链接:https://blog.csdn.net/wwt18811707971/article/details/74906149
- 定时器
- 定时器框图
将通用定时器分为四个部分:
1,选择时钟
2,时基电路
3,输入捕获
4,输出比较
- PWM工作原理
- 工作框图
1,TIMx_CCMR1寄存器的OC1M[2:0]位,设置输出模式控制器
110:PWM模式1
111:PWM模式2
2,计数器值TIMx_CNT与通道1捕获比较寄存器CCR1进行比较,通过比较结果输出有效电平和无效电平
OC1REF=0 无效电平
OC1REF=1 无效电平
3,通过输出模式控制器产生的信号
TIMx_CCER寄存器的CC1P位,设置输入/捕获通道1输出极性
0:高电平有效
1:低电平有效
4,TIMx_CCER:CC1E位控制输出使能电路,信号由此输出到对应引脚
0:关闭
1:开启
2.占空比产生原理
如图为向上计数:
定时器重装载值为ARR,比较值CCRx
t时刻对计数器值和比较值进行比较
如果计数器值小于CCRx值,输出低电平
如果计数器值大于CCRx值,输出高电平
PWM的一个周期
定时器从0开始向上计数
当0-t1段,定时器计数器TIMx_CNT值小于CCRx值,输出低电平
t1-t2段,定时器计数器TIMx_CNT值大于CCRx值,输出高电平
当TIMx_CNT值达到ARR时,定时器溢出,重新向上计数...循环此过程
至此一个PWM周期完成
影响因素
ARR : 决定PWM周期(在时钟频率一定的情况下,当前为默认内部时钟CK_INT)
CCRx : 决定PWM占空比(高低电平所占整个周期比例)
(3)PWM配置过程
这里参考原子哥的TIM3时钟产生一个PWM的过程。
(4)PWM口输出示例
/*
***************************************************
实验功能:
通过比较和溢出功能,模拟pwm输出,在PC8-PC15输出可变pwm
***************************************************
*/
#include "stdio.h"
#include "led.h"
#include "misc.h"
void TIM2_Config(uint16_t duty2);
unsigned char ucLed;
unsigned int Compare2=100;
unsigned int ulTick;
int main(void)
{
SysTick_Config(72000); // 定时1ms(HCLK = 72MHz)
TIM2_Config(999/4); //25%
TIM_SetCompare2(TIM2,Compare2);//直接调节占空比函数
LED_Init();
while(1)
{
if(ulTick%1000==0)
{
Compare2+=50;
if(Compare2>999)
Compare2=100;
TIM_SetCompare2(TIM2,Compare2);
}
}
}
//输出比较
void TIM2_Config(uint16_t duty1) //TIM2 CH2
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
//RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_TimeBaseStructure.TIM_Period = 999; //1KHz //自动重装载值
TIM_TimeBaseStructure.TIM_Prescaler = 71; //预分频系数
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//时钟分频系数
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //基本定时器配置
TIM_ClearFlag(TIM2,TIM_FLAG_Update);//清除中断
TIM_ITConfig(TIM2,TIM_IT_Update|TIM_IT_CC2,ENABLE);//使能TIM2的更新中断
TIM_PrescalerConfig(TIM2,71, TIM_PSCReloadMode_Immediate); // TIM2 预分频值 预分频重载模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式,脉冲宽度调制模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable;//禁用比较输出功能
TIM_OCInitStructure.TIM_Pulse = duty1;//占空比
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;//设置比较输出有效电平
TIM_OC2Init(TIM2, &TIM_OCInitStructure);//通道二
TIM_OC2PreloadConfig(TIM2,TIM_OCPreload_Enable);//使能寄存器TIM_CCMR1
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断分组
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;//设置TIM2中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//抢占优先级为0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//响应优先级为0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能中断源
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM2, ENABLE);//使能TIM2定时计数器
}
//中断处理函数
void TIM2_IRQHandler(void)
{
if(TIM_GetITStatus(TIM2,TIM_IT_Update) != RESET) //溢出中断
{
ucLed = 0x00; //关闭所有LED
LED_Disp(ucLed);
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
}
else if(TIM_GetITStatus(TIM2,TIM_IT_CC2) != RESET) //比较匹配
{
ucLed = 0xff;//打开所有LED
LED_Disp(ucLed);
TIM_ClearITPendingBit(TIM2,TIM_IT_CC2);
}
}
//此函数必须有
void SysTick_Handler(void)
{
ulTick++;
}
总结
本人在学习STM32过程中发现网上的PWM相关知识比较散乱,对于小白或新手而言会有很多不了解的地方。因此,这里结合自己的学习过程,将PWM这一版块的知识整合,如有错误之处,请批评指正!
参考链接归纳
链接:
霁风AI:STM32学习笔记一一PWM 输出
位文杰TOP:STM32 PWM基本知识及配置过程
菜鸟江多多:STM32普通io口模拟pwm输出的三种方法
版权声明:本文为CSDN博主「笛卡尔的叹息」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/dgut13432976621/article/details/120062700
一、PWM简介
1.定义
脉冲宽度调制(PWM) 是一种数字信号,最常用于控制电路。该信号在预定义的时间和速度中设置为高(5v或3.3v)和低(0v)。通常,我们将PWM的高电平称为1,低电平为0。
2.主要参数
(1)PWM占空比
PWM信号保持高电平的时间百分比称为占空比。如果信号始终为高电平,则它处于100%占空比,如果它始终处于低电平,则占空比为0%。如图1所示,T1为占空比,T为一个PWM周期。
图1 图片来源于网络
(2)PWM的频率
PWM信号的频率决定PWM完成一个周期的速度。STM32的MDK编译器可以选择5MHZ,10MHZ,20MHZ和50MHZ。
二、PWM产生方式
通过STM32控制板,有两种方式能产生PWM,第一是利用普通IO口输出PWM,第二种是利用定时器的PWM的IO口或复用IO口。
1.普通IO口与PWM口
(1)PWM端口
STM32 的定时器除了 TIM6 和 7。其他的定时器都可以用来产生 PWM 输出。其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出。而通用定时器也能同时产生多达 4路的 PWM 输出,这样,STM32 最多可以同时产生 30 路 PWM 输出。
(2)普通IO口
一般能够输出PWM的端口都会在主要功能那一栏出现CHx的标志,而普通定时器没有出现这种标志。如图所示,上面的红框就是普通的定时器,不是专用的PWM端口。
图2 普通IO定时器与PWM定时器
(3)两者区别
1)一般而言,尽量选用PWM口进行PWM输出,因为普通IO口模拟PWM的输出频率越高,进入定时器中断的次数就越快,中断间隔的时间越短,如果再有其他类型的中断也要处理时,会因为中断的优先级嵌套等待响应,影响控制精度,PWM输出误差增大,也会影响其他如ADC等中断处理,甚至会较出现单片机逻辑出错,死机或者跑飞的情况。
2)普通IO也可以输出PWM,只是产生PWM一般用转用芯片(开关电源上用的较多)或者单片机的PWM内置模块如定时器,很小直接用MCU的IO口线直接输出因为那样太耗MCU资源了。
(4)STM32f103c8t6的PWM口
因为自己在用stm32最小系统,因此在此贴出其PWM口配置。
[注]不是所有的芯片都有重映像功能的,STM32f103c8t6这四个定时器就不需要重映像。
详细配置如下:
TIM1_CH1->PA8;
TIM1_CH2->PA9;
TIM1_CH3->PA10;
TIM1_CH4->PA11;
TIM2_CH1->PA0;
TIM2_CH2->PA1;
TIM2_CH3->PA2;
TIM2_CH4->PA3;
TIM3_CH1->PA6;
TIM3_CH2->PA7;
TIM3_CH3->PB0;
TIM3_CH4->PB1;
TIM4_CH1->PB6;
TIM4_CH1->PB7;
TIM4_CH1->PB8;
TIM4_CH1->PB9;
2.普通IO口产生PWM
(1)方法:定时器中断
普通IO口如何产生一个pwm?其实就是通过一个高低电平周期性的变化。这种思想很重要,确定频率就可以确定周期(T=1/f)也就是在一个周期内产生pwm的时间可以确定下来了。
如何改变占空比?确定了时间,高电平的时间不就是想要的占空比么,比如要产生一个频率1khz,占空比为70%的pwm,根据频率我们知道了周期为1ms,产生一个占空比为70%的不就是0.7ms的时间给高电平么,(我们用定时器中断的方式,使0.1ms产生一次中断,计数中断次数,中断处理函数前七次中断都给高电平就ok了。
参考链接:https://blog.csdn.net/m0_51095029/article/details/116426226
代码如下(示例)
//#include "stm32f10x.h"
#include "stdio.h"
#include "usart.h"
#include "tim.h"
#include "led.h"
#include "misc.h"
void TIM2_NVIC(void);
void TIM2_Init(void);
unsigned char ucLed;
unsigned char ucLCK;
int main(void)
{
SysTick_Config(72000); // 定时1ms(HCLK = 72MHz)
TIM2_Init();
TIM2_NVIC();
LED_Init();
while(1)
{
LED_Disp(ucLed);
}
}
//unsigned int count;
//中断服务函数
unsigned int count=0;
unsigned int i;
void TIM2_IRQHandler(void)
{ count++;//计中断次数
if(TIM_GetITStatus(TIM2,TIM_IT_Update) != RESET)
{
if(count%10<i)//i:改变占空比值,这里i为变量,且让占空比一直变化
ucLed =0xff;//高电平
else
ucLed =0;
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
}
}
void TIM2_NVIC(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断分组
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;//设置TIM2中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//抢占优先级为0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//响应优先级为1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能中断源
NVIC_Init(&NVIC_InitStructure);
}
void TIM2_Init(void)//0.1ms定时
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
// RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_TimeBaseInitStruct.TIM_Prescaler = (2-1);//预分屏系数
TIM_TimeBaseInitStruct.TIM_Period = (36000/10)-1;//自动重载计数周期值
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//设置为向上计数方式
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;//时钟分频系数
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);
TIM_ClearFlag(TIM2,TIM_FLAG_Update);//清除中断
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//使能TIM2的更新中断
TIM_Cmd(TIM2, ENABLE);//使能TIM2定时器
}
//此函数必须有
void SysTick_Handler(void)
{
//ucLCK++;
if(ucLCK++%500==0)
{
i++;
if(i==10)
i=0;
}
}
3.PWM口产生PWM
(1)方法:比较匹配+溢出中断
(2)使用前的基本知识
- 寄存器
- 定时器中断相关寄存器:CNT、ARR、PSC、 CR1
(1)计数器当前寄存器CNT
(2)预分频寄存器PSC
(3)自动重装载寄存器PSC
(4)控制寄存器 CR1
- 控制 PWM 的输出寄存器:CCMR1/2、CCER、CCR1~4、BDTR
(1)捕获/比较模式寄存器( TIMx_CCMR1/2)
(2)捕获/比较使能寄存器( TIMx_CCER)
(3)捕获/比较寄存器( TIMx_CCR1~4)
(4)刹车和死区寄存器( TIMx_BDTR)
[注]刹车和死区寄存器( TIMx_BDTR)仅在高级定时器中使用,普通定时器只需要配置前三个寄存器即可。
有关这几个寄存器的学习内容请点击下面的链接
原文链接:https://blog.csdn.net/wwt18811707971/article/details/74906149
- 定时器
- 定时器框图
将通用定时器分为四个部分:
1,选择时钟
2,时基电路
3,输入捕获
4,输出比较
- PWM工作原理
- 工作框图
1,TIMx_CCMR1寄存器的OC1M[2:0]位,设置输出模式控制器
110:PWM模式1
111:PWM模式2
2,计数器值TIMx_CNT与通道1捕获比较寄存器CCR1进行比较,通过比较结果输出有效电平和无效电平
OC1REF=0 无效电平
OC1REF=1 无效电平
3,通过输出模式控制器产生的信号
TIMx_CCER寄存器的CC1P位,设置输入/捕获通道1输出极性
0:高电平有效
1:低电平有效
4,TIMx_CCER:CC1E位控制输出使能电路,信号由此输出到对应引脚
0:关闭
1:开启
2.占空比产生原理
如图为向上计数:
定时器重装载值为ARR,比较值CCRx
t时刻对计数器值和比较值进行比较
如果计数器值小于CCRx值,输出低电平
如果计数器值大于CCRx值,输出高电平
PWM的一个周期
定时器从0开始向上计数
当0-t1段,定时器计数器TIMx_CNT值小于CCRx值,输出低电平
t1-t2段,定时器计数器TIMx_CNT值大于CCRx值,输出高电平
当TIMx_CNT值达到ARR时,定时器溢出,重新向上计数...循环此过程
至此一个PWM周期完成
影响因素
ARR : 决定PWM周期(在时钟频率一定的情况下,当前为默认内部时钟CK_INT)
CCRx : 决定PWM占空比(高低电平所占整个周期比例)
(3)PWM配置过程
这里参考原子哥的TIM3时钟产生一个PWM的过程。
(4)PWM口输出示例
/*
***************************************************
实验功能:
通过比较和溢出功能,模拟pwm输出,在PC8-PC15输出可变pwm
***************************************************
*/
#include "stdio.h"
#include "led.h"
#include "misc.h"
void TIM2_Config(uint16_t duty2);
unsigned char ucLed;
unsigned int Compare2=100;
unsigned int ulTick;
int main(void)
{
SysTick_Config(72000); // 定时1ms(HCLK = 72MHz)
TIM2_Config(999/4); //25%
TIM_SetCompare2(TIM2,Compare2);//直接调节占空比函数
LED_Init();
while(1)
{
if(ulTick%1000==0)
{
Compare2+=50;
if(Compare2>999)
Compare2=100;
TIM_SetCompare2(TIM2,Compare2);
}
}
}
//输出比较
void TIM2_Config(uint16_t duty1) //TIM2 CH2
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
//RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_TimeBaseStructure.TIM_Period = 999; //1KHz //自动重装载值
TIM_TimeBaseStructure.TIM_Prescaler = 71; //预分频系数
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//时钟分频系数
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //基本定时器配置
TIM_ClearFlag(TIM2,TIM_FLAG_Update);//清除中断
TIM_ITConfig(TIM2,TIM_IT_Update|TIM_IT_CC2,ENABLE);//使能TIM2的更新中断
TIM_PrescalerConfig(TIM2,71, TIM_PSCReloadMode_Immediate); // TIM2 预分频值 预分频重载模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式,脉冲宽度调制模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable;//禁用比较输出功能
TIM_OCInitStructure.TIM_Pulse = duty1;//占空比
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;//设置比较输出有效电平
TIM_OC2Init(TIM2, &TIM_OCInitStructure);//通道二
TIM_OC2PreloadConfig(TIM2,TIM_OCPreload_Enable);//使能寄存器TIM_CCMR1
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断分组
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;//设置TIM2中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//抢占优先级为0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//响应优先级为0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能中断源
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM2, ENABLE);//使能TIM2定时计数器
}
//中断处理函数
void TIM2_IRQHandler(void)
{
if(TIM_GetITStatus(TIM2,TIM_IT_Update) != RESET) //溢出中断
{
ucLed = 0x00; //关闭所有LED
LED_Disp(ucLed);
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
}
else if(TIM_GetITStatus(TIM2,TIM_IT_CC2) != RESET) //比较匹配
{
ucLed = 0xff;//打开所有LED
LED_Disp(ucLed);
TIM_ClearITPendingBit(TIM2,TIM_IT_CC2);
}
}
//此函数必须有
void SysTick_Handler(void)
{
ulTick++;
}
总结
本人在学习STM32过程中发现网上的PWM相关知识比较散乱,对于小白或新手而言会有很多不了解的地方。因此,这里结合自己的学习过程,将PWM这一版块的知识整合,如有错误之处,请批评指正!
参考链接归纳
链接:
霁风AI:STM32学习笔记一一PWM 输出
位文杰TOP:STM32 PWM基本知识及配置过程
菜鸟江多多:STM32普通io口模拟pwm输出的三种方法
版权声明:本文为CSDN博主「笛卡尔的叹息」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/dgut13432976621/article/details/120062700
暂无评论