PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : TWI Multimaster Betrieb mit TWI_LCD möglich



mat-sche
19.12.2008, 09:09
Hallo

ich nutze die TWI Multimasterumgebung aus RN Wissen. Ich habe nun den TWI Bus und möchte nun gern ein LCD mit integrieren. Dazu habe ich den Artikel AN #118 - I2C LCD and Keboard library bei MCS gefunden.
Wie gelesen so auch getan, LCD aufgebaut und mit Testcode gefüttert. Siehe da => es funzt! Doch leider, wenn ich versuche diesen in meinen:


$regfile = "m8def.dat"
$crystal = 16000000

$include "MyTWI.bas" 'dafür wird noch die MyTWI.lib benötigt
$lib "Lcd_i2c.lib"
$baud = 19200

$hwstack = 80
$swstack = 80
$framesize = 80
'------------------------------------------------------------------------------- Config TWI-LCD 2x16
Config Lcd = 16 * 2
Config Lcdbus = 4
Initlcd
Cursor Off
Cls
Const Pcf8574_lcd = &H40 'Defines the address of the I/O expander for LCD
Config Scl = Portc.5 'Configure i2c SCL
Config Sda = Portc.4 'Configure i2c SDA
Dim _lcd_e As Byte 'Needed to control 4 line LCD
_lcd_e = 128 'Upper half of 4-line display is selected
Dim A As Byte
'------------------------------------------------------------------------------- Configuration DS1820
Config 1wire = Portd.4
Dim Bd(9) As Byte
Dim J As Byte , Tmp As Byte ,
Dim T1 As Integer
'------------------------------------------------------------------------------- Sendevariablen deklarieren

Dim Temp1 As Single
Dim Temperaturbyte(6) As Byte At Temp1 Overlay 'Temperaturbyte(5), 4 an der Zahl, wird über Temp1 (single=4byte) gelegt, byte(5) enthält Subadresse
'dabei nimmt Temperaturbyte(1) die Speicherstelle des 1.Byte von Temp1 ein
Dim Licht As Word
Dim Lichtbyte(6) As Byte At Licht Overlay
Dim Send_flag As Bit
'------------------------------------------------------------------------------- Timer1 konfigurieren
Config Timer1 = Timer , Prescale = 256 'Timer mit 1sec Überlauf
On Timer1 Counter_irq
Const Timer1vorgabe = 18661
Enable Timer1
Dim Timecount As Word

'------------------------------------------------------------------------------- Configuration Licht A/D Wandler an PortC=0 (10bit)
Config Adc = Single , Prescaler = Auto , Reference = Off


'Pc0 = Lichtsensor

'------------------------------------------------------------------------------- TWI Variablen
Const Mn1_adr = &H6C 'lokale I2C Adresse (als Slave)
'Const Mn2_adr = &H6A 'fremde I2C Adresse (als Master)

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 , Komando 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(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 Interrupts 'Generell

'************************************************* ****************************** Hauptprogramm
Do
Disable Interrupts
Lcd "licht " ; Licht
Enable Interrupts
1wwrite &HCC : 1wwrite &H44 'DS1820 Messung starten

'************************************************* ****************************** 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 :
For Temp = 1 To Twi_sr_cntr ' fülle "Temp" für empfangene Bytes
'If Twi_mst_addr = &H6A Then ' ist Masteradresse &H6E?
Print "SlaveAdress" ; Spc(10) ; Hex(twi_slv_addr) 'schreibe eigene Adresse
Print "MasterAdress" ; Spc(10) ; Hex(twi_mst_addr) 'schreibe Adresse von wem etwas empfangen wurde
Komando = Twi_slv_buff(temp) 'fülle "Temp1" mit Daten
Print "temp wasser" ; Komando 'schreibe gesendete DAten
'End If
Next 'wurden mehrere Bytes geschickt (Twi_mt_cntr = 1...) wird die Schleife durchlaufen
' und dabei "Temp" gefüllt bis "Twi_sr_cntr" leer ist
'( For Temp = 1 To Twi_sr_cntr
Print "TempZähler " ; Spc(10) ; Temp ' schreibe Zählerstand (empfangene Bytes)
If Twi_mst_addr = &H6C Then ' ist Masteradresse &H6C?
Print "SlaveAdress" ; Spc(10) ; Hex(twi_slv_addr)
Print "MasterAdress" ; Spc(10) ; Hex(twi_mst_addr)
Temp2 = Twi_slv_buff(temp)
Print "temp hof" ; Spc(10) ; Temp1
Next
End If
')

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

'************************************************* ****************************** Zeitcounter für Temperatur aus DS1820 und Übertragung über TWI

If Timecount = 8 Or Timecount = 24 Or Timecount = 48 Then ' aller 8,24,48sek. wird eine vollständige Temperatur convertierung angestoßen
Send_flag = 1 'Send_flag verhindert doppeltes senden
Start Adc
Licht = Getadc(0)
Stop Adc
'Locate 1 , 1
Lcd "licht " ; Licht

1wreset ' reset the bus
1wwrite &HCC ' read internal RAM
1wwrite &HBE ' read 9 data bytest
Bd(1) = 1wread(9) ' read bytes in array
1wreset ' reset the bus

If Tmp = 1 Then Decr Bd(1)
T1 = Makeint(bd(1) , Bd(2))
T1 = T1 / 2
Temp1 = Bd(8) - Bd(7)
Temp1 = Temp1 / Bd(8)
Temp1 = T1 + Temp1
Temp1 = Temp1 - 0.25
End If

Lowerline
Lcd "temp " ; Temp1

If Timecount = 10 Or Timecount = 26 Or Timecount = 50 Then 'sendet aller 10sec den Temperaturwert mit Adresse 6A
If Send_flag = 1 Then
Send_flag = 0
Slave_adress = &H6A 'Sendeadresse
Send_byte = 6
Temperaturbyte(5) = &H6C 'Anzahl zu sendene Bytes (ersten 4 sind die Tempwerte, 5 ist Subbyte
Temperaturbyte(6) = 1 'Subadresse entspricht der Herkunft der Daten: 1=> Temperaturwerte
Call Master_transmit(slave_adress , Send_byte , Temperaturbyte(1)) 'Aufruf der Callprozedur mit der Adresse und der zu übergebenen Adresspointer
Twi_sr_cntr = 0

Print "sende Temperatur" ; Spc(3) ; Temp1
Print "Temperaturbyte1" ; Spc(3) ; Hex(temperaturbyte(1)) 'ausgeben der 4 einzelnen Temperaturbyts aus dem Tempbytes vom Hofslave
Print "Temperaturbyte2" ; Spc(3) ; Hex(temperaturbyte(2))
Print "Temperaturbyte3" ; Spc(3) ; Hex(temperaturbyte(3))
Print "Temperaturbyte4" ; Spc(3) ; Hex(temperaturbyte(4))

End If
End If


If Timecount = 14 Or Timecount = 30 Or Timecount = 54 Then 'Timecounter für Sendeflag
Send_flag = 1 ' Sendeflagsetzen um nur immer einmal die Temp/Lichtwerte zu senden
End If

If Timecount = 15 Or Timecount = 31 Or Timecount = 55 Then 'sendet aller 10sec den Temperaturwert mit Adresse 6A
If Send_flag = 1 Then
Send_flag = 0
Slave_adress = &H6A 'Sendeadresse
Send_byte = 6
Lichtbyte(5) = &H6C ' zu sendene Bytes
Lichtbyte(6) = 2 'Subadresse entspricht der Herkunft der Daten: 1=> Lichtwerte
Call Master_transmit(slave_adress , Send_byte , Lichtbyte(1)) 'Aufruf der Callprozedur mit der Adresse und der zu übergebenen Adresspointer
Twi_sr_cntr = 0

Print "sende Licht" ; Spc(3) ; Licht
Print "Lichtbyte1" ; Spc(3) ; Hex(lichtbyte(1)) 'ausgeben der 4 einzelnen Temperaturbyts aus dem Tempbytes vom Hofslave
Print "Lichtbyte2" ; Spc(3) ; Hex(lichtbyte(2))
Print "Lichtbyte3" ; Spc(3) ; Hex(lichtbyte(3))
Print "Lichtbyte4" ; Spc(3) ; Hex(lichtbyte(4))

End If
End If

'************************************************* ****************************** nach Datenempfang als Slave umschalten auf Master und Daten senden

If Komando = &H1A Then
'Print "Temp:" ; Fusing(temp1 , "#.##") ; "C" 'ist Masteranforderung 26 dann schicke Temperatur1
'print "Lichtwert" ; Spc(3) ; licht
Slave_adress = &H6A
Send_byte = 5
'Sub_adr = 1
Call Master_transmit(slave_adress , Send_byte , Temperaturbyte(1))
Komando = 0
Twi_sr_cntr = 0 'ja
End If


Loop
End


'+++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++ SUBS
Counter_irq:

Timer1 = Timer1vorgabe
Incr Timecount
' increment every sec the counter with 1
If Timecount => 60 Then ' 60 here is the 1min
Timecount = 0
' wenn nicht dann lade StartWert in Timer1
End If
Return

'+++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++ Senderoutine TWI
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

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



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
'+++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++ LCD-TWI

einzufügen geht auf dem TWI Bus gar nichts mehr! Vertragen sich die beiden TWI Funktionen überhaupt und wie und was muss dazu geändert werden?
Eine Hilfestellung wäre super!

Danke MAT

linux_80
19.12.2008, 11:52
Hallo,

die Lib von Bascom, für das LCD über I2C, verwendet die Bascom-Internen TWI-Befehle, und wenn die TWI-lib nicht ins Programm aufgenommen wurde, macht es das per Software-I2C !
Aber Grundsätzlich verträgt sich das nicht mit der Version vom Wiki, da Bascom sich nicht um Multimaster kümmert, was der Grund für den Wiki-Artikel war.

guenter1604
19.12.2008, 13:14
Hallo Matsche,

vor einigen Wochen hab ich mit Hilfe von PicNick eine Lib für LCD an I2C erstellt. Diese ist aber sicherlich auch nicht Multimastertauglich. Jedoch ist sie quelloffen und kann/soll/darf erweitert und geändert werden. Für Detailfragen in den ASM-Tiefen bin ich aber der Falsche, da wäre PicNick mit Sicherheit der richtige Mann ;-)

http://www.gerold-online.de/cms/index.php?id=146

Günter