搜索
bottom↓
回复: 15

飞思卡尔单片机(MC9S12XS128)系列之3- PWM 的使用

[复制链接]

出0入0汤圆

发表于 2011-8-11 15:59:24 | 显示全部楼层 |阅读模式
作者     :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周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

 楼主| 发表于 2011-8-11 15:59:58 | 显示全部楼层
还有,继续发

出0入0汤圆

 楼主| 发表于 2011-8-11 16:01:42 | 显示全部楼层
回复【1楼】fire
-----------------------------------------------------------------------

这些代码都是我当年参考datasheet一句一句写的,可直接应用于飞思卡尔智能车竞赛

出0入0汤圆

 楼主| 发表于 2011-8-11 18:29:14 | 显示全部楼层
回复【2楼】fire
-----------------------------------------------------------------------

怎么还没有审核通过呢?

出0入0汤圆

发表于 2011-10-24 19:54:22 | 显示全部楼层
写的很好,能看懂
学到不少,谢谢!!

出0入0汤圆

发表于 2011-10-27 12:39:05 | 显示全部楼层
回复【楼主位】fire 野火
-----------------------------------------------------------------------
写得非常好!

出0入0汤圆

发表于 2011-11-9 21:05:11 | 显示全部楼层
学习学习

出0入0汤圆

发表于 2012-1-7 20:23:33 | 显示全部楼层
疑问,程序
/*-----------------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----------------------*/
中if (ms<1) ms=1;
   for(ii=0;ii<ms;ii++)
ms<1,那是不是ms==0?
为什么for循环中又可以这样写ii<ms?
求解释

出0入0汤圆

发表于 2012-1-7 23:48:40 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-2-10 17:11:35 | 显示全部楼层
楼主参加过飞思卡尔智能车吗

出0入0汤圆

发表于 2012-2-15 13:32:42 | 显示全部楼层
还不错~

出0入0汤圆

发表于 2012-2-25 22:03:28 | 显示全部楼层
回复【11楼】wcf3558 春风
-----------------------------------------------------------------------

大家好,看来楼主飞思卡尔学的不错。我初学这款单片机,大家能不能给点好的建议呢?谢谢

出0入0汤圆

发表于 2012-3-8 19:54:54 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-10-18 12:28:30 | 显示全部楼层

出0入0汤圆

发表于 2012-10-24 08:52:47 | 显示全部楼层
谢谢分享!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-6-14 16:53

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表