Frc Demo.c Ukážkový program
/******************************************************************************
- 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 */
}