第09章 PWM脉宽调制 PULSE WIDTH MODULATION---数字脉冲输出 Ton Toff 占空比=高电平时间/周期 =Ton/Tperiod Average Tperiod 0 % 10 % 50 % 90 % 99 % 应用: D/A转换 马达控制 音调生成 正弦波生成
9.1 PWM概述 S12X MCU可以不通过定时器,而使用专门的PWM模块以产生PWM波形,极少占用CPU资源 8个带周期占空比可程控的PWM独立通道(与PTP复用) 4个可程控选择的时钟源 脉冲输出极性可选 每个PWM通道有专用的计数器 每个PWM通道可使能/禁止 占空比可调范围0~100% 分辨率: 8位 (8通道), 16位 (4通道) 周期和占空比双缓冲 每个通道有中心对齐和左对齐方式 带中断功能的紧急切断
9.2 PWM结构原理和功能描述 PWM_8B8C 时钟选择 控制 使能(Enable) 极性(Polarity) PWM7 PWM通道 通道7 PWM6 通道6 PWM5 通道5 通道4 PWM4 通道3 PWM3 通道2 PWM2 通道1 PWM1 通道0 PWM0 周期和占空比 计数器 总线时钟 PWM时钟 对齐(Alignment)
PWM波形输出原理 开始 周期Tperoid 时钟源 8-bit Counter PWMCNTx Reset 8-bit Compare = Pin PWMDTYx 占空比 TDuty PWMDTYx PWMPERx PWMPERx 8-bit Compare = PWMPERx 0x00 0x00 fClock, TClock 当8位计数器的值等于PWMDTY(占空比常数寄存器)时,电平从有效跳到无效; 当8位计数器的值等于PWMPER(周期常数寄存器)时,电平从无效跳到有效,然后计数器清0,重新开始计数开始下一个周期
PWM 时钟源 4个时钟源: Clock A (Ch 0, Ch 1, Ch 4, Ch 5) Clock SA (Scaled A; Ch 0, Ch 1, Ch 4, Ch 5) Clock B (Ch 2, Ch 3, Ch 6, Ch 7) Clock SB (Scaled B; Ch 2, Ch 3, Ch 6, Ch 7) 4个时钟源: Clock A PWMSCLA 比例分频: 2、4、8、16、32、64、…512 PWMPRCLK Clock SA 预分频: 1、2、4、8、16、32、64、128 Bus Clock PWMSCLB 比例分频: 2、4、8、16、32、64、…512 Clock SB Clock B
对齐方式选择-左对齐 时钟源 选择= 10 MHz (100 ns period) PPOLx = 1 Clock=100ns 占空比=25% 周期=400ns 时钟源 选择= 10 MHz (100 ns period) PPOLx = 1 PWMPERx = 4 PWMDTYx = 1 PWMx 频率 = 10 MHz/4 = 2.5 MHz 即:PWMx 周期 = 1/2.5MHz=400 ns PWMx 占空比 = 1/4*100% = 25%
对齐方式选择-中心对齐 时钟源 Clock = 10 MHz (100 ns period) PPOLx = 0 Clock=100ns 占空比=75% 周期=800ns 时钟源 Clock = 10 MHz (100 ns period) PPOLx = 0 PWMPERx = 4 PWMDTYx = 1 PWMx 频率 = 10 MHz/8 = 1.25 MHz PWMx 周期 = 1/1.25MHz=800 ns PWMx 占空比 = (4-1)/4*100% = 75%
通道级联---16位分辨率 两个8位PWM通道可以组合成一个16位PWM通道,例如: PWM7 时钟源 周期/占空比 比较 PWM7输出 PWMCNT6 PWMCNT7 周期/占空比 比较 PWM7输出 CONxx PWMEx PPOLx PCLKx CAEx PWMx OUTPUT CON67 PWME7 PPOL7 PCLK7 CAE7 PWM7 CON45 PWME5 PPOL5 PCLK5 CAE5 PWM5 CON23 PWME3 PPOL3 PCLK3 CAE3 PWM3 CON01 PWME1 PPOL1 PCLK1 CAE1 PWM1 软件可选择通道组合 在级联模式下,可以左对齐或中心对齐输出 常数寄存器、计数器都合成为16位---增加了分辨率,周期可以更长
9.3 PWM模块的使用与设置 PWM 时钟预分频寄存器------PWMPRCLK R PCKB2 PCKB1 PCKB0 PCKA2 Bit 0 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 R PCKB2 PCKB1 PCKB0 PCKA2 PCKA1 PCKA0 W Reset: PCKx2 PCKx1 PCKx0 Value of Clock x Bus Clock 1 Bus Clock / 2 Bus Clock / 4 Bus Clock / 8 Bus Clock / 16 Bus Clock / 32 Bus Clock / 64 Bus Clock / 128 = Unimplemented or Reserved 可在任意时刻读写! x = A or B 例:设置 PRESCALE 寄存器------ PWMPRCLK = 0x22; // B= Bus/4, A = Bus/4 PWMPRCLK = 0x07; // B = Bus, A = Bus/128
PWM 时钟比例分频寄存器------PWMSCLA、PWMSCLB PWMSCLx = $00 PWMSCLx value is 256 可在任意时刻读写! x = A or B 例如: 要求: Clock Sx = 1 kHz 总线时钟 = 16 MHz Prescaler = 128 Prescaler = 64 Clock x = 125 kHz Clock x = 250 kHz PWMSCLx = 63 PWMSCLx = 125 Clock Sx = 992 Hz Clock Sx = 1000 Hz 准一些
PWM 时钟选择寄存器------ PWMCLK Bit 0 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 R PCLK7 PCLK6 PCLK5 PCLK4 PCLK3 PCLK2 PCLK1 PCLK0 W Reset: PCLK7 — 通道 7时钟选择 1 = 通道7的时钟源为SB 0 =通道7的时钟源为B. PCLK6 —通道 6时钟选择 1 =时钟源为SB. 0 =时钟源为B PCLK5 —通道 5时钟选择 1 =时钟源为SA 0 =时钟源为A PCLK4 —通道 4时钟选择 PCLK3 —通道 3时钟选择 1 =时钟源为SB. 0 =时钟源为B PCLK2 —通道 2时钟选择 1 =时钟源为SB PCLK1 —通道 1时钟选择 1 =时钟源为SA 0 =时钟源为A PCLK0 —通道 0时钟选择 PWM 极性选择寄存器------PWMPOL PPOLx=0---输出周期以低电平开始 =1---输出周期以高电平开始
PWM 中心对齐使能寄存器------PWMCAE @ $_04 Bit 0 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 R CAE7 CAE6 CAE5 CAE4 CAE3 CAE2 CAE1 CAE0 W Reset: ... CAEx – 中心对齐模式选择,通道 x 0 = 通道 x 左对齐输出 1 = 通道 x 中心对齐输出 PWM 关断寄存器------PWMSDN 主要用于处理通道7的紧急关闭中断 @ $_24 Bit 0 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 R PWMIF PWMIE PWMRSTRT PWMLVL PWM7IN PWM7INL PWM7ENA W Reset: = Unimplemented or Reserved
... 紧急关断 通道 7输入紧急关断触发 外部故障输入 信号 PWMLVL=1 PWMLVL=0 PWM7ENA=1 Channel 6 Period and Duty Counter PWM7INL=1 PWM7INL=0 Channel 5 Period and Duty Counter ... Channel 0 Period and Duty Counter PWMIE Interrupt PWMIF
PWM控制寄存器------PWMCTL 等待模式 冻结模式 在FREEZE模式下,PWM计数器继续 PFRZ = 1 在FREEZE模式下,PWM计数器停止 PSWAI = 1 在WAIT模式下,允许输入时钟到预分频器 在WAIT模式下,停止输入时钟到预分频器 @ $_05 Bit 0 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 R CON67 CON45 CON23 CON01 PSWAI PFRZ W 通道级联控制: 0---不级联 1---级联成16位 PWM计数器停止 在Freeze模式时 使能/禁止时钟 在WAIT模式时
PWM 通道周期寄存器------PWMPERx @ $_14-_1B Bit 0 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 R Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 W Reset: 1 1 1 1 1 1 1 1 PWM 通道占空比寄存器------PWMDTYx @ $_1C-_23 Bit 0 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 R Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 W Reset: 1 1 1 1 1 1 1 1 注:周期与占空比计算按书上公式
PWM使能/禁止寄存器------PWME @ $_00 Bit 0 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 R PWME7 PWME6 PWME5 PWME4 PWME3 PWME2 PWME1 PWME0 W Reset: 通道7 通道6 ...... 通道 0 0 = 通道x禁止 1 = 通道x使能,下一个时钟开始输出PWM 软件示例 使能/禁止 PWM 通道: PWME5 = 1; // Enable PWM channel 5 PWME3 = 0; // Disable PWM channel 3 PWME = 0xFF // Enable all 8 PWM channels PWME = 0; // Disable all 8 PWM channels
9.4 PWM的应用实例 S12X MCU中的PWM模块一旦设置完成,不需软件干预即可生成PWM信号,除非要改变周期或占空比。初始化步骤: ①关闭PWM通道 PWME ②选择极性 PWMPOL ③选择时钟 PWMCLK、PWMPRCLK、PWMSCLA、PWMSCLB ④选择对齐方式 PWMCAE ⑤设置占空比和周期 PWMDTY、PWMPER ⑥使能PWM通道 PWME 【例9-1】PWM输出脉冲序列 【例9-2】PWM用作D/A转换
【例9-1】使用S12X的PWM模块输出一定周期和占空比的脉冲序列。PWM波形从PP0口(PWM0)输出,频率为125Hz,占空比为50%的方波信号,时钟源采用ClockSA。假设总线时钟频率fBus=2 MHz。 C语言程序代码如下: //函数:PWM初始化/////////////////////////////////////////////////////////////// void PWM_Init() { PWME=0x00; //禁止PWM输出 PWMCTL=0x00; //通道独立不级联,Wait、Freeze模式下继续 PWMPOL=0xFF; //脉冲极性,先高后低 PWMCAE=0x00; //左对齐输出方式 PWMCLK=0xFF; //使用ClockSA时钟 PWMPRCLK=0x33; //ClockA时钟为总线时钟8分频,=2MHz/8=250KHz PWMSCLA=50; //ClockSA= ClockA / (2*PWMSCLA) = 250KHz/ (2*50) = 2.5KHz PWMPER0=20; //设定通道0周期 = (1/2.5KHz) * 20 = 8ms (125Hz) PWMDTY0=10; //设定通道0占空比 = 10/20 =50% } //主函数/////////////////////////////////////////////////////////////////////////////////////// void main() DisableInterrupts; //关总中断, = asm SEI PWM_Init(); //调用PWM初始化函数 PWME=0x01; //使能通道0的PWM输出 while(1) 【例9-2】
#include <hidef.h> /* common defines and macros */ #include "derivative.h" /* derivative-specific definitions */ //#define PWM_BEEP //条件编译,选择为PWM输出控制蜂鸣器或是LED亮暗控制 ///////////////////////////////////////////////////////////////////////////// // 程序说明:PWM脉宽调制的D/A输出控制范例:控制蜂鸣器或是LED亮暗 // 硬件平台:CQU-S12X-CORE&EXP // 参考书籍:《单片机原理及应用---使用Freescale S12X构建嵌入式系统》 by RY // 主函数 void main() { unsigned char i=0; unsigned long j=50000; DisableInterrupts; //关总中断 ,= asm("SEI") PWM_Init(); //调用PWM初始化函数 EnableInterrupts; //开总中断 ,= asm("SEI") ,可能用于其它 for(;;) #ifdef PWM_BEEP PWMDTY0 = i; PWME = 0x01; //使能通道0的PWM输出 #else PWMDTY1 = i; PWME = 0x02; //使能通道1的PWM输出 #endif while(j--); //延时 j=50000; if(i++>=20) i=0;//改变占空比,使其在0%~100%变化 }