fire 发表于 2011-8-11 16:04:48

飞思卡尔单片机(MC9S12XS128)系列之4- PWM 级联的设置

作者   :fire
时间地点 :2009 年于广州
开发平台 :MC9S12XS128最小系统(龙丘出品)
编译环境 :Freescale CodeWarrier 4.7

写在前面的话->:
PWM 级联可以 组合成 16 位的方波信号,精度更高。在飞思卡尔智能小车中级联的PWM信号用于控制舵机。下面简要的介绍下舵机的知识:舵机就像人们平时开车时用的方向盘,平时开始时调整方向是通过我们的手旋转方向盘来实现的。当然,在智能小车的控制中我们是不能够用手来控制小车的方向的,实在话来说我们也控制不了。那么在这种情况下控制舵机的信号就是 PWM 信号。在用 PWM 信号控制舵机时 还要考虑到 精度的问题,所以 PWM 就要级联起来使用。一般舵机对控制信号的频率都有一定的要求,那么现在以舵机 S3010 (S3010为智能车竞赛中使用的舵机)为例来说明:
有三根线,一根电源线,一根地线,一根控制信号线(接PWM信号)。一般情况下这三根线的颜色约定为:红色接 VCC,黑色接 GND,白色或着黄色为控制信号线。该舵机使用的频率范围为 50HZ -> 200HZ,转化为周期即为
5MS -> 20MS ,假如超出这个频率范围的话,舵机就不会线性工作。对舵机居中,左极限,有极限的约定如下:
                  1MS   的脉冲左极限。
                  1.5MS 的脉冲居中,即摆正。
                  2MS   的脉冲右极限。
//P392
/*------------------PWM级联知识点-------------*/
1 级联可以使PWM输出的波形的精度更高。
2 PWMCTL有四个控制位可以完成这个级联的功能。
3 通道012345   67 可以级联
4 //SB,B for ch2367
//SA,A for ch0145

注意XS128 中80脚的没有PWM6
            112脚的才有
5 当这些通道级联后,通道0 4 2 6 的寄存器会变成级联后寄存器的高8位,
当处于级联模式时,时钟是受级联后的低8位对应通道的寄存器控制的。
即由通道1 5 3 7的寄存器控制。同样,PWM波形的允许,极性,对齐方式也是由低8位对应
通道的寄存器控制的。即只有 1 3 5 7 这几个角才会有输出信号。
PWMCTL_CONxx=1   级联
PWMCTL_CONxx=0   非级联

//左对齐模式周期的计算方法
//PWMxPeriod = ChnenalClockPeriod * PWPERx
//居中对齐模式周期的计算方法
//PWMxPeriod = ChnenalClockPeriod * (2*PWPERx)
/***************************以下为代码实现*************************************/
对程序的一些说明->:
该例程中设置舵机的控制周期为 20MS ,即 PWMPER45=20000; 当 PWMDTY45=1500; 时舵机摆正。PWMDTY45=duty; 要想舵机工作在线性区域,duty 的取值范围为 1000 -> 2000 。
#include <hidef.h>      /* common defines and macros */
#include <MC9S12XS128.h>   /* derivative information */
#pragma LINK_INFO DERIVATIVE "mc9s12xs128"

#define ucharunsigned char
#define uintunsigned int
/*--------函数原型声明-------------------------*/
void SetBusCLK_64M(void);
void DE_64M_ms(int ms);
void Pwm45_Init(void);
void Pwm45_DutyCycle(uint duty);
/*----------------------------------------------*/
/*--------------------主函数---------------------
*
*如果舵机的信号线接了 PWM 信号的话,那么主函数
*中实现的是舵机在左右极限的范围内打舵。如果舵机
*没有接PWM信号的话,则PWM5 脚输出的就是占空比在
*0到100这个范围内变化的方波。
*
*---------------------------------------------*/
void main(void)
{
      byte i = 1500;
      
      DisableInterrupts;
      SetBusCLK_64M();
      
      Pwm45_Init();
      Pwm45_DutyCycle(1500);//舵机摆正
         
      for(;;)
      {
         if( i == 2000 )   //到达右极限
            i -= 50;
         if( i == 1000)    //到达左极限
            i += 50;
         Pwm45_DutyCycle(i);
      }
}

/*-----------PWM4跟PWM5级联初始化-----------*/
void Pwm45_Init(void)//2010-5-17
{//Bus clock=64m
   //PWM4 PWM5级联
   PWMPRCLK=0x22;//Clock A ,Clock B=Bus clock / 4=16MHZ见datasheet P374
   PWMSCLA =0x08;//Clock SA = Clock A / (2 * PWMSCLA)=20MHZ/(2*8)=1MHZ,T=1us P377
   PWMSCLB =0x08;//Clock SB = Clock B / (2 * PWMSCLB)=20MHZ/(2*8)=1MHZ,T=1us P377
   PWME=0X00;      //Disable PWM
   PWMCTL_CON45=1;    //4和5联合成16位PWM;P375
   PWMCNT45= 0;       //计数器清零;
   PWMPER45=20000;
   PWMPOL_PPOL5=1;   //left aligned
   PWMCAE_CAE5=0;    //hight first
   
   PWMCLK_PCLK5=1;
   PWME_PWME5=1;
}
/*------------------调节占空比-----------------*/
void Pwm45_DutyCycle(uint duty)
{
   PWMDTY45=duty;    // 舵机摆正占空比
}
/*-----------------配置系统时钟------------------*/
void SetBusCLK_64M(void)
{   
    CLKSEL=0X00;    //disengage PLL to system
    PLLCTL_PLLON=1;   //turn on PLL
    SYNR =0xc0 | 0x07;                        
    REFDV=0xc0 | 0x01;
    POSTDIV=0x00;       //pllclock=2*osc*(1+SYNR)/(1+REFDV)=80MHz;
    _asm(nop);          //BUS CLOCK=64M
    _asm(nop);
    while(!(CRGFLG_LOCK==1));   //when pll is steady ,then use it;
    CLKSEL_PLLSEL =1;          //engage PLL to system;
}
/*-----------------ms 级延时---------------------*/
void DE_64M_ms(int ms)//x取值1~255;
{
int ii,jj;
   if (ms<1) ms=1;
   for(ii=0;ii<ms;ii++)
   for(jj=0;jj<5341;jj++);//64MHz--1ms   
}

fire 发表于 2011-8-11 16:05:58

这里面的代码可直接用于控制舵机,至于舵机的型号我已经忘了,毕竟从我当年参赛到现在也2年多了。

激流NO.1 发表于 2012-8-9 16:22:22

GOOD,多谢楼主!
页: [1]
查看完整版本: 飞思卡尔单片机(MC9S12XS128)系列之4- PWM 级联的设置