前言
STM32学习之路——通用定时器库函数分析(为产生PWM)
前面我学习了使用通用定时器产生PWM,对相关库函数进行分析理解后,就产生了想要产生我所期望的PWM的想法,下面是我的对程序的一些更改,若有不对的地方,还请大家批评指正。
原理
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT __main
IMPORT SystemInit
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
这段代码是启动文件里的一部分,从这段代码可以看出,程序在进行编译的时候,首先执行SystemInit函数,然后在执行main函数,进过对SystemInit函数进行分析,这段代码实际上就是对系统的时钟进行了重配置。也就是说APB1以36MHz,APB2以72MHz时钟进行运行。通过时钟树进行分析,TIM2定时器的时钟频率需要再乘2,也就是72MHz。
所以输入定时器的时钟频率为72MHz。
产生PWM的原理是:计数器达到我在自动重装载寄存器中设定值后,恢复为零,在重新计数,而这一个过程就构成了输出PWM的一个周期。在捕获/比较寄存器1(CCR1)中我们设定了一个值,当计数器小于该值时,输出为低电平,反之为高电平,而这一过程就构成了PWM的占空比,按照这种思路将程序进行更改,达到想要的输出。
还有一种方法就是更改计数器的频率,进而实现PWM的周期。
从这个图中,我们可以看出,可以通过更改PSC预分频器的值来更改计数器的计数频率。
程序实现
首先需要进行一个小计算。
计数器的计数模式可以为1分频,2分频,4分频,我把他设置为1分频,所以计数频率也就是72MHz。
现在就有一个公式:
PWM周期=计数器周期x自动重装载寄存器设定值=(1/72000000)*自动重装载寄存器设定值
PWM占空比=捕获/比较寄存器1设定值/自动重装载寄存器设定值
变形后得:
自动重装载寄存器设定值=72000000/PWM频率
捕获/比较寄存器1设定值=PWM占空比x72000000/PWM频率
在程序中定义一个函数
void TIM2_CH1_PWMOut(uint32_t freq,float Duty_Ratio)//2000<=freq<=9000000,Duty_Ratio<1
{
uint16_t psc=0, x=0;
GPIO_InitTypeDef GPIO_Structure;
TIM_TimeBaseInitTypeDef TimeBaseStructure;
TIM_OCInitTypeDef Tim_OCInitypeStructure;
psc=72000000/freq;
x= (1-Duty_Ratio)*((72000000/freq));
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Perip h_AFIO,DISABLE);
//GPIO³õʼ»¯
GPIO_Structure.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_Structure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Structure.GPIO_Pin=GPIO_Pin_0;
GPIO_Init(GPIOA,&GPIO_Structure);
//TIM2³õʼ»¯
TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
TimeBaseStructure.TIM_Period=psc;
TimeBaseStructure.TIM_Prescaler=0;
TIM_TimeBaseInit(TIM2,&TimeBaseStructure);
//
Tim_OCInitypeStructure.TIM_OCMode=TIM_OCMode_PWM2;
Tim_OCInitypeStructure.TIM_OCPolarity=TIM_OCPolarity_High;
Tim_OCInitypeStructure.TIM_OutputState=TIM_OutputState_Enable;
TIM_OC1Init(TIM2,&Tim_OCInitypeStructure);
TIM_Cmd(TIM2,ENABLE);
TIM_SetCompare1(TIM2,x);
}
调试验证
一、在主函数中输入以以代码,设置的PWM周期为2000Hz,占空比为0.4。调试结果如下:
int main(void)
{
TIM2_CH1_PWMOut(2000,0.4);
while(1);
}
在主函数中输入以上代码,设置的PWM周期为2000Hz,占空比为0.4。调试结果如下:
从调试图中取得十个周期时间间隔为3.333424ms,所以一个周期也就是0.3333424ms,所以PWM的频率为2999Hz。占空比可以从波形中看出,大致相同。
二、设置的PWM周期为1MHz,占空比为0.4。调试结果如下:
从调试图中取得十个周期时间间隔为0.00676ms,所以一个周期也就是0.000676ms,所以PWM的频率为1.4MHz。占空比可以从波形中看出,大致相同。
二、设置的PWM周期为9MHz,占空比为0.4。调试结果如下:
从调试图中取得十个周期时间间隔为0.000833ms,所以一个周期也就是0.0000833ms,所以PWM的频率为12MHz。占空比可以从波形中看出,已经有些误差了。
总结
1、随着频率的增高,占空比的选取越来越不准。
这是由于捕获/比较寄存器1设定值=PWM占空比x72000000/PWM频率,而寄存器内的设定值只能为正数,随着PWM频率的升高,72000000/PWM频率就越来越小,而寄存器内的设定值只能为整数,所以导致了占空比的变化。
2、随着频率的增高,PWM的频率与设定间的误差在减少。