Archiv verlassen und diese Seite im Standarddesign anzeigen : TWi Problem =>Multimaster RN-Wissen
mat-sche
14.06.2008, 09:40
Moin Moin!
folgendes habe ich vor über TWI zu realisieren:
1. Master schickt einem Slave z.Bsp. ein Byte (ne 25)
Master geht wieder offline und hört als Slave den Bus ab
Slave empfängt und führt eine Aktion aus
2. ist ein Befehl für den Slave (25) eingetroffen soll er zum Master werden
und dem vorherigen Master, der jetzt Slave ist, ein Byte zurück schicken
Nun habe ich mir mal den Multimaster TWI Code aus RN Wissen angeschaut
und herumprobiert. Ich bin soweit gekommen, dass ich mit beiden Controllern jeweils als Master senden und als Slave empfangen kann.
Jetzt ist nur noch das Problem das ich keine automatische Kommunikation hin bekomme. Also ich drücke zu 1. einen Taster => Slave (Controller2) zeigt mir an das er was empfangen hat.
Aber ich kann jetzt mit dem Befehl leider nicht automatisch antworten.
In dem Progbeispiel unten sendet der zweite Controller aller 1seck den Wert den er eigentlich erst nach dem Befehl vom anderen Controller bekommen sollte.
Dann versteh ich auch folgen Code noch nicht so richtig:
For Temp = 1 To 1
Twi_mst_buff(temp) = 25
Next
in Verbindung mit:
Twi_mt_data = Varptr(twi_mst_buff(1))
$regfile = "m8def.dat"
$crystal = 14318181
$include "MyTWI.bas"
$baud = 9600
$hwstack = 80
$swstack = 80
$framesize = 80
Const Tmr_c_prescale = 64
Const Tmr_c_preload = 131
Const Tmr_c_divis = 1000 '250 alt
Declare Sub Twi_show_state(byref State As Byte)
'-----------------2x20 LCD Display an Port c =>Conector -------------------------------------------------------------------------------------------------
Config Lcdpin = Pin , Db4 = Portc.0 , Db5 = Portc.1 , Db6 = Portc.2 , Db7 = Portc.3 , E = Portb.2 , Rs = Portb.0 ' Pinbelegung "LCD-Port)"
' SV2 1 2 3 4 6 8 ' Pinbelegung SV9 Board
Config Lcd = 20 * 4
'Config Porta = Output
Config Lcdbus = 4
Initlcd
Cursor Off
Locate 1 , 1
Lcd "1 mS Ticker"
Cls
'------------------------------------------------------------------------------- Configuration DS1820
Config 1wire = Portb.1
Dim Id1(8) As Byte
Dim Id2(8) As Byte
Dim Ar1(2) As Byte
Dim Ar2(2) As Byte
Dim Temp1 As Byte
Dim Temp2 As Byte
Id1(1) = 1wsearchfirst()
Id2(1) = 1wsearchnext()
'-------------------------------------------------
' lokale I2C Adresse (als Slave)
'-------------------------------------------------
Const Mn1_adr = &H6E
'-------------------------------------------------
' fremde I2C Adresse (als Master)
'-------------------------------------------------
Const Mn2_adr = &H6A
Dim Slv_byte As Byte 'sende Byte (irgendwas)
Dim Twi_mst_buff(24) As Byte 'Buffer für Masterfunktionen
Dim Twi_slv_buff(24) As Byte 'Buffer für Slavefunktionen
'-------------------------------------------------
Config Timer0 = Timer , Prescale = Tmr_c_prescale 'Timer 1mS
On Timer0 Interrupt_ticker ' Timer for Timer Queue
Dim Timeout As Byte
Dim Timediv As Word
'-------------------------------------------------
Dim Temp As Byte , Temp3 As Byte , Temp4 As Byte
Twi_slv_addr = Mn1_adr 'lokale I2C-Adresse
Twi_sr_data = Varptr(twi_slv_buff(1)) 'datenbuffer empfang
Twi_st_data = Varptr(twi_slv_buff(1)) 'datenbuffer senden
Twar = Twi_slv_addr + 1 'I2C Adress Mega32 + GCA
Config Twi = 400000 'I2C Speed
On Twi Twi_mst_slv_isr , Nosave 'ISR f. TWI
Gosub Twi_sense 'Aktivieren Slave-Funktion
Enable Timer0 'Timer
Enable Interrupts 'Generell
'---------------------------------------------
'
'---------------------------------------------
Do
'************************************************* ***************************** Sensor 1
1wreset 'reset
1wwrite &H55 'Match Rom command
1wwrite Id1(1) , 8 'Id von Sensor 1
1wwrite &H44 'Convert T
'300 'warten bis convert T fertig ist
1wreset 'reset
1wwrite &H55 'match rom command
1wwrite Id1(1) , 8 'id von sensor 1
1wwrite &HBE
Locate 1 , 14
Ar1(1) = 1wread(2)
Temp1 = Makeint(ar1(1) , Ar1(2))
Temp1 = Temp1 / 2 'Ar(1)
Lcd "Out1:" ; Temp1
'************************************************* ****************************** Sensor2
1wreset 'reset
1wwrite &H55 'Match Rom command
1wwrite Id2(1) , 8 'Id von Sensor 2
1wwrite &H44 'Convert T
' 300 'warten bis convert T fertig ist
1wreset 'reset
1wwrite &H55 'match rom command
1wwrite Id2(1) , 8 'id von sensor 2
1wwrite &HBE 'scratchpad lesen
Locate 2 , 14
Ar2(1) = 1wread(2)
Temp2 = Makeint(ar2(1) , Ar2(2))
Temp2 = Temp2 / 2
Lcd "Out2:" ; Temp2
'************************************************* ****************************** I2C Betrieb
'Locate 1 , 1
' Lcd "1 mS Ticker " ; Timediv
'Locate 4 , 10
'Lcd Twi_sr_data
If Twi_slv_flag = &H60 Then Temp4 = 25
If Twi_slv_flag <> 0 Then
'-----------------------------------------------------------------
' Ergebnis als SLave auswerten
' Vorsicht, der Bus ist solange blockiert
'-----------------------------------------------------------------
Select Case Twi_slv_flag
Case &H60 :
Locate 1 , 1
Lcd ; "SLVrecv" ; 'es ist was empfangen worden Spc(30)
Locate 1 , 9
Lcd Hex(twi_slv_addr) ; " ";
For Temp = 1 To Twi_sr_cntr
Locate 1 , 11
Lcd Hex(twi_slv_buff(temp)); 'print der Daten Twi_slv_buff(temp)
Next
Case &HA8 :
Locate 2 , 1
Lcd ; "SLVtran" ; 'es ist was abgeholt worden Spc(30)
Locate 2 , 9
Lcd Hex(twi_slv_addr) ; " ";
For Temp = 1 To Twi_st_cntr
Locate 2 , 11
Lcd Twi_slv_buff(temp); 'print der Daten Hex(twi_slv_buff(temp));
Next
Case &H70 :
Locate 3 , 1
Lcd ; "SLAVE GCA :" ; 'ein General Call ist gekommen Spc(30)
Locate 3 , 10
Lcd Hex(twi_slv_addr) ; " ";
For Temp3 = 1 To Twi_sr_cntr
Print Hex(twi_slv_buff(temp)); 'print der Daten
Next
'Case Else:
'Print Chr(7) ; 'Irgendein Fehler
' Call Twi_show_state(twi_slv_flag) 'Print status-text
End Select
'Locate 4 , 1
'Lcd Twi_slv_buff(temp) ; Twi_sr_cntr ; Temp3
Print
Twi_slv_flag = 0 'löschen marker
Twi_slv_stat = 0 'löschen marker
Gosub Twi_sense 'alles wieder enablen
'und Bus freigeben
End If
For Temp4 = 1 To Twi_sr_cntr
Locate 4 , 15
Lcd Twi_slv_buff(temp4)
'-----------------------------------------------------------------
' Jede Sekunde was senden & empfangen
'-----------------------------------------------------------------
If Timeout = 1 Then
Gosub Master_transmit 'Senden in einer SUB
If Twi_mst_flag = 0 Then 'Hats geklappt ?
Timeout = 0 'ja
' else (sonst probieren wir's gleich nochmal)
End If
End If
'-----------------------------------------------------------------
Locate 4 , 1
Lcd Temp3 'Twi_slv_buff(temp) ; Twi_sr_cntr ;
Next
Loop
End
'----------------------------------------
' 1 mS Ticker
'----------------------------------------
Interrupt_ticker: ' Timer for Timer Queue
Timer0 = Tmr_c_preload
Incr Timediv
If Timediv = Tmr_c_divis Then
Timeout = 1 'eine Sekunde ist rum
Timediv = 0
End If
Return
'
'----------------------------------------
$include "Twi_show_state.bas"
'----------------------------------------
Run_wait_master:
Gosub Mst_start 'aufruf
Select Case Twi_mst_flag 'ergebnis ?
Case Twi_m_sent:
Locate 3 , 1 'gesendet
Lcd "<<MASTsent:" ; Hex(twi_mst_addr) ; " ";
Print
For Temp = 1 To Twi_mt_cntr
Locate 3 , 14
Lcd Twi_mst_buff(temp);
Next
Print
Twi_mst_flag = 0
Case Twi_m_recv:
Locate 4 , 1 'geholt
Lcd ">>MASTread:" ; Hex(twi_mst_addr) ; " ";
Print
For Temp = 1 To Twi_mr_cntr
Locate 4 , 14
Lcd Twi_mst_buff(temp); 'Hex(twi_mst_buff(temp))
Next
Print
Twi_mst_flag = 0
'Case Else: 'irgendein Problem
'Print Chr(7) ; Hex(twi_mst_addr) ; " ";
'Call Twi_show_state(twi_mst_flag)
End Select
Return
'----------------------------------------
' Beispiel 8 byte senden,
' dann mit Rep.Start von gleicher adresse 3 Byte empfangen
'----------------------------------------
Master_transmit:
' sende buffer (mit testdaten) füllen
For Temp = 1 To 1
Twi_mst_buff(temp) = Temp1 'Slv_byte
Next
Twi_mst_addr = Mn2_adr 'I2C adresse
Twi_mt_cntr = 1 '8 ' erstmal 8 Byte senden
Twi_mt_data = Varptr(twi_mst_buff(1)) ' adresse Daten
Twi_mr_cntr = 0
'Twi_mr_cntr = 1 ' dann 3 Byte empfangen
'Twi_mr_data = Varptr(twi_mst_buff(1)) ' empfangsbuffer
Gosub Run_wait_master ' auf gehts
Return
Ich weiss nicht wie ich die empfangenen Daten aus "Twi_sr_cntr" weiter verwenden kann, in eine Variable bekomme.
HILFE :)
Danke MAT
Also, das Konzept ist so:
Alle Teilnehmer definieren ihre Adresse und sind immer empfangsbereit.
Twi_slv_addr = Mn1_adr ' Der eine Controller
' Twi_slv_addr = Mn2_adr ' der andere Controlle
Twi_sr_data = Varptr(twi_slv_buff(1)) 'datenbuffer empfang
Twi_st_data = Varptr(twi_slv_buff(1)) 'datenbuffer senden
' wenn du eh' keine Broadcasts (GCA) verwendest, würde ich den "+1"-er auslassen, du brauchst dann auch nicht auf GCA abzufragen
Twar = Twi_slv_addr 'I2C Adress
'--------------etc, etc-
Do
'--------------etc, etc-
' das mit den Sensoren lass' ich da aus
'---------------------------------
If Twi_slv_flag = &H60 Then
'-----------------------------------------------------------------
' Ergebnis als Slave auswerten
'-----------------------------------------------------------------
Locate 1 , 1
Lcd ; "SLVrecv" ; 'es ist was empfangen worden
Locate 1 , 9
Lcd Hex(twi_slv_addr) ; " ";
For Temp = 1 To Twi_sr_cntr
Locate 1 , 11
Lcd Hex(twi_slv_buff(temp)); 'print der Daten
Next
Twi_slv_flag = 0 'löschen marker
Twi_slv_stat = 0 'löschen marker
Gosub Twi_sense 'alles wieder enablen
'und Bus freigeben
if twi_slv_buff(1) = 25 then ' ?
' ---------------------- Kommando ausführen ----------------------------
gosub antwort_daten_senden
End If
End If
'-----------------------------------------------------------------
' Unabhängig davon Jede Sekunde was senden & empfangen
'-----------------------------------------------------------------
If Timeout = 1 Then
Timeout = 0 'ja
Gosub frage_daten_senden 'Senden in einer SUB
End If
Loop
End
'----------------------------------------
' 1 mS Ticker
'----------------------------------------
Interrupt_ticker: ' Timer for Timer Queue
Timer0 = Tmr_c_preload
Incr Timediv
If Timediv = Tmr_c_divis Then
Timeout = 1 'eine Sekunde ist rum
Timediv = 0
End If
Return
'
'----------------------------------------
$include "Twi_show_state.bas"
'----------------------------------------
antwort_daten_senden:
For Temp = 1 To 8 ' 8 Byte
twi_mst_buff(temp) = temp ' 1,2,3,4,5,6,7,8
next
Twi_mst_addr = Mn2_adr 'jeweils der andere
Twi_mt_cntr = 8 '8 Byte
Twi_mr_cntr = 0 ' nix holen, nur senden
Twi_mt_data = Varptr(twi_mst_buff(1)) ' adresse Daten
Gosub Run_wait_master ' auf gehts
return
frage_daten_senden:
twi_mst_buff(1) = 25 'Kommando
Twi_mst_addr = Mn2_adr 'jeweils der andere
Twi_mt_cntr = 1 '1 Byte
Twi_mr_cntr = 0 ' nix holen, nur senden
Twi_mt_data = Varptr(twi_mst_buff(1)) ' adresse Daten
Gosub Run_wait_master ' auf gehts
return
' ----------------------------- sende kontrolle ------------------------
Run_wait_master:
Gosub Mst_start 'aufruf
Select Case Twi_mst_flag 'ergebnis ?
Case Twi_m_sent:
Locate 3 , 1 'gesendet
Lcd "<<MASTsent:" ; Hex(twi_mst_addr) ; " ";
Print
For Temp = 1 To Twi_mt_cntr
Locate 3 , 14
Lcd Twi_mst_buff(temp);
Next
Print
Twi_mst_flag = 0
Twi_mst_flag = 0
'Case Else: 'irgendein Problem
'Print Chr(7) ; Hex(twi_mst_addr) ; " ";
'Call Twi_show_state(twi_mst_flag)
End Select
Return
DIe Sache mit der Sende-WIederholung im Fehlerfall kannst du dir auch sparen, da ja nach einer Sekunde sowieso wieder ein Kommando kommt.
Auch die ganzen "slave transmitter" und "master receiver" Sachen brauchst du ja eigentlich nicht.
Theoretisch (ich konnte es jetzt nicht testen) schickt jeder der beiden
jede Sekunde eine Message mit "25", worauf der dann 8 bYte mit 1,2,..8 zurückschickt.
mat-sche
14.06.2008, 17:27
Hallo PicNick,
Danke für Deine schnelle Antwort! Nach dem ich die Forumsfrage gestellt habe, bin ich dann selber noch darauf gekommen. Aber ungeklärt bleiben da noch:
1.Twi_sr_data = Varptr(twi_slv_buff(1))
2. Twi_mt_data = Varptr(twi_mst_buff(1))
was versteckt sich hinter dieser Funktion?
3. und da ist auch ein Problem:
For Temp = 1 To 8 ' 8 Byte
twi_mst_buff(temp) = temp ' 1,2,3,4,5,6,7,8
next
wenn ich das richtig verstehe ist das eine Schleife bei der ein Arry mit 8byte gefüllt wird. wie kann ich bei dieser Schleife für "temp" unterschiedliche Bytewerte zuordnen?
Also in Byte1 ist eine Temperatur von 26°C, in Byte2 37°C...
und wie lese ich dann beim Empfäger das Arry aus und trenne die Bytes wieder auf?
Ich denke, dass ich mit dieser Multimastersource gut hinkomme! Gute Arbeit
MAT
TWI_SR_DATA ist die SRAM Adresse, wo ein anderer (sende)Master seine Daten hinschreiben kann. Da man ja (oft) nicht weiss, WAS da dann kommt, ist das eben in meinem Anwendungsbeispiel nur irgend ein Byte-Array.
Ebenso ist TWI_MT_DATA die adresse des ersten (oder einzigen Bytes), das gesendet werden soll.
Bei dir ist das ja nicht so allgemein,
Denn dein Master sendet immer nur EIN Kommando Byte
und empfängt 8 temperatur-Bytes
Dein slave sendet immer 8 temperatur-Bytes
und empfängt immer das eine Kommando-Byte
Du könntest das auch für deine Zwecke spezialisieren.
Master Senden
DIM Kommando as Byte
Jede_sekunde_mal:
Kommando = 25
twi_mt_data = VARPTR(Kommando) ' daten adresse
Twi_mst_addr = Mn2_adr 'twi-slave adresse
Twi_mt_cntr = 1 '1 Byte
Twi_mr_cntr = 0 ' nix holen, nur senden
Gosub Run_wait_master ' auf gehts
---etc-etc----
Slave-Empfang
DIM Kommando as Byte
twi_sr_data = VARPTR(Kommando)
---etc-etc----
If Twi_slv_flag = &H60 Then
if Kommando = 25 then
---- komando ausführen
---etc-etc----
beim Rücksenden der Temperaturen:
SLave Temperaturen senden
DIM Temp1 as Byte
DIM Temp2 as Byte
......
DIM Temp8 as Byte
twi_mt_data = VARPTR(Temp1) ' daten adresse
Twi_mst_addr = Mn1_adr 'twi-master adresse
Twi_mt_cntr = 8 '8 Byte
Twi_mr_cntr = 0 ' nix holen, nur senden
Gosub Run_wait_master ' auf gehts
---etc-etc----
Der Master hat nun ein Gegenstück
DIM Temp1 as Byte
DIM Temp2 as Byte
......
DIM Temp8 as Byte
twi_sr_data = VARPTR(Temp1)
---etc-etc----
If Twi_slv_flag = &H60 Then
Temp1 --> bis Temp8 auswerten
---etc-etc----
Zur Verwirrung: Natürlich könnte der Master sich die 8 Temperaturen auch selber holen, dann wäre der Slave nur passiv, er müßte nur bei Empfang eine Messung auslösen. Auf diese Art geht es ja meistens bei den fertigen I2C-Sensoren. Man schickt ein Kommando und liest die Daten dann aus.
Das wäre dann aber eben nicht Multimaster, sondern der übliche Master-Slave Betrieb
DIe Parameter etc. wären dann auch anders, natürlich
mat-sche
14.06.2008, 19:27
ich weiss nicht wie Du das machst, aber was du machst ist KLASSE! Danke für Deine Zeit!
DIM Temp1 as Byte
DIM Temp2 as Byte
......
DIM Temp8 as Byte
twi_mt_data = VARPTR(Temp1) ' daten adresse
Twi_mst_addr = Mn1_adr 'twi-master adresse
Twi_mt_cntr = 8 '8 Byte
werden hier automatisch alle 8 Temperaturen übertragen oder muss ich immer wieder VARPTR(Temp1,2...8) aufrufen?
Wenn du hintereinander "DIM" machst, liegen die Variablen auch hintereinander im Speicher. Daher genügt die Adresse des ersten Byte (varptr) und die Länge ( 8 ), dass alle acht auf einmal rausmarschieren.
:-)
mat-sche
14.06.2008, 19:42
aha...
Ist das immer so bzw. ist das abhängig wie Variablen im Programmabschnitt dimensioniert werden also hintereinander?
Bis jetzt habe ich alle Variablen am Anfang dimensioniert.
Wie kann man(n) z.Bsp. unterschiedliche Variablen in ein Arry schieben oder adressieren und dann verschicken und dann auch wieder "auseinander" nehmen?
Bascom legt Variablen IMMER in der Reihenfolge an, wie die DIM's daherkommen.
https://www.roboternetz.de/wissen/index.php/Bascom_Speicherstrukturen
Streng genommen ist es nicht "korrekt", sich darauf zu verlassen. Da Bascom aber keine Möglichkeit anbietet, z.B. "TEMP1" bis "TEMP8" irgendwie zusammenzufassen, bleibt einem nichts anderes übrig.
Genaugenommen müßte man beim slave
twi_mst_buff(1) = Temp1
twi_mst_buff(2) = Temp2
----etc---
twi_mst_buff(3) = Temp8
Twi_mt_cntr = 8
Twi_mt_data = Varptr(twi_mst_buff(1))
Gosub Run_wait_master
und beim Empfang umgekehrt
temp1 = twi_mst_buff(1)
---etc-
temp8 = twi_mst_buff(8)
Aber, ich schwör's, das ist nicht notwendig.
Bei PC-Compilern wie Visal-Irgendwas oder Java geht sowas natürlich nicht.
mat-sche
14.06.2008, 20:19
und genau das ist es, wie ich es gedacht habe.
Also werde ich mir mal dies beherzigen :D
Ich hätte noch sooooo viele Fragen, fange erst an mich in die Materie einzuarbeiten. Aber es ist Wochenende! Und da wünsch ich Dir nen gutes :)
Aber eine habsch da noch :lol:
in Bascom gibt es ne lib für SED GLCD`s (128 * 64sed or 120* 64SED or SED180*32) wie und ist es möglich sie so umzuschreiben das man noch andere Pixelanzahl nehmen kann?
Kenn' ich persönlich nicht. Klingt aber auch so nach Arbeit.
Theoretisch geht natürlich alles.
mat-sche
15.06.2008, 18:43
Nun das war`d nur mal eine Frage. Muss mich irgend wann mal damit beschäftigen, habe einige GLCD`s aus unserem Industrie Schrott gefischt.
Oki, einen schönen Sonntag noch!
MAT
mat-sche
23.06.2008, 22:52
Hallo PicNick
jetzt hab ich noch eine Frage.
Das Vorhergehende war nur zum probieren. Im grunde genommen will ich folgendes machen:
1. Byte ist ein Befehl für ein anderen Slave(Master) =>nur lesen oder in eine Sub springen
2. Byte ist ein Infobyte das besagt was es für Daten sind
3. Byte soll dann die Daten beinhalten => und hier ist das Problem: die Daten sind kein Byte sondern ein Single!
Kann ich dieses genauso senden oder muss ich es erst mit overlay in einzelne Byte zerlegen?
MAT
Du mußt deine Messag z.B so aufbauen, wenn du als Daten Bytes, Words, singles oder doubles senden willst. Die genau sende-Länge mußt du allerdings selbst ausrechnen
Beispiel:
DIM Befehl AS BYTE
DIM Info AS BYTE
DIM Datenbyte AS BYTE
DIM Datenword AS BYTE AT Datenbyte OVERLAY
DIM Datenlong AS BYTE AT Datenbyte OVERLAY
DIM Datensingle AS BYTE AT Datenbyte OVERLAY
DIM Datendouble AS BYTE AT Datenbyte OVERLAY
Twi_mt_data = Varptr(Befehl) ' ist immer gleich
Befehl = nnn ' was du magst
Info = 1
'-------------------------------------------
Datenbyte = 255 ' z.b
Info = 1
Twi_mt_cntr = 3 ' Befehl + Info + 1 Byte
gosub Run_wait_master
'-------------------------------------------
Datenword = 32768 ' z.b
Info = 2
Twi_mt_cntr = 4 ' Befehl + Info + word
gosub Run_wait_master
'-------------------------------------------
Datenlong = 41000000 ' z.b
Info = 3
Twi_mt_cntr = 6 ' Befehl + Info + long
gosub Run_wait_master
'-------------------------------------------
Datensingle = 3.14 ' z.b
Info = 4
Twi_mt_cntr = 6 ' Befehl + Info + single
gosub Run_wait_master
'-------------------------------------------
Datendouble = 3.1487967499 ' z.b
Info = 5
Twi_mt_cntr = 10 ' Befehl + Info + double
gosub Run_wait_master
Dabei ist WORD und INTEGER ggf. natürlich das Gleiche
Beim Slave das Gegenstück
twi_sr_data = VARPTR(Befehl)
---etc-etc----
If Twi_slv_flag = &H60 Then
select case Info
case 1: print Datenbyte
case 2: print Datenword
case 3: print Datenlong
case 4: print Datensingle
case 5: print Datendouble
Bei Dir könnte der Empfänger den Datentype eigentlich auch aus der Länge der Message entnehmen, die gibt ja weitgehend Aufschluss, was es ist
mat-sche
06.07.2008, 15:19
Hallo Robert,
nun habe ich mir eine weiter Platine mit einer TWI Funktion gebaut und habe versucht diese beiden mit unterschiedlicher Adresse anzusprechen. Leider meldet sich nur einer auf einen Befehl.
Ich seh langsam nicht mehr durch.... ](*,)
Wie erkennt der Controller das die Information für ihn bestimmt ist? Ausgehend ddavon ist doch so, dass alle Controller am bus mithören und wenn ihre Adresse kommt auch er dann antwortet.
Nun ich sehe in dem Code aber nicht die Funktion, nur die Case &H60 Funktion. Dem nach würde ich darauf schließen das alle Controller oder der erste an dem die Info geschickt wird dem Master zurückschickt, dass sie eine Info bekommen haben, auch wenn sie nicht für sich bestimmt war? Oder schickt nur der jenige ein Ack zu dem die Adresse gehört?
Vom Code her hatte ich zwei Slave mit der gleichen Software beschrieben (siehe oben) nur mit unterschiedlichen Adressen, dabei konnte ich aber nur einen Controller ansprechen...
Kannst Du dies einwenig näher beschreiben oder was mache ich falsch?
Danke und Gruß MAT
Die Adress-Erkennung und das ACK, wenn es passt, macht schon die TWI-Hardware
nur der kriegt twi-slv-flag &H60. diese Zahl kommt auch von der Hardware und ist eindeutig, da können wir beide nix falsch machen.
Dein Effekt ist seltsam. Du mußt feststellen, ob das auch oder nur dann auftritt, wenn mehrere angeschlossen sind.
mat-sche
06.07.2008, 17:48
Dann werd ich mich noch einmal hinsetzen müssen und meinen Code überprüfen sowie die Hardware.
Ist die Variable "Twi_mst_addr" das TWI Register vom Controller? Oder durch welche Variable wird wo in Deinem Programm die TWI Adresse festgelegt?
Parallel werd ich mir noch mal das Datenblatt zum M8 zur Hand nehmen.
Werde mich jetzt in den Zug setzen....Die Arbeit ruft :-s
Schönen Sontag Dir noch!
https://www.roboternetz.de/wissen/index.php/TWI_Praxis_Multimaster#Setup_als_Slave
Das eigentliche Hardware-Adress-Register heisst "TWAR"
"Twi_mst_addr" ist die Ziel-Adresse, wenn man als Master was wegschickt.
mat-sche
07.07.2008, 18:52
Ich habe gelesen das 128 mögliche Slaves adressiert werden kann. Von wo bis wohin, oder besser wie kann ich Adressen für einen Slave vergeben?
alle geraden Zahlen von &H02 - &HFE
Meist muss man aber den anderen Geräten ausweichen, die man sonst noch dranhängen hat.
Kommt also darauf an, was du alles verwenden willst.
https://www.roboternetz.de/wissen/index.php/I2C_Chip-%C3%9Cbersicht#Adressen_g.C3.A4ngiger_I2C_Chips
mat-sche
12.07.2008, 14:37
Hallo Robert,
nun sitze ich schon wieder den halben Tag... Inzwischen kann ich beide Slaves ansprechen und sie senden auch. Besser einer schickt seine Info an den Slave, der zweite schickt auch seine Info (lt. rs232 Ausgabe sagt er mir: Master sent: 6C 1F) aber leider kommt immer nur eine 0!?
Ich habe den identischen Code für die 2 Slaves, woran kann das liegen?
Slave Nr.2 bei dem es nicht funst:
$regfile = "m8def.dat"
$crystal = 16000000
$include "MyTWI.bas" 'dafür wird noch die MyTWI.lib benötigt
$baud = 19200
$hwstack = 80
$swstack = 80
$framesize = 80
'------------------------------------------------------------------------------- Configuration DS1820
Config 1wire = Portd.4
Dim Ar1(2) As Byte
Dim Temp1 As Byte
'------------------------------------------------------------------------------- Timer0 aktivieren
'------------------------------------------------------------------------------- lokale I2C Adresse (als Slave)
Const Mn1_adr = &H6C
'------------------------------------------------------------------------------- fremde I2C Adresse (als Master)
Const Mn2_adr = &H6A
Dim Twi_mst_buff(24) As Byte 'Buffer für Masterfunktionen
Dim Twi_slv_buff(24) As Byte 'Buffer für Slavefunktionen
'------------------------------------------------------------------------------- TWI Variablen
Dim Temp As Byte , Temp3 As Byte
Dim Temp2 As Byte
Twi_slv_addr = Mn1_adr 'lokale I2C-Adresse
Twi_sr_data = Varptr(twi_slv_buff(1)) 'datenbuffer empfang
Twi_st_data = Varptr(twi_slv_buff(1)) 'datenbuffer senden
Twar = Twi_slv_addr + 1 'I2C Adress Mega32 + GCA
Config Twi = 100000 'I2C Speed
On Twi Twi_mst_slv_isr , Nosave 'ISR f. TWI
Gosub Twi_sense 'Aktivieren Slave-Funktion
Enable Timer2 'Timer
Enable Interrupts 'Generell
'************************************************* ****************************** Hauptprogramm
Do
'************************************************* ****************************** Sensor 1
1wreset 'reset
1wwrite &HCC ' read internal RAM
1wwrite &HBE ' read 9 data bytest '300 'warten bis convert T fertig ist
Ar1(1) = 1wread(2)
1wreset
Temp1 = Makeint(ar1(1) , Ar1(2))
Temp1 = Temp1 / 2 'Ar(1)
Temp2 = Temp1
'************************************************* ****************************** TWI Betrieb
'praktisches Beispiel zu Anzeige der Daten, werden im Prog nicht benötigt bis auf die Flagabfrage
'Twi_slv_flag =
' * 0 Keine Slave Aktion hat stattgefunden
' * &H60 Daten wurden empfangen. Sie stehen im Buffer mit der Länge Twi_sr_cntr
' * &HA8 Daten wurden gesendet. Sie stehen im Buffer mit der Länge Twi_st_cntr
' * &H70 Gca -daten Wurden Empfangen.
If Twi_slv_flag <> 0 Then
Select Case Twi_slv_flag
Case &H60 : Print Spc(30) ; "als SLAVE receivd:" ; 'es ist was empfangen worden
Print Hex(twi_slv_addr) ; " ";
For Temp = 1 To Twi_sr_cntr
Print Twi_slv_buff(temp)
Temp3 = Twi_slv_buff(temp) ' Hex(twi_slv_buff(temp)); 'print der Daten
Print "temp1" ; Temp1
Next
Case &HA8 : Print Spc(30) ; "als SLAVE transmit:" ; 'es ist was abgeholt worden
Print Hex(twi_slv_addr) ; " ";
For Temp = 1 To Twi_st_cntr
Print Twi_slv_buff(temp) 'Hex(twi_slv_buff(temp)); 'print der Daten
Next
Case &H70 : Print Spc(30) ; "SLAVE GCA :" ; 'ein General Call ist gekommen
Print Hex(twi_slv_addr) ; " ";
For Temp = 1 To Twi_sr_cntr
Print Hex(twi_slv_buff(temp)); 'print der Daten
Next
Case Else:
Print Chr(7) ; 'Irgendein Fehler
End Select
Print
Twi_slv_flag = 0 'löschen marker
Twi_slv_stat = 0 'löschen marker
Gosub Twi_sense 'alles wieder enablen
'und Bus freigeben
End If
' Print "DatenM" ; Twi_slv_buff(temp)
'Print Spc(30) ; Temp3
'************************************************* ****************************** nach Datenempfang als Slave umschalten auf Master und Daten senden
If Temp3 = 26 Then
Print "empfange komando" 'ist Masteranforderung 25 dann schicke Temperatur1
Gosub Master_transmit 'Senden in einer SUB
Temp3 = 0
Twi_sr_cntr = 0 'ja
'
End If
1wwrite &HCC : 1wwrite &H44 ' start measure
Loop
End
'################################################# ############################## 1 mS Ticker =>Timerroutine wird in der .Lib benötigt
'################################################# ##############################
Run_wait_master:
Print "versuche zu senden"
Gosub Mst_start 'aufruf
Select Case Twi_mst_flag 'ergebnis ?
Case Twi_m_sent: 'gesendet
Print "<<<<<<MASTER sent:" ;
Print Hex(twi_mst_addr) ; " ";
For Temp = 1 To Twi_mt_cntr
Print Hex(twi_mst_buff(temp1));
Next
Print
Twi_mst_flag = 0
Case Twi_m_recv: 'geholt
Print ">>>>>>MASTER read:" ;
Print Hex(twi_mst_addr) ; " ";
For Temp = 1 To Twi_mr_cntr
Print Twi_mst_buff(temp1); 'Hex(twi_mst_buff(temp));
Next
Print
Twi_mst_flag = 0
Case Else: 'irgendein Problem
Print Chr(7) ; Hex(twi_mst_addr) ; " ";
End Select
Return
'################################################# ############################## Sendesub
' Beispiel 8 byte senden,
' dann mit Rep.Start von gleicher adresse 3 Byte empfangen
'Nur senden
'Twi_mst_addr = Mn2_adr 'I2C adresse ZIEL
'Twi_mt_cntr = 8 ' 8 Byte senden
'Twi_mt_data = Varptr(twi_mst_buff(1)) ' Daten
'Twi_mr_cntr = 0
'Nur abholen
'Twi_mst_addr = Mn2_adr + 1 'I2C adresse ZIEL (+R)
'Twi_mr_cntr = nn ' wieviele Byte
'Twi_mr_data = Varptr(twi_mst_buff(1)) ' empfangsbuffer
Master_transmit:
' sende buffer (mit testdaten) füllen
'For Temp = 1 To 1
Twi_mst_buff(temp1) = Temp1 'Temperatur Sensor1
' Next
Twi_mst_addr = Mn2_adr 'I2C adresse
Twi_mt_cntr = 1 '8 ' erstmal 8 Byte senden
Twi_mt_data = Varptr(twi_mst_buff(1)) ' adresse Daten
Twi_mr_cntr = 0
'Twi_mr_cntr = 1 ' dann 3 Byte empfangen
'Twi_mr_data = Varptr(twi_mst_buff(1)) ' empfangsbuffer
Gosub Run_wait_master ' auf gehts
Return
und Slave1:
$regfile = "m8def.dat"
$crystal = 14318181
$include "MyTWI.bas" 'dafür wird noch die MyTWI.lib benötigt
$baud = 9600
$hwstack = 80
$swstack = 80
$framesize = 80
'-----------------2x20 LCD Display an Port c =>Conector -------------------------------------------------------------------------------------------------
Config Lcdpin = Pin , Db4 = Portc.0 , Db5 = Portc.1 , Db6 = Portc.2 , Db7 = Portc.3 , E = Portb.2 , Rs = Portb.0 ' Pinbelegung "LCD-Port)"
' SV2 1 2 3 4 6 8 ' Pinbelegung SV9 Board
Config Lcd = 20 * 4
Config Lcdbus = 4
Initlcd
Cursor Off
Cls
'------------------------------------------------------------------------------- Configuration DS1820
Config 1wire = Portb.1
Dim Id1(8) As Byte
Dim Id2(8) As Byte
Dim Ar1(2) As Byte
Dim Ar2(2) As Byte
Dim Temp1 As Byte
Dim Temp2 As Byte
Id1(1) = 1wsearchfirst()
Id2(1) = 1wsearchnext()
'------------------------------------------------------------------------------- Timer0 aktivieren
'------------------------------------------------------------------------------- lokale I2C Adresse (als Slave)
Const Mn1_adr = &H6E
'------------------------------------------------------------------------------- fremde I2C Adresse (als Master)
Const Mn2_adr = &H6A
Dim Twi_mst_buff(24) As Byte 'Buffer für Masterfunktionen
Dim Twi_slv_buff(24) As Byte 'Buffer für Slavefunktionen
'------------------------------------------------------------------------------- TWI Variablen
Dim Temp As Byte , Temp3 As Byte
Twi_slv_addr = Mn1_adr 'lokale I2C-Adresse
Twi_sr_data = Varptr(twi_slv_buff(1)) 'datenbuffer empfang
Twi_st_data = Varptr(twi_slv_buff(1)) 'datenbuffer senden
Twar = Twi_slv_addr + 1 'I2C Adress Mega32 + GCA
Config Twi = 400000 'I2C Speed
On Twi Twi_mst_slv_isr , Nosave 'ISR f. TWI
Gosub Twi_sense 'Aktivieren Slave-Funktion
Enable Timer2 'Timer
Enable Interrupts 'Generell
'************************************************* ****************************** Hauptprogramm
Do
'************************************************* ****************************** Sensor 1
1wreset 'reset
1wwrite &H55 'Match Rom command
1wwrite Id1(1) , 8 'Id von Sensor 1
1wwrite &H44 'Convert T
'300 'warten bis convert T fertig ist
1wreset 'reset
1wwrite &H55 'match rom command
1wwrite Id1(1) , 8 'id von sensor 1
1wwrite &HBE
Locate 1 , 14
Ar1(1) = 1wread(2)
Temp1 = Makeint(ar1(1) , Ar1(2))
Temp1 = Temp1 / 2 'Ar(1)
Lcd "Out1:" ; Temp1
'************************************************* ****************************** Sensor2
1wreset 'reset
1wwrite &H55 'Match Rom command
1wwrite Id2(1) , 8 'Id von Sensor 2
1wwrite &H44 'Convert T
' 300 'warten bis convert T fertig ist
1wreset 'reset
1wwrite &H55 'match rom command
1wwrite Id2(1) , 8 'id von sensor 2
1wwrite &HBE 'scratchpad lesen
Locate 2 , 14
Ar2(1) = 1wread(2)
Temp2 = Makeint(ar2(1) , Ar2(2))
Temp2 = Temp2 / 2
Lcd "Out2:" ; Temp2
'************************************************* ****************************** TWI Betrieb
'praktisches Beispiel zu Anzeige der Daten, werden im Prog nicht benötigt bis auf die Flagabfrage
'Twi_slv_flag =
' * 0 Keine Slave Aktion hat stattgefunden
' * &H60 Daten wurden empfangen. Sie stehen im Buffer mit der Länge Twi_sr_cntr
' * &HA8 Daten wurden gesendet. Sie stehen im Buffer mit der Länge Twi_st_cntr
' * &H70 Gca -daten Wurden Empfangen.
If Twi_slv_flag <> 0 Then 'ständige Abfrage ob als Slave Daten anliegen =>Vorsicht, der Bus ist solange blockiert
Select Case Twi_slv_flag
Case &H60 :
Locate 1 , 1
Lcd ; "SLVrecv" ; 'es ist was empfangen worden
Locate 1 , 9
Lcd Hex(twi_slv_addr) ; " "; 'von Adresse in Hex
For Temp = 1 To Twi_sr_cntr 'Daten aus Twi_sr_cntr in den puffer schreiben
Locate 1 , 11
Lcd Hex(twi_slv_buff(temp)); 'print der Daten
Temp3 = Twi_slv_buff(temp)
Next
Case &HA8 :
Locate 2 , 1
Lcd ; "SLVtran" ; 'es ist was abgeholt worden Spc(30)
Locate 2 , 9
Lcd Hex(twi_slv_addr) ; " ";
For Temp = 1 To Twi_st_cntr
Locate 2 , 11
Lcd Twi_slv_buff(temp); 'print der Daten Hex(twi_slv_buff(temp));
Next
End Select
Locate 4 , 1
Lcd Twi_mst_flag
Print
Twi_slv_flag = 0 'löschen marker
Twi_slv_stat = 0 'löschen marker
Gosub Twi_sense 'alles wieder enablen
'und Bus freigeben
End If
Locate 4 , 6
Lcd "DatenM" ; Twi_slv_buff(temp)
'************************************************* ****************************** nach Datenempfang als Slave umschalten auf Master und Daten senden
Locate 4 , 19
Lcd Temp3
If Temp3 = 25 Then 'ist Masteranforderung 25 dann schicke Temperatur1
Gosub Master_transmit 'Senden in einer SUB
Temp3 = 0
Twi_sr_cntr = 0 'ja
'
End If
Loop
End
'################################################# ############################## 1 mS Ticker =>Timerroutine wird in der .Lib benötigt
'################################################# ##############################
Run_wait_master:
Gosub Mst_start 'aufruf
'( Select Case Twi_mst_flag 'ergebnis ?
Case Twi_m_sent:
Locate 3 , 1 'gesendet
Lcd "<<MASTsent:" ; Hex(twi_mst_addr) ; " ";
Print
For Temp = 1 To Twi_mt_cntr
Locate 3 , 14
Lcd Twi_mst_buff(temp);
Next
Print
Twi_mst_flag = 0
Case Twi_m_recv:
Locate 4 , 1 'geholt
Lcd ">>MASTread:" ; Hex(twi_mst_addr) ; " ";
Print
For Temp = 1 To Twi_mr_cntr
Locate 4 , 14
Lcd Twi_mst_buff(temp); 'Hex(twi_mst_buff(temp))
Next
Print
Twi_mst_flag = 0
'Case Else: 'irgendein Problem
'Print Chr(7) ; Hex(twi_mst_addr) ; " ";
'Call Twi_show_state(twi_mst_flag)
End Select
')
Return
'################################################# ############################## Sendesub
' Beispiel 8 byte senden,
' dann mit Rep.Start von gleicher adresse 3 Byte empfangen
'Nur senden
'Twi_mst_addr = Mn2_adr 'I2C adresse ZIEL
'Twi_mt_cntr = 8 ' 8 Byte senden
'Twi_mt_data = Varptr(twi_mst_buff(1)) ' Daten
'Twi_mr_cntr = 0
'Nur abholen
'Twi_mst_addr = Mn2_adr + 1 'I2C adresse ZIEL (+R)
'Twi_mr_cntr = nn ' wieviele Byte
'Twi_mr_data = Varptr(twi_mst_buff(1)) ' empfangsbuffer
Master_transmit:
' sende buffer (mit testdaten) füllen
For Temp = 1 To 1
Twi_mst_buff(temp1) = Temp1 'Temperatur Sensor1
Next
Twi_mst_addr = Mn2_adr 'I2C adresse
Twi_mt_cntr = 1 '8 ' erstmal 8 Byte senden
Twi_mt_data = Varptr(twi_mst_buff(1)) ' adresse Daten
Twi_mr_cntr = 0
'Twi_mr_cntr = 1 ' dann 3 Byte empfangen
'Twi_mr_data = Varptr(twi_mst_buff(1)) ' empfangsbuffer
Gosub Run_wait_master ' auf gehts
Return
mat-sche
14.07.2008, 19:28
so...
leider komme ich nicht weiter. Jetzt ist es auch noch so, dass noch nicht mal das alte Programm funktioniert, mit dem orginalcode läuft alles noch, jedenfalls bei einme der Slavs.
Ich weiss nicht mehr weiter...Irgend eine Idee?
Gruß & Danke MAT
Keep cool, das kriegen wir schon hin.
Ich hab nur leider dieser Tage jobmäßig den A.. offen. Aber ich bin dran !
mat-sche
14.07.2008, 21:49
Schön von einer Unterstüzung zu lesen! Ich komme immer nur am WE dazu etwas zu machen (der job eben) und das wurmt mich...
Ok bin mal gespannt und werd am we mich noch mal melden.
MAT
mat-sche
19.07.2008, 10:31
Hallo Robert,
inzwischen kommunizieren meine Master/Slaves recht gut miteinander.
Doch leider hab ich noch das Problem das ich nicht richtig mit dem Overlay umgehen kann.
Ich habe die Variable Datensingle in dem die Temperatur aus dem ds1820 drin steht (23.55). Nun wollte ich diese senden:
Auszug:
Dim Datensingle As Single
Dim Datenbyte (4) As Byte At Datensingle Overlay
und dann so rausschicken:
Master_transmit:
' sende buffer (mit testdaten) füllen
For Temp = 1 To 4
Twi_mst_buff(1) = Datenbyte 'Temp1 'Temperatur Sensor1
Next
'
'Print "Datenbyte" ; Datenbyte
Twi_mst_addr = Mn2_adr 'I2C adresse
Twi_mt_cntr = 4 '8 ' erstmal 8 Byte senden
Twi_mt_data = Varptr(twi_mst_buff(1)) ' adresse Daten
Twi_mr_cntr = 0
'Twi_mr_cntr = 1 ' dann 3 Byte empfangen
'Twi_mr_data = Varptr(twi_mst_buff(1)) ' empfangsbuffer
Gosub Run_wait_master ' auf gehts
Return
doch leider kommt nicht der richtige Wert heraus, was mache ich falsch?
MAT
mat-sche
23.08.2009, 15:40
HiRobert,
ich habe mal wieder ein kleines problem mit dem TWI-Multimasterbetrieb!
Inzwischen hole ich mir von 2 Slaves einige Daten ab, was auch gut geht:
Master:
Sub Aufrufen
If Twi_1 = 0 Then 'Timerabfrage erst starten wenn die Uhr gestellt wurde
If Timecount1 = 2 Then
Gosub Daten_hofslave
Timecount1 = 3
End If
If Timecount1 = 6 Then
Gosub Daten_kellerslave
Timecount1 = 7
End If
If Timecount1 = 9 Then
Gosub Daten_kellerzentrale
Timecount1 = 0
End If
End If
Subprozeduren:
Daten_hofslave:
If Send_flag = 0 Then
Send_flag = 1
'(
Slave_adress = &H6C 'dann Slaveadresse (Empfänger) setzen
Send_byte = 6 'zu sendende Bytes
Fenster_komando(1) = 5 'Komando an den Slave 5= Slave schreibt momentan die Absenderadresse mit in die zu holenden Daten
Fenster_komando(5) = &H6A 'von wem kommt die Anfrage
Call Master_transmit(slave_adress , Send_byte , Fenster_komando(1)) 'obrige Daten werden der Sendesub übergeben
')
Twi_mst_addr = &H6C 'jetzt gleich wieder daten vom Slave holen
Twi_mr_cntr = 7 ' dann 7 Byte empfangen:1-4.=Temperatur_single, 5-6.=Licht_word, 7.=Absender_byte
Twi_mr_data = Varptr(tout) 'Daten direkt in die Variablen schreiben, beginnend bei mit: dim Tout as Single
Gosub Run_wait_master
End If
Return
Daten_kellerslave:
If Send_flag = 0 Then
Send_flag = 1
Slave_adress = &H6E
Send_byte = 6 ' dann Slaveadresse (Empfänger) setzen
Fenster_komando(1) = 5
Fenster_komando(5) = &H6A ' Kommado
Call Master_transmit(slave_adress , Send_byte , Fenster_komando(1)) 'nach Tastendruck aus der select case Übergabe werden
'Twi_sr_cntr = 0
Twi_mst_addr = &H6E 'Daten vom DS1307 &hD01 (Lesebefehl) holen =>
Twi_mr_cntr = 6 'dann 6 Byte empfangen:1.=T_vorl, 2.=T_rückl, 3.=Automatik, 4.=Portbrenner, 5.=Absender, 6.=Relwasser
Twi_mr_data = Varptr(t_vorl) ' empfangsbuffer
Gosub Run_wait_master
End If
Return
Daten_kellerzentrale:
If Send_flag = 0 Then
Send_flag = 1
Slave_adress = &H5A
Send_byte = 6 ' dann Slaveadresse (Empfänger) setzen
Fenster_komando(1) = 5
Fenster_komando(5) = &H6A ' Kommado
Call Master_transmit(slave_adress , Send_byte , Fenster_komando(1)) 'nach Tastendruck aus der select case Übergabe werden
'Twi_sr_cntr = 0
Twi_mst_addr = &H5A 'Daten vom DS1307 &hD01 (Lesebefehl) holen =>
Twi_mr_cntr = 6 ' dann 6 Byte empfangen:1-4=Single Bat-Spannung, 5.=Türkontakte, 6.=Absender
Twi_mr_data = Varptr(batdata) 'Empfangsbuffer
Gosub Run_wait_master
End If
Return
Die Subs für die Daten_hofslave und Daten_kellerslave funktionieren ohne Weiteres. Aber für Daten_kellerzentrale bekomme ich immer ein: MT Sla W Transmitted Not Acked"
als Antwort. Was kann hier der Fehler sein??
Hier noch der Code vom Daten_kellerzentrale:
$regfile = "m644pdef.dat"
$crystal = 14745600
$include "MyTWI.bas"
$baud = 19200
$hwstack = 64
$swstack = 64
$framesize = 64
Ddrb = &B00000000 'PortB als Eingang für die Funksensorüberwachung
Portb = &B11111111 'PullUp's einschalten
Ddrc = &B00000000 'PortB als Eingang
Portc = &B00000100
Ddrd = &B11111000
Portd = &B00000100
Config Adc = Single , Prescaler = Auto , Reference = Off
Start Adc
Config Timer1 = Timer , Prescale = 1024 'Timer1 (16bit, 65535) läuft mit Quarztakt/1024
Const Timervorgabe = 36735 'Anfangswert ab der der Timer1 beginnen soll zu zählen (von 58336=>65535)
Enable Timer1 ' Schalte Überlaufinterupt von Timer1 ein
On Timer1 Timer_irq ' 1secint => Sprungmarke an die gesprungen wird, wenn timer1 übergelaufen ist => danach weiter Start ADC
Config Int0 = Rising 'Interrupt zur Netzspannungsdedektion
On Int0 Int0_isr 'Sprungmarke interrupt nach dem infrarot Signal anliegt
Enable Int0
Enable Interrupts
Dim Irq_z As Byte
'------------------------------------------------------------------------------- Programmvariablen
Dim Relon As Bit
'------------------------------------------------------------------------------- Config TWI
Dim Batterie As Word
Dim Batspannung As Single
Dim Tuerkontakt As Byte
Dim Absender As Byte
Declare Sub Twi_show_state(byref State As Byte) ' Fehleranzeige für TWI übertragung
Const Mn1_adr = &H5A 'lokale I2C Adresse (als Slave)
Dim Twi_mst_buff(24) As Byte 'Buffer für Masterfunktionen
Dim Twi_slv_buff(24) As Byte 'Buffer für Slavefunktionen
Dim Temp As Byte
Dim Slave_adress As Byte , Send_byte As Byte , Speicherpointer As Byte
Declare Sub Master_transmit(byref Slave_adress As Byte , Byref Send_byte As Byte , Byref Speicherpointer As Byte) 'Declarierung der Sub =>mit byref wird immer nur ein Zeiger auf die Speicherstelle
' verwiesen und nicht ein Wert übergeben
Twi_slv_addr = Mn1_adr 'lokale I2C-Adresse
Twi_sr_data = Varptr(twi_slv_buff(1)) 'datenbuffer empfang
Twi_st_data = Varptr(batspannung) 'datenbuffer senden, von dort holt sich der Master die Daten
Twar = Twi_slv_addr + 1 'I2C Adress Mega32 + GCA
Config Twi = 100000 'I2C Speed
On Twi Twi_mst_slv_isr , Nosave 'ISR f. TWI
Gosub Twi_sense 'Aktivieren Slave-Funktion
Enable Interrupts 'Generell
'################################################# ############################## Programmstart
Do
If Portd.7 = 1 Then Set Relon
If Pinc.2 = 0 And Portd.7 = 1 Then
Portd.7 = 0
Irq_z = 0 'Netzspannung wieder da? Or Batmin = 0
Enable Int0
Reset Relon
End If
'************************************************* ****************************** Überwachung Batteriespannung
Batterie = Getadc(1)
Batspannung = Batterie * 4.5 ' Potivoreinstellung 4,5V = 10V Battspannung
Batspannung = Batspannung / 920 ' Spannung auf Wandlerrate umstellen
Batspannung = Batspannung * 2.22 ' Faktor für Umrechnung in tatsächlichen Bat-Wert 10V/4,5V
If Portd.7 = 1 Then ' Unterspannungsüberwachung
If Batspannung =< 6.7 Then
Portd.7 = 0
End If
End If
If Relon = 1 Then ' Übermittlung das Netzausfall vorliegt => Meldung an Zentrale
Tuerkontakt.7 = 1
Else
Tuerkontakt.7 = 0
End If
'************************************************* ****************************** Überwachung Türkontakte
If Pinb.0 = 1 Then
Tuerkontakt.0 = 1
Else
Tuerkontakt.0 = 0
End If
If Pinb.1 = 0 Then
Tuerkontakt.1 = 1
Else
Tuerkontakt.1 = 0
End If
If Pinb.2 = 1 Then
Tuerkontakt.2 = 1
Else
Tuerkontakt.2 = 0
End If
If Pinb.3 = 1 Then
Tuerkontakt.3 = 1
Else
Tuerkontakt.3 = 0
End If
If Pinb.5 = 1 Then
Tuerkontakt.4 = 0
Else
Tuerkontakt.4 = 0
End If
If Pinb.6 = 1 Then
Tuerkontakt.5 = 1
Else
Tuerkontakt.5 = 0
End If
If Pinb.7 = 1 Then
Tuerkontakt.6 = 1
Else
Tuerkontakt.6 = 0
End If
'************************************************* ****************************** TWI Slavefunktion, hier wird gehört, ob ein andere Master etwas sendet
If Twi_slv_flag <> 0 Then 'ständige Abfrage ob als Slave Daten anliegen =>Vorsicht, der Bus ist solange blockiert
Select Case Twi_slv_flag
Case &H60 :
Print ; "Slave empfängt" ; 'es ist was empfangen worden
Print Hex(twi_slv_addr) ; " "; 'von Adresse in Hex
For Temp = 1 To Twi_sr_cntr 'Daten aus Twi_sr_cntr in den puffer schreiben
Print Hex(twi_slv_buff(temp)); 'print der Daten
Next
Case &HA8 :
Print ; "Slave sendet" ; 'es ist was abgeholt worden Spc(30)
Print Hex(twi_slv_addr) ; " ";
For Temp = 1 To Twi_st_cntr
Print Twi_slv_buff(temp); 'print der Daten Hex(twi_slv_buff(temp));
Next
Case &H70 : Print Spc(30) ; "SLAVE GCA :" ; 'ein General Call ist gekommen
Print Hex(twi_slv_addr) ; " ";
For Temp = 1 To Twi_sr_cntr
Print Hex(twi_slv_buff(temp)); 'print der Daten
Next
Case Else:
Print Chr(7) ; Hex(twi_mst_addr) ; " "; 'Irgendein Fehler
Call Twi_show_state(twi_slv_flag) 'Print status-text
End Select
Print
Twi_slv_flag = 0 'löschen marker
Twi_slv_stat = 0 'löschen marker
Gosub Twi_sense 'alles wieder enablen
'und Bus freigeben
End If
'************************************************* ******************************
Print " IRQ-Zaehler " ; Irq_z
Print " Batspannung " ; Batspannung
Print " Relon " ; Relon
Loop
End
'+++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++ SUBROUTINEN
'+++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++ Timerschaltung für Impulse Resetbaustein Netzüberwachung
Timer_irq:
Toggle Portd.6
Timer1 = Timervorgabe
Return
'+++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++ Interruptabfrage Netzausfall
Int0_isr:
Portd.7 = 1
Disable Int0
Return
'+++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++
$include "Twi_show_state.bas"
'+++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++ Senderoutine TWI
Run_wait_master:
Gosub Mst_start 'aufruf
Select Case Twi_mst_flag 'ergebnis ?
Case Twi_m_sent: 'gesendet
'Print "<<<<<<MASTER sent:" ;
'Print Hex(twi_mst_addr ) ; " ";
'Print "twi_mst_buff(temp):" ; Hex(twi_mst_buff(temp));
For Temp = 1 To Twi_mt_cntr
Next
Print
Twi_mst_flag = 0
Case Else: 'irgendein Problem
'Print "Übertragungsfehler" ; Chr(7) ; Hex(twi_mst_addr) ; " ";
Call Twi_show_state(twi_mst_flag)
End Select
Return
'################################################# ############################## Sendesub
Sub Master_transmit(byref Slave_adress As Byte , Byref Send_byte As Byte , Byref Speicherpointer As Byte) 'Sub in der die Adresse des Empfängers steht und der Zeiger aus der Callprozedur
Twi_mst_addr = Slave_adress 'I2C Adresse Slave
Twi_mt_cntr = Send_byte '4 Byte senden
Twi_mt_data = Varptr(speicherpointer(1)) 'Daten senden => Varptr(Speicherpointer(1)) Speicherpointer = Zeiger auf eine
' Speicherstelle, nicht auf den Wert, aus der Callsubroutine (Temperaturbyte(1))
Twi_mr_cntr = 0
'Twi_mr_cntr = 1 ' dann 3 Byte empfangen
'Twi_mr_data = Varptr(twi_mst_buff(1)) ' empfangsbuffer
Gosub Run_wait_master ' auf gehts
End Sub
Return
Mmmhh.
Bei der Kellerzentrale werden ja erstmal Bytes gesendet.
Und da kriegt der Master offenbar schon kein ACK.
Bis zu diesem ACK macht eigentlich die TWI-Hardware alles alleine.
d.h. man müsste wohl erstmal sicherstellen, das elektrisch auch alles o.k. ist.
Ideal wäre dazu, einen anderen, dzt. funktionierenden Slave dort mal anzuschliessen, wo die Kellerzentrale drauf steckt. Die Sinnhaftigkeit der Daten wäre ja mal wurst, Hauptsache, er ACKed seine Adresse
(oder eben auch nicht)
mat-sche
23.08.2009, 19:32
Das Spielchen habe ich schon durch... Teilweise hatte es auch funktioniert und das wundert mich! Ich werde mal dennnoch einen anderen Slave kreieren.
melde mich später wieder!
Danke Dir schon jetzt mal :)
mat-sche
28.08.2009, 19:11
Hallo Robert,
heute bin ich dazu gekommen einen Mega32 mit einem gekürzten Code einzubauen. Also die Hardware ist funktionstüchtig und auf dem Mega wird nur ein ADC ausgelesen, also nur der Code für den ADC siehe oben.
das Gleiche werde ich jetzt auch noch mit nem Mega 644p versuchen. Ansonsten gibt es in meinem Code von oben ein Problem, doch wo nur?
Kannst Du bitte noch einmal darüber schauen?
Danke und Gruß
MAT
mat-sche
28.08.2009, 20:13
Hmmm,
habe jetzt die Programmteile wo irgend ein IRQ angesprungen werden kann (außer TWI) herausgenommen aber trotz allerdem geht es nicht :(
Irgend eine Idee?
mat-sche
30.08.2009, 12:29
Update:
* habe die Hardware nochmal überprüft => ist i.O.
* mitterweilen wird von Zeit zu Zeit Daten versendet, jetzt ist es so, dass öffters hintereinander ein Timeout bei dem Slave entsteht
Werde weiter suche und auf Hilfe hoffen!
MAT
Ich bin da und schau dir über die Schulter.
Besondere Weisheit fällt mir nicht ein, wenn's mal geht und mal nicht.
Vielleicht irgendwie eine knappe Sache (pullups ausreichend ?)
mat-sche
31.08.2009, 11:41
Moin Moin,
gestern hab ich noch einwenig gebastelt und habe herausgefunden, dass wenn ich die Printanweisung am Ende vom Code herausgenommen habe das Programm läuft und nur von Zeit zu Zeit mir der Master ein Time Out bringt. Es muss irgendwie ein Timingproblem sein, was mir aber schleierhaft ist. Die TWI Übertragung macht doch die Hardware fast für sich allein oder?
MAT
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.