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
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.
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....
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.