www.mikrocontroller.net

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


Autor: Jens (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Jens (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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....

Autor: Jens (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.