Difference between revisions of "Frc Demo.c Ukážkový program"
From RoboWiki
(New page: <code lang="c"> /****************************************************************************** * * Freescale Semiconductor Inc. * (c) Copyright 2008 Freescale Semiconductor, Inc. * ALL RI...) |
|||
Line 1: | Line 1: | ||
− | < | + | <source lang="c"> |
/****************************************************************************** | /****************************************************************************** | ||
* | * | ||
Line 421: | Line 421: | ||
} /* loop forever */ | } /* loop forever */ | ||
} | } | ||
− | </ | + | </source> |
Latest revision as of 22:44, 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 */
}