Forum: Mikrocontroller und Digitale Elektronik megaAVR 0-Series Programmierung


von Felix L. (flex)


Lesenswert?

Hallo,

ich beschäftige mich gerade mit der Programmierung des ATmega4809. Wie 
ich gelesen habe stammt der Syntax der neuen AVR von den AVR XMEGA ab, 
mit denen ich mich noch nie befasst habe. Ich habe folgenden Code:
1
int main(void)
2
{
3
  PORTF.DIR |= PIN5_bm;
4
    while (1) 
5
    {
6
    PORTF.DIRSET = PIN5_bm;
7
    _delay_ms(500);
8
    PORTF.DIRCLR = PIN5_bm;
9
    _delay_ms(500);
10
    }
11
}
Nun zu meiner Frage: Wann wird PIN5_bm und wann PIN5_bp verwendet?

Dann habe ich noch folgenden Code:
1
void USART_init()
2
{
3
    USART0.BAUD = (uint16_t)USART0_BAUD_RATE(9600);
4
    USART0.CTRLB |= USART_TXEN_bm;
5
    stdout = &USART_stream;
6
}
Warum wird bei USART0.BAUD ein einfaches = verwendet und bei 
USART0.CTRLB ein |=?

Und dann habe ich noch einen Teil der Timer Initialisierung:
1
TCA0.SINGLE.CTRLA = TCA_SINGLE_CLKSEL_DIV2_gc | TCA_SINGLE_ENABLE_bm;
Wenn ich es wie oben schreibe funktioniert es, allerdings nicht wenn ich 
es so schreibe:
1
TCA0.SINGLE.CTRLA = TCA_SINGLE_CLKSEL_DIV2_gc;
2
TCA0.SINGLE.CTRLA = TCA_SINGLE_ENABLE_bm;

Ich denke das sind einfache Fragen, aber auch aus den Getting Started 
Notes von Microchip werde ich leider nicht schlau.

von S. Landolt (Gast)


Lesenswert?

1. bm - bp: bit-mask vs. bit-position, siehe z.B.:
.equ CCL_RUNSTDBY_bm = 0x40              ; Run in Standby bit mask
.equ CCL_RUNSTDBY_bp = 6                 ; Run in Standby bit position


2. Weiß nicht, warum ver-odert wird, ich hätte
USART0.CTRLB = USART_TXEN_bm;
verwendet.

3. Ohne Ver-oderung wird mit dem zweiten Befehl der erste zunichte 
gemacht, d.h. der vorige Wert überschrieben.

von Oliver L. (olubritz)


Lesenswert?

Hallo Felix,

deine Fragen beziehen sich grundlegend alle auf das Thema 
Bit-Manipulation von Registerinhalten.

> Nun zu meiner Frage: Wann wird PIN5_bm und wann PIN5_bp verwendet?

PIN5_bm ist ein Define für die Bitmaske. In diesem Fall 0x20, wenn ich 
mich nicht irre. Du nutzt ihn in deinem Fall, um das Bit 6 in einem 
Register zu setzen. Beispiel: "PORTF.DIRSET = PIN5_bm;" schreibt 0x20 in 
das Register DIRSET des PORT F, um die Direction des Pin 5 von Port F 
auf auf 1 zu setzen (das müsste "Input" sein).

PIN5_bp ist ein Define für die Bitposition im Register. In diesem Fall 
müsste der Wert 6 sein. Beispiel: Das 6.te Bit im Register DIRSET dient 
der Einstellung des Pin 5.


> Warum wird bei USART0.BAUD ein einfaches = verwendet und bei
> USART0.CTRLB ein |=?

Bei USART0.BAUD überschreibst du das Ganze Register BAUD der USART0 mit 
dem Wert.
Mit "USART0.CTRLB |= USART_TXEN_bm;" setzt du nur das Bit TXEN im 
Register CTRLB der USART0.


>
> Und dann habe ich noch einen Teil der Timer Initialisierung:
>
1
> TCA0.SINGLE.CTRLA = TCA_SINGLE_CLKSEL_DIV2_gc | TCA_SINGLE_ENABLE_bm;
2
>
> Wenn ich es wie oben schreibe funktioniert es, allerdings nicht wenn ich
> es so schreibe:
>
1
> TCA0.SINGLE.CTRLA = TCA_SINGLE_CLKSEL_DIV2_gc;
2
> TCA0.SINGLE.CTRLA = TCA_SINGLE_ENABLE_bm;
3
>
>

Das kann nicht funktionieren, da du bei deinem Beispiel den gesamten 
Registerwert von CTRLA wieder überschreibst. Mit der ersten Zeile setzt 
du dir über das "|" (oder) mit den beiden Define einen Wert zusammen und 
schreibst dann das Resultat.


Ich würde dir empfehlen dich einmal mit dem Thema Bit-Manipulation 
auseinander zu setzen. Ich habe jetzt leider keine Guten Tutorials oder 
ähnliches zur Hand, aber vielleicht kann jemand anderes aus dem Forum 
helfen.

Gruß
Olli

von Oliver L. (olubritz)


Lesenswert?

Hallo S. Landolt,
entschuldige ich habe zu spät gesehen, dass du schon geantwortet hast.

Hierzu:
> 2. Weiß nicht, warum ver-odert wird, ich hätte
> USART0.CTRLB = USART_TXEN_bm;
> verwendet.

Dies wird verwendet, um den Rest des Registers nicht mit 0 zu 
überschreiben. Ggf. sind dort einige Bit, die standardmäßig auf 1 
gesetzt sind und deren Einstellung man dann ungewollt ändert. Ein "|=" 
ist an dieser Stelle sicherer.

Gruß
Olli

von S. Landolt (Gast)


Lesenswert?

> ... Ggf. sind dort einige Bit ...

Allenfalls aus der Vorgeschichte des Programms, Reset-Wert von 
USART0.CTRLB ist 0.

von S. Landolt (Gast)


Lesenswert?

> entschuldige ...

Keinerlei Ursache, so hat Felix zwei Antworten, ist doch prima.

von Felix L. (flex)


Lesenswert?

Vielen Dank für die Antworten, das hilft mir auf jeden Fall.

Oliver L. schrieb:
> PIN5_bm ist ein Define für die Bitmaske. In diesem Fall 0x20, wenn ich
> mich nicht irre. Du nutzt ihn in deinem Fall, um das Bit 6 in einem
> Register zu setzen. Beispiel: "PORTF.DIRSET = PIN5_bm;" schreibt 0x20 in
> das Register DIRSET des PORT F, um die Direction des Pin 5 von Port F
> auf auf 1 zu setzen (das müsste "Input" sein).

Das bedeutet dann, dass der Befehl
1
PORTF.DIRSET = PIN5_bm;
nur Pin5 auf "high" setzt und alle anderen mit "low" überschreibt? Wenn 
ich aber die anderen behalten möchten , dann muss ich ein |= verwenden?

Viele Grüße
Felix

von S. Landolt (Gast)


Lesenswert?

(falls Oliver gerade Kaffee trinkt ...)

Korrekt.
Hat aber nichts mit 'mask' oder 'position' zu tun. Man könnte auch
1
PORTF.DIRSET = (1<<PIN5_bp);
schreiben.

von Oliver L. (olubritz)


Lesenswert?

S. Landolt schrieb:
>> ... Ggf. sind dort einige Bit ...
>
> Allenfalls aus der Vorgeschichte des Programms, Reset-Wert von
> USART0.CTRLB ist 0.

Ok das stimmt, in diesem Fall geht es. Ich habe es mir nur allgemein 
angewöhnt, um keine Probleme zu bekommen, falls es doch einmal anders 
ist. :)

von Oliver L. (olubritz)


Lesenswert?

> Das bedeutet dann, dass der Befehl
>
1
PORTF.DIRSET = PIN5_bm;
> nur Pin5 auf "high" setzt und alle anderen mit "low" überschreibt? Wenn
> ich aber die anderen behalten möchten , dann muss ich ein |= verwenden?

Ja das stimmt und man kann es auch so schreiben, wie S. Landolt es 
angemerkt hat.

Hier aber noch eine kleine Info:
Das Register DIRSET dient speziell dem setzen der Bit im Register DIR. 
Es ist eine Vereinfachung, um schnell ein Bit im Register DIR setzen zu 
können. Als Pendant dazu gibt es das Register DIRCLR, mit dem man im 
Register DIR das entsprechende Bit löscht.
1
PORTF.DIRSET = PIN5_bm;

führt also dazu, dass Bit 6 im Register DIR gesetzt wird, jedoch nicht, 
dass alle anderen Bit im Register DIR gelöscht werden.

von leo (Gast)


Lesenswert?

Felix L. schrieb:
> PORTF.DIRSET = PIN5_bm;

Was machst du hier? Du setzt/resetzt zyklisch die Richtung des Pins, 
nicht den Level.

leo

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.