- 3D-Druck Einstieg und Tipps         
Seite 5 von 7 ErsteErste ... 34567 LetzteLetzte
Ergebnis 41 bis 50 von 66

Thema: Dicker Fehler in der RP6I2CmasterTWI.h der RP6Lib + Bugfix

  1. #41
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    21.04.2009
    Beiträge
    523
    Anzeige

    Praxistest und DIY Projekte
    Schön, dass ihr heir so schöne Fortschritte macht!
    So wie ich das jetzt verstanden habe, warte ich mit dem Testen noch bis du deine neue Version draußen hast? Scheinst ja bei dir noch einige Änderungen zu haben.

    Aber auch von mir schonmal ein Kompliment Ohne guten Debugger würde ich mich an sowas nicht rantrauen

  2. #42
    Erfahrener Benutzer Roboter-Spezialist Avatar von RolfD
    Registriert seit
    07.02.2011
    Beiträge
    414
    @Fabian
    ja warte besser bis morgen Nachmittag. Aber so viel wird sich dann erst mal nicht mehr ändern.

    Zum Thema debuggen... da sag'ste was... ich hab noch gelernt Fehler zu suchen indem man mit nem Schraubendreher auf nen Bauteil kloppt... Aber nen 2.ter USB Adapter wär schon klasse damit ich nicht mehr ständig umstecken muss. Sonst arbeite ich mit dem gcc... bis ich mich in eine IDE eingefunden hab... puh... aber da freue ich mich schon auf die M128 Unit.
    LG Rolf

  3. #43
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    21.04.2009
    Beiträge
    523
    Ja, da klappt das tatsächlich ganz gut. Zumindest wenn du die UART Schnittstelle nicht debuggen willst... das ist nämlich nicht so ganz einfach

  4. #44
    Erfahrener Benutzer Roboter-Spezialist Avatar von RolfD
    Registriert seit
    07.02.2011
    Beiträge
    414
    *breitgrins....

  5. #45
    Erfahrener Benutzer Roboter-Spezialist Avatar von RolfD
    Registriert seit
    07.02.2011
    Beiträge
    414
    So.. der Fehler mit hängen bleiben lang tatsächlich an E_INT1.
    Kurze Beschreibung dazu: Ich habe eine pcf8583 Uhr am I2C hängen dessen INT Leitung am E_INT1 der Base liegt. Dies ist ansich ein harmloser ADC-Port. Ich möchte deren Alarmfunktion später mal nutzen.
    Die Uhr gibt wenn das Register 0 mit 0 beschrieben ist, pro Sek ein Impuls aus. Ich hatte dem Baustein das die Tage abgewöhnt aber irgend ein rumflitzendes Byte auf dem I2C bus hat es zurück gesetzt. Die Base juckt das nicht weiter, für sie ist das nur ein normaler Port an dem jemand klopft. Die Leitung ist aber auch über den XBUS an den INT1 der M32 geführt was ein echter Interrupt ist - und ich nicht bedacht hatte. Dem zu Folge löste die M32 pro Sek ein irq aus wo der Master drauf läuft. Die INT Leitung hat eine höhere Priorität als TWI - daher wurde die TWI immer wieder unterbrochen was zu Timingproblemen und letztlich zum Abbruch des Datenflusses führte.

    Für euch interssant ist eigentlich die Info, das wenn man den E_INT1 z.B. als Ausgang nutzt - warum auch immer - ihr damit die M32 quasi ständig in eine ISR schickt. Ich finde das sogar sehr gut durchdacht vom Entwickler... nur darf man das halt nicht vergessen wenns um die Leitung geht. Die E_INT1 ist als Steuerleitung Tabu wenn man eine M32 oder vermutlich auch M128 nutzt. Eigentlich logisch aber man denkt eben nicht immer dran.

    Nun zum TWI. Ich hab euch meine aktuellen Files zum Projekt bzw. Dirks modifiziertes Testprogramm zusammen mit der TWI in ein Zip gepackt. Damit können jetzt auch mehr Leute mal versuchen wie es klappt. Achtet bitte auf Pfade und Abhänigkeiten im makefile und kommentiert die defines zum lcd und das lcd.h aus wenn ihr kein I2C lcd mit pcf Baustein habt. Benötigt zum testen mit Dirks Programm werden die Base, eine M32 sowie ein M32Display.

    I2CTWI_isBusy() (bit_is_set(TWI_statusReg,STR_isr))
    #define I2CTWI_needAction() (bit_is_set(TWI_statusReg,STR_needAction) && bit_is_clear(TWI_statusReg,STR_isr))
    #define I2CTWI_waitAction() (bitset(TWI_statusReg,STR_needAction))
    #define I2CTWI_doneAction() (bitclr(TWI_statusReg,STR_needAction))
    #define I2CTWI_NACKonAction() bitset(TWI_statusReg,STR_NACKonAction)
    #define I2CTWI_ACKonAction() bitclr(TWI_statusReg,STR_NACKonAction);bitclr(TWI_ statusReg,STR_needAction)

    Das hier sind Befehle, die für die Ablaufsteuerung relevant sind. Sie fragen oder setzen alle Flags ab die die ISR steuert.

    I2CTWI_isBusy() ist gesetzt wenn die ISR ein Datagram überträgt. Egal ob als Master oder Slave, vom Start bis zum Stop.
    Achtung, die Befehle
    I2CTWI_requestRegisterFromDevice
    und
    I2CTWI_readRegisters
    bestehen je aus 2 Einzelbefehlen in denen die ISR zwischendurch "Frei" meldet was zur Ausführung nachfolgend wartender TWI Befehle führen kann. Dafür muss ich noch eine Lösung stricken. Alle anderen TWI-Befehle sind Einzelbefehle, da sollte das Problem nicht auftauchen.

    I2CTWI_needAction() prüft ob die Slave Register beschrieben wurden was mit einem gesetzten Bit angezeigt wird. Wenn ja, sollte der Slave als Zeichen das er die Daten verarbeitet hat immer I2CTWI_doneAction() ausführen was das Bit zurück setzt. Der Master hat dazwischen keine Schreibmöglichkeit und wird geblockt (was der natürlich auch über I2CTWI_isBusy() merken kann). Will man den Master ohne vorherige Schreiboperation zwingen zu warten (was eigentlich nur für mich zum testen relevant ist) nutzt man I2CTWI_waitAction() was das schreiben der Register simuliert. Soll der Master immer schreiben können (Verhalten wie bisher, führt zum überschreiben von Registern) nutzt man I2CTWI_ACKonAction(), mit I2CTWI_NACKonAction() blockt der Slave wieder das überschreiben.
    Das Blocken geschiet durch senden von NACK wäred der Master ein Datenbyte auf ein bereits beschriebenes Registerset schreiben will, was wiederum mit einen neuen Anlauf der Übertragung mündet bis er erfolgreich war. Quasi eine Endlosschleife. Das Beschreiben des Adressbytes müsste aber noch gehen so lange der Master keine Daten mitsendet. Zur Not könnte der Master also auch noch darüber dem Slave was mitteilen. Morsen sozusagen... Vielleicht eine Möglichkeit für weitere Master zu signalisieren, wenn sie Daten haben und der Slave gefälligst die Register frei zu geben hat.... aber das ist dann schon leicht abgedreht und scheitert noch an fehlender Busarbitierung . Derzeit ist der Bus belegt wenn der Slave nackt und ein 2.ter Master müsste den ersten von der Leitung schubsen um reden zu dürfen, wobei sich der erste vermutlich dann gehörig verschluckt. Bildlich gesprochen...

    I2CTWI_waitAction() werde ich vermutlich wieder entfernen da es für euch kaum Sinn macht. I2CTWI_(N)ACKonAction() wird bleiben.

    Die Variablen

    I2CTWI_genCallCMD
    I2CTWI_dataWasRead
    I2CTWI_dataReadFromReg
    I2CTWI_readBusy
    I2CTWI_writeBusy

    sind obsolet, I2CTWI_genCallCMD tut es eh nicht weil gencalls derzeit garnicht gehen, die anderen 4 Vars machen quasi das gleiche wie I2CTWI_isBusy() und I2CTWI_needAction() mit der Ausnahme das sie nun auch zu gebrauchen sind und den Ablauf am TWI beeinflussen.

    Konfiguriert wir die Anwendung mit twi_target.h, sie ist selbsterklärend, jedes Projekt hat sein eigenes File. Es gelten die üblichen Vorgaben für TWI.

    Flags wie DEBUG, XDEBUG können kommentiert wreden (//) dabei bedeutet:
    TWISLAVE=Slave & Master
    TWIMASTER=Master
    TWILOW=(Slave & Master | Master) & TWILOW
    Ich glaube, es geht nichts kaputt wenn man TWISLAVE und TWIMASTER setzt aber es ist doppelt gemoppelt. TWILOW sind Bascom ähnliche Funktionen die - wenn genutzt - das Handling auf dem TWI erlauben ohne das die ISR dazwischen funkt. Dazu müssen die Funktionen ein paar Dinge berücksichtigen, insbesondere das Ausschalten des TWI Interrupts und das Einschalten wenn man fertig ist. Gedacht ist das zum debuggen eigener Devices/Hardware, man kann sich natürlich auch kompexe Funktionen daraus basteln die mit der ISR koexistieren. Damit ist jedoch kaum Slave Betrieb möglich oder man müsste wie blöde TWI-Register pollen, daher nur einfache Masterfunktion.

    Im Base Programm sitzt noch ein vagabundierender extINT Befehl, der kann/muss raus... und einige Kommentare wo ich am basteln war.. kann auch raus.

    Ich bin mir noch nicht sicher wie die TWI auf Busarbitation reagiert, grundsätzlich können und dürfen am Bus mehrere Master laufen. Evtl. stürtzt aber die aktuelle TWI ab bzw. baut Mist. Aber es geht nichts kaputt.
    Wer möchte, kann also Dirks Programm so umbauen das auf beiden Prozessoren Master und Slave laufen und die sich gegenseitig Daten zuwerfen und abfragen.... schlimmstenfalls bleiben die Programme nur nach einigen Bytes hängen. Nur hätte ich den Source dann bitte gern am Montag da ich dann auch die Arbitation in Angriff nehmen kann. Sonst muss ich mir das erst selbst schreiben.

    Das sind mal grob alle wichtigen Infos zusammen gepackt.
    Sonst schaut auch mal in die .h und .c files ... die beissen nicht...
    Der compilerlauf mit GCC klappt hier, wenn was nicht klappt, bitte zuerst in der twi_target prüfen. Dirks Programm testet alle 4 Teilfunktionen der TWI, also MR/MT/SR/ST und sollte damit auch in eigenen Projeken funktionieren. Alles weitere findet sich auch im Thread hier.
    Ich hab am WE keine Zeit und werde mich erst Montag wieder intensiv darum kümmern, ihr habt also die Möglichkeit damit zu spielen bevor ich wieder alles auf den Kopf stell. Es werden noch weitere Veränderungen und Betatests kommen, insbesondere Fabian sollte mit der Lösung und Remotrol aber schon arbeiten können. Sonst fragt einfach hier, ich werde sicher mal reinschauen am WE.

    LG Rolf
    Angehängte Dateien Angehängte Dateien

  6. #46
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    21.04.2009
    Beiträge
    523
    Cool, dann habe ich ja was zu tun. =)
    Das ist mit dem E_INT1 ist ja genau für den Interrupt gedacht, der RP6 muss ja quasi Interupts an die M32 schicken können.
    Aber wenn man das vergisst, kann das natürlich ganz schön verwirrend sein. =)

    Ich hatte da aber auch schon Probleme mit, zwar nicht bei der M32 sondern bei der M128... Da ist ein Interuptpin hinüber... Zum Glück kann man das da ja auf einen anderen umstecken.

  7. #47
    Erfahrener Benutzer Robotik Einstein Avatar von Dirk
    Registriert seit
    30.04.2004
    Ort
    NRW
    Beiträge
    3.803
    @Rolf:

    ... ich komme eigentlich von 68000er CPUs (asm) die heute kaum einer noch kennt...
    Doch, ich schon. Meine ersten ASM-Versuche waren mit dem 6502, da habe ich auch noch an "Treibern" (z.B. Druckerspooler, ich glaube für den 6510) gearbeitet, dann aber in ASM nur noch bis zum 8086 mithalten können.

    ... mich wundert schon etwas, das sich noch niemand rangetraut hat um dem RP6 bzw. die Libs zu verbessern, schließlich sagt SlyD selbst das nicht alles optimal ist.
    Naja, da gab es z.B. von mir schon über die Jahre Libs und Verbesserungen vorhandener Libs.
    Kurze unvollständige Liste: M32-Lib-Version 1.3beta, M32-EEPROM-Zugriff, M32/Base/M128-Clock-Lib und DCF-Lib, M32/Base-Servo-Lib, M32/M128-TRX433-Lib, M32/Base-Uart_2-Lib

    ... aber da freue ich mich schon auf die M128 Unit.
    Ja, wenn du die in die Finger kriegst, geht es hier wohl erst richtig ab. \/

    Die E_INT1 ist als Steuerleitung Tabu wenn man eine M32 oder vermutlich auch M128 nutzt.
    Ja, das ist so und gilt auch für die M128: Dort ist E_INT1 der Base (und INT0 (PD2) der M32) mit INT5 (PE5) verbunden, also auch mit einem interruptfähigen Eingang.

    Gruß Dirk

  8. #48
    Erfahrener Benutzer Robotik Einstein Avatar von Dirk
    Registriert seit
    30.04.2004
    Ort
    NRW
    Beiträge
    3.803
    @Rolf:
    So, ich habe jetzt die neue Version getestet und die Bytes herumsausen lassen.
    Ergebnis: Es gibt keine Probleme.

    Ich habe dann im Base-Programm noch die task_RP6System() aufgenommen, um eine realistische Umgebung zu haben.
    Ergebnis: Keine Probleme.

    Dann habe ich noch im M32-Programm die task_RP6M32System() aufgenommen, die es aber nur in meiner Version 1.3beta der RP6ControlLib gibt.
    Ergebnis: Auch keine Probleme.

    Fragen eines kleinen Testers:
    1. Die Funktionen I2CTWI_needAction() und I2CTWI_doneAction() umschließen ja den ganzen Komplex der I2C-Kommunikation. Im Grunde will ja der Nutzer des I2C-Busses ja nur Bytes senden oder empfangen, genau wie bei der Uart-Lib. Ihm ist es wohl eher egal, ob TWI eine "action" braucht oder ob die zuende ist. Daher meine (vorsichtige) Frage, ob man das auf der Befehlsebene wirklich braucht? Müßte nicht der Treiber selbst entscheiden, ob er eine action (bzw. Busaktivitäten) durchführen muss oder wann er damit fertig ist? Wie gesagt: Vielleicht verstehe ich auch nicht die Intention. Eigentlich brauche ich auf der Befehlsebene nur Schreib-/Lesebefehle und evtl. ein oder 2 Flags, ob der Bus wieder frei ist. Sonst will ich als Nutzer eigentlich nicht unbedingt wissen, was sich im Busprotokoll tut.

    2.
    Wer möchte, kann also Dirks Programm so umbauen das auf beiden Prozessoren Master und Slave laufen und die sich gegenseitig Daten zuwerfen und abfragen...
    Oh,- da bräuchte ich von dir Anregungen, wie das zu initialisieren wäre ... Dann mache ich da gern was draus ...

    Gruß Dirk

  9. #49
    Erfahrener Benutzer Roboter-Spezialist Avatar von RolfD
    Registriert seit
    07.02.2011
    Beiträge
    414
    6502 ? nettes Teil... auch einer der mit ner Brotkiste angefangen hat? Mein erster war ein ZX81 Hach ja die alten Zeiten ...

    Aber zur TWI. Ich war unzufrieden, das der IRQ mir die Daten auf dem I2C zerbröselte - auf Grund der Sache mit der Uhr - und hab eine Lösung gefunden. Einfach aber effektiv. Die ISR wird zukünftig (steuerbar über twi_target.h) im Eingang ein cli(); ausführen und im Ausgang ein sei(); , das verhindert nach nun 24h lang laufenden Dauertests absolut zuverlässig die Unterbrechung und Abbruch trotz sekündlichen Uhrenticks. Wird in der nächsten Release drin sein.

    Dann freut es mich erst mal sehr, das Du reproduzierbar stabile Funktion berichten kannst. Zu Deiner Frage, nun wenn Du dich nicht um das "Protokoll" kümmern willst, kannst Du mit I2CTWI_ACKonAction() kurz nach der Initialisierung das so einstellen, das der Master nicht behindert wird.

    I2CTWI_init()
    I2CTWI_ACKonAction();
    ...
    Programmlauf
    ...

    Wenn aber dein Programm auf der Base sowas wie ein Handshake braucht, (Fabians Remotrol braucht das z.B. zwingend) oder verhindert werden muss das der Master Daten überschreibt (weil Befehlssequenzen übertragen werden, kommst Du um eine Verarbeitung der Daten/Befehle und letztlich auch einem Handshake.. nicht rum. Da bietet sich die default Einstellung bzw. I2CTWI_NACKonAction(); und dann endsprechendes bearbeiten mit I2CTWI_needAction() und I2CTWI_doneAction() an.

    Es kommt also ein wenig auf deine Anforderungen an das Programm an, es gibt keine ja/nein Antwort dazu. Man kann überlegen, die Defaulteinstellung auf I2CTWI_ACKonAction zu setzen was dem alten Verhalten entspricht, ohne ein Handshake ist allerdings eine gesicherte Datenübertragung nicht möglich. Vergleich es mit den RTS/CTS Leitungen und dem Software Protokoll XON/XOFF, es würde auch keiner eine stabile UART ohne die Leitungen betreiben können und wenn doch, so muss zumindest das Softwareprotokoll XON/XOFF vorhanden sein. I2C hat kein RTS/CTS bzw. XON/XOFF, also braucht es da was anderes, die ACK/NACK Signale sind quasi eine Mischumg aus beidem und ohne die klappt so gut wie nix wirklich sicher auf dem Bus - der alte Treiber welcher alles ACKte, ist bester Beleg dazu. Natürlich muss man sich als Programm... nein.. man muss nicht, man kann... sich drum kümmern... und sicher stellen das die Daten korrekt verarbeitet werden. Aber es gibt auch Anwendungen wo das nicht so wichtig ist. Das entscheidest letztlich Du als Programmierer bzw. die Aufgabenstellung.

    Man kann grundsätzlich das Ganze in ein Task packen und mit einem
    If I2CTWI_needAction() task_do_i2c();
    erledigen, wo dann halt in task_do_i2c alles verarbeitet wird. Incl. einem I2CTWI_doneAction(); am Taskende. Die Libs und Examples liefern dazu reichlich Beispiele. Das hatte ich in deinem Programm auch schon im Kommentar irgendwo angemerkt. Ich werde dazu am Montag ein kleines Beispiel bauen, denke aber das ihr da jetzt schon mit klar kommt.

    Eigentlich reicht für das genannte Programm also:

    while (true)
    {
    die_üblichen_System_Tasks();
    If I2CTWI_needAction() task_do_i2c(); //Receiver bedienen (Daten kopieren wie im Slavebeispiel)
    Master_task();//Selber aktiv werden, so wie in dem Masterbeispiel
    }

    Das ist echt nicht kompliziert, Du hast bereits alles geschrieben da was wir da brauchen...
    LG Rolf

    PS: Ich hab noch was für Dich Dirk, extra eben noch geknipst Du wirst sie erkennen, für die anderen: Eine 6502 CPU von MOS aus dem Jahr 1983 aus meiner Grabbelkiste. Hier noch bissel Text dazu. http://de.wikipedia.org/wiki/MOS_Technology_6502
    Die 6509 war ein direkter Verwandter und wurde im CBM610 z.B. verbaut. http://www.zock.com/8-Bit/D_CBM610.HTML Ich hatte auch mal einen. Und nicht zu vergessen die allseits berühmte 6510 CPU aus dem C64 und die 6508 aus dem NES Eine Z80 CPU aus der Generation hab ich auch noch, und hüte sie wie Dagobert Duck sein ersten Taler

    EDIT: Ich hab über die Handshake Geschichte nachgedacht und stelle fest, das es da noch einiges zu verbessern gibt. Z.B. kann der Masterzugriff bisher nicht beeinflussen was bei einem NACK passiert, bzw. ist einem hängendem Slave quasi ausgeliefert. Das ist unschön und wird demnächst behoben. Beide Seiten werden also steuern können, ob und wie sie mit NACKS umgehen. Dazu wird die ISR ein weiters Flag bekommen, das mit 1 oder 2 Funktionen/Macros steuerbar ist.
    Miniaturansichten angehängter Grafiken Miniaturansichten angehängter Grafiken 6502.jpg  

  10. #50
    Erfahrener Benutzer Robotik Einstein Avatar von Dirk
    Registriert seit
    30.04.2004
    Ort
    NRW
    Beiträge
    3.803
    @Rolf:

    Hier 'mal meine Testprogramme, die (erwartungsgemäß) nicht funktionieren. Das "erwartungsgemäß" hat damit zu tun, dass ich nicht wirklich verstanden hatte (SORRY!), wie auf beiden Systemen Master- und Slavefunktionen zu initialisieren sind.
    Ich bin sicher, du kannst da rasch weiter helfen.

    Meine Idee war, in einer Richtung einen Aufwärtszähler laufen zu lassen, in die andere Richtung einen Abwärtszähler. Abwechselnd würden dann beide Systeme den Master machen. Auf dem LCD der M32 wäre die eine Zeile für die (eigene) Masterfunktion, die andere für die Gegenrichtung, für die Base würden die Textausgaben über UART mit "M-" für die eine und "S-" für die andere Richtung ausgegeben. Vielleicht habe ich mir das Ganze auch zu naiv so vorgestellt.
    In der twi_target.h habe ich beide Systeme als TWISLAVE definiert (richtig?).
    Als TWI-Adresse für die M32 nehme ich 12 dezimal (NICHT hex!). An der Base habe ich kein I2C-LCD.

    Testprogramm 3 (RP6Control M32):
    Code:
    /* 
     * ****************************************************************************
     * RP6 ROBOT SYSTEM - RP6 CONTROL M32 EXAMPLES
     * ****************************************************************************
     * Example: I2C Master/Slave - I2C Send/Receive Test 3
     * Author(s): Dirk
     * ****************************************************************************
     * Description:
     *
     * This Example sends/receives data via I2C.
     *
     *
     * ############################################################################
     * The Robot does NOT move in this example! You can simply put it on a table
     * next to your PC and you should connect it to the PC via the USB Interface!
     * ############################################################################
     * ****************************************************************************
     */
    
    /*****************************************************************************/
    // Includes:
    
    #include "twi_target.h"         // Include the new I2C-Bus Library
    
    #include "RP6ControlLib.h"	 	// The RP6 Control Library.
    								// Always needs 
    
    to be included!
    
    /*****************************************************************************/
    // Defines:
    
    // The Slave Address of the RP6Base on the I2C Bus can be specified here:
    #define RP6BASE_I2C_SLAVE_ADR 10
    
    #define CMD_SHOW_DATA 99		// Command to display the data
    
    #define TEXT_OUTPUT				// Show text
    
    /*****************************************************************************/
    // I2C Event handlers:
    
    /**
     * This function gets called automatically if there was an I2C Error like
     * the slave sent a "not acknowledge" (NACK, error codes e.g. 0x20 or 0x30).
     * The most common mistakes are: 
     *   - using the wrong address for the slave
     *   - slave not active or not connected to the I2C-Bus
     *   - too fast requests for a slower slave
     * Be sure to check this if you get I2C errors!
     */
    void I2C_transmissionError(uint8_t errorState)
    {
    	writeString_P("\nI2C ERROR --> TWI STATE IS: 0x");
    	writeInteger(errorState, HEX);
    	writeChar('\n');
    }
    
    /*****************************************************************************/
    // Variables:
    
    uint8_t buffer[4];
    uint16_t error_cnt = 0;
    uint8_t controlbyte; 
    uint8_t highbyte = 0; 
    uint8_t lowbyte = 0; 
    
    /*****************************************************************************/
    // Functions:
    
    void task_Slave(void)
    {
    static uint16_t cnt;
    	if I2CTWI_needAction() {
    		controlbyte = I2CTWI_writeRegisters[0];			// Read 
    
    control byte 
    		I2CTWI_writeRegisters[0] = 0;					
    
    //  and reset it (!!!) 
    		lowbyte = I2CTWI_writeRegisters[1];				
    
    // Read lowbyte 
    		highbyte = I2CTWI_writeRegisters[2];			// Read 
    
    highbyte 
    
    		I2CTWI_readableRegisters[0] = controlbyte;		// copy 
    
    controlbyte 
    		I2CTWI_readableRegisters[1] = lowbyte;			// copy 
    
    lowbyte 
    		I2CTWI_readableRegisters[2] = highbyte;			// copy 
    
    highbyte       
           
    		cnt = ((highbyte << 8) | lowbyte);				
    
    // Restore 16-bit value 
    #ifdef TEXT_OUTPUT 
    		setCursorPosLCD(1, 0); 
    		writeStringLCD_P("S-Rcved ");					
    
    // What was received? 
    		writeIntegerLCD(cnt, DEC); 
    		writeStringLCD_P("    ");
    #endif 
    		if (!cnt) error_cnt = 0;						
    
    // Reset error counter 
    		else error_cnt++;							
    
    	// Error counter + 1 
    		if (cnt != error_cnt) { 
    			setCursorPosLCD(1, 0); 
    			writeStringLCD_P("S-ERROR!");
    			error_cnt = cnt; 
    		}
    		else { 
    			setCursorPosLCD(1, 0); 
    			writeStringLCD_P("        ");
    		}
    		controlbyte = 0; 
    		I2CTWI_doneAction();
    	}
    }
    
    void task_Master(void)
    {
    static uint16_t cnt = 32768;
    	if (!I2CTWI_isBusy()) {
    		cnt--;									
    
    	// TEST: COUNTER!!! 
    		if (cnt > 32767) cnt = 32767; 
    		buffer[0] = 0; 
    		buffer[1] = CMD_SHOW_DATA; 
    		buffer[2] = cnt; 
    		buffer[3] = (cnt >> 8); 
    		I2CTWI_transmitBytes(RP6BASE_I2C_SLAVE_ADR, buffer, 4); 
    
    		buffer[0] = 0;								
    
    // reset buffer 
    		buffer[1] = 0; 
    		buffer[2] = 0; 
    		buffer[3] = 0; 
    
    		I2CTWI_readRegisters(RP6BASE_I2C_SLAVE_ADR, 0, buffer, 4); 
    
    		if (cnt == ((buffer[2] << 8) | buffer[1])) {
    #ifdef TEXT_OUTPUT 
    			setCursorPosLCD(0, 0); 
    			writeStringLCD_P("M-Moved ");			// What 
    
    was sent? 
    			writeIntegerLCD(cnt, DEC); 
    			writeStringLCD_P("    ");
    #endif 
    		}
    		else { 
    			setCursorPosLCD(0, 0); 
    			writeStringLCD_P("M-ERROR!     ");		// What 
    
    was sent? 
    		}
    //		if (cnt==3) while(true);					
    
    // countertrap 
    	}
    }
    
    /*****************************************************************************/
    // Main - The program starts here:
    
    int main(void) 
    {
    	initRP6Control(); 
    
    	initLCD(); 
    
    //	I2CTWI_init(100);		// Initialize the TWI Module for Master 
    
    operation 
    							// with 100kHz SCL 
    
    Frequency 
    
    	// Register the event handlers: 
    	I2CTWI_setTransmissionErrorHandler(I2C_transmissionError); 
    
    	setLEDs(0b1111); 
    	mSleep(500);      
    	setLEDs(0b0000); 
    
    	while(true) 
    	{
    		task_Slave();
    		task_Master();
    		if (RP6LIB_VERSION == 15) {					
    
    // Only for
    			task_RP6M32System();					
    
    //  Lib V1.3beta!!!
    		}
    		else mSleep(5);								
    
    // Other Libs: 5ms
    	} 
    	return 0; 
    }
    
    /******************************************************************************
     * Additional info
     * ****************************************************************************
     * Changelog:
     * - v. 1.0 (initial release) 27.02.2011 by Dirk
     *
     * ****************************************************************************
     */
    
    /*****************************************************************************/

    Testprogramm 3 (RP6Base):
    Code:
    /* 
     * ****************************************************************************
     * RP6 ROBOT SYSTEM - ROBOT BASE TESTS
     * ****************************************************************************
     * Example: I2C MaSTER/Slave - I2C Send/Receive Test 3
     * Author(s): Dirk
     * ****************************************************************************
     * Description:
     *
     * This Example sends/receives data via I2C.
     *
     *
     * ############################################################################
     * The Robot does NOT move in this example! You can simply put it on a table
     * next to your PC and you should connect it to the PC via the USB Interface!
     * ############################################################################
     * ****************************************************************************
     */
    
    /*****************************************************************************/
    // Includes:
    
    #include "twi_target.h"			// Include the new I2C-Bus Library
    
    //#include "PCF8583.h"
    
    //#include "RP6RobotBaseLib.h"	// The RP6 Robot Base Library. 
    								// Always needs 
    
    to be included!
    /*****************************************************************************/
    // Defines:
    
    // The Slave Address of the Control M32 on the I2C Bus can be specified here:
    #define RP6CONTROL_I2C_SLAVE_ADR 12
    
    #define CMD_SHOW_DATA 99		// Command to display the data
    
    #define TEXT_OUTPUT				// Show text
    
    /*****************************************************************************/
    // Variables:
    
    uint8_t buffer[4];
    uint16_t error_cnt = 0;
    uint8_t controlbyte; 
    uint8_t highbyte = 0; 
    uint8_t lowbyte = 0; 
    
    /*****************************************************************************/
    // Functions:
    
    void task_Slave(void)
    {
    static uint16_t cnt;
    	if I2CTWI_needAction() {
    		controlbyte = I2CTWI_writeRegisters[0];			// Read 
    
    control byte 
    		I2CTWI_writeRegisters[0] = 0;					
    
    //  and reset it (!!!) 
    		lowbyte = I2CTWI_writeRegisters[1];				
    
    // Read lowbyte 
    		highbyte = I2CTWI_writeRegisters[2];			// Read 
    
    highbyte 
    
    		I2CTWI_readableRegisters[0] = controlbyte;		// copy 
    
    controlbyte 
    		I2CTWI_readableRegisters[1] = lowbyte;			// copy 
    
    lowbyte 
    		I2CTWI_readableRegisters[2] = highbyte;			// copy 
    
    highbyte       
           
    		cnt = ((highbyte << 8) | lowbyte);				
    
    // Restore 16-bit value 
    #ifdef TEXT_OUTPUT 
    		writeString_P("S-Received: ");					
    
    //  and show it 
    		writeInteger(cnt, DEC); 
    		writeChar('\n');
    #endif 
    		if (!cnt) error_cnt = 0;						
    
    // Reset error counter 
    		else error_cnt--;							
    
    	// Error counter - 1 
    		if (cnt != error_cnt) { 
    			writeString_P("S-ERROR!\n"); 
    			error_cnt = cnt; 
    		}
    		controlbyte = 0; 
    		I2CTWI_doneAction();
    	}
    }
    
    void task_Master(void)
    {
    static uint16_t cnt = 0;
    	if (!I2CTWI_isBusy()) {
    		cnt++;									
    
    		// TEST: COUNTER!!! 
    		if (cnt > 32767) cnt = 0; 
    		buffer[0] = 0; 
    		buffer[1] = CMD_SHOW_DATA; 
    		buffer[2] = cnt; 
    		buffer[3] = (cnt >> 8); 
    		I2CTWI_transmitBytes(RP6CONTROL_I2C_SLAVE_ADR, buffer, 4); 
    
    		buffer[0] = 0;								
    
    	// reset buffer 
    		buffer[1] = 0; 
    		buffer[2] = 0; 
    		buffer[3] = 0; 
    
    		I2CTWI_readRegisters(RP6CONTROL_I2C_SLAVE_ADR, 0, buffer, 4); 
    
    		if (cnt == ((buffer[2] << 8) | buffer[1])) {
    #ifdef TEXT_OUTPUT 
    			writeString_P("M-Moved: ");
    			writeInteger(cnt, DEC); 
    			writeChar('\n');
    #endif 
    		}
    		else { 
    			writeString_P("M-ERROR!\n"); 
    		}
    //		if (cnt==3) while(true);						
    
    // countertrap 
    	}
    }
    
    /*****************************************************************************/
    // Main function - The program starts here:
    
    int main(void) 
    { 
    	extIntOFF();
    
    	initRobotBase(); 
    //	initLCD();
    
    	setLEDs(0b111111);
    	mSleep(500);	   
    	setLEDs(0b000000);
    
    //	I2CTWI_init(RP6BASE_I2C_SLAVE_ADR); 
    
    //	clearI2CLCD();
    //	setCursorPosLCD(0,0);
    //	writeStringLCD("I2C Init "); writeIntegerLCD(1,DEC);
    //---------------------------------------
    
    /*
    	writeString("START ----------------------------------\n");
    
    
    
    	uint8_t results[15];
    
    	I2CTWI_transmitByte(PCF8583_ADDR_WRITE, 0);
    	
    	I2CTWI_readBytes(PCF8583_ADDR_READ, results, 7); 
    
    */
    
    //---------------------------------------
    //while (true);
    
    
    
    	while (true) 
    	{    
    		task_Slave();
    		task_Master();
    		task_RP6System();
    	} 
    	return 0; 
    }
    
    /******************************************************************************
     * Additional info
     * ****************************************************************************
     * Changelog:
     * - v. 1.0 (initial release) 27.02.2011 by Dirk
     *
     * ****************************************************************************
     */
    
    /*****************************************************************************/
    Vielleicht kannst du ja daraus was machen. Ich brauche auf jeden Fall noch ein paar Anregungen.

    Gruß Dirk

    P.S.: Oh, ja, ich habe auch noch eine 6502 und eine 6510 liegen. Ich gehe mal in den Keller,- suchen ...

Seite 5 von 7 ErsteErste ... 34567 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

12V Akku bauen