Forum: Compiler & IDEs Probleme mit PORT's und Zeitverhalten


von Jens (Gast)


Lesenswert?

Hallo,
ich habe hier ein kleines Problem bzw. Fragen zu den PORT Befehlen.

Ich arbeite hier an einem Atmel AT90CAN.

Über PORT A werden Daten geschickt oder gelesen, das wird anhand eines 
Flags von PORTB entschieden, desweiteren enthält PORT B noch 3 Bytes für 
eine Adresse (welches Datenbyte ich von einer Karte lesen will) und 
einer Chipselectadresse.

Also das Prinzip ist so, das ich bei PORTB eine bestimmte Adresse 
angeben so das eine Karte mir Daten auf den Datenbus der an PORTA geht 
anlegt.

Irgendwie schafft er es aber nicht immer das richtige zu lesen, somit 
habe ich eine Frage, gibt es "Regeln" in welcher Reihenfolge oder in 
welchem Abstand ich bestimmte PORT Befehle nur benutzen darf?
Momentan sieht das ganze so aus:


unsigned char ReadIO(unsigned char ucSlot, unsigned char ucByteNumber)
{
  unsigned char ucData = 0x00;
  unsigned char ucAdresse = 0x00;

  cli();

  DDRA  = 0x00;
  PORTA = 0x00;
  DDRB = 0xFF;

  ucAdresse = ( 0xA0 | (g_aucIOSlotBitMask[ucSlot] & 0x18) | 
(ucByteNumber & 0x07)) ;

  PORTB = ucAdresse;
  PORTB &= ~(1<<PB5);
        mywait();
  ucData = PINA;

  PORTB |= (1<<PB5);
  PORTB = 0xFF;
  sei();

  return ucData;
}

Quellcode zu myWait:
void mywait(void)
{
  DDRD &= 0xFE;
  do
  {
  }while( (PIND & 0x01) == 0x00 );
}

Bei wait wartet er einfach bis ein PIND1 wieder auf 1 gesetzt wird von 
dem "Kommunikationspartner". Dabei ist DDRD mit DDRD &= 0xFE 
initialisiert zum lesen und es wird (PIND & 0x01) in einer Whileschleife 
nur angefragt.


Also meine Frage ist einfach, kann es daran liegen das hier bestimmte 
befehle zu schnell hintereinander kommen??? Oder woran kann noch so ein 
Fehler liegen?

Danke für eure Hilfe im Vorraus

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Jens wrote:

> ich habe hier ein kleines Problem bzw. Fragen zu den PORT Befehlen.

Ist eher das falsche Forum, da das mit dem GCC eigentlich nichts zu
tun hat.

> Irgendwie schafft er es aber nicht immer das richtige zu lesen,
> somit habe ich eine Frage, gibt es "Regeln" in welcher Reihenfolge
> oder in welchem Abstand ich bestimmte PORT Befehle nur benutzen
> darf?

Generell erfolgt das Sampling der PINx-Werte vor dem Setzen der
PORTx-Werte.  Steht irgendwo im Datenblatt.  Wenn man also einen Port
setzt und möchte danach die Reaktion auf dieses Signal in einem
PINx-Register sehen, so muss man einen NOP einfügen.  Zwar machst du
das nicht direkt, aber...

>   DDRD &= 0xFE;
>   do
>   {
>   }while( (PIND & 0x01) == 0x00 );

...ich vermute, dass hier ein ählicher Effekt zuschlagen könnte: der
Port steht möglicherweise noch auf Ausgang (mit low-aktivem Signal) in
dem Moment, da PIND gelesen wird.  In diesem Falle würde nicht
gewartet.  Probier mal, nach dem DDRD-Ändern ein

asm volatile("nop");

reinzunehmen.

von Jens (Gast)


Lesenswert?

hmm der Admin darf gerne den Thread verschieben wenn ich dann noch mehr 
schlaue köpfe über mein Problem nachdenken :)

Ich habe das mit dem NOP nun versucht, aber keine Besserung. Was hat das 
denn mit diesem Tri-State aufsich und dem PUD im MCUCR Register ... so 
ganz habe ich das dort noch nicht verstanden. Der PORT A geht übrigens 
an ein 74HC244 der über diese Readleitung also PD6 geändert wird ob dort 
daten rein oder raus gehen.

ahja, wenn ich mit 16 MHz arbeite, muss ich dann 2 NOP's nehmen? hatte 
ich irgendwo hier im forum mal gelesen.


Meine Write funktion sieht übrigends so aus:

void seWriteIO(UCHAR ucSlot, UCHAR ucByteNumber, UCHAR ucData)
{
  UCHAR ucI = 1;

  cli();
//  unsigned char i = 40;

  DDRB = 0xFF;

  PORTB = (0x60 | (g_aucIOSlotBitMask[ucSlot] & 0x18) | (ucByteNumber & 
0x07));
  DDRA  = 0xFF;
  PORTA = ucData;
  PORTB &= ~(1<<PB5);
  mywait(ucSlot);
  PORTB |= (1<<PB5);

  PORTB = 0xFF;
  DDRA  = 0x00;

//  while (i--);

  sei();
}


Nach mehreren Tests war ich eingetlich Freitag sicher das der Fehler an 
der Readfunktion liegen muss aber irgendwie bin ich mir da auch nicht 
mehr so sicher. :(

Wenn ich übrigends die while schleife da wieder einbaue dann klappt 
alles....

von Jens (Gast)


Lesenswert?

Also für alle die es Interessiert,
der Fehler lag daran, das der Mikrokontroller auf der anderen Seite ( 
ein alter 3,4Mhz "schneller" Motorollar) nicht schnell genug aus seinem 
Interrupt raus kam. Der brauchte 20µs bis er wirklich wieder lese bereit 
war, hat mir aber schon vorher gesagt das er fertig sei. Die ganzen 
Befehle RTI etc dauerten noch so lang. Also noch eine kleine Wait 
schleife iengebaut und es klappt.

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.