概述
STM32定时器输出pwm输出比较模式与PWM模式区别
一:PWM模式:
pwm模式就是最简单的输出pwm的方法,通过配置定时器的ARR寄存器来确定输出的频率,配置比较寄存器(CRR)来控制pwm的占空比,当CNT小于CRR输出一种电平,当CNT介于CRR与ARR之间时输出另一种电平。
但是由于四个通道使用一个定时器,ARR值一更改,四个通道都更改,所以无法使不同通道输出不同频率。
二:输出比较模式
输出比较模式就是当CNT达到CRR值时,翻转输出的电平,我们可以利用这一特性,实现不同通道输出不同频率,因为每一个通道均有自己的CRR。
(1)实现原理:
我们将ARR设置成一个值Y,令最初的CRR值为X,当CNT加载到X时,我们开启一个中断,在中断中,我们更改X的值,这样就可以实现频率与占空比控制。
由图可知,我们更改CRR值可以实现在一个ARR内,输出多个周期的方波,且只要**(CRR1+CRR2)N=ARR+1* ,(N为正整数)我们就可以实现稳定的pwm输出。
例如令ARR=65535,CRR1=4915,CRR2=3277,(CRR3与CRR4与前面重复就可,理解简单不在赘述)所以经过一个周期需要计数8192下,我们只需要将定时器时钟(72MHZ)进行8分频,就可以实现1KHZ,60%占空比的波形输出。
当我们的ARR设置不是65535时,我们需要在中断服务函数中判断读取到的CRR的值,若CRR的值大于ARR值,则令CRR=0,则可继续实现功能
例如:
u16 oc2crr1=3600;
u16 oc2crr2=900;
_Bool oc2_sta=0;
void TIM3_IRQHandler(void)
{
u16 capture=0;
u16 capture2=0;
if(TIM_GetITStatus(TIM3,TIM_IT_CC1)!=RESET)
{
TIM_ClearITPendingBit(TIM3,TIM_IT_CC1);
capture=TIM_GetCapture1(TIM3);
if(capture>=9000)
{
capture=0;
}
if(oc1_sta==0)
{
TIM_SetCompare1(TIM3,capture+oc1crr2);
oc1_sta=1;
}
else
{
TIM_SetCompare1(TIM3,capture+oc1crr1);
oc1_sta=0;
}
}
if(TIM_GetITStatus(TIM3,TIM_IT_CC2)!=RESET)
{
TIM_ClearITPendingBit(TIM3,TIM_IT_CC2);
capture2=TIM_GetCapture2(TIM3);//读当前CRR值
if(capture2>=9000)//判断crr值是否大于ARR
{
capture2 =0;
}
if(oc2_sta==0)
{
TIM_SetCompare2(TIM3,capture2+oc2crr2);
oc2_sta=1;
}
else
{
TIM_SetCompare2(TIM3,capture2+oc2crr1);
oc2_sta=0;
}
}
}
main
time3_initer(9000,7);//arr为9000;
补充说明:
简单函数介绍
1.更改CRR值的函数
TIM_SetCompare2();//设置TIM3的通道2CRR值
2.读取当前CRR值的函数
TIM_GetCapture2(TIM3);//读取通道2的TIM3CRR值
(2)代码实现
1.配置时钟:开启GPIO和定时器时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
2.配置gpio
GPIO_InitTypeDef GPIO_InitTypestu;
GPIO_InitTypestu.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitTypestu.GPIO_Pin=GPIO_Pin_6;
GPIO_InitTypestu.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(GPIOA,&GPIO_InitTypestu);
GPIO_InitTypestu.GPIO_Pin=GPIO_Pin_7;
GPIO_Init(GPIOA,&GPIO_InitTypestu);
3.配置定时器
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitTypestu;
TIM_TimeBaseInitTypestu.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInitTypestu.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInitTypestu.TIM_Period=arr;
TIM_TimeBaseInitTypestu.TIM_Prescaler=psc;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitTypestu);
4,.配置通道:注意要关闭 TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Disable);
TIM_OCInitTypeDef TIM_OCInitTypeSTU;
TIM_OCInitTypeDef TIM_OCInitTypeSSS;
TIM_OCInitTypeSTU.TIM_OCMode=TIM_OCMode_Toggle;
TIM_OCInitTypeSTU.TIM_OCPolarity=TIM_OCPolarity_Low;
TIM_OCInitTypeSTU.TIM_OutputState=TIM_OutputState_Enable;
TIM_OCInitTypeSTU.TIM_Pulse=oc1crr1;
TIM_OC1Init(TIM3,&TIM_OCInitTypeSTU);
TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Disable);
TIM_OCInitTypeSSS.TIM_OCMode=TIM_OCMode_Toggle;
TIM_OCInitTypeSSS.TIM_OCPolarity=TIM_OCPolarity_Low;//如果使用HIGH那么占空比计算应该相反,CRR1=3277,CRR2=4915
TIM_OCInitTypeSSS.TIM_OutputState=TIM_OutputState_Enable;
TIM_OCInitTypeSSS.TIM_Pulse=oc2crr1;
TIM_OC2Init(TIM3,&TIM_OCInitTypeSSS);
TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Disable);
5.开启中断
NVIC_InitTypeDST.NVIC_IRQChannel=TIM3_IRQn;
NVIC_InitTypeDST.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitTypeDST.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitTypeDST.NVIC_IRQChannelSubPriority=1;
NVIC_Init(&NVIC_InitTypeDST);
TIM_ITConfig(TIM3,TIM_IT_CC1|TIM_IT_CC2,ENABLE);
6.使能
TIM_Cmd(TIM3,ENABLE);
7:配置中断服务函数:记得清除标志位
u16 oc1crr1=4915;
u16 oc1crr2=3271;
_Bool oc1_sta=0;
u16 oc2crr1=3277;
u16 oc2crr2=819;
_Bool oc2_sta=0;
void TIM3_IRQHandler(void)
{
u16 capture=0;
u16 capture2=0;
if(TIM_GetITStatus(TIM3,TIM_IT_CC1)!=RESET)
{
TIM_ClearITPendingBit(TIM3,TIM_IT_CC1);//要清楚标志位 切记
capture=TIM_GetCapture1(TIM3);
if(oc1_sta==0)
{
TIM_SetCompare1(TIM3,capture+oc1crr2);
oc1_sta=1;
}
else
{
TIM_SetCompare1(TIM3,capture+oc1crr1);
oc1_sta=0;
}
}
if(TIM_GetITStatus(TIM3,TIM_IT_CC2)!=RESET)
{
TIM_ClearITPendingBit(TIM3,TIM_IT_CC2);
capture2=TIM_GetCapture2(TIM3);
if(oc2_sta==0)
{
TIM_SetCompare2(TIM3,capture2+oc2crr2);
oc2_sta=1;
}
else
{
TIM_SetCompare2(TIM3,capture2+oc2crr1);
oc2_sta=0;
}
}
}
(3)完整代码
a.time.c
#include "time.h"
u16 oc1crr1=4915;
u16 oc1crr2=3271;
_Bool oc1_sta=0;
u16 oc2crr1=3277;
u16 oc2crr2=819;
_Bool oc2_sta=0;
void time3_initer(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitTypestu;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitTypestu;
NVIC_InitTypeDef NVIC_InitTypeDST;
TIM_OCInitTypeDef TIM_OCInitTypeSTU;
TIM_OCInitTypeDef TIM_OCInitTypeSSS;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
GPIO_InitTypestu.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitTypestu.GPIO_Pin=GPIO_Pin_6;
GPIO_InitTypestu.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(GPIOA,&GPIO_InitTypestu);
GPIO_InitTypestu.GPIO_Pin=GPIO_Pin_7;
GPIO_Init(GPIOA,&GPIO_InitTypestu);
TIM_TimeBaseInitTypestu.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInitTypestu.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInitTypestu.TIM_Period=arr;
TIM_TimeBaseInitTypestu.TIM_Prescaler=psc;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitTypestu);
NVIC_InitTypeDST.NVIC_IRQChannel=TIM3_IRQn;
NVIC_InitTypeDST.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitTypeDST.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitTypeDST.NVIC_IRQChannelSubPriority=1;
NVIC_Init(&NVIC_InitTypeDST);
TIM_OCInitTypeSTU.TIM_OCMode=TIM_OCMode_Toggle;
TIM_OCInitTypeSTU.TIM_OCPolarity=TIM_OCPolarity_Low;
TIM_OCInitTypeSTU.TIM_OutputState=TIM_OutputState_Enable;
TIM_OCInitTypeSTU.TIM_Pulse=oc1crr1;
TIM_OC1Init(TIM3,&TIM_OCInitTypeSTU);
TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Disable);
TIM_OCInitTypeSSS.TIM_OCMode=TIM_OCMode_Toggle;
TIM_OCInitTypeSSS.TIM_OCPolarity=TIM_OCPolarity_Low;
TIM_OCInitTypeSSS.TIM_OutputState=TIM_OutputState_Enable;
TIM_OCInitTypeSSS.TIM_Pulse=oc2crr1;
TIM_OC2Init(TIM3,&TIM_OCInitTypeSSS);
TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Disable);
TIM_Cmd(TIM3,ENABLE);
TIM_ITConfig(TIM3,TIM_IT_CC1|TIM_IT_CC2,ENABLE);
}
void TIM3_IRQHandler(void)
{
u16 capture=0;
u16 capture2=0;
if(TIM_GetITStatus(TIM3,TIM_IT_CC1)!=RESET)
{
TIM_ClearITPendingBit(TIM3,TIM_IT_CC1);
capture=TIM_GetCapture1(TIM3);
if(oc1_sta==0)
{
TIM_SetCompare1(TIM3,capture+oc1crr2);
oc1_sta=1;
}
else
{
TIM_SetCompare1(TIM3,capture+oc1crr1);
oc1_sta=0;
}
}
if(TIM_GetITStatus(TIM3,TIM_IT_CC2)!=RESET)
{
TIM_ClearITPendingBit(TIM3,TIM_IT_CC2);
capture2=TIM_GetCapture2(TIM3);
if(oc2_sta==0)
{
TIM_SetCompare2(TIM3,capture2+oc2crr2);
oc2_sta=1;
}
else
{
TIM_SetCompare2(TIM3,capture2+oc2crr1);
oc2_sta=0;
}
}
}
b.time.h
#ifndef __TIME_H
#define __TIME_H
#include "stm32f10x.h"
void time3_initer(u16 arr,u16 psc);
#endif
c.main.c
#include "time.h"
#include "stm32f10x.h"
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
time3_initer(65535,7);
while(1)
{
}
}
最后
以上就是忐忑蜻蜓为你收集整理的学习笔记:stm32定时器翻转模式实现同一个定时器不同通道不同频率占空比输出的全部内容,希望文章能够帮你解决学习笔记:stm32定时器翻转模式实现同一个定时器不同通道不同频率占空比输出所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复