基于通用定时器的PWM波形生成
作者:互联网
今天终于写到PWM了,关于PWM是什么我这里不再赘述,下面我们来看看通用定时器的PWM模式吧!
脉冲宽度调制模式可以产生一个由TIMx_ARR寄存器确定频率、由TIMx_CCRx寄存器确定占空比的信号。ARR是啥?可以简单记为从0数到ARR(向上计数)或从ARR数到0(向下计数),我们的TIM是16位的,所以ARR取值范围是0~65535。CCR则是当CNT(计数器的值)小于CCR是为1或者0,具体取决于PWM模式和输出极性。
我们再仔细看看输出模式,有边沿对齐和中央对齐,用的便是计数器的向上计数、向下计数和中央对齐模式。
上图是下图为TIMx_ARR=8时边沿对齐的向上计数的PWM波形实例。大家看各个CCR配置下的OCXREF即可。在这个模式中,有效电平是从复位后立刻生效的,到CNT不再小于CCR为止,应该很好理解吧。注意,在向下计数模式中产生无法占空比为0的波形。
上图给出了一些中央对齐的PWM波形的例子
- TIMx_ARR=8
- PWM模式1
- TIMx_CR1寄存器中的CMS=01,在中央对齐模式1时,当计数器向下计数时设置比较标志。
使用中央对齐模式的提示:
- 进入中央对齐模式时,使用当前的向上/向下计数配置;这就意味着计数器向上还是向下计数取决于TIMx_CR1寄存器中DIR位的当前值。此外,软件不能同时修改DIR和CMS位。
- 不推荐当运行在中央对齐模式时改写计数器,因为这会产生不可预知的结果。特别地:
- 如果写入计数器的值大于自动重加载的值(TIMx_CNT>TIMx_ARR),则方向不会被更新。例如,如果计数器正在向上计数,它就会继续向上计数。
- 如果将0或者TIMx_ARR的值写入计数器,方向被更新,但不产生更新事件UEV。
- 使用中央对齐模式最保险的方法,就是在启动计数器之前产生一个软件更新(设置TIMx_EGR 位中的UG位),不要在计数进行过程中修改计数器的值。
下面就是编程环节了
先想想我们需要配置一些什么东西?我们要输出波形到逻辑分析仪就要配置GPIO,有时候还得重映射就要配置AFIO,PWM功能要配置时钟和PWM的两个结构体,一个是ARR和CCR,还有一个是输出信号的模式的配置。下面我们就开始吧!
点击查看代码
void TIM4_CH1_PWM_Init(u16 per,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
/* 开启时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
/* 配置GPIO的模式和IO口 */
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
GPIO_Init(GPIOD,&GPIO_InitStructure);
GPIO_PinRemapConfig(GPIO_Remap_TIM4,ENABLE);//改变指定管脚的映射
TIM_TimeBaseInitStructure.TIM_Period=per; //自动装载值
TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //分频系数
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //设置向上计数模式
TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStructure);
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
TIM_OC1Init(TIM4,&TIM_OCInitStructure); //输出比较通道1初始化
TIM_OC1PreloadConfig(TIM4,TIM_OCPreload_Enable); //使能TIMx在 CCR1 上的预装载寄存器
TIM_ARRPreloadConfig(TIM4,ENABLE);//使能预装载寄存器
TIM_Cmd(TIM4,ENABLE); //使能定时器
重映射了为什么是这个引脚呢?这就要去看中文参考手册的8.3.7定时器复用功能重映射章节了
下面是主函数的内容
点击查看代码
int main()
{
u16 i=0;
u8 fx=0;
SysTick_Init(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断优先级分组 分2组
LED_Init();
TIM4_CH1_PWM_Init(500,72-1); //频率是2Kh
while(1)
{
if(fx==0)
{
i++;
if(i==300)
{
fx=1;
}
}
else
{
i--;
if(i==0)
{
fx=0;
}
}
TIM_SetCompare1(TIM4,i); //i值最大可以取499,因为ARR最大值是499.
LED1=!LED1;
delay_ms(100);
}
}
切记,在更换输出通道或定时器时一点要更改想要的函数以及变量,例如
TIM_SetCompare1(TIM4,i);
在换为TIM3,CH2时应该为
TIM_SetCompare2(TIM3,i);
其他的函数如上设置就可以了。
标签:ARR,定时器,波形,TIM4,TIMx,TIM,GPIO,PWM 来源: https://www.cnblogs.com/CottonTAT/p/16456282.html