|
作者 :fire
时间地点 :2009 年于广州
开发平台 :MC9S12XS128最小系统(龙丘出品)
编译环境 :Freescale CodeWarrier 4.7
写在前面的话->:
PWM 是 Pulse-Width Modulator 的英文缩写,即脉冲宽度可调。通俗点来说PWM就是一种占空比(占空比就是在一个周期的信号中高电平占整个周期的百分比)可调的方波信号。在飞思卡尔智能车中用于控制电机跟舵机。在MC9S12XS128 中 PORTP 与PWM复用,还要注意XS128只有 7 个通道,分别为PWM0 PWM1 PWM2 PWM3 PWM4 PWM5 PWM7,这点大家在编程时要注意,特别是在使用 PWM 级联时。
PWM 初始化步骤->:
英文为 Datasheet 里面的原话
1、时钟初始化
Select clock (prescaler and scale) for the PWM,Each PWM channel has a choice of two clocks to
use as the clock source.PWMCLK selects the prescale clock source for clocks A and B
independently.
用的的寄存器为 PWMPRCLK、PWMSCLA、PWMSCLB。首先设置寄存器 PWMPRCLK 从 Busclock(总线时钟)分频
得到得到 Clock A ,Clock B 这两个时钟。设置寄存器 PWMSCLA 可以从 Clock A 中分频得到 Clock SA,设
置 PWMSCLB 这个寄存器 可以从 Clock B 中分频得到 Clock SA。具体的时钟计算公式和寄存器在
datasheet 里面的位置例程里面有注释,这里不再赘述。
其中 Clock SA,Clock A 是用做 PWM0、PWM1、PWM4、PWM5这四个通道,Clock SB,Clock B 是用做 PWM2、
PWM3、PWM6、PWM7这四个通道.
2、禁止 PWM
Disable PWM,用到的寄存器 为PWME,设置 PWME 时 起作用的是 7 个通道的 PWM,要设置单个通道的PWM可
以设置寄存器 PWME_PWMEX ,X 代表的是 0、1、2、3、4、5、7,即是用户要使用的通道。
3、选择极性
Select polarity。选择极性的意思就是在一个周期的方波信号中首先输出的是高电平还是低电平。
用到的寄存器为 PWMPOL。
PWMPOL_PPOLX=1 首先输出高电平,占空比计数器计数完毕后变为低电平
PWMPOL_PPOLX=0 首先输出低电平,占空比计数器计数完毕后变为高电平
4、选择对齐模式
Select center or left aligned mode。用到的寄存器为 PWMCAE。
PWMCAE_CAEX=1 输出波形为居中对齐方式(指的是高电平居中)
PWMCAE_CAEX=0 输出波形为左对齐方式(指的是高电平左对齐)
5、设定信号的周期跟占空比
Program duty cycle and period PWMDTYx, PWMPERx。
6、选择时钟
Choose the Clock Source for the chanal.
用到的寄存器为 WMCLK_PCLKX
7、使能PWM
Enable PWM,用到的寄存器为 PWME .
/******************以下为占空比的计算公式*****************/
//Page 389
//(左对齐时)PWMFrequency=Clock(A,B,SA,or SB)/PWMPERx
//(右对齐时)PWMFrequency=Clock(A,B,SA,or SB)/2*PWMPERx
//Polarity=0 首先输出低电平,占空比计数器计数完毕后变为高电平
//Duty Cycle =[(PWMPERx-PWMDTYx)/PWMPERx]*100%
//Polarity=1 首先输出高电平,占空比计数器计数完毕后变为低电平
//Duty Cycle =(PWMDTYx/PWMPERx)*100%
//左对齐模式频率的计算方法
//PWMx Frequency = Clock (A, B, SA, or SB) / PWMPERx
//居中对齐模式周期的计算方法
//PWMx Frequency = Clock (A, B, SA, or SB) / (2*PWMPERx)
PWM 的具体使用方法 可参考 datasheet的 Chapter 13 Pulse-Width Modulator (S12PWM8B8CV1)。
当用户要使用 PWM 的其他通道时 只需要修改 PWMPOL_PPOL0、PWMPOL_PPOL0、PWMDTY0、PWMPER0、PWMCLK_PCLK0、PWME_PWME0 这几个寄存器即可,即将里面的数字 0 改为 1、2、3、4、5、7。这里只是以 PWM0 来做演示。
/*****************************代码实现***************************************/
#include <hidef.h> /* common defines and macros */
#include <MC9S12XS128.h> /* derivative information */
#pragma LINK_INFO DERIVATIVE "mc9s12xs128"
#define uchar unsigned char
#define uint unsigned int
/*--------函数原型声明-------------------------*/
void SetBusCLK_40M(void);
void DE_40M_ms(int ms);
void Pwm0_Init(void);
void Pwm0_DutyCycle(uint duty);
/*----------------------------------------------*/
/*-----主函数实现PWM0输出20KHZ的占空比80%100的方波----*/
void main(void)
{
DisableInterrupts;
SetBusCLK_40M();
Pwm0_Init();
Pwm0_DutyCycle(80); //80%100 的占空比
//可用示波器来看
for(;;){} //让程序停在这,输出稳定的方波。
}
/*-----------------PWM0初始化------------------*/
void Pwm0_Init(void)
{ //PWM0 Frequency=20khz
//SA,A for ch0145
//SB,B for ch2367
PWMPRCLK=0X11; //Clock A ,Clock B=Bus clock / 2=20MHZ 见datasheet P374
PWMSCLA=0X05; //Clock SA = Clock A / (2 * PWMSCLA)=20MHZ/(2*5)=2MHZ P377
PWMSCLB=0X05; //Clock SB = Clock B / (2 * PWMSCLB)=2MHZ
PWME=0X00; //Disable PWM P371
PWMPOL_PPOL0=1; /*1:hight at the beginning of the period, then go low when the duty
count is reached*/
//0:low at the beginning of the period, then go high when the duty count is reached
PWMCAE_CAE0=0; //0:left aligned
//1:center aligned
//PWMDTY0=80; //占空比
/*Depending on the polarity bit, the duty registers will contain the
count of either the high time or the low time. If the polarity bit
is one, the output starts high and then goes low when the duty count
is reached, so the duty registers contain a count of the high time.
If the polarity bit is zero, the output starts low and then goes high
when the duty count is reached, so the duty registers contain acount
of the low time.*/
PWMPER0=100; //周期
PWMCLK_PCLK0=1; //Choose the Clock SA Source
PWME_PWME0=1; //Enable PWM0
}
/*---------------调节PWM0的占空比---------------*/
void Pwm0_DutyCycle(uint duty) //duty 范围为 0~100
{
PWMDTY0=duty; //when hight first,left aligned.DutyCycle =(PWMDTYx / PWMERx) X 100%
}
/*-----------------配置系统时钟------------------*/
void SetBusCLK_40M(void)
{
CLKSEL=0X00; //disengage PLL to system
PLLCTL_PLLON=1; //turn on PLL
SYNR =0xc0 | 0x04;
REFDV=0xc0 | 0x01;
POSTDIV=0x00; //pllclock=2*osc*(1+SYNR)/(1+REFDV)=80MHz;
_asm(nop); //BUS CLOCK=40M
_asm(nop);
while(!(CRGFLG_LOCK==1)); //when pll is steady ,then use it;
CLKSEL_PLLSEL =1; //engage PLL to system;
}
/*-----------------ms 级延时---------------------*/
void DE_40M_ms(int ms)
{
int ii,jj;
if (ms<1) ms=1;
for(ii=0;ii<ms;ii++)
for(jj=0;jj<3338;jj++); //40MHz--1ms
}
/*---------------end of file----------------------*/ |
阿莫论坛20周年了!感谢大家的支持与爱护!!
一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。
|