PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Problem beim Auslesen von ADC mit I2C



feldmueller
29.05.2006, 17:54
Hallo zusammen,

ich will einen I2C-12bit ADC ADS7828 auslesen und habe gerade ein Problem bei dem ich nicht weiterkomme. Da ich mich in Bascom mit dem Buch von Walter eingearbeitet habe, hab ich seine Unterprogramme fuer I2C uebernommen, aber die machen wahrscheinlich nicht viel anderes, als die Standard-Bascom I2C Befehle. Bisher jedenfalls konnte ich problemlos EEPROMs und auch den CMPS03 damit ansteuern.

Nun zum Problem:

Ich steuere den ADC wie im Datenblatt beschrieben an und bekomme auch richtige Statuscodes zurueck. Nur beim Auslesen des 12bit-ADC-Werts funktioniert was nicht.
Nach dem wiederholten Startbefehl, sende ich die Slaveadresse im Lesemodus und danach sollte ich High- und Lowbyte des AD-Wertes empfangen koennen. Nach dem Highbyte muesste ein ACK und nach dem Lowbyte, also dem letzten Byte ein NACK kommen. Nur leider bekomme ich schon nach dem ersten Byte (dem Highbyte) einen Statuscode H58, also Datenbyte empfangen NACK zurueck.

Was mach ich da falsch?

Ich hoffe, ich hab mein Problem einigermassen verstaendlich beschrieben und hoffe, dass mir jemand auf die Spruenge helfen kann.

Danke im voraus!

Viele Gruesse,
Stefan



'************************************************* *************
'ads7828_test.bas : Testprogramm fuer den I2C-ADC ADS7828
'************************************************* *************

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

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()

Dim I As Byte 'temporaere Variable fuer Statuscodes
Dim Highdatabyte As Byte
Dim Lowdatabyte As Byte
Dim Result As Word

Twsr = &B00000000 'Bits1+0=00: TWI-Vorteilung 1
Twbr = 0 'Twi-Prescale

Do
'Ch0 auslesen:

If Twistart() <> &H08 Then Goto Raus 'START-Signal generieren
If Twisend(&B10010000) <> &H18 Then Goto Raus 'Slave-Adresse im Sendemodus senden
If Twisend(&B10001100) <> &H28 Then Goto Raus 'Commandbyte senden, Byte7=1 SinglEndInp
'Byte6+5+4=Ch0,Byte3+2=RefOn+ADCon

If Twistart() <> &H10 Then Goto Raus 'erneutes START-Signal
If Twisend(&B10010001) <> &H40 Then Goto Raus 'SlvAdr(R) senden

I = Twireceive(highdatabyte)
Printbin I;
If I <> &H50 Then Goto Raus 'Highbyte empfangen ->ACK

I = Twireceive(lowdatabyte)
Printbin I;
If I <> &H58 Then Goto Raus 'Lowbyte empfangen ->NO ACK

Raus:
Twistop

'Print "*";
'Print Highdatabyte;
'Print "+";
'Print Lowdatabyte;
Shift Highdatabyte , Left , 4
Result = Highdatabyte + Lowdatabyte
'Print Result
Waitms 500
Loop


'================================================= ===============================
=========
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
'-------------------------------------------------------------------------------

feldmueller
16.06.2006, 17:08
Also irgendwie ist da Ganze sehr komisch... Ich habs jetzt mal mit den "herkoemmlichen" Bascom-I2C-Befehlen versucht und da funktionierts! Also nach folgendem Strickmuster:

i2cstart
i2cwbyte adres_write
i2cwbyte command_byte
i2cstart
i2cwbyte adres_read
i2crbyte highbyte, ack
i2crbyte lowbyte, nack
i2cstop

so gehts. Ich wuerd aber zu gerne wissen, warum ich das mit den anderen Subroutinen nicht auch hinbekomme. Ich mach doch im Endeffekt dasselbe!

Hat da denn keiner ne Idee???

Wie gesagt, mit den Subroutinen kann ich prima EEPROMs beschreiben und lesen, nur bei diesem ADC komm ich nicht weiter!

Ciao,
Stefan

linux_80
16.06.2006, 20:12
Hallo,

ich sehe nur das TWBR auf 0 gesetzt wird, der Prescaler ist auch auf 1 also läuft der Bus mit maximaler Geschwindigkeit.
Wenn ich richtig gerechnet habe ca. 230kHz.
Da im Atmel-Datenblatt steht, das es bei einem Wert in TWBR kleiner 10 zu Problemen mit der Startsequenz kommen kann, solltest Du mal probieren hier den richtigen berechneten Wert bei TWBR einzusetzen, bzw. nicht kleiner als 10.

Edit:
mit 10 hat der Bus knapp über 100kHz, also eigentlich immer noch ein wenig zu schnell, aber besser als vorher.
siehe -> TWI