Guten Tag zusammen! Ich versuche mit dem R8C23 über I²C eine Porterweiteurng anzusteuern. Leider funktioniert dies nicht ganz so wie ich das gern hätte. Um dem Fehler auf den Grund zu gehen habe ich das ausgehende Signal vom Controller mit dem scope gemessen: Es werden nicht die richtigen Bytes versandt (zumindest glaub ich das :-)). Ebenso erhelte ich kein Acknowledge vom Slave. Wenn ich das alles richtig sehe, dann stimmt irgendetwas mit der Kommunikation zwischen den beiden Teilen nicht. Hat irgendjemand schon mal ähnliches versucht und hat evtl. sogar einen C-code?!? Bin über jede Hilfe dankbar! Beste ...
Angenummen du sendest wirklich falsche Byte ... Warum sollte der Chip ein Ackn senden, wenn er sich nicht angesprochen fühlt? Warst du schon mal auf der Renesas Seite? Dort gibt es Code-Beispiele ohne Ende.
Danke für deine Antwort! Ja eben, das ist mir auch klar. Wenn der Master nix anständiges sendet kann der Slave auch nix antworten. Eigenartig ist es, dass der master, wenn ich ihm z.b. 0b11101000 über das register icdrt senden lasse auf dem SDA port 101010101 sendet. Der SCL schmeißt bloß undefinierbares raus. Suche der Weil mein Passwort für renesas ... :-)
VERMUTLICH hast du eine Falsche Adresse. Aus z.b. 01100110 wird 00110011, die 0 am Rechten Ende (R/W) Bit muss für manche Libraries abgeschnitten werden, für andere nicht.
Danke ... Die Änderung der Adresse macht leider keinen Unterschied ... Ich glaube ich habe insgesamt etwas falsch eingestellt. :-(
Fabi D. schrieb: > bracuhe ich eigentlich für IIC unbedingt einen Interrupt? Nein, kannst ja mit einem Timer oder sonstwie (un)regelmäßig den Slave ansteuern und Daten austauschen
Fabi D. schrieb: > Suche der Weil mein Passwort für renesas ... :-) Dafür brauchst du kein Benutzernamen oder Passwort.
Fabi D. schrieb: > bracuhe ich eigentlich für IIC unbedingt einen Interrupt? Da musst du mal ins Datenblatt schaun, da gibt es bestimmt ein Bit welches gesetzt wird, wenn ein Byte gesendet wurde. Dises kannst du dann auch per polling abfragen. Dieses Bit nutzt üblicherweise auch die Interruptlogik.
Bist du an den richtigen Pins? 101010101 sieht wie ein Taktsignal aus.
Moin Moin! Habe die pins noch einmal kontrolliert; sind die richtigen ... So, SCL läuft perfekt und auch SDA. Spricht die Clock rattert und die Daten bzw. die Slave Adresse wird übertragen. ... Nur leider kein Ackowledge in Sichtweite. Was sagt ihr zum code? (Ich hoffe er ist noch net zu lang fürs Forum) void master_transmit (void) { unsigned char temp; stop_icsr = 0; //Stop bit zum Reset ice_iccr1 = 1; //I²C Bus enable iicsel= 1; wait_icmr = 1; mls_icmr = 1; // Daten werden als MSB-first versandt while (bbsy_iccr2 != 0);// I2C besetzt? warten bis frei trs_iccr1 = 1; // 11 --> Master transmit mode mst_iccr1 = 1; //start condition: temp = iccr2; temp &= 0b10111111; //scp = 0 b6 temp |= 0b10000000; //bbsy = 1 b7 iccr2 = temp; icdrt = port_erweiterung_master_transmit; // read/write Data: slaveadress + R/W while (tend_icsr != 1); // warten bis byte übermittelt wurde if (ackbr_icier == 0)// Acknowledge/Bestätigung vom slave { [...] }else{ tend_icsr = 0; stop_icsr = 0; temp = iccr2; temp &= 0b10111111; //scp = 0 b6 temp |= 0b01111111; //bbsy = 0 b7 iccr2 = temp; while (stop_icsr != 1); // warten bis stopcondition gesetzt ist trs_iccr1 = 0; mst_iccr1 = 0; tdre_icsr = 0; }}
nein. um einen PCA9539. Nun kann ich ohne Probleme vom Master zum Slave daten senden und an der Porterweiterung z.b. LEDs steuern. Aber schon steht das nächste Problem ins Haus: Wie kann ich einen taser am Slave betreiben? Dazu muss ich doch den auslesen, oder? bzw. Master_receive mode, oder? Sobald ich das LSB von 0 auf 1 setzte, um ein Auslesen zu initiieren (alle anderen bits bleiben --> Slaveadresse), passiert nichts mehr. Besten Gruß!
Fabi schrieb: > Sobald ich das LSB von 0 auf 1 setzte, um ein Auslesen zu initiieren > (alle anderen bits bleiben --> Slaveadresse), passiert nichts mehr. Nur um sicherzugehen... Du hast beachtet, dass du zunächst einen Schreib -Zugriff machst um mittels Command Byte das Register zu definieren, von dem du danach den Lese -Zugriff wünscht. Siehe Datenblatt Seite 7 Absatz 2 "Reading the port registers" und Figure 8 "READ from register" > Dazu muss ich doch den auslesen, oder? Ja. > bzw. Master_receive mode, oder? Dein R8C bleibt im Master mode und führt (nach dem transmit) ein receive durch.
Danke für die Antwort! Ich glaube ich habe all diese Dinge berücksichtigt. Aber irgendetwas wohl nicht, sonst würde es funktionieren. Auszug aus code: icdrt = adresse_iic_chip_write; icdrt = command_input_port; while (tdre_icsr != 1); while (ackbr_icier != 0); icdrt = adresse_iic_chip_receive; while (tend_icsr != 1); tend_icsr = 0; trs_iccr1 = 0; mst_iccr1 = 1; tdre_icsr = 0; ackbt_icier = 0; icdrt = adresse_iic_chip_receive; --> hier hängt er sich auf while (tend_icsr != 1); dummy_data_0 = icdrr; while (rdrf_icsr != 1); ackbr_icier = 1; dummy_data_1 = icdrr; Achso, ich möchte einen Taster betreiben und LEDs. Die LEDs kann ich ansteuern. Allerdings nur über das Configuration Register. Munter bleiben!
Ich bin's noch einmal ... welche Register muss ich steuern, um LEDs bzw./und Taster an der Porterweiterung anzusteuern/zu lesen. Ich kann, wie ich oben beschrieben habe, die LEDs nur per Configurationsregister an und ausschalten. beim Output bekomme ich kein Signal, d.h. die Leds rühren sich nicht; obwohl das Signal auf dem Scope gar nicht schlecht aussieht. Probleme über Probleme ... Fragen über Fragen ... :-)
Hallo Fabi, also mit deinem Code stimmt noch vieles nicht. Ohne mir das korrekte Handling der I2C bits im R8C anzuschauen, fällt mir schonmal das Folgende auf. (siehe Kommentare)
1 | icdrt = adresse_iic_chip_write; // schreib-operation ausloesen |
2 | icdrt = command_input_port; // setzte input port register (per command byte) |
3 | while (tdre_icsr != 1); |
4 | while (ackbr_icier != 0); |
5 | icdrt = adresse_iic_chip_receive; // lese-operation ausloesen |
6 | while (tend_icsr != 1); |
7 | tend_icsr = 0; |
8 | trs_iccr1 = 0; // irgendwo hier sollten mal die Daten GELESEN werden. |
9 | mst_iccr1 = 1; |
10 | tdre_icsr = 0; |
11 | ackbt_icier = 0; |
12 | icdrt = adresse_iic_chip_receive; --> hier haengt er sich auf |
13 | // lese-operation ausloesen (Aber von welchem command byte nur?)
|
14 | while (tend_icsr != 1); |
15 | dummy_data_0 = icdrr; // lese ??? register |
16 | while (rdrf_icsr != 1); |
17 | ackbr_icier = 1; |
18 | dummy_data_1 = icdrr; // lese ??? register nochmal (Warum? Jedes Register hat nur 8 byte) |
Du solltest den ganzen Code systematischer und in Funktionen gegliedert schreiben. Dann fällt dich auch viel schneller auf, was du eigentlich machst. > Achso, ich möchte einen Taster betreiben und LEDs. > Ich kann die LEDs nur per Configurationsregister an und ausschalten. > beim Output bekomme ich kein Signal, d.h. die Leds rühren sich nicht Leider fängt dein Problem schon etwas Grundlegender an; Du hast den PCA9539 noch nicht richtig verstanden. Also mal von Anfang an. Du hast 4 LEDs an Output 0.0 bis Output 0.3 und einen Schalter an Input 1.0. Jetzt müssen zunächst die Teiber konfiguriert werden (Eingang oder Ausgang). Dazu wird ein Wert für beide 'Configuration Port Register' geschrieben.
1 | PCA9539_Schreibe(Configuration_port_0, 0xF0); // Port 0.0 bis 0.3 ist Ausgang für die LEDs (andere 0.x sind Eingang) |
2 | PCA9539_Schreibe(Configuration_port_1, 0xFF); // Port 1.0 ist Eingang für den Schalter (andere 1.x sind Eingang) |
Jetzt möchtest du zwei LEDs einschalten. Dazu wird ein Wert für das 'Output port 0 Register' geschrieben. Achtung: Wenn du nur den Wert in dieses Register schreibst, aber den Port nicht als Ausgang konfiguriert hast (s.o.) dann ist der Port ein Eingang und kann auch keinen Strom durch die LED treiben. -> Das war einer deiner Fehler.
1 | PCA9539_Schreibe(Output_port_0, 0x03); // LEDs 0.0 und 0.1 an, LEDs 0.2 und 0.3 aus (0x03 = 0000_0011) |
Und dann noch einen Schalter abfragen. Dazu wird ein Wert vom 'Input port 1 Register' gelesen.
1 | uint8_t wert; |
2 | wert = PCA9539_Lese(Input_port_1); // lese Wert |
3 | wert = (wert & 0x01); // ausmaskieren des bits für Ausgang 1.0 an dem der Schalter ist |
4 | if (wert == 0) { |
5 | // Schalter nicht gedrueckt
|
6 | } else { |
7 | // Schalter gedrueckt
|
8 | }
|
Bleibt die Frage, was machen die Funktionen PCA9539_Lese und PCA9539_Schreibe? Sie sorgen dafür das die richtigen I2C Kommandos benutzt werden um vom PCA9539 zu scheiben und zu lesen. Und das steht auf Seite 7-9 im Datenblatt. PCA9539_Schreibe besteht aus zwei I2C Operationen. 1. I2C schreiboperation, wert 'registernummer' 2. I2C schreiboperation, wert 'daten' welche in 'registernummer' beschrieben werden sollen.
1 | void PCA9539_Schreibe(uint8_t register, uint8_t daten) { |
2 | I2C_Write(PCA9539_SLAVE_ADDR, register); |
3 | I2C_Write(PCA9539_SLAVE_ADDR, daten); |
4 | }
|
PCA9539_Lese besteht auch aus zwei I2C Operationen. 1. I2C scheiboperation, wert 'registernummer' 2. I2C lese operation, welche den Wert aus 'registernummer' ausliest.
1 | uint8_t PCA9539_Lese(uint8_t register) { |
2 | uint8_t daten; |
3 | I2C_Write(PCA9539_SLAVE_ADDR, register); |
4 | daten = I2C_Read(PCA9539_SLAVE_ADDR); |
5 | return daten; |
6 | }
|
Die Funktionen I2C_Write und I2C_Read kannst du jetzt selber implementieren. Hier machst du die eigentlichen Registerzugriffe auf die I2C hardware des R8C. So wie du es schon mit deinem Code versuchst hast. Du solltest versuchen diese Systematik ein wenig zu üben. Alles direkt mit Registerzugriffen runterzuschreiben führt zu schnell zu Fehlern die man nur schwer findet. Und der Code wird unübersichtlich und nicht erweiterbar. Stell dir nur vor was passiert, wenn du noch eine weitere LED anschießen möchtest. ;-)
Danke, Tobyas H., für die sehr detaillierte Hilfestellung!
... im Grunde habe ich alles schon so gemacht, wie du (Tobyas) es auch hier schreibst. der oben geschriebene code ist wirklich nur minimal aus verschiedenen Funktionen herauskopiert. Naja nichts desto trotz funzt das lesen nicht. der Taster gibt ein Signal, das ich auf dem scope lesen kann. Vor dem Lesebefehl schreibe ich in das zu lesende Register ... usw. doch wenn der Controller das Lese-Signal sendet. Bekomme ich kein Ackknowledge vom slave. Beim Schreibebefhl dagegen immer. Ich fürchte eine Ferndiagnose ist nicht wirklich möglich ...
Gerne geschehen Fabian. Du solltest auf jeden Fall dran bleiben. Irgendwo gibt es bestimmt noch einen kleinen 'unbedeutenden' Fehler, der dir das Leben schwer macht. Wenn du Ihn gefunden und gelöst hast lass es uns wissen...
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.