Difference between revisions of "Frc Demo.c Ukážkový program"
 (New page: <code lang="c"> /****************************************************************************** * * Freescale Semiconductor Inc. * (c) Copyright 2008 Freescale Semiconductor, Inc. * ALL RI...)  | 
			
(No difference) 
 | 
Revision as of 22:43, 24 March 2009
/******************************************************************************
- 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.
 - 
- /
 
 
- include <hidef.h> /* for EnableInterrupts macro */
 - include "derivative.h" /* include peripheral declarations */
 - include "slotcarutils.h" /* utilities */
 - 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. */
- define SET_LED_HL_ON PTAD_PTAD0 = 1
 - define SET_LED_HL_OFF PTAD_PTAD0 = 0
 - define SET_LED_HR_ON PTAD_PTAD1 = 1
 - define SET_LED_HR_OFF PTAD_PTAD1 = 0
 - define SET_LED_BL_ON PTAD_PTAD2 = 1
 - define SET_LED_BL_OFF PTAD_PTAD2 = 0
 - define SET_LED_BR_ON PTAD_PTAD3 = 1
 - 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. */
- 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) */
- define SET_ACC_RANGE_1_5_G PTCD_PTCD2 = 0
 - define SET_ACC_RANGE_6_G PTCD_PTCD2 = 1
 - define ACC_X 2
 - define ACC_Y 1
 - 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. */
- define MOTOR_ENABLE PTCD_PTCD4 = 1
 - define MOTOR_DISABLE PTCD_PTCD4 = 0
 - define SET_MOTOR_VOLTAGE(x) TPM1C2V = (x)
 - define GET_MOTOR_VOLTAGE TPM1C2V
 - define GET_MOTOR_FAULT_STATUS PTGD_PTGD2
 - define MOTOR_STATUS_OK 1
 - define MOTOR_STATUS_FAULT 0
 - 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. */
- 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) */
- define START_CONV(channel) ADCSC1 = ADCSC1_AIEN_MASK | (channel)
 - define READ_ADC_SAMPLE ADCR
 - define GET_ADC_ACTIVE_FLAG ADCSC2_ADACT
 - define SET_ADC_MODE_8_BIT ADCCFG_MODE = 0
 - define SET_ADC_MODE_10_BIT ADCCFG_MODE = 2
 - 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. */
- define GET_OUTAGE_DIR1 PTGD_PTGD0
 - 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 */
}