PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Programm stoppt in einer Funktion - Wo ist mein Fehler



Jon
03.10.2007, 15:26
Hallo,
ich sitze jetzt schon seit heute morgen an diesem Problem ](*,) :
Ich habe diese Code:

Declare Function Twi_read_byte(byval Slave As Byte) As Byte
Declare Function Srf02_entfernung(byval Slaveid As Byte) As Integer

$regfile = "M32def.dat" ' the used chip
$crystal = 16000000 ' frequency used
$framesize = 84
$swstack = 84
$hwstack = 84
$baud = 19200 ' baud rate

Config Scl = Portc.0
Config Sda = Portc.1
I2cinit
Const Srf02_slaveid = &HE0

Dim Entfernung_hi As Integer
Dim Gegenstand_hi As Byte

Dim Gegenstand_alle As Byte

Dim Twi_control As Byte ' Controlregister lokale kopie
Dim Twi_status As Byte
Dim Twi_data As Byte

Dim Eingang_slave_senoren As Byte
Dim Eingang_slave_led As Byte
Dim Error As Byte ' Fehlermerker

' TWI Init
Twcr = &B00000100 ' erstmal nur TWI aktivieren
Twsr = 0 ' Status und Prescaler Register
Twbr = 72 ' Bit Rate Register, 100kHz

'Motoren:
Config Servos = 2 , Servo1 = Portc.2 , Servo2 = Portc.3 , Reload = 5

Config Portc.2 = Output 'rechts
Config Portc.3 = Output 'links

Enable Interrupts

Dim Servo_1 As Byte
Dim Servo_2 As Byte

'192 = Stopp
'128 = Vollgas vor
'255 = Vollgas rück

'Main ++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++
Wait 2

Do
'Entfernung_hi = Srf02_entfernung(srf02_slaveid)
'If Entfernung_hi < 40 Then
' Gegenstand_hi = 4
' Else
' Gegenstand_hi = 0
'End If
Gegenstand_hi = 0
Eingang_slave_senoren = Twi_read_byte(&H40)
Print Eingang_slave_senoren ;

Gegenstand_alle = Eingang_slave_senoren + Gegenstand_hi

Select Case Gegenstand_alle
Case 0 : Gosub Vorm
Case 1 : Gosub Rechtsm
Case 2 : Gosub Linksm
Case 3 : Gosub Rueckm
Case 4 : Gosub Vorm
Case 5 : Gosub Rechtsm
Case 6 : Gosub Linksm
Case 7 : Gosub Stopm
End Select

Waitms 100

Loop

End

'Subs ++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++

'------------- Empfangen von Slave_sensoren @ &H40 -----------------------------
Function Twi_read_byte(slave As Byte) As Byte
Error = 0
Twi_read_byte = 0
Twcr = &B10100100
Gosub Twi_wait_int

If Twi_status = &H08 Or Twi_status = &H10 Then
Twdr = Slave Or &H01 ' slave adresse + Read
Twcr = &B10000100 ' TWINT löschen, Byte senden
Gosub Twi_wait_int

If Twi_status = &H40 Then
Twcr = &B10000100
Gosub Twi_wait_int

If Twi_status = &H58 Or Twi_status = &H50 Then
Twi_read_byte = Twdr ' Daten lesen
Error = 0 ' kein Fehler
Else
Error = Twi_status ' Fehler
End If

Else
Error = Twi_status ' Fehler
End If

Twcr = &B10010100

Else
Twcr = &B10000100 ' TWINT löschen, Bus freigeben
Error = Twi_status ' Fehler
End If

End Function


Twi_wait_int:
Do
Twi_control = Twcr And &H80
Loop Until Twi_control = &H80
Twi_status = Twsr And &HF8
Return

'------------- SRF02 (hinten) --------------------------------------------------
Function Srf02_entfernung(byval Slaveid As Byte) As Integer
Local Lob As Byte
Local Hib As Byte
Local Slaveid_read As Byte

Slaveid_read = Slaveid + 1

I2cstart
I2cwbyte Slaveid
I2cwbyte 0
I2cwbyte 81 'in Zentimetern messen
I2cstop

I2cstart
I2cwbyte Slaveid
I2cwbyte 2 'Leseregister festlegen
I2cstop
I2cstart
I2cwbyte Slaveid_read
I2crbyte Hib , Ack
I2crbyte Lob , Nack
I2cstop
Srf02_entfernung = Makeint(lob , Hib)
End Function
End

'------------- Motorbefehle ----------------------------------------------------
Vorm:
Servo(1) = 150
Servo(2) = 150
Return

Linksm:
Servo(1) = 225
Servo(2) = 158
Return


Rechtsm:
Servo(1) = 158
Servo(2) = 225
Return

Stopm:
Servo(1) = 192
Servo(2) = 192
Return

Rueckm:
Servo(1) = 230
Servo(2) = 230
Return
Die ersten paar Sekunden läuft das auch so, wie es soll. Aber danach endet er in der Funktion Twi_read_byte, die ich aus der Wiki habe. Die Abfrage des SRF02 habe ich im Moment auskommentiert, da ich damit weitere Fehlerquelle vermeiden möchte, und weitere Geräte am I2C-bus gibt es nicht.

Kann mir jemand weiterhelfen, oder braucht ihr noch irgendwelche Infos?

Ich bin dankbar für jede Antwort, da ich das für den Robotiktreff in Braunschweig brauche!

jon

linux_80
03.10.2007, 15:44
Hallo,

auf jeden Fall passt wohl nicht zusammen, das Du Hardware-TWI und Software-I2C im gleichen Programm verwendest.
Da kommt am Port irgendwas durcheinander.

Probier mal als erstes die i2c-twi lib einzubinden, dann braucht man diese Config SCL nicht mehr, nur noch
Config TWI = 100000
und die anderen TWI-Register am Anfang auch nicht mehr selber setzen.


Dann noch eine Frage, das ist noch alles nur Master was da passiert, warum verwendet Du nicht nur die Bascom-Befehle ?

Jon
03.10.2007, 17:09
Probier mal als erstes die i2c-twi lib einzubinden, dann braucht man diese Config SCL nicht mehr, nur noch
Config TWI = 100000
und die anderen TWI-Register am Anfang auch nicht mehr selber setzen.
Habe ich jetzt mal gemacht... Bringt aber nichts.



Dann noch eine Frage, das ist noch alles nur Master was da passiert, warum verwendet Du nicht nur die Bascom-Befehle ?
Wenn ich wüsste, wie ich das mache, würde ich das machen. Ich habe die Master und Slave Elemente in der Wiki gefunden, und versuche nun mit denen zurecht zu kommen. Nur irgendwie will mir das nicht gelingen.

Ich weiß aber mittlerweile, dass es an diese do-Loop until Schleife scheitert:
Twi_wait_int:
Do
Twi_control = Twcr And &H80
Loop Until Twi_control = &H80
Twi_status = Twsr And &HF8
Return

Jemand ne Idee, was da nicht stimmen könnte?

jon

Jon
03.10.2007, 17:32
Hallo,
das Problem ist wohl nicht im Programm.
wenn ich die Sprungmarken in "select case Gegenstand_alle" durch Printbefehle ersetze, läuft es so, wie es soll.

Könnte es daran liegen, dass unter der Platine die Kabel zu den Motoren verlaufen und deren elektromagnetisches Feld den I2C-Bus stört??
Wie gesagt, wenn die Motoren aus sind, geht es klasse, auch mit dem SRF02.

jon

linux_80
03.10.2007, 17:51
Hallo,

die i2c-twi lib würde ich auf jeden Fall verwenden, denn damit wird das TWI verwendet, so wie ich das im Prinzip im Wiki manuell gamacht habe.
Man kann damit genauso die Bascom-I2C-Befehle verwenden wie in der Sub für den SRF02 auch, ist etwas übersichtlicher als alles per Hand zu bauen ;-)

Diese Do..Loop-Schleife wartet bis ein Byte über TWI raus- oder rein ging, und die wartet solange bis der Strom ausgeht ;-)
Wenn hier wirklich etwas stört kanns schon vorkommen, das der Slave die Daten nicht mitbekommt, und sich der Master zu Stromende wartet. In so einem Fall müsste eigentlich in der Do-Loop-Schleife eine weitere Abbruch-Bedingung rein, damit sich nix aufhängt.

Hast Du etwas zum messen, also ein Oszi, um die Signale auf den I2C-Leitungen zu kontrollieren ?

Du kannst auch mal den I2C langsamer machen, bei Config TWI zB. 20000 angeben.

PicNick
03.10.2007, 18:58
Loop Until Twi_control = &H80

auf "=" wird das wohl nie werden.
Du mußt das Bit abfragen
z.B.

Loop Until Twi_control.7 = 1

linux_80
03.10.2007, 19:08
Hi,

@PicNick,
das passt schon so, denn in der Schleife wird ja dieser gemacht:
Twi_control = Twcr And &H80

PicNick
03.10.2007, 19:16
:oops: :oops: :oops:

linux_80
03.10.2007, 19:19
Das ich das mal erleben darf =P~

Ich wollte es ausserdem nicht zu Bascom-spezifisch machen im Wiki, damits auch andere evtl. kapieren.