脉冲宽度调节器 PWM(Pulse Width Modulation)
PWM信号任然是数字的,依靠产生的矩形波,将矩形波的占空比作为模拟量(模拟电压)。
输出电压=(接通时间/周期时间)X 最大电压值
优点:无需模数(A/D)转换,从处理器到被控系统都是数字信号,可以将噪声影响降至最低,技术成本低,易于实现,控制灵活,抗噪声能力强。
TM4C123H6PM微控制器包含两个PWM模块(PWM Model,PWM0和PWM1),每个PWM模块中又有四个PWM发生器模块(PWMGenerator0~3)和一个控制模块,每个发生器模块又对应两个PWM输出(PWM Output),每个输出都有其对应的输出引脚,这些引脚许多都有复用,具体使用时需要设置为PWM输出模式。一个发生器模块有两个输出,意味着对同一个发生器模块的两个输出来说,PWM频率是相同的,但占空比可以是不同的。
PWM有两种计数模式Count-Down和Count-Up/Down
各寄存器的偏移地址在用户手册PWM中的Register Map中有表格,其中PWM0的基地址为0x4002.8000,PWM1的基地址为0x4002.9000。
PWMCTL 控制模块的寄存器,包含更新模式的位和字段等
PWMSYNC PWM 时基同步
PWMENABLE PWM输出使能
PWMnLOAD 存放Load重载值
PWMnCMPA 发生器寄存器 存放匹配(比较)值A
PWMnCMPB 存放匹配(比较)值B
PWMnINTEN PWM的中断和触发使能
PWMSignals
PWM脉冲宽度调制程序实例-三色循环呼吸灯
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_gpio.h"
#include "driverlib/sysctl.h"
#include "driverlib/rom.h"
#include "driverlib/gpio.h"
#include "driverlib/pwm.h"
#include "driverlib/fpu.h"
#include "driverlib/pin_map.h"
int main (void)
{
uint32_t R = 0;
uint32_t B = 0;
uint32_t G = 0;
//设置系统时钟为50MHz
SysCtlClockSet(SYSCTL_SYSDIV_1 |SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
SysCtlPWMClockSet(SYSCTL_PWMDIV_1);// PWM时钟配置:不分频
//使能
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1);
//配置PWM功能
GPIOPinConfigure(GPIO_PF1_M1PWM5);
GPIOPinConfigure(GPIO_PF2_M1PWM6);
GPIOPinConfigure(GPIO_PF3_M1PWM7);
GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);
//配置PWM发生器
PWMGenConfigure(PWM1_BASE,PWM_GEN_2,PWM_GEN_MODE_UP_DOWN|PWM_GEN_MODE_NO_SYNC);
PWMGenConfigure(PWM1_BASE,PWM_GEN_3,PWM_GEN_MODE_UP_DOWN|PWM_GEN_MODE_NO_SYNC);
//设置PWM发生器的周期 load
PWMGenPeriodSet(PWM1_BASE, PWM_GEN_2, 640);
PWMGenPeriodSet(PWM1_BASE, PWM_GEN_3, 640);
//设置输出的脉冲宽度
PWMPulseWidthSet(PWM1_BASE, PWM_OUT_5, R);
PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6, B);
PWMPulseWidthSet(PWM1_BASE, PWM_OUT_7, G);
//使能PWM发生器
PWMGenEnable(PWM1_BASE, PWM_GEN_2);
PWMGenEnable(PWM1_BASE, PWM_GEN_3);
//使能输出
PWMOutputState(PWM1_BASE, PWM_OUT_5_BIT | PWM_OUT_6_BIT | PWM_OUT_7_BIT, true);
while(1){
while(R != 600){
R++;
PWMPulseWidthSet(PWM1_BASE, PWM_OUT_5, R);
SysCtlDelay(10000);
}
while(R != 10){
R--;
PWMPulseWidthSet(PWM1_BASE, PWM_OUT_5, R);
SysCtlDelay(10000);
}
while(B != 600){
B++;
PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6, B);
SysCtlDelay(10000);
}
while(B != 10){
B--;
PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6, B);
SysCtlDelay(10000);
}
while(G != 600){
G++;
PWMPulseWidthSet(PWM1_BASE, PWM_OUT_7, G);
SysCtlDelay(10000);
}
while(G != 10){
G--;
PWMPulseWidthSet(PWM1_BASE, PWM_OUT_7, G);
SysCtlDelay(10000);
}
}
}
各函数作用
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1);
使能GPIO F和PWM模块1,此处的使能需要对照PWM Signales确定自己使用的PWM模块对应的GPIO引脚在哪
论坛资料
PWM初始化流程
以PWM1通道为例,由引脚图可知PWM1对应着PF1引脚。
1.使能PWM和GPIOF时钟
2.设置PF1,复用PF1
GPIOPinConfigure(GPIO_PF1_M0PWM1);
GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_1);
注意复用IO的库函数写法,其他复用函数请查看库函数手册
3.PWMGEN设置
PWMGenConfigure(PWM0_BASE,PWM_GEN_0,PWM_GEN_MODE_UP_DOWN|PWM_GEN_MODE_NO_SYNC);
4.设置PWM周期占空比
PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0,64000);
PWMPulseWidthSet(PWM0_BASE,PWM_OUT_0,PWMGenPeriodGet(PWM0_BASE, PWM_GEN_0)/ 4)
;//产生占空比为25%的PWM,等同于PWMPulseWidthSet(PWM0_BASE,PWM_OUT_0,16000)注意PWMGenPeriodGet函数用法。
注意:每个PWMGenraator产生的两路PWM频率相同,但占空比可以不同。
关于PWM频率的设置,因为PWM内部的负责计数寄存器只有16位,所以保存在里面的数字不能大于65535。这就限制了PWM的频率不能低于时钟频率/65535。若想产生更低的频率,则必须对PWM进行预分频,预分频函数为PWMClockSet,在使能PWM时钟后紧接着调用该函数。例如,系统主时钟为120MHz,设置分频系数为2,即
PWMClockSet(PWM0_BASE,PWM_SYSCLK_DIV_2)
然后设置
PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0,64000);
PWMPulseWidthSet(PWM0_BASE,PWM_OUT_0,32000);
则该PWM周期为:120M / 2/64000 = 937.5Hz
占空比为 32000 / 64000 = 50%。
5.使能PWMGEN
6.设置PWM输出状态
PWMGenEnable(PWM_BASE,PWM_GEN_0);
PWMOutputState(PWM_BASE,(| PWM_OUT_1_BIT),true);