智能车制作

标题: SCI和AD的例子 [打印本页]

作者: Cupor    时间: 2010-4-14 12:12
标题: SCI和AD的例子
#include <hidef.h>      /* common defines and macros */
#include <MC9S12XS128.h>     /* derivative information */
#pragma LINK_INFO DERIVATIVE "mc9s12xs128"


/*********************************************************************************/
/*                    ***********    角度检测    ***********                     */
/*********************************************************************************/


int Angle_Cur ;          //  当前竖直角度


int Angle_Last ;         //  之前竖直角度


int Angle ;              //  绝对偏移角度


int Angle_Velocity_V;       //  竖直角速度,也是相对偏移角度
int Angle_Last2;


unsigned char RxData;               //串口数据
int output_right;




#define MOTOR_PERIOD        1000     //  直流电机PWM周期




#define MOTOR_RIGHT_PER1  PWMPER01       //  右电机正转PWM周期
#define MOTOR_RIGHT_DTY1  PWMDTY01       //  右电机正转PWM占空比


#define MOTOR_RIGHT_PER0  PWMPER23       //  右电机反转PWM周期
#define MOTOR_RIGHT_DTY0  PWMDTY23       //  右电机反转PWM占空比


/*===============================================================================*/
/*                  -------------    I/O口初始化    ------------                  */
/*===============================================================================*/


void IO_Init(void)
{
    DDRA = 0xFF;        //  PORT A 拨码开关输出
    PORTA = 0xFF;


    DDRB = 0xFF;        //  PORT B LED输出
    PORTB = 0x00;




}


/*===============================================================================*/
/*                  ------------    锁相环初始化    ------------                 */
/*===============================================================================*/


//  PLL_CLOCK = 2 * OSC_CLOCK * (SYNR + 1) / (REFDV + 1); BUS_CLOCK = PLL_CLOCK / 2


void PLL_Init(void)
{
    CLKSEL_PLLSEL = 0;            //  选择晶振为系统时钟源
    PLLCTL_PLLON = 0;             //  关闭PLL


    REFDV = 0x43;
    SYNR = 0x49;                  //  BUS_CLOCK = 2 * 16MHz * (9 + 1) / (3 + 1) / 2 = 40MHz


    PLLCTL_PLLON = 1;             //  打开PLL


    while(CRGFLG_LOCK == 0);      //  等待锁相环稳定
    CLKSEL_PLLSEL = 1;            //  选择PLL为时钟源
}


/*===============================================================================*/
/*                  ------------    定时器初始化    ------------                 */
/*===============================================================================*/


void ECT_Init(void)
{
    TIOS = 0x00;                  //  设为输入捕捉
    TSCR1_TEN = 1;                //  定时器使能
    TSCR2_TOI = 0;                //  禁止定时器溢出中断
    TCTL3 = 0xA0;                 //  触发边沿:下降沿
    TIE = 0xC0;                   //  中断允许
    TFLG1 = 0xFF;                 //  清除输入捕捉/输出比较中断标志
}


/*===============================================================================*/
/*                  --------    周期中断定时器初始化    --------                 */
/*===============================================================================*/


//  定时周期 = (PITLD + 1) * (PITMTLD + 1) * BUS_CLOCK


void PIT_Init(void)
{
    PITMUX = 0x00;                //  与微定时器0相关联
    PITLD0 = 0x9C3F;
    PITMTLD0 = 0x09;              //  定时周期 = (39999 + 1) * (19 + 1) / 40MHz = 20ms
    PITINTE_PINTE0 = 1;           //  通道0中断使能
    PITTF_PTF0 = 1;               //  清除通道0中断标志位
    PITCE_PCE0 = 1;               //  周期中断定时期通道0使能
    PITCFLMT_PITE = 1;            //  周期中断定时器使能
}


/*===============================================================================*/
/*                  -------------    串口初始化    ------------                  */
/*===============================================================================*/


void SCI_Init(void)
{
    SCI0BDL = 0x83;
    SCI0BDH = 0x80;               //  Bt = BUS_CLOCK / (32 * BR) = 40M / (32 * 131) = 9541 bit/s
    SCI0CR1 = 0x00;               //  8位数据,无校验
    SCI0CR2 = 0x2C;               //  允许发送与接受  


}
void PWM_Init(void)
{   
    //-------------------------------------------------------------------------------//
    //  禁止PWM输出


    PWME = 0x00;


    //-------------------------------------------------------------------------------//
    //  01,23,45 ,67 通道级联


    PWMCTL_CON01 = 1;
    PWMCTL_CON23 = 1;
    PWMCTL_CON45 = 1;
    PWMCTL_CON67 = 1;


    PWMPOL = 0xFF;


    PWMCAE = 0x00;


    PWMCLK = 0x00;


    PWMPRCLK = 0x33;


    //-------------------------------------------------------------------------------//
    //  左、右电机的周期和占空比设定


    MOTOR_RIGHT_PER1 = MOTOR_PERIOD;      //  5MHz / 2500 = 2kHz
    MOTOR_RIGHT_DTY1 = 0;  //  1250 / 2500 = 50%


    MOTOR_RIGHT_PER0 = MOTOR_PERIOD;      
    MOTOR_RIGHT_DTY0 = 0;  




    //-------------------------------------------------------------------------------//


    PWME = 0xAA;


}


void AD_Init(void)
{
    ATD0CTL1=0x00;//12位精度
    ATD0CTL2=0x40;//禁止外部触发,标志位快速清零,中断禁止
    ATD0CTL3=0x90;//右对齐无符号.转换序列长度为2,No FIFO模式,Freeze模式下继续转换
    ATD0CTL4=0x43;//4AD采样周期,ATDClock=[BusClock*0.5]/[PRS+1] =4MHz ; PRS=3
    ATD0CTL5=0x30;//特殊通道禁止,单通道采样,扫描模式连续采样,
    ATD0DIEN=0x00;//禁止数字输入


}


void Sys_Init(void)
{


    DisableInterrupts;


    //-------------------------------------------------------------------------------//
    //  I/O口初始化


    IO_Init();


    //-------------------------------------------------------------------------------//
    //  锁相环初始化


    PLL_Init();


    //-------------------------------------------------------------------------------//
    //  定时器初始化


    ECT_Init();


    //-------------------------------------------------------------------------------//
    //  周期中断定时器初始化


    PIT_Init();


    //-------------------------------------------------------------------------------//
    //  PWM初始化


    PWM_Init();   




    //-------------------------------------------------------------------------------//
    //  串口初始化


    SCI_Init();


    //-------------------------------------------------------------------------------//
    //  AD初始化


    AD_Init();


    EnableInterrupts;




}
void
SCI_Tx( char TxData )
{

SCI0DRH
= 0;

SCI0DRL
= TxData;
    //将待发数据写入寄存器

while( !SCI0SR1_TDRE );
//等待发送结束
}


//-------------------------------------------------------------------------------//
//绝对值
int Abs(int abs)
{
    if (abs>0)
        return abs;
    else
    {
      abs=0-abs;
      return abs;
    }
}


//平衡控制
void Car_Control(void)
{   


    int P,I,D;
    Angle = 121-Angle_Cur;      //绝对角度减去实际角度,绝对角度模拟值为2.5V,则8位AD转换后为128
    if(Angle>-1&&Angle<1)
    {
        P = 40* (Angle - Angle_Last);
        I = 23*Angle;
        D = 30*(Angle_Cur - 2 * Angle_Last + Angle_Last2);
        Angle_Last2 = Angle_Last;
        Angle_Last = Angle;
        output_right = P+I+D;
    }else{
    Angle_Last =  Angle_Cur;
    Angle_Last2 = Angle_Cur - Angle_Last;
    output_right = 80* Abs(Angle) + 400* Angle_Last2;
    }


    if( Angle >0)
    {


        MOTOR_RIGHT_DTY1 = output_right;       //  右电机正转PWM占空比


        MOTOR_RIGHT_DTY0 =0;                                  //  右电机反转PWM占空比






    } else if(Angle<0)
    {
        Angle =0-Angle;            //取绝对值




        MOTOR_RIGHT_DTY0 =output_right;       //  右电机正转PWM占空比


        MOTOR_RIGHT_DTY1 =0;                                 //  右电机反转PWM占空比
    }


    else
    {
        MOTOR_RIGHT_DTY1=0;
        MOTOR_RIGHT_DTY0=0;
    }


}
void main(void)
{


  Sys_Init();


  for(;;)
  {


    Car_Control();




PORTB
=  ~( byte ) ATD0DR0L  ;//显示转换结果


  }


}
//  用于测量赛车速度,周期20ms


__interrupt 66 void Vpit0_ISR(void)
{
    PITTF_PTF0 = 1;
    while( !ATD0STAT0_SCF );
//等待一个序列结束
    Angle_Cur = ( int )ATD0DR0L;


}
interrupt 20 void SCI_Rx_IRS( void )
{



DisableInterrupts;



RxData
= SCI0DRL;



EnableInterrupts;
}




#pragma CODE_SEG DEFAULT
作者: rkrlovewy    时间: 2010-7-25 13:39

作者: weiweidgao    时间: 2010-8-29 14:00
好东西!谢了!
作者: 拒绝者    时间: 2010-11-20 00:13
谢谢


哈哈
作者: 13xchun    时间: 2010-11-24 16:23
太棒了
作者: 小鑫    时间: 2010-12-14 16:22
ding




欢迎光临 智能车制作 (http://111.231.132.190/) Powered by Discuz! X3.2