一、什么是PWM脉冲?
PWM (Pulse Width Modulation) 脉冲宽度调制,通常应用于惯性系统中,(不是不能即停的设备,因为如果设备不具有关心,那么运动是断断续续的,不具有连续性),通过脉宽调节输出不同的波形作用域受控对象。
二、 PWM中三个重要的参数
1.频率=1/Ts ;这个很好理解,就是在单位时间内输出的波形的个数啦。
2.占空比= Ton/Ts; 在一个脉冲周期内,脉冲波形中高电平的宽度占整个周期内波形宽度的比值。
3.分辨率=占空比变化步距,指PWM最小能设定到的高电平时间所占周期的比例,也即最小占空比,意思就是把一个周期的时间分成了多少份,如果是10份,那么占空比的精度就为10%。如果分成1000份,那么占空比的精度就为0.1%。譬如频率为600HZ的PWM,若最小能给到的时钟是60kHZ,则分辨率即为(1/60k)/(1/600)=1%。在同一个系统中,由于时钟不变,提高频率,则周期变小,分辨率会变大。(前面的话可能不太好理解,那我就以自己的大白话给大家解说一下吧: 说白了其意思就是说把一个波形脉冲分成了多少分,例如分辨率为0.1%,那就是把一个波形脉冲分割成了1000分,分别由不同份数的高低电平组个,例如占空比为50%d的脉冲,那就是有500份高电平,500份低电平,注意是连续的)
三、 PWM脉冲输出配置(重点来啦)
事实上,需要输出PWM脉冲,仅需要进行两部分寄存器的配置,分别是时基单元(前面定时器中断的时候已经详细说过这里不再赘述)、输出比较单元的配置。首先看一下基本的结构如图3所示。
定时器在不断进行计数,其CNT不断增大,(我这里说的是向上计数),同在不断的与CRR(使用者自己设定的值)寄存器的值进行比较,通过比较与CRR的值大小关系,与设定的模式进行工作,具体的模式如图4所示。
本试验使用的是PWM1 模式,计数的方式使用向上计数。其中计数从0到A点的工程中CNT<CRR,输出有效电平(高电平),A点到B点过程中CNT>=RCC,输出无效电平(低电平),这就完成了一个波形输出,不断的循环便能输出一系列波形。
四、 具体程序
好了废话不多说下面我们一起来看看具体的代码吧。这里是输出占空比 0---->100,100--->0不断变化的的脉冲波,其频率为1000HZ,分辨率为1%.
CODE :PWM.c
#include"pwm.h"
void PwmInit(void)
{
//打开定时器时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); //定时器2是通用定时器,其时钟挂在到APB1时钟线上
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA,ENABLE); //打开对应的GPIO的时钟,注意这里不同的外设可能挂载的时钟不同,所以需要看原理图,
GPIO_DeInit(GPIOA);// 注意这里的函数非常的重要,这里是将对应的GPIO端口初始化成默认的样子,因为这个端口可能在以前使用过,其他的配置可能发生了改变
GPIO_InitTypeDef GPIOC_LED_PWM_Init; // 定义GPIO的结构体,也就是外设的结构体
GPIOC_LED_PWM_Init.GPIO_Pin= GPIO_Pin_0; // 配置需要使用的引脚
GPIOC_LED_PWM_Init.GPIO_Mode=GPIO_Mode_AF_PP; //配置引脚的输出的模式,这里使用大额CH1输出波形,所以是复用模式
GPIOC_LED_PWM_Init.GPIO_Speed=GPIO_Speed_50MHz; // 配置输出的频率,这个在输入的时候不需要配置
GPIO_Init(GPIOA ,&GPIOC_LED_PWM_Init); // 使用初始化函数初始化刚刚定义的结构体,以及对应的GPIO端口
//配置定时器2的时钟源来自内部时钟源,其实这里系统默认的就是内部时钟,所以这一步配置可以省去
TIM_InternalClockConfig(TIM2);
//定时器结构体配置
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1 ; //内部时钟分频
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period=100-1; //定时器溢出值
TIM_TimeBaseInitStructure.TIM_Prescaler=720-1; //分频系数
TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0; //这里使用的是通用定时器没有复用计数功能,这里设置为0
//配置定时器2初始化
TIM_TimeBaseInit(TIM2 ,&TIM_TimeBaseInitStructure);
TIM_Cmd(TIM2,ENABLE); //使能定时器
//配置比较输出单元
TIM_OCInitTypeDef PwmStruct;
TIM_OCStructInit(&PwmStruct); //给结构体赋初值,保证结构体中每一个变量都有初始值,防止使用高级定时器的时钟时出现错误,应为通用定时器不具有某一个功能
PwmStruct.TIM_OCMode=TIM_OCMode_PWM1; // 输出模式
PwmStruct.TIM_Pulse=0; //CCR
PwmStruct.TIM_OutputState=ENABLE; // PWM 输出使能
PwmStruct.TIM_OCPolarity= TIM_OCPolarity_High;
TIM_OC1Init(TIM2,&PwmStruct);
}
//程序运行过程中设置不同的占空比
void PWM_SetCompare1(uint16_t Compare)
{
TIM_SetCompare1(TIM2 ,Compare);
}
CODE :main.c
int main(){
Led_funcing();
PwmInit();
uint8_t i;
while(1)
{
for(i=0;i<=100;i++)
{
PWM_SetCompare1(i);
delay(100);
}
for(i=0;i<=100;i++)
{
PWM_SetCompare1(100-i);
delay(100);
}
}
}
有条件的宝宝可以使用LED灯 马达自己模拟一下,我是用的是仿真模式输出。
好啦,今天就给大家分享到这里,如有错误和不合理的地方请大家指正。
标签:定时器,STM32,TIM,占空比,GPIO,PWM,时钟 From: https://www.cnblogs.com/Nic-zhang/p/17589275.html