Forum: Digitale Signalverarbeitung / DSP / Machine Learning TMS320F28xx Timer kleines Verständnisproblem


von Loesungssucher (Gast)


Lesenswert?

Hallo erstmal,

ich arbeite gerade mit dem ober genannten MCU. Ich möchte einen Timer 
implementieren für meine Duplex Kommunikation. Ich habe mir die 
Beispiele von der TI seite angeschaut. Hatte auch erfolgreich den Code 
für den Timer0 in meinen Code eingebaut. Der Timer erzeugt einen 
Interrupt jede Sekunde. Leider verstehe ich nicht ganz wie diese Zeit 
mit Hilfe der Register eingestellt worden ist.

Hier ein bisschen vom Code,
1
//initialisierung des timers0
2
//************************ TIMER0
3
void InitCpuTimers(void)
4
{
5
    // CPU Timer 0
6
    // Initialize address pointers to respective timer registers:
7
    CpuTimer0.RegsAddr = &CpuTimer0Regs;
8
    // Initialize timer period to maximum:
9
    CpuTimer0Regs.PRD.all  = 0xFFFFFFFF;
10
    // Initialize pre-scale counter to divide by 1 (SYSCLKOUT):
11
    CpuTimer0Regs.TPR.all  = 0;
12
    CpuTimer0Regs.TPRH.all = 0;
13
    // Make sure timer is stopped:
14
    CpuTimer0Regs.TCR.bit.TSS = 1;
15
    // Reload all counter register with period value:
16
    CpuTimer0Regs.TCR.bit.TRB = 1;
17
    // Reset interrupt counters:
18
    CpuTimer0.InterruptCount = 0;
19
20
}
21
22
//---------------------------------------------------------------------------
23
// ConfigCpuTimer:
24
//---------------------------------------------------------------------------
25
// This function initializes the selected timer to the period specified
26
// by the "Freq" and "Period" parameters. The "Freq" is entered as "MHz"
27
// and the period in "uSeconds". The timer is held in the stopped state
28
// after configuration.
29
//
30
void ConfigCpuTimer(struct CPUTIMER_VARS *Timer, float Freq, float Period)
31
{
32
    Uint32  temp;
33
34
    // Initialize timer period:
35
    Timer->CPUFreqInMHz = Freq;
36
    Timer->PeriodInUSec = Period;
37
    temp = (long) (Freq * Period);
38
    Timer->RegsAddr->PRD.all = temp;
39
40
    // Set pre-scale counter to divide by 1 (SYSCLKOUT):
41
    Timer->RegsAddr->TPR.all  = 0;
42
    Timer->RegsAddr->TPRH.all  = 0;
43
44
    // Initialize timer control register:
45
    Timer->RegsAddr->TCR.bit.TSS = 1;      // 1 = Stop timer, 0 = Start/Restart Timer
46
    Timer->RegsAddr->TCR.bit.TRB = 1;      // 1 = reload timer
47
    Timer->RegsAddr->TCR.bit.SOFT = 1;
48
    Timer->RegsAddr->TCR.bit.FREE = 1;     // Timer Free Run
49
    Timer->RegsAddr->TCR.bit.TIE = 1;      // 0 = Disable/ 1 = Enable Timer Interrupt
50
51
    // Reset interrupt counter:
52
    Timer->InterruptCount = 0;
53
}
54
55
void timer0_init(void)
56
{
57
   EALLOW;  // This is needed to write to EALLOW protected registers
58
   PieVectTable.TINT0 = &cpu_timer0_isr;
59
   EDIS;    // This is needed to disable write to EALLOW protected registers
60
}
61
62
63
64
interrupt void cpu_timer0_isr(void)
65
{
66
  timer_var=timer_var;
67
   test_variable=CpuTimer0.InterruptCount++;
68
69
   // Acknowledge this interrupt to receive more interrupts from group 1
70
   PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
71
}
72
73
//*************************** TIMER 0

Für die interrupt Einstellung benutze ich, soweit ich es verstanden 
habe, die "ConfigCpuTimer()" Funktion. Aufgerufen wird diese in meiner 
Haupdatei, mit
1
// Configure CPU-Timer 0 to interrupt every second:
2
  // 100MHz CPU Freq, 1 second Period (in uSeconds)
3
     ConfigCpuTimer(&CpuTimer0, 100, 3000000);

Soweit ich es überblicken kann wird kein Prescaler benutzt, also mit 
jedem Takt meines CPUs wird das TIMH:TIM dekrementiert. Und bei null 
wird der Wert welcher im PRD steht in den TIMH:TIM Register wieder 
geschrieben wobei dieser wieder runterzählt.

Jetzt kriegt das PDR in der ConfigCpuTimer() Funktion den Wert 
300.000.000 zugewiesen.
1
temp = (long) (Freq * Period);
2
Timer->RegsAddr->PRD.all = temp;
 Ich komme aber nicht drauf, wie jetzt jede Sekunde ein Interrupt 
erzeugt wird. Eigentlich würde ja jede dritte Sek. ein Interrupt erzeugt 
werden mit Freq.=100MHZ -> 300.000.000Takte/100MHz=3sek. Könnte mich 
einer bitte aufklären!

Danke

von Peter D. (pdiener) Benutzerseite


Lesenswert?

So, wie das aussieht, sollte der Interrupt nur alle 3 Sekunden kommen.
Der Timer kann nicht schneller runterzählen, als die CPU getaktet wird.

// The "Freq" is entered as "MHz"
// and the period in "uSeconds".

Wenn man dem Kommentar glaubt, ist das auch so.

Ich konfiguriere die Register normal von Hand, ohne die umständliche 
Konfigfunktion.

Das sieht dann z.B. so aus:
1
void Timebase_init()
2
{
3
   // CPU Timer 1 setup -- TBD
4
   CpuTimer1Regs.TCR.bit.TSS = 1;                  // Stop timer
5
   CpuTimer1Regs.TIM.all = 0;                      // Timer counter register
6
   CpuTimer1Regs.PRD.all = 100000 - 1;             // Period (reload value) of down counter, 1 ms
7
   CpuTimer1Regs.TPRH.bit.TDDRH = 0;               // Divide down register high
8
   CpuTimer1Regs.TPR.bit.TDDR = 0;                 // Divide down register low
9
   CpuTimer1Regs.TCR.bit.TRB = 1;                  // Reload now!
10
   CpuTimer1Regs.TCR.bit.TSS = 0;                  // Start timer   
11
}

Das einzige, was mir gerade auffält, ist dass ich am Periodregister noch 
1 subtrahiere, das macht der Code von Ti nicht. Da muss ich mal 
nachprüfen, was richtig ist.

Grüße,

Peter

von Peter D. (pdiener) Benutzerseite


Lesenswert?

Also, das spru712g sagt dazu folgendes:

"When the TIMH:TIM decrements to zero, the
TIMH:TIM register is reloaded with the period value contained in the 
PRDH:PRD registers, at the start of
the next timer input clock cycle (the output of the prescaler)."

Nach meiner Interpretation ist es so, dass der Timer bis auf Null zählt 
und dort auch für einen Takt bleibt.

Also so:

Timerwert:     4   3   2   1   0   PRD   PRD-1 usw...
Clockinput:    |   |   |   |   |    |     |

Angenommen, PRD ist 4.

Dann braucht es 5 Takte, um einmal im Kreis zu zählen:
4  3  2  1  0  4  3  2  1  0  4  usw...

Also muss doch in PRD ein weniger stehen, als die Periode sein soll. 
Oder hab ich da was übersehen?

Grüße,

Peter

von Loesungssucher (Gast)


Lesenswert?

Hi Peter, danke für deine Antwort,

du hast recht. Ich glaube der Kommentar von der TI
//interrupt every second
hatte mich irretiert. Der interrupt kamm alle 3 Sekunden mit 3.000.000, 
hatte den Wert auf 10.000.000 gesetzt und hatte nen Interrupt alle 10 
Sekunden.

Was das Laden des Wertes aus dem PRD in den TIM angeht, ich würde es 
genauso sehen wie du. Anscheinend haben es die TI Leute nicht 
berücksichtingt in ihrem Beispiel. Für meine Sache macht es aber nichts 
aus, drei Takte mehr oder weniger.

Grüß

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.