Forum: Mikrocontroller und Digitale Elektronik Timer-Register-Adresse in Variable speichern


von Markus (Gast)


Lesenswert?

Hallo,
ich möchte gerne die Timer-Register-Adresse in einer Variable speichern. 
Bisher habe ich eine Funktion
1
timerInit(volatile uint8_t &tccra, uint8_t tccraSet,
2
          volatile uint8_t &tccrb, uint8_t tccrbSet,
3
          volatile uint8_t &ocra, uint8_t ocraSet,
4
          volatile uint8_t &timsk, uint8_t timskSet)
5
{
6
7
    tccra |= tccraSet;
8
    tccrb |= tccrbSet;
9
    ocra |= ocraSet;
10
    timsk |= timskSet;
11
}

aufgerufen wird die FUnkton aus der main.c
1
timerInit(TCCR0A,  ~(1 << WGM00) | (1 << WGM01),
2
          TCCR0B,  (1 << CS00) | (1 << CS01) & ~(1 << CS02),
3
          OCR0A,   250 - 1,
4
          TIMSK0,  (1 << OCIE0A));

Jetzt möchte ich gerne, die Adresse von TCCR0B in eine Variable 
speichern, sodass ich zwei neue Funktionen hinzufügen kann, wo ich den 
Timer starten bzw. stoppen kann. Dazu würde ich in der Funktion 
timerInit tccrb = 0x00 setzen und bei der funktion start dann das 
entsprechende bit (tccrbSet) setzen.
Aber irgendwie will das absolut nicht hinhauen

habe eine neue variable
volatile uint8_t _tccrb erstellt

setze in in der Funktion timerInit dann noch zusätzlich
_tccrb = tccrb;
passiert nichts. (tccrb = 0).
mache ich
_tccrb = *tccrb
bekomme ich den error
invalid type argument of unary '*' (have 'uint8_t{aka unsigned char}')

Wie ist es möglich, die Adresse von TCCR0B in die Variable _tccrb zu 
speichern?

Gruß

Markus

von Oliver S. (oliverso)


Lesenswert?

Die "Register" sind nichts anderes Pointer auf Adressen. Schau dir doch 
in den Header die Definitionen an. Die kannst du, so wie sie sind, 
übergeben.

Oliver

: Bearbeitet durch User
von S. Landolt (Gast)


Lesenswert?

Pardon, das hat jetzt nichts mit der Fragestellung zu tun, nur 
interessehalber, weil es mir gestern schon auffiel - was ist das 
Resultat von
> TCCR0A,  ~(1 << WGM00) | (1 << WGM01),
?

von Falk B. (falk)


Lesenswert?

@ Markus (Gast)

>ich möchte gerne die Timer-Register-Adresse in einer Variable speichern.
>Bisher habe ich eine Funktion

>timerInit(volatile uint8_t &tccra, uint8_t tccraSet,
>          volatile uint8_t &tccrb, uint8_t tccrbSet,
>          volatile uint8_t &ocra, uint8_t ocraSet,
>          volatile uint8_t &timsk, uint8_t timskSet)
>{

Sieht nach einer Super Duper Timer Init Funktion aus ;-)

>    tccra |= tccraSet;
>    tccrb |= tccrbSet;
>    ocra |= ocraSet;
>    timsk |= timskSet;
>}

Passt so nicht! Du braucht POINTER!!!


>aufgerufen wird die FUnkton aus der main.c

>timerInit(TCCR0A,  ~(1 << WGM00) | (1 << WGM01),
>          TCCR0B,  (1 << CS00) | (1 << CS01) & ~(1 << CS02),
>          OCR0A,   250 - 1,
>          TIMSK0,  (1 << OCIE0A));

Das funktioniert nicht so, wie du das willst.

>Wie ist es möglich, die Adresse von TCCR0B in die Variable _tccrb zu
>speichern?

Ja, aber richtig, wenn gleich sich dafür eine Funktion kaum lohnt.
1
timerInit(volatile uint8_t* tccra, uint8_t tccraSet,
2
          volatile uint8_t* tccrb, uint8_t tccrbSet,
3
          volatile uint8_t* ocra, uint8_t ocraSet,
4
          volatile uint8_t* timsk, uint8_t timskSet)
5
{
6
7
    *tccra |= tccraSet;
8
    *tccrb |= tccrbSet;
9
    *ocra |= ocraSet;
10
    *timsk |= timskSet;
11
}
12
13
14
timerInit(&TCCR0A,  ~(1 << WGM00) | (1 << WGM01),
15
          &TCCR0B,  (1 << CS00) | (1 << CS01) & ~(1 << CS02),
16
          &OCR0A,   250 - 1,
17
          &TIMSK0,  (1 << OCIE0A));
18
19
volatile uint8_t* _tccrb = &TCCRB;
20
21
*_tccrb = 0xwhatever;

von Markus (Gast)


Lesenswert?

S. Landolt schrieb:
> Pardon, das hat jetzt nichts mit der Fragestellung zu tun, nur
> interessehalber, weil es mir gestern schon auffiel - was ist das
> Resultat von
>> TCCR0A,  ~(1 << WGM00) | (1 << WGM01),
> ?

Im Register TCCR0A wird das bit WGM01 gesetzt und WGM00 nicht gesetzt

von Wilhelm M. (wimalopaan)


Lesenswert?

Markus schrieb:
> Hallo,
> ich möchte gerne die Timer-Register-Adresse in einer Variable speichern.

...


> Wie ist es möglich, die Adresse von TCCR0B in die Variable _tccrb zu
> speichern?

Du musst das Datenelement vom Typ volatile uint8_t* deklarieren.

Zudem initialisiert man Datenelemente in einer 
Elementinitialisiererliste und weist ihnen keine Werte im ctor zu.

Allerdings ist der Ansatz, zur Compilezeit konstante Werte wie Adressen 
von Registern in (kostbarem) RAM des AVRs zu speichern, nicht sinnvoll. 
Das solltest Du ändern (s.a. templates).

: Bearbeitet durch User
von S. Landolt (Gast)


Lesenswert?

> Im Register TCCR0A wird das bit WGM01 gesetzt und WGM00 nicht gesetzt
Im Ernst? Na, Schuster bleib bei deinem Leisten, soll heißen, Landolt
bleib bei Assembler.
Danke für die Antwort.

von Wilhelm M. (wimalopaan)


Lesenswert?

Markus schrieb:
> S. Landolt schrieb:
>> Pardon, das hat jetzt nichts mit der Fragestellung zu tun, nur
>> interessehalber, weil es mir gestern schon auffiel - was ist das
>> Resultat von
>>> TCCR0A,  ~(1 << WGM00) | (1 << WGM01),
>> ?
>
> Im Register TCCR0A wird das bit WGM01 gesetzt und WGM00 nicht gesetzt

Die einzige "0", die in dem Ausdruck

~(1 << WGM00) | (1 << WGM01)

enthalten ist, ist an der Position WGM00.

Wenn das mit dem Timerregister "ver-odert" wird, ist alles auf "1", bis 
auf den Wert von Bit WGM00, der erhalten bleibt.

: Bearbeitet durch User
von posti (Gast)


Lesenswert?

Hi

Wird das Register wirklich ver-oder-t?
Hieße ja, daß im compiliertem Code zuerst das Register ausgelesen wird, 
mit den zu setzenden Bits ver-oder-t und mit den zu löschenden Bits 
negiert ver-and-et werden würde - kA von BasCom, kann mir Das aber nur 
schwer vorstellen.

Aber sinnvoll, wenn die Werte immer wieder in die gleiche Variabel 
eingeodert bzw rausge-nand werden, da sonst Bit-Reste über bleiben 
könnten.

Irgendwie scheint mir Assembler doch der einfachere Weg - da weiß man 
wenigstens, wo man drehen kann, wenn man ins Datenblatt schaut.
Wobei dort, wenn eh der Timer1 genommen wird, man Diese zwar durch einen 
Alias ersetzen kann, aber zum Ändern auch die ganzen anderen Bits (CS10 
zB.) mit ändern muß, da nicht alle Möglichkeiten des Timer1 auch in 
einem anderen Timer vorhanden sind.
Auch ist (1<<CS01)|(1<<CS00) vom Bitmuster identisch 
mit(1<<CS11)|(1<<CS10), jedoch macht das Control-Register daraus 1x nen 
1:2 (TCCR0B = 0x33) und 1x nen 1:8 (TCCR1 = 0x30) Takt (z.B. ATtiny45).

Ggf. ist in BasCom das Wechseln auf einen anderen Timer aber auch 
einfacher, da BasCom die Änderungen beim Compilieren entsprechend 
einplant.

von Wilhelm M. (wimalopaan)


Lesenswert?

posti schrieb:
> Hi
>
> Wird das Register wirklich ver-oder-t?

Schau hier:
1
   tccra |= tccraSet;

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.