Der Cortex M3 Kern hat einen internen 24 Bit Abwärtszähler (SysTick)
Dazu lediglich 4 Register von denen ich nur 2 benötige.
Das SysTick reload value register bestimmt den Intervall
hier schreibt man den Wert rein wie oft ein Interrupt auftreten soll
und ein Control Register, wo man festlegt welcher Clock benutzt wird und obo der Interrupt eingeschaltet wird.
Ich hab das so berechnet:
Code: Alles auswählen
#define SYSTIMER_IN_FREQ 72000000 // Quarzfrequency 72 MHz
#define SYSTIMER_INTERVAL 1000 // 1000 interrupts per second ==> 1ms
STK_LOAD = (SYSTIMER_IN_FREQ / SYSTIMER_INTERVAL)-1; // 1 Millisekunden Interrupt
STK_CTRL = 7; // counter enable, enable interrupt use processor clock
Wichtig ist, dass der Name der Interruptfunktion entsprechend in die Vectorentabelle eingetragen wird.
Hier haben verschiedenen Hersteller anscheinend verschiedene Namen vergeben.
Die stehen meist in der startup datei. Sonst sucht man sich einen Wolf warum der Interrupt nie aufgerufen wird.
im Prinzip wie Du schon gemacht hast:
Code: Alles auswählen
procedure TIM2_global_interrupt; public Name 'TIM2_global_interrupt'; interrupt;
Übrigens braucht man in der Interrupt Funktion bei diesem Timer kein Interrupt Bit löschen.
Bei mir in "C"
sieht das so aus: wobei das "volatile" Problem in Pascal vermutlich nicht existiert.....
Code: Alles auswählen
/* EXTREM wichtig: volatile, sonst erzeugt der C-Compiler FALSCHEN code */
/* bzw. kürz den Code komplett weg....*/
volatile static uint_32t DelayCount; /* used for delay_ms function */
/*----------------------------------------------------------------------------*/
void Delay_ms(uint_32t ms)
{
DelayCount = ms;
while (DelayCount)
{
}
}
/*----------------------------------------------------------------------------*/
/* this Interrupt handler is called every Millisecound */
/* we dont need to clear any interrupt flag in this handler */
void SysTick_Handler(void) // Der Name ist hier ganz entscheidend, damit er in die Vectoren Tabelle eingetragen wird.
{
if (DelayCount) DelayCount--;
}
/*----------------------------------------------------------------------------*/
void SysTickInit(void)
{
SYST_RVR = (SYSTIMER_IN_FREQ / SYSTIMER_INTERVAL)-1;
/* Count enable, Interrupt enable, Clock source is Systemclock */
SYST_CSR = 0x0007;
}
/*----------------------------------------------------------------------------*/
in PASCAL müsste das vermutlich irgendwie so aussehen:
Code: Alles auswählen
const SYSTIMER_IN_FREQ = 72000000; // Quarzfrequenz 72 MHz bei meinem LPC1347
const SYSTIMER_INTERVAL = 1000; // 1000 interrupts pro Sekunde ==> 1ms
const SYSTICK_BASE_ADDRESS = $E000E010; // Basisadresse beim STM32Fxxx
var STK_CTRL : DWORD absolute SYSTICK_BASE_ADDRESS + 0; // Steuerung interupt Clock select usw.
var STK_LOAD : DWORD absolute SYSTICK_BASE_ADDRESS + 4; // Zaehlerwert welcher beim Erreichen von 0 wieder geladen werden soll
var STK_VAL : DWORD absolute SYSTICK_BASE_ADDRESS + 8; // aktuelle Zählerstand des 24 Bit Zählers
var STC_CALIB : DWORD absolute SYSTICK_BASE_ADDRESS + 12; // $2328 ==> 9000 dez. warum steht der Wert stanbdardmässig auf 9000 ????
var delayCount : DWORD; // für die Delay procedure
// !!!! ich weis nicht wie der interrupt heissen muss....bitte den richtigen Namen eintragen
procedure SYSTICK_global_interrupt; public Name 'SYSTICK_global_interrupt'; interrupt;
begin
if delayCount > 0 then dec(delayCount);
end;
procedure Delay_ms(ms:DWORD);
begin
delayCount := ms; // gewünschten Zeitwert setzen
while (delayCount > 0) do ; // wird dann im SysTick-Interrupt jede Millisekunde runtergezählt
end;
// SysTick auf eine Millisekunde initialisieren
// bei meinem LPCxx läuft das zumindest so:
procedure InitDelay;
begin
STK_LOAD := (SYSTIMER_IN_FREQ DIV SYSTIMER_INTERVAL)-1; // 1 Millisekunden Interrupt
STK_CTRL := 7; // counter enable, enable interrupt, use processor clock
end;
Der Vorteil von dem internen Zähler des CORTEX M3 ist, das man sich vorerst nicht um den recht komplexen NVIC (Nested Interrupt Vector Controller) kümmern muss...
Siro