Forum: Mikrocontroller und Digitale Elektronik XMEGA128A1 Pin einlesen


von Stefan (Gast)


Lesenswert?

Hallo Zusammen,

ich arbeite mich gerade in die Welt der µC und habe ein Problem.

Das schalten der Pins als Ausgang hat funktioniert. Jetzt möchte ich den 
Eingang einlesen. Habe dazu folgenden simplen Code geschrieben. Dieser 
wird ausgeführt (ohne Fehler) jedoch funktioniert nichts.


Wo ist der Fehler in meinem Code?
Wenn ich den Taster drücke <--> loslasse sollte sich doch etwas tun?




#include <avr/io.h>
#include <avr/interrupt.h>

void io_init(void);
void clock_init(void);

int main(void){

  clock_init();
  io_init();

  while(1){
    PORTE.IN = PORTE.OUT;
    }

  return 0;
}
void io_init(void){
  PORTE.DIR = 0xff;
  PORTE.DIR = 0x00;

}


void clock_init(void){
  //Oszillator auf 32Mhz stellen
  OSC.CTRL |= OSC_RC32MEN_bm;
  // Warten bis der Oszillator bereit ist
  while(!(OSC.STATUS & OSC_RC2MEN_bm));
  //Schützt I/O Register, Interrupts werden ignoriert
  CCP = CCP_IOREG_gc;
  //aktiviert den internen Oszillator
  CLK.CTRL = (CLK.CTRL & ~CLK_SCLKSEL_gm) | CLK_SCLKSEL_RC32M_gc;
}




Vielen Dank.

Gruß,
Stefan

von Stefan (Gast)


Lesenswert?

Blödsinn ich meine natürlich in der main- Schleife:

PORTE.IN = PORTD.OUT;



und in der io_init

PORTE.DIR = 0xff;
PORTD.DIR = 0x00;

Sorry für den Fehler!

von Timmo H. (masterfx)


Lesenswert?

Überleg mal was passiert wenn du einen Port der als Output eingestellt 
ist, einen Wert im "IN"-Register zuweist (welches ganz abgesehen davon 
Read-Only ist)

Vermutlich meinst du
1
PORTE.OUT = PORTD.IN;

: Bearbeitet durch User
von Stefan (Gast)


Lesenswert?

Was heißt Read-Only ?


Muss ich den Weg über eine Variable nehmen?

char Taster;

...




Taster = PORTD.IN;

PORTE.OUT = Taster;

von Stefan (Gast)


Lesenswert?

ich habe den Code geändert. Leider ist da scheinbar noch ein Fehler 
drin.

Hat noch jemand ein Idee?




#include <avr/io.h>
#include <avr/interrupt.h>

void io_init(void);
void clock_init(void);

int main(void){

  clock_init();
  io_init();

  char Taster;

  while(1){

    Taster = PORTD.IN;

    PORTE.OUT = Taster;

    }

  return 0;
}
void io_init(void){
  PORTE.DIR = 0xff;
  PORTE.DIR = 0x00;

}


void clock_init(void){
  //Oszillator auf 32Mhz stellen
  OSC.CTRL |= OSC_RC32MEN_bm;
  // Warten bis der Oszillator bereit ist
  while(!(OSC.STATUS & OSC_RC2MEN_bm));
  //Schützt I/O Register, Interrupts werden ignoriert
  CCP = CCP_IOREG_gc;
  //aktiviert den internen Oszillator
  CLK.CTRL = (CLK.CTRL & ~CLK_SCLKSEL_gm) | CLK_SCLKSEL_RC32M_gc;
}



Danke!

von rred (Gast)


Lesenswert?

1
  PORTE.DIR = 0xff;
2
  PORTE.DIR = 0x00;
3
      ^------------- ?

von Stefan (Gast)


Lesenswert?

oh.... richtig --> behoben zu.

PORTE.DIR = 0xff;
PORTD.DIR = 0x00;


Geht leider immer noch nicht.

von Robert W. (robwa)


Lesenswert?

Hallo Stefan,

wie ist Dein xmega beschaltet?
Leds über Vorwiderstand von Port E an VCC oder GND?
Taster mit Pullup / Pulldownwiderstand an Port D?
Funktioniert das Ein- Ausschalten einzelner LEDS?
Wenn Du z.B. statt
    Taster = PORTD.IN;

    Taster = 0x55;
schreibst, leuchtet dann jede 2. Led?
Hast Du einen Debugger?
Wenn ja, ändert sich das PORTD.IN-Register wenn Du eine Taste drückst?

Grüße, Robert.

von Stefan (Gast)


Lesenswert?

Ich benutze ein Evalboard: Xplained 128A1 mit einem ARV Dragon.

Die Ausgänge sind getestet d.h. mit einem anderen Code schaltbar.


Wo ich leider nicht weiterkomme ist die Taster vom Evalboard einzulesen.

von Robert W. (robwa)


Lesenswert?

Beim Xplained 128A1-Board sind die Taster mit Vorwiderständen gegen 
Masse geschaltet. Um definierte Zustände einzulesen musst Du vorher 
interne Pullup-Widerstände zuschalten. z.B.
    PORTD.PIN0CTRL |= PORT_OPC_PULLUP_gc
    PORTD.PIN1CTRL |= PORT_OPC_PULLUP_gc
...

Probier das mal aus.

Grüße,
Robert.

von Stefan (Gast)


Lesenswert?

Danke Robert du hast mir geholfen.

Es war jedoch noch etwas nicht vollständig:

Im Datenblatt steht dass:

"The input is not sampled and cannot be read if the digital input 
buffers are disabled."

Es fehlte also zusätzlich noch die Anweisung:

PORTD.PIN0CTRL |= PORT_ISC_BOTHEDGES_gc;

Danach ging es.

Danke allen die geholfen haben.


Gruß,
Stefan

von Timmo H. (masterfx)


Lesenswert?

Das was du da machst bzw. was du uns zeigst hat absolut nichts mit 
Interrupts zu tun. Du hast sie ja nicht mal via sei()  aktiviert 
geschweige denn eine entsprechende Interrupt Routine

von Timmo H. (masterfx)


Lesenswert?

Bzw. das Digital Inputbuffer Disable ist für PINs gedacht, die nur für 
Analoge Signale verwendet werden (also die Ports die am ADC hängen, also 
PORTA und PORTB). Damit kann man etwas Strom sparen. Dieser steht nach 
dem Reset eh auf PORT_ISC_BOTHEDGES. Solange du nach dem Reset dort 
nichts gemacht hast, was ja nach deinem geposteten Code nicht der Fall 
ist ändert das also nicht. Alle anderen Werte außer INTPUT_DISABLE haben 
nur Einfluss auf die Interrupt Funktionalität (wenngleich zumindest 
einer davon eingestellt sein muss damit der Pin überhaupt funktioniert)

: Bearbeitet durch User
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.