Frc Demo.c Ukážkový program

From RoboWiki
Revision as of 22:43, 24 March 2009 by Balogh (talk | contribs) (New page: <code lang="c"> /****************************************************************************** * * Freescale Semiconductor Inc. * (c) Copyright 2008 Freescale Semiconductor, Inc. * ALL RI...)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

/******************************************************************************

  • Freescale Semiconductor Inc.
  • (c) Copyright 2008 Freescale Semiconductor, Inc.
  • ALL RIGHTS RESERVED.
  • File main.c
  • Author Milan Brejl
  • Version 0.2
  • Date 19-Nov-2008
  • Brief Quick start with the Self-Driven Slot Car development
  • History:
  • 0.1 (14-Oct-2008) Initial version
  • 0.2 (19-Nov-2008)
  • This file includes initialization code and macros enabling to quickly start
  • with the development of a Self-Driven Slot Car.
  • At the current state, the application branches into one of 2 modes, based on
  • the slot car vertical position. If the car is placed on the track, it slowly
  • starts up, drives the car by a 50% voltage, samples all analog signals (motor
  • current, X, Y, and Z accelerations, and DC-Bus voltage) and stores the X
  • acceleration into the EEPROM. In the wheels-up position, detected using the
  • gravitational acceleration in Z axis, the data from EEPROM can be downloaded
  • into an Excel sheet using the ReadEEPROM.pmp FreeMASTER project.
  • Notes:
  • 1) The MCU S08JM32 is configured to run at 48MHz CPU clock and 24MHz BUS
  • clock.
  • The OSBDM debugger can be used to program the flash and run the
  • application, but it can not step and break the code at such a high rate.
  • 2) The motor is controlled in one direction only, using a motorVoltage
  • unsigned int variable (range 0 to 6000) and a PWM signal of corresponding
  • duty-cycle.
  • In order to control the motor in both directions (active breaking), the
  • initialization of the TPM1 module needs to be modified for a generation of
  • 2 PWM signals. For more information refer to the MC33887 H-bridge manual.
  • 3) The external EEPROM is handled by the Jaroslav Necesany's driver
  • eeprom.c/.h, included into the project.
                                                                                                                                                            • /
  1. include <hidef.h> /* for EnableInterrupts macro */
  2. include "derivative.h" /* include peripheral declarations */
  3. include "slotcarutils.h" /* utilities */
  4. include "eeprom.h" /* driver for external EEPROM via IIC */

/******************************************************************************

  • Constants and macros
                                                                                                                                                            • /

/* LEDs */ /*

* There are 4 LEds build into the head and break lights.
*   HL = head light - left, HR = head light - right, 
*   BL = break light - left, BR = break light - right 
* The following macros control the LEDs state, ON or OFF.
*/
  1. define SET_LED_HL_ON PTAD_PTAD0 = 1
  2. define SET_LED_HL_OFF PTAD_PTAD0 = 0
  3. define SET_LED_HR_ON PTAD_PTAD1 = 1
  4. define SET_LED_HR_OFF PTAD_PTAD1 = 0
  5. define SET_LED_BL_ON PTAD_PTAD2 = 1
  6. define SET_LED_BL_OFF PTAD_PTAD2 = 0
  7. define SET_LED_BR_ON PTAD_PTAD3 = 1
  8. define SET_LED_BR_OFF PTAD_PTAD3 = 0

/* SWITCH */ /*

* There is a 2-position switch.
* The following macro reads the switch position, returning 1 or 0.
*/
  1. define GET_SWITCH_STATE PTCD_PTCD6

/* ACCELEROMETER */ /*

* There is a 3-axis accelerometer with analog outputs.
* The accelerometer range is configurable for either +/- 1.5g or +/- 6g.
* The accelerometer analog outputs can be sampled by the on-chip Analog-to-
* -Digital Converter.
* The following macros set the accelerometer range and define the ADC 
* channels of the X, Y and Z accelerometer outputs:
*   X ... left and right (+ left, - right)
*   Y ... ahead and back (+ ahead, - back)
*   Z ... up and down (+ down, - up)
*/
  1. define SET_ACC_RANGE_1_5_G PTCD_PTCD2 = 0
  2. define SET_ACC_RANGE_6_G PTCD_PTCD2 = 1
  3. define ACC_X 2
  4. define ACC_Y 1
  5. define ACC_Z 0

/* MOTOR */ /*

* There is an H-brigde driving the DC motor.
* The motor drive can be enabled or disabled. When enabled, the applied motor
* voltage is controlled by a PWM duty-cycle.
* The H-brigde circuit returns a fault status in case of undervoltage,
* short circuit, or overtemperature condition.
* The motor current feedback can be sampled by the on-chip Analog-to-Digital
* Converter.
* The following macros enable or disable the motor drive, set the motor 
* voltage, get the motor fault status and define the ADC channel of
* the motor current.
*/
  1. define MOTOR_ENABLE PTCD_PTCD4 = 1
  2. define MOTOR_DISABLE PTCD_PTCD4 = 0
  3. define SET_MOTOR_VOLTAGE(x) TPM1C2V = (x)
  4. define GET_MOTOR_VOLTAGE TPM1C2V
  5. define GET_MOTOR_FAULT_STATUS PTGD_PTGD2
  6. define MOTOR_STATUS_OK 1
  7. define MOTOR_STATUS_FAULT 0
  8. define MOTOR_CURRENT 5

/* DC-BUS VOLTAGE */ /*

* There is a circuit which enables to measure the DC-Bus voltage.
* The DC-Bus Voltage Compensation technique enables to set a correct motor 
* voltage and keep it independent of a the actual DC-Bus voltage.
* The following macros defines the ADC channel of the DC-Bus voltage.
*/
  1. define DC_BUS_VOLTAGE 11

/* ADC */ /*

* The following macros enable to initializes the sampling and 
* conversion of an analog signal a defined read a conversion result - a 12-bit sample,
* to check if the Analog-to-Digital Converter is busy by an active conversion, and
* switch conversion resolution (8/10/12-bit mode)
*/
  1. define START_CONV(channel) ADCSC1 = ADCSC1_AIEN_MASK | (channel)
  2. define READ_ADC_SAMPLE ADCR
  3. define GET_ADC_ACTIVE_FLAG ADCSC2_ADACT
  4. define SET_ADC_MODE_8_BIT ADCCFG_MODE = 0
  5. define SET_ADC_MODE_10_BIT ADCCFG_MODE = 2
  6. define SET_ADC_MODE_12_BIT ADCCFG_MODE = 1

/* OUTAGE */ /*

* There is a circuit which enables to detect a power supply outage
* on the line change or crossover track pieces.
*/
  1. define GET_OUTAGE_DIR1 PTGD_PTGD0
  2. define GET_OUTAGE_DIR2 PTGD_PTGD1

/******************************************************************************

  • Global variables
                                                                                                                                                            • /

/* application */ enum {

 APP_MODE_RUN,
 APP_MODE_DOWNLOAD

} appMode;

/* accelerometer */ unsigned int accX, accY, accZ; /* 12-bit unsigned samples */

/* motor */ unsigned int motorVoltage; /* range 0 to 6000 */ unsigned int motorCurrent; /* 12-bit unsigned sample */

/* dc-bus */ unsigned int dcBus; /* 12-bit unsigned sample */

/* global time */ unsigned int timeCounter; /* global free-running 1/2ms counter */

/* extern global variables */ extern enum SEMAPHORE semaphore1;

/******************************************************************************

  • Functions
                                                                                                                                                            • /

/******************************************************************************

  • Interrupt Handlers
                                                                                                                                                            • /

/* Timer/PWM Interrupt */ interrupt VectorNumber_Vtpm1ovf void Vtpm1ovf_isr(void) {

 /* clear interrupt flag */
 TPM1SC_TOF = 0;
 
 /* update PWM duty-cycle according to the global variable motorVoltage */
 SET_MOTOR_VOLTAGE(motorVoltage);
 
 /* Start sequence of analog inputs sampling */
 START_CONV(MOTOR_CURRENT);
 
 /* Update the global 1/2ms timeCounter */
 timeCounter++;

}

/* ADC Conversion Complete Interrupt */ interrupt VectorNumber_Vadc void Vadc_isr(void) {

 /* 
  * Read the new sample using GET_ADC_SAMPLE macro.
  * The reading also clears the interrupt flag.
  * Put all samples into the buffer.
  */
 switch(ADCSC1_ADCH)
 {
 case MOTOR_CURRENT:
   motorCurrent = READ_ADC_SAMPLE;
   START_CONV(ACC_X);
   break;
 case ACC_X:
   accX = READ_ADC_SAMPLE;
   START_CONV(ACC_Y);
   PutToBuffer16(accX);  /* store accX to EEPROM */
   break;
 case ACC_Y:
   accY = READ_ADC_SAMPLE;
   START_CONV(ACC_Z);
   break;
 case ACC_Z:
   accZ = READ_ADC_SAMPLE;
   START_CONV(DC_BUS_VOLTAGE);
   break;
 case DC_BUS_VOLTAGE:
   dcBus = READ_ADC_SAMPLE;
   break;
 }

}

/* Keyboard Interrupt */ interrupt VectorNumber_Vkeyboard void Vkeyboard_isr(void) {

 /* clear interrupt flag */
 KBISC_KBACK=1;

}

/******************************************************************************

  • Main
                                                                                                                                                            • /

void main(void) {

 /********** Device Initialization **********/
 /* initialize the Multi-Purpose Clock Generator (MCG) 
    for 48MHz CPU clock and 24MHz bus clock */
 MCGC2 = 0x36;   /* MCGC2: BDIV=0,RANGE=1,HGO=1,LP=0,EREFS=1,ERCLKEN=1,EREFSTEN=0 */
 MCGC1 = 0xB8;   /* MCGC1: CLKS=2,RDIV=7,IREFS=0,IRCLKEN=0,IREFSTEN=0 */
 while(!MCGSC_OSCINIT);  /* Wait until external reference is stable */
 while(MCGSC_IREFST);    /* Wait until external reference is selected */
 while((MCGSC & 0x0C) != 0x08);  /* Wait until external clock is selected as a bus clock reference */
 MCGC2 = 0x3E;   /* MCGC2: BDIV=0,RANGE=1,HGO=1,LP=1,EREFS=1,ERCLKEN=1,EREFSTEN=0 */
 MCGC1 = 0x88;   /* MCGC1: CLKS=2,RDIV=1,IREFS=0,IRCLKEN=0,IREFSTEN=0 */
 MCGC3 = 0x46;   /* MCGC3: LOLIE=0,PLLS=1,CME=0,VDIV=6 */
 MCGC2 &= (unsigned char)~0x08;   /* MCGC2: LP=0 */
 while(!MCGSC_PLLST);    /* Wait until PLL is selected */
 while(!MCGSC_LOCK);     /* Wait until PLL is locked */
 MCGC1 = 0x08;   /* MCGC1: CLKS=0,RDIV=1,IREFS=0,IRCLKEN=0,IREFSTEN=0 */
 while((MCGSC & 0x0C) != 0x0C);  /* Wait until PLL clock is selected as a bus clock reference */
 /* disable the COP watchdog */
 SOPT1_COPT = 0;
 
 /* initialize the LEDs as outputs */
 PTADD_PTADD0 = 1; /* output to LED1 */
 PTADD_PTADD1 = 1; /* output to LED2 */
 PTADD_PTADD2 = 1; /* output to LED3 */
 PTADD_PTADD3 = 1; /* output to LED4 */
 /* initialize the SWITCH as an input with pull-up */
 PTCDD_PTCDD6 = 0; /* input from switch */
 PTCPE_PTCPE6 = 1; /* pull-up enable */
 /* initialize the ACCELEROMETER range select as an output */
 PTCDD_PTCDD2 = 1; /* output to G-select */
 
 /* initialize the MOTOR driver inputs as outputs */
 PTCDD_PTCDD4 = 1; /* output to EN */
 PTADD_PTADD5 = 1; /* output to D1 */
 PTADD_PTADD4 = 1; /* output to D2 */
 PTFDD_PTFDD2 = 1; /* output to IN2 */
 
 /* initialize the MOTOR driver fault status output as an input */
 PTFDD_PTFDD1 = 0; /* input from fault status */
 
 /* initialize TPM1 for PWM generation */
 TPM1SC = 0;
 TPM1MOD = 6000;     /* Modulo = 6000 => f = 24MHz/1/(6000*2) = 2kHz */
 TPM1SC_CLKSx = 1;   /* clock source = bus clock */
 TPM1SC_PS = 0;      /* prescaler divider = 1 */
 TPM1SC_CPWMS = 1;   /* center-aligned PWM */
 TPM1C2SC_ELS2x = 2; /* low-true pulses */
 TPM1SC_TOIE = 1;    /* enable overflow interrupt */
 /* initialize the ADC */
 ADCCFG_ADICLK = 1;/* input clock = bus clock divided by 2 */
 ADCCFG_ADIV = 1;  /* input clock div = 2 */
 ADCCFG_ADLSMP = 1;/* long sample time enabled */
 ADCCFG_MODE = 1;  /* 12-bit mode */
 ADCSC2_ADTRG = 0; /* software trigger */
 APCTL1_ADPC0 = 1; /* pin ADP0 is ADC input - accelerometer Z */
 APCTL1_ADPC1 = 1; /* pin ADP1 is ADC input - accelerometer Y */
 APCTL1_ADPC2 = 1; /* pin ADP2 is ADC input - accelerometer X */
 APCTL1_ADPC5 = 1; /* pin ADP5 is ADC input - motor current */
 APCTL2_ADPC11 = 1; /* pin ADP11 is ADC input - dc-bus voltage */
 
 /* initialize Keyboard Interrupt to detect outage */
 KBIES_KBEDG0 = 0;  /* detect falling edge from OUTAGE_DIR1 */
 KBIES_KBEDG1 = 0;  /* detect falling edge from OUTAGE_DIR2 */
 KBISC_KBMOD = 0;   /* detect edge only */
 KBIPE_KBIPE0 = 1;  /* enable OUTAGE_DIR1 pin interrupt */
 KBIPE_KBIPE1 = 1;  /* enable OUTAGE_DIR2 pin interrupt */
 KBISC_KBIE = 1;    /* enable interrupts */
 
 /* enable interrupts */
 EnableInterrupts;
 /************ Board HW Initialization *************/
 /* initialize the Accelerometr */
 SET_ACC_RANGE_1_5_G;
 /* initialize the Motor H-bridge driver */
 PTAD_PTAD5 = 0;  /* set D1 low */
 PTAD_PTAD4 = 1;  /* set D2 high */
 PTFD_PTFD2 = 0;  /* set IN2 low */
 MOTOR_DISABLE;
 motorVoltage = 0;
 /* initialize EEPROM */
 EepromInit(0x45);  /* 400kbit/sec at 24MHz Bus clock */
 /************* Start-up *************/
 /* indicate the actual switch position */
 Wait(1000);
 if(GET_SWITCH_STATE == 1)
 {
   /* blink front lights once */
   SET_LED_HL_ON;
   SET_LED_HR_ON;
   Wait(300);
 }
 else
 {
   /* blink front lights twice */
   SET_LED_HL_ON;
   SET_LED_HR_ON;
   Wait(100);
   SET_LED_HL_OFF;
   SET_LED_HR_OFF;
   Wait(100);
   SET_LED_HL_ON;
   SET_LED_HR_ON;
   Wait(100);
 }
 SET_LED_HL_OFF;
 SET_LED_HR_OFF;


 /* test if the car is in the wheels up position and set application mode */
 if (accZ > 2048)
 {
   appMode = APP_MODE_DOWNLOAD;
   DisableInterrupts;
 }
 else
 {
   appMode = APP_MODE_RUN;
   /* slowly speed up */
   MOTOR_ENABLE;
   while(motorVoltage <= 3000)
   {
     motorVoltage++;
     Wait(1);
   }
 }
 /************* Background Loop *************/
 for(;;) 
 {
   switch(appMode)
   {
   case APP_MODE_DOWNLOAD:
     /* Download buffer from EEPROM if empty */
     LoadBufferFromEeprom();
     /* Show page-by-page downloading on break LEDs */
     if (semaphore1)
     {
       SET_LED_BR_ON;
       SET_LED_BL_OFF;
     }
     else
     {
       SET_LED_BR_OFF;
       SET_LED_BL_ON;
     }
     break;
   case APP_MODE_RUN:
     /* Upload buffer to EEPROM if filled up */
     StoreBufferToEeprom();
     /* Check motor fault status */
     if(GET_MOTOR_FAULT_STATUS == MOTOR_STATUS_FAULT)
     {
       motorVoltage = 0;
       SET_LED_BL_ON;
       SET_LED_BR_ON;
     }
     break;
   }
 } /* loop forever */

}