PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : TWi Problem =>Multimaster RN-Wissen



mat-sche
14.06.2008, 08: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

PicNick
14.06.2008, 14:29
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, 16: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

PicNick
14.06.2008, 18:04
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, 18: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?

PicNick
14.06.2008, 18:36
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, 18: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?

PicNick
14.06.2008, 18:59
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, 19: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?

PicNick
14.06.2008, 20:10
Kenn' ich persönlich nicht. Klingt aber auch so nach Arbeit.
Theoretisch geht natürlich alles.

mat-sche
15.06.2008, 17: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, 21: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

PicNick
24.06.2008, 09:32
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, 14: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

PicNick
06.07.2008, 16:29
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, 16: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!

PicNick
06.07.2008, 17:49
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, 17: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?

PicNick
07.07.2008, 19:14
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, 13: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, 18: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

PicNick
14.07.2008, 18:34
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, 20: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, 09: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, 14: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

PicNick
23.08.2009, 18:06
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, 18: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, 18: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, 19: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, 11: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

PicNick
30.08.2009, 18:14
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, 10: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