一、PWM介绍
pwm的工作电路
它的四种时钟信号
1.1 PWM的频率
1.2 PWM的周期
1.3 总结
二,pwm的工作设置
1. 选择合适的定时器模块
ARM 芯片通常有多个通用定时器(General Purpose Timer,GPT)可供选择用于产生 PWM 信号,需要根据具体的应用需求,比如所需的定时精度、PWM 频率范围等,来选定一个合适的定时器。查看芯片手册确定所选定时器对应的寄存器地址范围等相关信息。
2. 时钟配置
时钟源选择:
通过时钟源选择寄存器,从可用的时钟源(如内部系统时钟、外部时钟引脚输入等)中挑选适合的时钟信号来驱动定时器。如前文所述,依据不同的应用场景,像需要高精度同步时可选择系统主时钟分频后的时钟;对精度要求不高且注重功耗时,可选内部低频时钟等。按照芯片手册对相应寄存器位进行赋值操作来确定时钟源。
预分频设置:
使用预分频设置寄存器对选定的时钟源进行分频处理,以获得期望的计数时钟频率。根据想要达到的 PWM 频率以及定时器的计数特性,设置合适的分频系数。比如,如果定时器的计数器是 32 位,期望 PWM 频率为 1kHz,而系统时钟频率为 10MHz,可能就需要通过合适的分频使得最终输入到定时器计数部分的时钟频率满足能产生该 1kHz 频率 PWM 的要求,同样按寄存器位规定写入相应的值来配置分频。
3. 定时器工作模式配置
设置定时器为 PWM 模式:
在定时器的控制寄存器中,有专门的位用于配置定时器的工作模式。找到对应设置为 PWM 模式的位并将其置为相应的值(通常按芯片手册规定,比如置 1 表示选择 PWM 模式等),使定时器进入可产生 PWM 信号的工作状态。
确定计数方向和周期:
根据需要设置定时器计数器的计数方向(向上计数、向下计数或向上向下同时计数),一般通过控制寄存器中的相关位来配置。然后,通过周期设置寄存器来设定计数的周期,也就是 PWM 信号的周期对应的计数值。例如,如果定时器是向上计数,且期望 PWM 周期对应的计数值为 1000(这个值取决于定时器的位数以及预分频后的时钟频率等因素),就在周期设置寄存器中写入 1000。
4. PWM 占空比设置
配置比较寄存器:
对于每个定时器通道(通常有多个通道可同时产生 PWM 信号,用于控制多个不同的外部设备等),都有对应的比较寄存器。占空比的设置就是通过调整这些比较寄存器的值来实现的。比较寄存器的值与计数器的值进行比较,当计数器的值达到比较寄存器的值时,PWM 信号的电平就会发生翻转(比如从高电平变为低电平或者反之)。
计算占空比对应的比较寄存器值,公式一般为:比较寄存器值 = 周期计数值 × 期望占空比(以分数形式表示,如期望占空比为 50%,则为 0.5)。按照计算结果将相应的值写入比较寄存器中。
5. 死区时间设置(如果需要)
配置死区寄存器(部分芯片支持):
在一些应用中,比如控制电机等感性负载时,为避免上下桥臂同时导通造成短路等故障,需要设置死区时间。通过对应的死区寄存器来设置该时间,按照芯片手册规定的单位和计算方法,将所需死区时间对应的数值写入寄存器中,使定时器在产生 PWM 信号时,能在电平翻转的间隙插入相应的死区时间。
6. 使能定时器及相关中断(可选,根据需求)
使能定时器:
在完成上述各项配置后,通过控制寄存器中的使能位(通常为某个特定位,置 1 表示使能定时器开始计数工作)将定时器使能,使其开始按照设定的模式、周期、占空比等产生 PWM 信号。
使能中断(若有需求):
如果需要在 PWM 周期的某些特定时刻(比如计数到周期开始、结束或者比较值匹配时)触发中断来执行额外的任务,如更新占空比、记录相关数据等,可以在定时器的中断使能寄存器中设置相应的中断使能位,开启对应的中断功能,并且在中断服务程序中编写相应的处理代码。
三,代码案例
#include "pwm.h"
//管脚初始化
void pwm_gpio()
{
IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO09 &= ~(0xf << 0);
}
//pwm初始化
void pwm_init()
{
PWM2->PWMCR &= ~(0x1<<0);
PWM2->PWMCR |= (0x1<<3);
while (PWM2->PWMCR &(0x1<<3))
{
/* code */
}
PWM2->PWMCR &= ~(0x3<<16);
PWM2->PWMCR |= (0x1<<16);
PWM2->PWMCR &= ~(0xfff<<4);
PWM2->PWMCR |= (0x41<<4);
PWM2->PWMPR = PERIOD -2;
}
//打开pwm
void pwm_on()
{
PWM2->PWMCR |= (0x1<<0);
}
//关闭pwm
void pwm_off()
{
PWM2->PWMCR &= ~(0x1<<0);
}
void pwm_set_val(int val)
{
PWM2->PWMSAR = val;
}