Hallo, ich komme einfach nicht mehr weiter. Ich benutze einen PIC 16F877A und betreibe einen TMC222 über I2C damit. Senden an I2C ist kein Problem. Das auslesen von Adressen geht aber nicht, da erhalte ich immer 255. Prinzipiell kann das auslesen aber nicht falsch sein, da sich der TMC222 sonnst auch nicht ansprechen lassen würde. (Man MUSS erst Daten lesen) Ein weiteres Problem ist, das ich wenn ich I2C OFF schalte das System hängt, wenn ich auf eine Reaktion warte.... ; I2C-BUS WIEDER FREIGEBEN I2C_OFF BANKSEL SSPCON2 BSF SSPCON2, PEN ; BUS FREIGABE ANWEISEN BANKSEL 0 Return <---Ohne steht das System, es gehört da aber nicht hin !!! I2C_WARTE BTFSS PIR1, SSPIF ; FERTIG? GOTO I2C_WARTE ; NEIN, NOCH NICHT BCF PIR1, SSPIF ; JA, ALLES FERTIG, NUN NOCH SSPIF ZURÜCKSETZEN RETURN ; WEITERE UNTERPROGRAMME I2C_ON BCF PORTA , 0 BCF PIR1, SSPIF ; SSPIF BIT LÖSCHEN BSF STATUS, RP0 BSF SSPCON2, SEN ; BUS ÜBERNAHME ANWEISEN BCF STATUS, RP0 GOTO I2C_WARTE ; EIN BYTE AUS W SENDEN I2C_TX MOVWF SSPBUF ; -> ZUM I2C-SLAVE ÜBERTRAGEN GOTO I2C_WARTE ;EIN BYTE VOM SLAVE EMPFANGEN (NACH SSPBUF) I2C_RX BSF STATUS, RP0 BSF SSPCON2, RCEN ; DATEN EMPFANG EINSCHALTEN BCF STATUS, RP0 I2C_R7 BTFSS PIR1, SSPIF ; FERTIG? GOTO I2C_R7 ; NEIN, NOCH NICHT BCF PIR1, SSPIF ; JA, ALLES FERTIG, SSPIF ZURÜCKSETZEN MOVF SSPBUF,0 ;DATEN NACH W <-----hier habe ich immer 255 ;CALL SENDEN Return ACK BANKSEL SSPCON2 ; ACK SENDEN BSF SSPCON2, ACKEN BANKSEL 0 RETURN Das meiste ist von SPRUT! Mit den PullUPs habe ich auch schon experimentiert, Nichts Ich vermute das es ein Problem mit I2C OFF ist, da ich ja erst die Adresse an den TMC senden muss, dann I2C ausschalten und wieder einschalten zum lesen. Das Prinzip I2C ist auch klar, einen EEPROM kann ich lesen und beschreiben. Die Taktrate ist auch sehr niedrig eingestellt (mehreres probiert) Vielen Dank für jeden Tipp.
Den Bus nach dem Senden der Adresse wieder freizugeben ist meiner Meinung nach falsch. Du willst lesen, also holst du dir als erstes den Bus (I2C_ON), dann sendest du die Adresse mit Bit0=1 (lesen). Danach empfängst du einfach die beiden Bytes (I2C_RX). Erst wenn alle Daten empfangen wurden, gibst du den Bus mit I2C_OFF wieder frei. Auch wenn du lesen willst liefert der Master den Takt. Die Daten werden also nicht vom Slave gesendet, sondern vom Master abgeholt. Wenn du vor dem Senden den Bus wieder frei gibst, könnte es sein, dass den TMC den Lesevorgang abbricht, weil dein Master dann auch kein ACK mehr sendet. Sven
Ich kann nicht mehr weiter!!! kann jemandem mir sagen wie man der Compiler scb9328 installieren kann und zwar unter Linux?Ich habe das Programm mir per mail zugeschickt,aber kann nicht aufrufen und damit das einfache Programm "Hallo world" schreiben. Ich brauche eure hilfe Bitte!!!!!!
Hallo Sven, das verstehe ich jetzt nicht. Wenn ich an den Slave etwas senden möchte, gebe ich die Adresse vom Slave an und sende dann gleich die Daten. Beim lesen geht das doch nicht. Hier muss ich doch erst die Adresse vom Slave senden und die Adresse was ich möchte. Dann muss ich aber I2C OFF und wieder ON schalten um dem Slave zu sagen das ich wieder lesen will. (Bit 0 von 0 auf 1). Jedenfalls habe ich das so verstanden. Bei einem EEPROM funktioniert das so. Laut Datenblatt des TMC ist das auch so, nur das er nach dem letzten gelesenem Byte ein NoACK möchte. Den Bus gebe ich erst frei, wenn die Daten auch angekommen sind, bzw das NoACK gesendet ist.( etwa wie in I2C_R7 ) Nur scheint unter gewissen Umständen der Bus nicht auf H zu gehen und das System hängt dann. Aber mal agesehen von dem letzen empfangenen Byte, ist das erste auch schon 255, obwohl es einen anderen Wert haben sollte. RS232 ist ok! Gruß Mario
Ich kenne zwar deinen Chip nicht, aber bei einem LM75 Temperatursensor habe ich das Lesen des Statusbyte ähnlich programmiert. Allerdings habe ich nach dem senden der Adresse und dem senden des gewünschten Registers den Bus nicht frei gegeben. Das Lesen der Antwortdaten wird dann mit einem Restartkommando eingeleitet. Dadurch kannst du auf Lesen umschalten ohne den Bus freizugeben. Eventuell reagiert dein IC ja ähnlich. Ich hänge mal meine I2C Routinen mit an.
1 | ;***I2C UNTERPROGRAMME************************************************************ |
2 | ; |
3 | ; I2C-Bus im Master-Mode übernehmen |
4 | ; Warten bis MSSP-Modul frei ist |
5 | i2c_idle |
6 | Bank1 |
7 | btfsc SSPSTAT, R_W ;läuft eine Übertragung? |
8 | goto $-1 ;ja, warten... |
9 | i2cidle_loop2 |
10 | movfw SSPCON2 ;nein, läuft ein anderes Ereignis? |
11 | andlw 0x1F ;test auf ACKEN, RCEN, PEN, RSEN, SEN |
12 | btfss STATUS,Z |
13 | goto i2cidle_loop2 ;ja, warten... |
14 | Bank0 |
15 | return ;MSSP Modul ist nicht beschäftigt |
16 | |
17 | i2c_start |
18 | call i2c_idle ;Bus frei? |
19 | Bank1 |
20 | bsf SSPCON2, SEN ;Bus Übernahme anweisen und Startbit senden |
21 | btfsc SSPCON2, SEN ;Auf das Ende der Startkondition warten |
22 | goto $-1 |
23 | Bank0 |
24 | return |
25 | |
26 | ;Restart aktivieren |
27 | i2c_rstart |
28 | call i2c_idle ;Bus frei? |
29 | Bank1 |
30 | bsf SSPCON2, RSEN ;Restart Sequence einleiten |
31 | btfsc SSPCON2, RSEN |
32 | goto $-1 |
33 | Bank0 |
34 | return |
35 | |
36 | ;ein Byte aus W senden |
37 | ;Rückgabewert in W: 0=ACK empfangen, 1=ACK nicht empfangen |
38 | i2c_tx |
39 | movwf i2c_Puffer |
40 | call i2c_idle ;Bus frei? |
41 | bcf PIR1, SSPIF ;Lösche Interrupt Flag |
42 | movfw i2c_Puffer |
43 | movwf SSPBUF ;Byte wird gesendet |
44 | btfss PIR1, SSPIF ;Senden fertig? |
45 | goto $-1 |
46 | |
47 | Bank1 |
48 | btfss SSPCON2, ACKSTAT ;Test ob ACK vom Slave empfangen wurde |
49 | goto i2c_tx_ack |
50 | Bank0 |
51 | retlw d'1' ;ACK wurde nicht empfangen |
52 | i2c_tx_ack |
53 | Bank0 |
54 | retlw d'0' ;ACK wurde empfangen |
55 | |
56 | ;ein Byte vom Slave empfangen ohne ACK |
57 | ;Rückgabewert in W |
58 | i2c_rx |
59 | call i2c_idle |
60 | bcf PIR1,SSPIF ;Interrupt Flag löschen |
61 | Bank1 |
62 | bsf SSPCON2, RCEN ;Empfang einschalten |
63 | Bank0 |
64 | btfss PIR1,SSPIF ;Byte empfangen? |
65 | goto $-1 ;noch nicht |
66 | |
67 | Bank1 |
68 | bsf SSPCON2, ACKDT ;kein ACK senden (ACK=High) |
69 | bsf SSPCON2, ACKEN ;sende negatives ACK |
70 | btfsc SSPCON2, ACKEN ;fertig? |
71 | goto $-1 |
72 | Bank0 |
73 | movfw SSPBUF ;Empfangenen Wert nach W |
74 | return |
75 | |
76 | ;ein Byte vom Slave empfangen mit ACK |
77 | ;Rückgabewert in W |
78 | i2c_rx_ack |
79 | call i2c_idle |
80 | bcf PIR1,SSPIF ;Interrupt Flag löschen |
81 | Bank1 |
82 | bsf SSPCON2, RCEN ;Empfang einschalten |
83 | Bank0 |
84 | btfss PIR1,SSPIF ;Byte empfangen? |
85 | goto $-1 ;noch nicht |
86 | |
87 | Bank1 |
88 | bcf SSPCON2, ACKDT ;ACK senden |
89 | bsf SSPCON2, ACKEN |
90 | btfsc SSPCON2, ACKEN ;fertig? |
91 | goto $-1 |
92 | Bank0 |
93 | movfw SSPBUF ;Empfangenen Wert nach W |
94 | return |
95 | |
96 | ; I2C-Bus wieder freigeben |
97 | i2c_stop |
98 | call i2c_idle |
99 | Bank1 |
100 | bsf SSPCON2, PEN ;Stop Bit senden und Bus frei geben |
101 | btfsc SSPCON2, PEN ;fertig? |
102 | goto $-1 |
103 | Bank0 |
104 | return |
105 | |
106 | ;***ENDE UNTERPROGRAMME********************************************************** |
Hallo Sven, Du bist mein Retter ;o) Ich habe jetzt deinen Code übernommen und in der Programiersprache entsprechend angepasst. Ich benutze zwar den RESTART nicht, aber es funktionierte auf anhieb. Nun wüste ich gerne warum das so ist, da ich nicht nur den Code kopieren sondern auch verstehen will. Mir fällt allerdings schon auf, das Du andere Bits abfragst ob I2C beschäftigt ist oder nicht. Mein Code entspricht in etwa dem von der Microchip-Seite. Wie schon geschrieben funktionierte das auch mit einem EEPROM. Bin mal gespannt ob es später mit dem EEPROM auch noch geht, da der auch an diesen I2C-Bus kommt. Also nochmals BESTEN DANK!!! Gruß Mario
Ehrlich gesagt, hatte ich die Routinen auch nur irgendwo im iNet gefunden, nachdem die sprut Routinen bei meinem LM75 nicht klappten (der Fehler lag allerdings woanders, glaube ich). Ich hatte vor ein paar Wochen den Fehler hier beschrieben allerdings finde ich den Beitrag nicht mehr. Wie sucht man hier eigentlich nach seinen eigenen Beiträgen? Ich habe mich aber ein wenig mit den Routinen beschäftigt und mit dem Datenblatt verglichen. Mir erschienen diese Routinen irgendwie richtiger als die von sprut, da hier immer genau die Bits abgefragt werden, welche für den jeweiligen Vorgang relevant sind. Auch die Abfrage auf Idle ist so im Datenblatt beschrieben. Bei mir laufen die Routinen mit dem LM75 und einem I/O Driver am Bus bisher problemlos. Ein EEPROM soll auch noch dran, das hab ich aber noch nicht probiert. Freut mich das es bei dir geht. Sven
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.