Veit D. schrieb:
Hallo,
man muss versuchen das Grundprinzip zu verstehen, weil das Prinzip ist
immer gleich. Leider finde ich auch für andere PICs keine Timer AppNote.
Aber 3 Anleitungen auf Youtube. Ob die qualitativ gut sind weiß ich
nicht, wäre jedenfalls ein Anfang.
https://www.youtube.com/watch?v=I3x519D9NC0
https://www.youtube.com/watch?v=pAs9Up6Ap2M
https://www.youtube.com/watch?v=vD2jqWxuGEM
Auch wenn die sich nicht explizit auf deinen µC Typ beziehen kann man
das adaptieren. Die Registernamen sollten gleich bzw. ähnlich sein. Mit
einmal Timer Kapitel lesen im Manual sollte eine Anpassung möglich sein.
Du musst verstehen was die warum machen und notfalls die gleiche
Funktionalität in den Registern zusammensuchen. Also versteife dich
nicht so sehr auf die Register- und Bitnamen.
Danke für die Links.
Wie (fast immer) behandelt man in den Tutorials die Erzeugung eines "genauen" delays. Ich habe aber nach so etwas wie "Solange 1msec noch nicht vorbei ist" gesucht, denn in delays mit beliebigen Schleifen wird einfach nur "sinnlos" Zeit verbraten. Im Grunde genommen implementiere ich eine primitive Nebenläufigkeit mittels Zeitscheiben. Also so etwas wie:
1 |
wiederhole unendlich
|
2 |
{
|
3 |
Eine Periode Task1
|
4 |
Eine Periode Task2
|
5 |
...
|
6 |
Eine Periode TaskN
|
7 |
}
|
Mit Hilfe von MCC habe ich nun folgendes gemacht:
o es wird eine Flagvariable instantiert, die mir zeigen soll, wenn eine Periode (hier: 1msec) abgelaufen ist:
1 |
volatile bool periodFinished = false;
|
o Timer0 wird so konfiguriert , dass er nach 1msec einen Interrupt auslöst
1 |
void TMR0_Initialize(void)
|
2 |
{
|
3 |
// Set TMR0 to the options selected in the User Interface
|
4 |
|
5 |
// PSA not_assigned; PS 1:2; TMRSE Increment_hi_lo; mask the nWPUEN and INTEDG bits
|
6 |
OPTION_REG = (uint8_t)((OPTION_REG & 0xC0) | (0xD8 & 0x3F));
|
7 |
|
8 |
// TMR0 131;
|
9 |
TMR0 = 0x83;
|
10 |
|
11 |
// Load the TMR value to reload variable
|
12 |
timer0ReloadVal= 131;
|
13 |
|
14 |
// Clear Interrupt flag before enabling the interrupt
|
15 |
INTCONbits.TMR0IF = 0;
|
16 |
|
17 |
// Enabling TMR0 interrupt
|
18 |
INTCONbits.TMR0IE = 1;
|
19 |
|
20 |
periodFinished = false;
|
21 |
// Set Default Interrupt Handler
|
22 |
TMR0_SetInterruptHandler(TMR0_DefaultInterruptHandler);
|
23 |
}
|
o in der zugeordneten ISR wird ein Flag auf true gesetzt, wenn die msec vorbei ist.
1 |
void TMR0_DefaultInterruptHandler(void){
|
2 |
periodFinished = true;
|
3 |
}
|
Jedes mal, wenn ich im main einen Programmzweig habe, der genau eine
Periode dauern soll wird davor der Timer neu initialisiert
und dann solange der Zweig abgearbeitet, bis die Periode vorbei ist
1 |
while (!periodFinished)
|
2 |
{
|
3 |
// TuwasSinvolles};
|
4 |
}
|
Was ich noch nicht gut gelöst habe ist, dass ich jedes mal den Timer neu initialisiere. Mir wäre eine startTimer und eine stopTimer-Function lieber.
Also:
o Initialisieren des Timers am Anfang von main()
Schleife :
a) Aufruf von startTimer wenn eine Periode Arbeit anliegt
b) Arbeiten bis Periode vorbei : (periodFinished == true)
c) danach kann der Timer erst mal ruhen : stopTimer
d) zurück zu a)
So könnte ein startTimer stopTimer aussehen:
1 |
void startTimer()
|
2 |
{
|
3 |
periodFinished = false;
|
4 |
Irgendwie den Timer starten
|
5 |
}
|
6 |
|
7 |
void stopTimer()
|
8 |
{
|
9 |
Irgendwie den Timer stopen/einfrieren deaktivieren
|
10 |
}
|
Wenn mir jemand einen Tipp geben könnte, wie ich start/stopTimer implementiere
wäre ich sehr dankbar.
Der verwendete µC ist übrigens ein PIC16F1705
Danke und Grüße