📄 mc_timer.c
字号:
/* Author : Frank Wornle
*
* File : mc_timer.c (Freescale 9S12DP256C - ECT)
*
*/
/* Microcontroller specific and system headers */
#include <mc9s12dp256.h> /* port definitions etc. */
#include <float.h>
#include <math.h> /* floor */
/* System macros (EXT_MODE, etc.) -- generated by 'gen_cpp_req_defines_h.tlc' */
#include "cpp_req_defines.h"
/* RTW headers */
#include "tmwtypes.h"
#include "mc_main.h" /* model_run() */
#include "mc_timer.h" /* macros... */
/* global variables */
static uint32_T timerTicks; /* timer runs with a resolution of 100 us... fw-02-05 */
static uint32_T timerTicksReload; /* reload value for 'timerTicks' */
#if CORE_TIMER == CORE_RTI /* RTI */
/* Function: init_timebase =============================================================
*
* Abstract:
* Initialise 'time base' (core time RTI)
*/
void init_timebase(time_T sampleTime) {
time_T temp;
uint16_T RTR = 0x0010;
uint16_T p = 1;
#if TARGET_BOARD == 1
#define MIN_PERIOD 0.000256 // RTI minimum period
#define MAX_PERIOD 0.262144 // RTI maximum period
#define MIN_FREQ 3906.25
#endif
#if ((TARGET_BOARD == 2) | (TARGET_BOARD == 3))
#define MIN_PERIOD 0.000064 // RTI minimum period
#define MAX_PERIOD 0.065526 // RTI maximum period
#define MIN_FREQ 15625
#endif
/* check if variable 'timerTicks' has to be used to extend range of timer */
if(sampleTime >= MAX_PERIOD) {
RTICTL = 0x10; // RTI control register, setup timer for a base resolution of 0.256us(0.064us for MiniDragon+)
/* sample period in units of base resolution */
timerTicks = (uint32_T)(sampleTime*MIN_FREQ); //timerTicks = (uint32_T)(sampleTime/base resolution);
timerTicksReload = timerTicks;
} else {
/* no -> program exact value */
/* determine settings of the core timer RTI */
while(sampleTime*MIN_FREQ>(time_T)p && RTR != 0x007F){
temp = sampleTime*MIN_FREQ - (time_T)p;
RTR++;
p = ((RTR & 0x000F) + 1) << ((RTR >> 4) - 1);
}
if ( ((time_T)p-sampleTime*MIN_FREQ) > temp ) RTR--;
RTICTL = (uint8_T)RTR; // RTI control register
/* reset 'timerTicks' -> every interrupt counts... */
timerTicks = 1;
timerTicksReload = timerTicks;
}
} /* End of init_timebase */
#endif /* CORE_TIMER == CORE_RTI */
#if CORE_TIMER == CORE_T7ISR /* TC7 */
/* Function: init_timebase =============================================================
*
* Abstract:
* Initialise 'time base' (core time TC7)
*/
void init_timebase(void) {
uint16_T n = 1; /* base period multiplier: 1 = 2.73 ms, 2 = 5.46 ms, ... 128 = 349.5 ms */
uchar_T PR0_2 = 0; /* bits PR0, PR1, PR2 (see TSCR2) */
time_T sampleTime; /* time base as set in the block diagram */
#define MIN_PERIOD 0.002730625 // Timer 7 minimum period : 2.73 ms (65536*42 ns = 2.73 ms)
#define MAX_PERIOD MIN_PERIOD*128 // maximum period : 349.5 ms (MIN_PERIOD * 2^7 = 349.5 ms)
/* Determine the base sample rate (sampletime) -> this one is used by the 'solvers' (minor integration step)
* continuous states also use this minimum value
*/
sampleTime = rtmGetStepSize(S);
/* setup core timer T7 */
/* note these three lines have to precede the remaining initialisation to allow the code to run
* in release mode (otherwise only debug/monitor mode is possible... strangely! supposedly a timing
* timing issue. -- fw-03-05 (see /microcontroller/_work/_oddErrors/myOddTimer for further details)
*/
TIOS |= 0x80; // Configure channel 7 for output compare (OC) mode
TCTL1 &= 0x3F; // 00xx.xxxx -> OM7 = OM7 = 0 (disconnect pin 'IOC7' from o/p logic)
OC7M = 0x00; // do not affect any of the linked output pins (IOC0 - IOC6)
/* check if variable 'timerTicks' has to be used to extend range of timer */
if(sampleTime >= MAX_PERIOD) {
/* yes -> setup timer for a base resolution of 100 us */
/* Bottom three bits of TSCR2 (PR2,PR1,PR0) determine TCNT period
divider resolution maximum period
000 1 42ns 2.73ms
001 2 84ns 5.46ms
010 4 167ns 10.9ms
011 8 333ns 21.8ms
100 16 667ns 43.7ms
101 32 1.33us 87.4ms
110 64 2.67us 174.8ms
111 128 5.33us 349.5ms */
TSCR2 = 0x08; // Divide clock by 1, disable TOI (timer overflow interrupt)
// TCRE = 1 (reset TCNT upon output compare match of channel 7)
TC7 = 2400; /* actual period : 2400 * 1/24e6 = 100 us */
/* sample period in units of base resolution */
timerTicks = (uint32_T)(sampleTime*10000); //timerTicks = (uint32_T)(sampleTime/1e-4);
timerTicksReload = timerTicks;
} else {
/* no -> program exact value */
/* determine settings of the core timer T7 */
while (sampleTime > ((time_T)MIN_PERIOD)*n) {
n <<= 1; /* insufficiently long maximum period -> try next slower period */
PR0_2++; /* new value of PR0, PR1, PR2 */
}
TSCR2 = 0x08|PR0_2; // Divide clock by 128, disable TOI (timer overflow interrupt)
// TCRE = 1 (reset TCNT upon output compare match of channel 7)
/* Calculate reload value for timer T7 */
TC7 = (uint16_T)(65536 * sampleTime/(((time_T)MIN_PERIOD)*n));
/* reset 'timerTicks' -> every interrupt counts... */
timerTicks = 1;
timerTicksReload = timerTicks;
}
TSCR1 = 0x80; // enable timer 7 (set TEN bit)
TFLG1 = 0x80; // initially clear C7F (event flag for channel 7)
} /* End of init_timebase */
#endif /* CORE_TIMER == CORE_T7ISR */
#if CORE_TIMER == CORE_RTI
/* Function: RTI_isr =============================================================
*
* Abstract:
* The actual control algorithm (triggered by RTI, interrupt vector 07)
*/
#pragma CODE_SEG __NEAR_SEG NON_BANKED /* Interrupt section for this module. Placement will be in NON_BANKED area. */
__interrupt void RTI_isr(void) {
//PORTB |= 0x01;
/* first thing to do: acknowledge interrupt -> otherwise there's no real-time operation! -- fw-03-05 */
CRGFLG = 0x80; // acknowledge, clear RTIF flag
/* disable RTI interrupt */
CRGINT_RTIE = 0; // avoid pre-emption...
/* re-enable all interrupts (to allow servicing of RxD interrupt) */
asm cli // re-enable interrupts to allow this one to be interrupted
/* check if sampletime interval has elapsed */
if(--timerTicks == 0) {
/* yes -> reset 'timerTicks' to reload value */
timerTicks = timerTicksReload;
/* ----------------------- payload section : start ----------------------- */
// set cyctime_pin high (timing -> scope)
#ifdef TIMING
setCycTiPin;
#endif
/* run model code */
model_run();
// reset cyctime_pin (timing -> scope)
#ifdef TIMING
clrCycTiPin;
#endif
/* ----------------------- payload section : end ----------------------- */
}
/* re-enable RTI interrupt */
CRGINT_RTIE = 1;
//PORTB &= ~0x01;
} /* End of RTI_isr */
#pragma CODE_SEG DEFAULT
#endif
#if CORE_TIMER == CORE_T7ISR
/* Function: isr_timer7 =============================================================
*
* Abstract:
* The actual control algorithm (triggered by timer T7, interrupt vector 15)
*/
#pragma CODE_SEG __NEAR_SEG NON_BANKED /* Interrupt section for this module. Placement will be in NON_BANKED area. */
__interrupt void isr_timer7(void) {
//PORTB |= 0x01;
/* first thing to do: acknowledge interrupt -> otherwise there's no real-time operation! -- fw-03-05 */
TFLG1 = 0x80; // acknowledge interrupt (clears C7F)
/* disable (channel 7) timer interrupt */
TIE &= ~0x80; // avoid pre-emption...
/* re-enable all interrupts (to allow servicing of RxD interrupt) */
asm cli // re-enable interrupts to allow this one to be interrupted
/* check if sampletime interval has elapsed */
if(--timerTicks == 0) {
/* yes -> reset 'timerTicks' to reload value */
timerTicks = timerTicksReload;
/* ----------------------- payload section : start ----------------------- */
// set cyctime_pin high (timing -> scope)
#ifdef TIMING
setCycTiPin;
#endif
/* run model code */
model_run();
// reset cyctime_pin (timing -> scope)
#ifdef TIMING
clrCycTiPin;
#endif
/* ----------------------- payload section : end ----------------------- */
}
/* re-enable (channel 7) timer interrupt */
TIE |= 0x80;
//PORTB &= ~0x01;
} /* End of isr_timer7 */
#pragma CODE_SEG DEFAULT
#endif
/* ===================================================================================== */
#if ((HAS_TIMERBLOCKS > 0) | (HAS_RFCOMMS > 0))
/* This section is only included if the block diagram has timer blocks or RFComms blocks.
In this case, the ECT unit is configured using 'ECT_Init' and each timer channel can
be set up using 'TChannel_Conf'
fw-09-06
*/
/* global variables: reload values */
#if T0_MODE == TMode_OC
unsigned int TC0_ReloadValue;
#endif
#if T1_MODE == TMode_OC
unsigned int TC1_ReloadValue;
#endif
#if T2_MODE == TMode_OC
unsigned int TC2_ReloadValue;
#endif
#if T3_MODE == TMode_OC
unsigned int TC3_ReloadValue;
#endif
#if T4_MODE == TMode_OC
unsigned int TC4_ReloadValue;
#endif
#if T5_MODE == TMode_OC
unsigned int TC5_ReloadValue;
#endif
#if T6_MODE == TMode_OC
unsigned int TC6_ReloadValue;
#endif
#if T7_MODE == TMode_OC
unsigned int TC7_ReloadValue;
#endif
#if T0_MODE == TMode_IC
unsigned int TC0_Capture_last;
unsigned int TC0_diff;
#endif
#if T1_MODE == TMode_IC
unsigned int TC1_Capture_last;
unsigned int TC1_diff;
#endif
#if T2_MODE == TMode_IC
unsigned int TC2_Capture_last;
unsigned int TC2_diff;
#endif
#if T3_MODE == TMode_IC
unsigned int TC3_Capture_last;
unsigned int TC3_diff;
#endif
#if T4_MODE == TMode_IC
unsigned int TC4_Capture_last;
unsigned int TC4_diff;
#endif
#if T5_MODE == TMode_IC
unsigned int TC5_Capture_last;
unsigned int TC5_diff;
#endif
#if T6_MODE == TMode_IC
unsigned int TC6_Capture_last;
unsigned int TC6_diff;
#endif
#if T7_MODE == TMode_IC
unsigned int TC7_Capture_last;
unsigned int TC7_diff;
#endif
unsigned int TCx_latch;
unsigned long myTOFcounter;
float myECTperiod = MIN_ECT_PERIOD; // initialize with smalles possible base period (2.73 ms)
/* timer unit initialization (base rate) */
void ECT_Init(void) {
#ifdef ERASE /* ====================================================================================== */
/* no longer used... fw-09-06 */
unsigned int n = 1; /* base period multiplier: 1 = 2.73 ms, 2 = 5.46 ms, ... 128 = 349.5 ms */
unsigned char PR0_2 = 0; /* bits PR0, PR1, PR2 (see TSCR2) */
/* work out prescaler value */
while (myECTperiod < TIMER_BASEPERIOD) {
n <<= 1; /* insufficiently long maximum period -> try next slower period */
if(n > 128) break; /* max prescaler is '128' -> this should really throw an error... */
PR0_2++; /* new value of PR0, PR1, PR2 */
/* update maximum period */
myECTperiod = ((float)MIN_ECT_PERIOD)*n;
}
TSCR2 = 0x80|PR0_2; // TOF = 1 (enable timer overflow interrupt)
#endif /* ERASE ====================================================================================== */
/* set ECT period (used in TChannel_Conf) */
myECTperiod = (float)(MIN_ECT_PERIOD*TIMER_PRESCALER);
TSCR2 = 0x80|TIMER_PRESCALER_MASK;
OC7M = 0x00; // OC mode: do not affect any of the linked output pins (IOC0 - IOC6)
/* OC mode: output logic always disconnected -> everything is controlled from within the ISR */
TCTL1 = 0x00; /* channel 4 - 7 */
TCTL2 = 0x00; /* channel 0 - 3 */
}
/* start timer unit */
void ECT_Start(void) {
/* activate ECT */
TSCR1 |= 0x80; // start timer (set TEN bit)
}
/* stop timer unit */
void ECT_Stop(void) {
/* deactivate ECT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -