PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : I2C problem ??



schnassi
28.06.2007, 11:50
Hallo !
Ich möchte meine Ampeln steuern ich habe dazu einen Master und mehrere Slave. Der I2c allein im Programm funzt, die Ampelschleife auch, nur beides zusammen nicht.
Problem:
Ich möchte immer einen Slave "anstoßen" dann soll das Programm laufen.
Bei mir kann ich zwar den Slave "anstoßen" und das Programm beginnt, allerdings kann ich dann nichts mehr tun als warten bis die Ampelschleife durch ist + ca. 5 Secunden und dann kann ich die nächste Ampel schalten.


$regfile = "m8def.dat" 'ATmega8-Deklarationen
$crystal = 3686400 'Quarz: 3,6864 MHz
$baud = 9600 'Baudrate zum PC: 9600 Baud
'
Declare Function Twistart() As Byte
Declare Function Twisend(byval Databyte As Byte) As Byte
Declare Function Twireceive(byref Databyte As Byte) As Byte
Declare Sub Twistop()
Declare Sub Schleife
'
Dim I As Byte 'Für temporären Gebrauch
Dim Command As Byte 'Aktuelles UART-Kommando
Dim Adree As Byte 'Für die jeweilige EEPROM-Adresse
Dim Sbuffer As String * 20 'Nimmt die zu brennenden Daten auf
Dim Buffer(20) As Byte At Sbuffer Overlay 'Vereinfacht den Zugriff auf sBuffer
Dim Slad As Byte 'Slaveadresse
'
Twsr = &B00000000 'Bits1+0=00: TWI-Vorteilung 1
Twbr = 0 'IC2-Bitrate 230400Hz bei 3,6864MHz
'BitRate=AvrClock/(16+2*TWBR*4^TwiPrescale)
'----------------------------------------------------------
Do 'Hauptschleife
Inputbin Command 'Warte auf "Kommando"-Byte aus der UART
Select Case Command
Case "A" 'UART-Kommando "Write": EEPROM schreiben
Slad = &B10100000
GoSub Schleife
Case "B"
Slad = &B10100010
GoSub Schleife
End Select

Sub Schleife()
Sbuffer = "1"
Adree = 1 'Initiale EEPROM-Adresse (EE-Adresse wird 0 als Vereinfachung ignoriert)
While Buffer(Adree) <> 0 'Solange kein String-Ende
If Twistart() <> &H08 Then Exit While
I = Twisend(Slad) 'Slave-Adresse im Schreibmodus senden (Bit0=0)
If I = &H20 Then GoTo Writedone 'NO ACK: EEPROM brennt noch, später noch mal probieren
If I <> &H18 Then Exit While
If Twisend(0) <> &H28 Then Exit While 'HighByte der EEPROM-Adresse senden (bei uns immer 0)
If Twisend(adree) <> &H28 Then Exit While 'LowByte der EEPROM-Adresse senden
If Twisend(&B00000001) <> &H28 Then Exit While 'Aktuelles String-Byte senden
Printbin Buffer(adree) ; 1 'Aktuelles Byte zum Debuggen auch zur UART ausgeben
Incr Adree 'EEPROM-Adresse erhöhen
Writedone:
Twistop
Wend
Print "<Schreiben fertig>";
Loop
End Sub
'----------------------------------------------------------
Function Twistart() As Byte
Twcr = &B10100100 'START-Signal erzeugen
Do: Loop Until Twcr.twint = 1 'Warten bis fertig
Twistart = Twsr And &B11111000 'Status-Code zurückgeben
End Function
'----------------------------------------------------------
Function Twisend(ByVal Databyte As Byte) As Byte
Twdr = Databyte 'Byte ins Datenregister
Twcr = &B10000100 'TWI-Operation starten
Do: Loop Until Twcr.twint = 1 'Warten bis fertig
Twisend = Twsr And &B11111000 'Status-Code zurückgeben
End Function
'----------------------------------------------------------
Function Twireceive(ByRef Databyte As Byte) As Byte
Twcr = &B10000100 'TWI-Operation starten
Do: Loop Until Twcr.twint = 1 'Warten bis fertig
Databyte = Twdr
Twireceive = Twsr And &B11111000 'Status-Code zurückgeben
End Function
'----------------------------------------------------------
Sub Twistop()
Twcr = &B10010100 'STOP-Signal erzeugen
End Sub



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

'Config Portd = Output

Dim Twi_status As Byte
Dim Twi_data As Byte

Declare Sub Twi_init_slave 'Declaration der Sub bzw. Funktionen
Declare Function Twi_wait() As Byte
Declare Sub Ampelschleife
Dim X As Integer
Dim Y As Integer

Ddrb = &B00111111 'Pins PB0 - PB5: Ausgang
Ddrd = &B11110011 'Eingang PD2-PD3
Portd = &B00001101 'Pullup von Pin PD2 - PD3 aktivieren

Enable Int0
Enable Int1
Config Timer1 = Timer, Prescale = 1024 'Timer-Takt ist Quarz/1024
Enable Timer1 'Timer1-Overflow-Interrupt ein
Enable Interrupts

Twi_data = 0
Call Twi_init_slave
'---------------------------------------------------------
'Hauptschleife
Do
Twi_status = Twi_wait()
If Twi_status = &H80 Then
Portd 0# = Twi_data
End If
If Portd.0 = 0 Then
GoSub Ampelschleife
End If
Loop
'----------------------------------------------------------
'Unterprogramme
Sub Twi_init_slave() 'Twi als Slave aktivieren
Twsr = 0
Twdr = &HFF
Twcr = &B00000100
Twar = &B10100010 'Slaveadresse
Twcr = &B01000100
End Sub

Function Twi_wait() As Byte
Local Twcr_local As Byte
Twi_wait = &HF8
'warten Twint gesetzt
Twcr_local = Twcr And &H80
If Twcr_local = &H80 Then
Twi_data = Twdr
Twi_wait = Twsr And &HF8
Twcr = Twcr Or &B10000000
End If
End Function
'----------------------------------------------------------
Sub Ampelschleife()
Timer1 = 1
Do
X = Timer1
If X = 0 Then
Exit Do
End If
Select Case X
Case 2 'Hauptschleife: LED's blinken lassen
Portd 0.6 = 1
Portd 0.5 = 1
Case 5000
Portd 0.7 = 1
Portd 0.6 = 0
Portd 0.5 = 0
Case 30000
Portd 0.7 = 0
Portd 0.6 = 1
Case 35000
Portd 0.5 = 1
Portd 0.6 = 0
End Select
Disable Timer1
Loop
End Sub
'----------------------------------------------------------


Danke für eure Antworten und Hilfe
MfG Schnassi

linux_80
28.06.2007, 18:01
Hallo,

beim Master sollte der Wert für TWBR mind. 10 sein, da Atmel sonst nicht garantiert, das es immer funktioniert ! Siehe Datenblatt eines bel. AVR.

Beim Slave gibts da mind. einen Verschreiber beim setzen des PortD's.
Die Function TWI_Wait() wartet nicht, sondern läuft gleich durch, oder ist das mit der Hauptschleife verknüpft ?!

schnassi
29.06.2007, 08:56
Hallo !
Danke erst einmal für die Antwort. Ich werde die Werte erst einmal ändern und schauen was passiert. Ich habe die Grundschleife vom Master aus dem AVR - Buch übernommen und war froh überhaupt ein kleinen Lichtblick zu haben. Beim Slave habe ich den Schreibfehler oben im Code entdeckt, aber in meinen Programm ist der nicht. (wird wohl beim kopieren pasiert sein, da ich dort noch kleinigkeiten gelöscht habe).
Mfg Schnassi