Der 8051 zerstückelt eine long Variable in 4 einzelne Bytes, wobei das höchstwertige Byte nicht benötigt und daher weggelassen wird. Diese 3 Bytes werden dann nacheinander am Port des 8051 ausgegeben. Hier die Ausgabe Routine (Keil C Compiler): P0_0=0; //Ruheposition für Enable-Bit P0_1=1; //Ruheposition für Bit, dass den INT0 beim ATmega16 auslöst P5=0; acc=freq_einst/0.10596381293403; //Berechnung b1=acc&0xff; //Byte1 (niederwertigstes Byte) b2=(acc>>8)&0xff; //Byte2 b3=(acc>>16)&0xff; //Byte3 //Übergabe Routine P0_1=0; //INT0 auslösen P0_1=1; P5_0=1; //Mitteilen, dass Byte1 übergeben wird P5=b1; //Byte1 am Port ausgeben P0_0=1; //mega16 übernimmt das Byte P0_0=0; P5=0; P5_1=1; //Byte2 wird übergeben P5=b2; //usw ... P0_0=1; P0_0=0; P5=0; P5_2=1; P5=b3; P0_0=1; P0_0=0; P5=0; Umrechnung funktioniert (testweise am LCD angezeigt), jedoch nimmt der mega16 die Daten nicht an. ATmega16 asm Code: int0_isr: sbic PINA,0 rjmp r24_load sbic PINA,1 rjmp r25_load sbic PINA,2 rjmp r26_load rjmp int0_isr r24_load: sbis PIND,3 rjmp r24_load in r24,PINA wait_r24: sbic PIND,3 rjmp wait_r24 rjmp int0_isr r25_load: sbis PIND,3 rjmp r25_load in r25,PINA wait_r25: sbic PIND,3 rjmp wait_r25 rjmp int0_isr r26_load: sbis PIND,3 rjmp r26_load in r26,PINA reti Am Anfang wartet er darauf welches Register geladen werden soll (r24,r25,r26), dann wird in die jeweilige Routine gewechselt und die Daten sollten danach eingelesen werden, dann springt er zurück in die INT0_ISR und wartet wieder. Abgeschlossen wird die ISR mit dem r26_load. Bei dem 8051 handelt es sich um einen AT89C51ED2, der mit 24MHz betrieben wird. Der mega16 wird mit 16MHz getaktet. Beide führen ihre Hauptaufgaben ohne Probleme durch, jedoch scheitert das Ganze noch an der Übergabe :-( Als Anhang ist ein JPG File dabei, das die Verbindung der 2 µC zeigt. Ich bin für jeden noch so kleinen Hinweis sehr dankbar :-)
Dir fehlt die Synchronisation. Ich habe von C keine Ahnung, aber soweit ich das interpretiere, sendest Du über den "Datenbus" P5 zuerst eine Adresse, wohin das Byte soll (1,2 oder 3) und dann das Datenbyte selbst direkt hinterher. Zwischen der Mitteilung, welches Byte übergeben wird und dem Byte selbst mußt Du irgendein Signal generieren, das die Adresse von den Daten trennt, sonst liest der Mega-16 Mist. Dementsprechend muß der Mega16 auf der anderen Seite auf dieses Signal warten. Du hast doch 2 Steuerleitungen vorgesehen, ich würde es folgendermaßen machen: Steuerleitung 1 ist das A/D (Adresse / Daten), Steuerleitung 2 ist das Strobe (Übernahme von Daten bei steigender oder fallender Flanke). Schau Dir mal die Anbindung von RAM / Displays an einen Daten/Adressbus an. In Pseudocode könnte das so aussehen: A/D = 0 (Adresse) Datenbus = Byte-Nr. Strobe A/D = 1 (Daten) Datenbus = Datenbyte Strobe Du könntest auch auf das Adressbyte ganz verzichten, wenn Du die Reihenfolge festlegst und immer die gleiche Anzahl Daten überträgst.
Damit ich dem mega16 mitteile, dass die Daten gültig sind ist der Ausgang P0.0 da. Also dieser geht auf High, der mega16 liest ein und wartet bis es wieder auf Low geht, dann gehts zurück in die ISR, wo er wieder wartet bis die nächste Adresse kommt. Ich bin davon ausgegangen, dass der mega16 schneller als der 8051 arbeitet - deswegen wartet nur der mega16 und der 8051 sendet alles nacheinander. Wahrscheinlich hab ich das Ganze etwas komplizierter gemacht als es eigentlich sein sollte, aber Assembler ist nicht so mein Ding.
da beide controller nach dem einschalten unterschiedlich lange brauchen, um den programmteil zu erreichen, ist es wahrscheinlich, daß der atm 16 nich das erste byte als erstes empfängt, sondern byte 2 oder 3. ads meinte bernhard mit der synchronisation. mfg michael
Du solltest wirklich am besten zwischen der Adressausgabe und der Datenausgabe einen Synchonisationsimpuls erzeugen. Wie wäre es denn, wenn Du erst die Adresse an den Port ausgibst, dann die ISR des ATmega durch den L-H-Übergang an P0_1 triggerst, damit der ATmega merkt, welches Byte als nächstes übertragen wird? Die Adresse ist dann solange gültig, wie H-Pegel am INT0-Pin anliegt. Sobald L-Pegel anliegt, handelt es sich um Daten. Damit würde man sogar einen Handshake-Pin sparen. INT0 könnte man doch auch zustandsgesteuert auslösen lassen, oder? Sonst halt die L-H-Flanke (oder anders herum). Bei Eintreffen einer Flanke oder Anliegen von H-Pegel weiss der ATmega dann, dass eine Adresse anliegt. Gruß Rahul
Hab gerade festgestellt, dass es sich bei deiner Flanke um eine fallende handelt. Also alles umgekehrt: Bei L-Pegel liegt die Adresse an, bei H Daten. Nach meiner Einschätzung sollte das so funktionieren (habe es nicht ausprobiert). Was sein kann, ist, dass zwischen den Umschaltvorgängen eine gewisse Zeit vergehen muss, wegen der Port-Kapazitäten. Notfalls mehrfach den Port abfragen (ähnlich dem Tastenenprellen). Gruß Rahul
P5_0=1; //Mitteilen, dass Byte1 übergeben wird P5=b1; //Byte1 am Port ausgeben Das kann doch nicht gehen ! Du überschreibst ja P5_0 sofort wieder. Du must ein Handshake machen, wo der M16 mitteilen kann, daß er die aktion gelesen hat und dann erst der 8051 den nächsten wert ausgeben kann. Peter
Ausserdem wird der ATmega beim Programm in dieser Form nicht erkennen, ob es sich um eine Adresse oder Daten handelt. Gruß Rahul
Ich hab jetzt die Version von Rahul mal ausprobiert. Keiner der controller hängt sich mehr auf, jedoch übernimmt der mega anscheinend irgendwelche Daten, nur nicht die Richtigen. Um dem mega etwas Zeit zum einlesen zu geben, hab ich Warteschleifen beim 8051 eingefügt, hat aber auch nichts geändert. Danke für alle Beiträge :-)) --------------------- P0_1=1; P5=0xff; b1=0xDD; b2=0x24; b3=0x00; P5_0=0; //Adresse for(x=0;x<1000;x++); P0_1=0; //fallende Flanke => Int. for(x=0;x<1000;x++); P5=b1; //byte ausgeben for(x=0;x<1000;x++); P0_1=1; //wieder auf High for(x=0;x<1000;x++); P5=0xff; P5_1=0; for(x=0;x<1000;x++); P0_1=0; for(x=0;x<1000;x++); P5=b2; for(x=0;x<1000;x++); P0_1=1; for(x=0;x<1000;x++); P5=0xff; P5_2=0; for(x=0;x<1000;x++); P0_1=0; for(x=0;x<1000;x++); P5=b3; for(x=0;x<1000;x++); P0_1=1; for(x=0;x<1000;x++); P5=0xff; --------------------- int0_isr: sbic PINA,0 rjmp r24_load sbic PINA,1 rjmp r25_load sbic PINA,2 rjmp r26_load rjmp int0_isr reti r24_load: sbis PIND,2 ;Warten bis wieder auf High rjmp r24_load in r24,PINA ;einlesen out PORTC,r0 reti r25_load: sbis PIND,2 rjmp r25_load in r25,PINA reti r26_load: sbis PIND,2 rjmp r26_load in r26,PINA reti
Was hast du denn bloß gegen ein Handshake ? Und wenn Du soviel Warteschleifen einbaust, warum nimmst Du nicht gleich SPI, wäre dann sogar schneller. Peter
Und Quellcode immer als Anhang, sonst muß man sich ja totscrollen. Peter
Hallo Bernhard! So wie ich dein Programm verstehe, gibts du am Port 5 Adressen und Daten aus. Ich bin jetzt nicht mehr wirklich fit in Bezug auf 8051, aber wieso gibst du die Adresse invertiert aus? Liefert der 8051 bei Ausgabe von 0xFF am Ausgang 0V? Ich würde halt P5=0 für Adresse 0, P5=1 für Adresse 1 und P5=2 für Adresse 2 ausgeben. Mein 8051-Wissen ist etwas eingestaubt... Würde mich freuen, wenn es nur an so einer simpler Sache liegen würde... Gruß Rahul
>Würde mich freuen, wenn es nur an so einer simpler Sache liegen >würde... Du darfst dich freuen. Einfach P5=1 / P5=2 / P5=4 und es funktionierte. Danke!!! Achja, die Warteschleifen sind egal, der Controller hätte sowieso nichts zu tun.
Naja, auf diese Art und Weise kannst Du zwar maximal 8 Byte übertragen, aber wenigstens funktioniert es erst mal. Herzlichen Glückwunsch! Damit das System flexibler würde, könnte man jetzt doch den Vorschlag von thkais anwenden (und verändern): Mit dem einen Kanal P0_0 anzeigen, dass Daten geschickt werden (Enable), und mit P0_1 die Daten rübertakten. Solange P0_0 gesetzt ist, werden bei jeder fallenden Flanke die anliegenden Daten in ein Feld übernommen. So stelle ich mir das vor. Gute Nacht! Gruß Rahul
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.