Forum: Mikrocontroller und Digitale Elektronik xmega Ports schalten


von Hans (Gast)


Lesenswert?

Hallo,

ich habe ein XMEGA -E5 Xplained Board und versuche grundlegende Dinge zu 
programmieren komme aber schon bei der LED-Ansteuerung nicht weiter.


Die LED ist laut Schaltplan an PORTD Pin 4 angeschlossen und wird nach 
Masse über den µController geschaltet.

Jetzt das komische Verhalten:

Wenn ich PORTD.DIR |= PIN4_bm;

in main programmiere leuchtet die LED sofort auf ohne das ich

PORTD.OUT &= ~ PIN4_bm; gesetzt habe wie kann das sein?

Ich habe den Port doch nur als Ausgang definiert aber noch nicht bewusst 
auf GND gesetzt.


Hat einer ne Idee ich bin am verzweifeln...

von Mitlesa (Gast)


Lesenswert?

Hans schrieb:
> Hat einer ne Idee ich bin am verzweifeln...

Naja, einen Wert muss der Ausgang ja haben, entweder low oder high.

Bei dir ist er zufällig der richtige, wenn die LED mit dem Wert low
leuchten muss.

Der Low-Zustand rührt wohl daher dass der Port nach dem Reset
defaultmässig per Definition des Herstellers low ist.

von Hans (Gast)


Lesenswert?

Mitlesa schrieb:
> Hans schrieb:
>> Hat einer ne Idee ich bin am verzweifeln...
>
> Naja, einen Wert muss der Ausgang ja haben, entweder low oder high.
Die Vermutung hatte ich auch aber ich kenne das von der Atmel 
Mega-Familie so nicht. Hat sich das bei der xmega-Famile etwa verändert?
>
> Bei dir ist er zufällig der richtige, wenn die LED mit dem Wert low
> leuchten muss.
>
> Der Low-Zustand rührt wohl daher dass der Port nach dem Reset
> defaultmässig per Definition des Herstellers low ist.

d.h heißt für mich ich muss schon beim I/O Init

PORTD.DIR |= PIN4_bm; /*PORTD.4 auf Ausgang gesetzt*/
PORTD.OUT |= PIN4_bm; /*PORTD.4 auf high-> LED aus*/

auf high setzen?

von Mitlesa (Gast)


Lesenswert?

Hans schrieb:
> d.h heißt für mich ich muss schon beim I/O Init
> ..............

Von müssen kann keine Rede sein.
Setze den Port so wie du es für richtig und notwendig hältst.

Wenn du nichts daran tust dann steht der Port eben so wie er
steht. Wie schon gesagt:

Mitlesa schrieb:
> einen Wert muss der Ausgang ja haben, entweder low oder high.

Schau dir die Beschaltung der LED an deinem Board an. Daraus
kannst du ja ermitteln wie der Port stehen muss um die LED
zum Leuchten zu bringen.

von Samuel C. (dragonsam)


Lesenswert?

BTW: Das ist bei den Atmega/Attiny nicht anders.

von Karl H. (kbuchegg)


Lesenswert?

Hans schrieb:

>> Naja, einen Wert muss der Ausgang ja haben, entweder low oder high.
> Die Vermutung hatte ich auch aber ich kenne das von der Atmel
> Mega-Familie so nicht. Hat sich das bei der xmega-Famile etwa verändert?

Das ist bei allen digitalen Systemen so.
Wenn etwas angesteuert wird, dann muss es entweder low oder high sein. 
So etwas wie 'nicht gesetzt' gibt es nicht.

Maximal gibt es noch bei manchen Logik-ICs so etwas wie den 
Tristate-Zustand, bei dem man im Grunde nichts anderes tut, als die 
Ansteuerung der Leitung gezielt abzuschalten.

Bei einem µC ist das normalerweise genau dann der Fall, wenn der Pin auf 
Eingang steht. Dann ist der Ausgangstreiber abgeschaltet und die Leitung 
darf jeden beliebigen Zustand annehmen, der ihr von irgendjemandem 
aufgezwungen wird. Der µC ist einfach nur Messgerät, welches feststellt, 
welcher Pegel das ist.
Steht der Pin aber auf Ausgang, dann hat der µC seine Ausgangstreiber 
zugeschaltet und dann treibt der die ausgehende Leitung entweder auf Low 
oder auf High. Aber eines von beiden muss es sein.

> PORTD.DIR |= PIN4_bm; /*PORTD.4 auf Ausgang gesetzt*/
> PORTD.OUT |= PIN4_bm; /*PORTD.4 auf high-> LED aus*/
>
> auf high setzen?

oder auch in der Reihenfolge anders rum, so dass der Portpin auch dann 
schon high ist, wenn der Ausgangstreiber aktiviert wird und es nicht 
einen Mykrosekunden langen Zwischenzustand gibt, in dem der Pin schon 
auf Ausgang aber noch low ist.

von Hans (Gast)


Lesenswert?

ok. jetzt habe ich folgendes versucht wollte die LED toggeln lassen aber 
die LED bleibt aus einzeln kann ich sie ein oder ausschalten jedoch 
nicht blinken lassen.  Mach ich noch was verkehrt?

#include <avr/io.h>
#define F_CPU 8000000
#include <util/delay.h>

void clock_init (void)
{
  OSC.CTRL |= OSC_RC8MEN_bm; /*Oszillator auf 8 Mhz einstellen*/
  while(!(OSC.STATUS & OSC_RC8MRDY_bm)); /*Warten bis der Oszillator 
bereit ist*/
  CCP = CCP_IOREG_gc; /*Schützt I/O Register, Interrupts werden 
ignoriert*/
  CLK.CTRL = (CLK.CTRL &~ CLK_SCLKSEL_gm) | CLK_SCLKSEL_RC8M_gc; 
/*aktiviert den internen Oszillator*/
}

int main(void)
{
  clock_init();

        PORTD.OUT |= PIN4_bm;
  PORTD.DIR |= PIN4_bm;


  while(1)
  {

    PORTD.OUTTGL &= ~ PIN4_bm;
          _delay_ms(500);
  }

return 0;
}

von Peter II (Gast)


Lesenswert?

Hans schrieb:
> PORTD.OUTTGL &= ~ PIN4_bm;

ohne die xmega zu kennen, würde ich vermute das man in ein Toggle 
Register ein wert reinschreiben muss.

teste mal mit

PORTD.OUTTGL = PIN4_bm;

von Falk B. (falk)


Lesenswert?

@ Hans (Gast)

>ok. jetzt habe ich folgendes versucht wollte die LED toggeln lassen

Vielleicht solltest du mal "versuchen", das Datenblatt zu lesen?

>nicht blinken lassen.  Mach ich noch was verkehrt?

Ja.
 Besser so.
1
  while(1)
2
  {
3
4
    PORTD.OUTTGL = PIN4_bm;
5
    _delay_ms(500);
6
  }
7
8
return 0;
9
}

Ein Schreiben einer 1 auf das Register OUTTGL bewirkt ein Umschalten des 
Bits in OUT! RTFM!

Und ja, die Xmegas unterscheiden sich schon recht stark von den normalen 
AVRs.

von Hans (Gast)


Lesenswert?

Peter II schrieb:
> Hans schrieb:
>> PORTD.OUTTGL &= ~ PIN4_bm;
>
> ohne die xmega zu kennen, würde ich vermute das man in ein Toggle
> Register ein wert reinschreiben muss.
>
> teste mal mit
>
> PORTD.OUTTGL = PIN4_bm;

die LED ist zwar jetzt an aber blinkt nicht.

von Falk B. (falk)


Lesenswert?

@ Hans (Gast)

>> PORTD.OUTTGL = PIN4_bm;

>die LED ist zwar jetzt an aber blinkt nicht.

Dun Nase sollst ja auch den Befehl in die Schleife mit der Verzögerung 
reinschreiben, nicht einfach so!

von Mitlesa (Gast)


Lesenswert?

Hans schrieb:
> ok. jetzt habe ich folgendes versucht

Bitte auch mal an die Regeln denken.

C-Code in C-Code posten (Formatierung ).

von Hans (Gast)


Lesenswert?

Falk Brunner schrieb:
> @ Hans (Gast)
>
>>> PORTD.OUTTGL = PIN4_bm;
>
>>die LED ist zwar jetzt an aber blinkt nicht.
>
> Dun Nase sollst ja auch den Befehl in die Schleife mit der Verzögerung
> reinschreiben, nicht einfach so!

int main(void)
{
  clock_init();


  PORTD.OUT |= PIN4_bm;
  PORTD.DIR |= PIN4_bm;


  while(1)
  {
    PORTD.OUTTGL =  PIN4_bm;
    _delay_ms(500);
  }

return 0;
}

so hab ich das jetzt funktioniert immer noch nicht oder bin ich blind 
...

von Mitlesa (Gast)


Lesenswert?

Hans schrieb:
> funktioniert immer noch nicht oder bin ich blind

Hast du Warnings beim Compilieren? Vermutlich läuft der
Prozessor nicht mit dem Takt den du erwartest ....

von Hans (Gast)


Lesenswert?

Mitlesa schrieb:
> Hans schrieb:
>> funktioniert immer noch nicht oder bin ich blind
>
> Hast du Warnings beim Compilieren? Vermutlich läuft der
> Prozessor nicht mit dem Takt den du erwartest ....

leider keine Warnings.

der µController läuft mit 8MHz auch andere delay zeiten haben keinen 
einfluss..


Kann einer vllt ein Testcode schreiben wo er sicher weiß das er 
funktioniert?

ich sehe den Wald vor lauter Bäumen nicht mehr....

von Falk B. (falk)


Lesenswert?

Das sollte funktionieren. Und du hast SICHER die Datei neu compiliert 
und auf den uC gebrannt?

von Mitlesa (Gast)


Lesenswert?

Hans schrieb:
> der µController läuft mit 8MHz

Woran erkennst du das? Hast du dir den Prozessortakt irgendwo
physikalisch ausgeben lassen und nachgemessen? Ich schätze mal
nicht. Dann kannst du auch nicht sicher sein das er das tut was
du erwartest.

von Hans (Gast)


Lesenswert?

funktioniert jetzt hatte noch einen Timer Interrupt drinne der immer 
dazwischen gehauen hat.

von Mitlesa (Gast)


Lesenswert?

aus iox128a1.h:

1
/* Clock Output Port */
2
typedef enum PORTCFG_CLKOUT_enum
3
{
4
    PORTCFG_CLKOUT_OFF_gc = (0x00<<0),  /* Clock Output Disabled */
5
    PORTCFG_CLKOUT_PC7_gc = (0x01<<0),  /* Clock Output on Port C pin 7 */
6
    PORTCFG_CLKOUT_PD7_gc = (0x02<<0),  /* Clock Output on Port D pin 7 */
7
    PORTCFG_CLKOUT_PE7_gc = (0x03<<0),  /* Clock Output on Port E pin 7 */
8
} PORTCFG_CLKOUT_t;

Mit diesen Zeilen kann man sich den Clock auf einen Pin ausgeben
lassen (in diesem Fall Port C, Bit 7):
1
    PORTC_DIRSET = 0x80;  /*  SysClock on bit 7  */
2
    PORTCFG_CLKEVOUT = PORTCFG_CLKOUT_PC7_gc;

von Falk B. (falk)


Lesenswert?

@ Hans (Gast)

>funktioniert jetzt hatte noch einen Timer Interrupt drinne der immer
>dazwischen gehauen hat.

HA! NIEMALS! Dann hast du uns den FALSCHEN Quelltext gezeigt! Vielen 
Dank!

von Falk B. (falk)


Lesenswert?

1
  CCP = CCP_IOREG_gc; /*Schützt I/O Register, Interrupts werden 
2
ignoriert*/
3
  CLK.CTRL = (CLK.CTRL &~ CLK_SCLKSEL_gm) | CLK_SCLKSEL_RC8M_gc; 
4
/*aktiviert den internen Oszillator*/
5
}

Sowas funktioniert NICHT sicher, je nach Optimierung des Compilers! Das 
macht man besser mit einem ASM-Makro! Das ist sicher!

Beitrag "Re: PLL Startprobleme beim ATXmega128A1U"

Für die Nichtganzsomitdenker. Natürlich darf währen eines CCP Zugriffs 
KEINERLEI Interrupt aktiv sein, denn sonst kann es passieren, dass der 
genau in die Sequenz reinhaut und diese somit schief geht!

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.