Forum: Mikrocontroller und Digitale Elektronik Berechnung von TWBR


von Harry (Gast)


Lesenswert?

Gesundes 2005 euch allen!


Als erstes möchte ich mich entschuldigen, dass ich trotz der
zahlreichen Postings zu diesem Thema hier so blöd fragen muss.

Ich mochte mit einem MEGA32 einen PCF8574 (8-Bit IO-Expander)
ansteuern.
Der Bustakt ist 100kHz. Meine CPU wird mit 16MHz getaktet.

Nach der wundervollen Formel (SCL = CPU/(16+2TWBR*4^TWPS)) sollte mein
TWBR 72 betragen (bei TWPS = 0x00  also Prescaler von 1)

doch das funzt net.

Jetzt das skuriele:

Rechlich Tests haben einen funktionstüchtigen Wert von 0 bis
15 für TWBR ergeben!!!
Häää??? Bustakt von bis zu 1MHz???

Es spielt auch keine Rolle ob ich vom Quarz, vom STK500 oder vom
internen RC Takten lasse. Es funktionieren immer Werte die weit von den
Berechneten abweichen.

Nun bitte ich euch meine Berechnung zu überprüfen.
Danke!

von Thorsten (Gast)


Lesenswert?

CPU=16000000
TWPS=1
SCL=100000

Richtig so?

Dann komme ich auf TWBR=18

von Harry (Gast)


Lesenswert?

CPU = 16000000
TWPS = 0
SCL = 1000000

ergibt TWBR von 72


Deine Berechnung mit TWPS=1 (also Prescaler 4) kann ich bestätigen. Hab
ich getestet, ohne Erfolg.
(Es funzen aber TWBRs von 0 bis 3 bei TWPS = 1)

von Thorsten (Gast)


Lesenswert?

"TWPS = Value of the prescaler bits in the TWI Status Register"

Also kommen 1, 4, 16 und 64 laut Datenblatt in Frage. Oder sehe ich das
falsch?

von Harry (Gast)


Lesenswert?

Legende der Formel  auf Seite 173:
"TWPS = Value of the prescaler !!!BITS!!! in the TWI Status
Register"
also 0 bis 3  (sind ja auch nur 2 Bit)

Kommentat zur Tabelle auf Seite 177:
"The value of TWPS1..0 is used in the equation"

Soll heisen:
Wenn in der Formel  ...4^3   steht, ergibt sich ein Prescaler von 64

von Thorsten (Gast)


Lesenswert?

:) Ja ok, 4^64 wäre auch geringfügig zu viel :)

von Harry (Gast)


Lesenswert?

die Berechnung zu stimmen scheint, hier mal ne kurze Zusammenfassung
meines Progs:

Reset:
   interne Pullups an
   72 nach TWBR
   0 nach TWPS

Main:
   Error-Led aus
   Adresse setzen
   zu sendende Byte setzen
   rcall SENDEN
rjmp Main

SENDEN:
   siehe Datenblatt Seite 180 (fast eins-zu-eins abgetipt)

Error:
   STOP
   Error-LED an


ergibt eine flackernde Error-Led.
Ne Idee?

von Harry (Gast)


Angehängte Dateien:

Lesenswert?

So, hier mal noch eine leicht vereinfachte Version meines Quelltextes,
mit TWBR=0 und TWPS=0,die mehr oder weniger stabil lauft.
Mit den berechnete Werten läufts net!

Hab grad mal nen Mega16 probiert: Verhält sich ähnlich.

Warum funzts bei allen andern, nur bei mir net? heul

Bitte helft mir!

von Thorsten (Gast)


Lesenswert?

Hallo,

in I2CInit:

ldi r16,0      ;nach Formel: 72 bei TWSR = 0 oder 18 bei...
out TWBR,r16

Du schreibst hier aber doch 0 in TWBR.

von dave (Gast)


Lesenswert?

Ich hab vorgestern auch das erste mal meinen TWI angeschmissen
bekommen.. hab mir die Routinen aussem Datablatt abgeschaut:

twi_transmission:
  out TWDR, temp1
  ldi temp1, (1<<TWINT)|(1<<TWEN)
  out TWCR, temp1

  rjmp twi_wait


twi_read:
  ldi temp1, (1<<TWINT)|(1<<TWEN)
  out twcr, temp1

  rjmp twi_wait


twi_start:
  ldi temp1, (1<<TWINT)|(1<<TWSTA)|(1<<TWEN)
  out TWCR, temp1

  rjmp twi_wait


twi_stop:
  ldi temp1, (1<<TWINT)|(1<<TWSTO)|(1<<TWEN)
  out TWCR, temp1
  ret


twi_wait:
  push temp2
  ldi temp2, 0xFF
twi_wait_2:
  dec temp2
  breq twi_wait_3
  in temp1, TWCR
  sbrs temp1, TWINT
  rjmp twi_wait_2

  in temp1, TWDR
  pop temp2
  ret
twi_wait_3:
  ldi temp1, 99
  pop temp2
  ret

Bei twi_wait kann man natürlich das mit temp2 rauslassen, ist aber
deswegen, damit sich das Ding nicht aufhängt, wenn mal nen Sensor
spinnt.. bei mir wird dann halt "99°C" angezeigt und das is dann OK.
Geschmackssache.

Aber Thorsten wird auch Recht haben ...

Meine Init (@8Mhz):
; twi
  ldi temp1, 32
  out twbr, temp1

Die Formel ist:
 CLK  = Takt/(16+(2xTWBRx 4^TWPS))
Wenn TWPS = 0, dann ergibts sich für 4^TWPS = 1.. also
vernachlässigbar. Außerdem sollte man mit TWBR nicht niedriger als 10
gehen..

dave

von Thany (Gast)


Lesenswert?

Wie ich das sehe, du willst, statt mehere Byte an eine Device, ein Byte
an mehrere Device senden ?

        ldi Adr,0xXX
  rcall Senden

wenn einer dovon nicht vorhanden ist, gibt's  kein MT_SLA_ACK zurück
!

Gruß

Thany

von Harry (Gast)


Lesenswert?

Ich kann dem Thorsten nur zustimmen!
Und auch deine Rechnung (Thany) ist meines Erachtens richtig.
Nur funktioniert das nicht!
Erst ein Wert zw 0 und 15 führt zu einer Datenübertragung (mehr oder
weniger stabil). Und um einen einigermasen funktionstüchtigen Quellcode
zu posten, hab ich die 0 ins TWBR geschrieben und als Kommentar die
berechneten Werte.

Die Frage ist halt, wo der Fehler liegt.

(Hätte ich ein Oszi, würd ich einfach messen, hab ich aber nich)

Ich habs übrigens auch schon in anderen Foren probiert, aber da bekam
ich weder so schnell noch so sachliche  Antworten. Großes Lob an
euch!!!

Ich bin optimistisch dass wir das Problem in kürze lösen. Bitte weiter
so! Danke!

von Harry (Gast)


Lesenswert?

Die Rechnung stammt natürlich vom "Dave im Grab" nicht von Thany.
Sorry.

Thany hat aber auch recht, dass ich einen Wert an viele PCF8574s sende.

von dave (Gast)


Lesenswert?

Also verwechsle bei meiner Rechnung:

 CLK  = Takt/(16+(2xTWBRx 4^TWPS))
Wenn TWPS = 0, dann ergibts sich für 4^TWPS = 1.. also
vernachlässigbar.

nicht PS mit BR...

Kannst ja mal umstellen:
CLK = TWclk
 CLK = Takt/(16+(2xTWBR))
 CLK * (16+(2xTWBR)) = Takt
 (16+(2xTWBR)) = Takt/CLK
 2xTWBR = (Takt/CLK) - 16
 TWBR = (Takt/Clk -16)/2

bei 8Mhz und 100khz : (80/1 - 16)/2 = 32
und 16Mhz und 100khz: (160/1 - 16)/2 = 72
Also stimmt doch alles.. So, was funktioniert jetzt nicht?

Der Dave aussem Grab

von Harry (Gast)


Lesenswert?

Es fließen keine Daten wenn ich die (bewiesenermaßen) korekten Werte
einprogramiere (TWBR=72 & TWPS=0).
Erst wenn ich wesentlich kleiner Werte nehme "läuft" es .
Was ich aber nicht verstehe! Denn eine kleineres TWBR ist eine größeres
fSCL. Und ich glaube einfach nicht daran, dass ein Busstakt von 1MHz
(TWBR=0 & TWBS=0) so gut funktionieren kann!

@Dave: Du hast offensichtlich ein anderes Datenblatt als ich. Was ist
das?

von dave (Gast)


Lesenswert?

LOL.. ich arbeite auch die ganze Zeit nur mit dem M32 (von Atmel g)

Was meinst du mit "Was ist das?"

Ich kapier genau so wenig, warum er das bei dir nicht macht.. bei 8Mhz
und Wert 32 klappts bei mir gut.

Gib mal deinen Quelltext rüber.

dave

von Harry (Gast)


Lesenswert?

Quelltext findest du oben: "TWI2.asm"

Was ist das? ...für ein Datenblatt von dem du sprichst?

Mir liegt das vom Mega32 Rev. G vor!

von dave (Gast)


Lesenswert?

Achso.. ja das ganz normale M32, welches ich runtergeladen habe..
Wow.. ich hab A...

Also bei mir sind die Routinen unter USING TWI

Und das is drin:

SCL frequency= CPU Clock frequency
                 16+2(TWBR)*4^TWPS

Ich lade mir jetzt mal schnell das G... aber was da anders sein soll..

dave

von Harry (Gast)


Lesenswert?

Neue Erkenntnisse:

Hab mal den Code von Dave nachvollzogen. Der 1. Unterschied ist die
Warteschleife. Und der 2. Unterschied ist die völlige Ignoranz des
Status-Registers.

Ich hab also seinen Code meinem Code angepasst und siehe da: ES GEHT!
Aber VIIIIEEEEL langsamer als meine Version. enttaüsch

Ich hab dann alle Hebel in bewegung gesetzt und mir doch noch ein Oszi
besorgt und die SCL gemessen.

Nur Interessehalber die Ergebnisse mit MEINEM Proggi:


TWBR      SCL rech        SCL mess      Beschreibung

72         100000          100000       Nichts geht
12         400000          400000       alles Geht, kurz darauf FREEZ
10         444444          434782       2 von 8 PCFs gehen nicht
0         1000000          666666       alles geht (schnell)


Zurück zur Sachlichkeit:

Bei meinen Messungen hab ich gesehen, dass ein 5V Impuls doppelt so
lang ist wie alle anderen. (Der wievielte Impuls das ist hab ich
vergessen zu zählen). Bei Daves Prog trat das nicht auf.


Ich wäre euch sehr verbunden wenn ihr trotz der recht guten Ergebnisse
weiter meinen Code durchdenkt und mir meinen Fehler zeigen könntet. Mit
Daves Code ist das Arbeiten (in meinem Fall) viel komplizierter, was ich
vermeiden möchte. Danke trotzdem!

von dave (Gast)


Lesenswert?

Also ich hab auch keinen Plan... die PCF machen ja nach Datasheet nur
100khz mit.
Etwas ist da noch komisch:
 Quarz/Clock -16 = TWBR

 16.000.000/666.666 = 24
 24 - 16 = 8

Das hieße ja, dass TWBR in Realität 8 ist.. komisch komisch, vielleicht
ziehen die PCFs auch einfach den Clock runter.

Mein wait kannste auch einfach so ersetzten:
wait:
in r16,TWCR
sbrs r16,TWINT
rjmp wait

ret

Ich hab mir nur nicht die Mühe gemacht, meine Spezifizierung wieder
rückgänig zu machen.. Setz das nochmal ein, dann bleibt der delay mit
den 256 Takten weg.

Hat niemand anders ne Ahnung?

dave

von dave (Gast)


Lesenswert?

Ich hab das 2xTWBR unterschlagen.. dann dürfte 4 rauskommen...

Es is halt scho spät..

dave

von Harry (Gast)


Lesenswert?

Ich nehm auch an, dass die PCFs den Takt runterziehen. Die sind
eigentlich nur für 100kHz. So richtig rechteckig sah der Takt auch
nicht aus (bei 666 kHz) und unter dem Aspekt, dass schon im Datenblatt
des Mega32 ein TWBR von >10 gefordert wird, glaube ich dass es reiner
Zufall ist, dass das funktioniert.
Ich wünsche mir einen ganz normalen I2C-Bus mit 100kHz (auch wenn er
viieel langsamer ist)

Deine wait-Schleife hatte ich von Anfang an so geändert (Hey, ich bin
garnich so blöd wie ich aussehe. Aber ich seh verdammt blöd aus).

von dave (Gast)


Lesenswert?

Stimmt ;) Unser Dirty-Harry sieht beschissen aus.. wie son Hund...

Und du bist dir sicher, dass bei 100khz nichts anderes reingespielt
hat? Vielleicht mal PS etwas höher setzten und dann in TWBR 18 reinhaun
oder ähnlich.

Also mein PCF (nur kurz zum Test-Zweck) hat schön bei 100khz
mitgespielt.

Isch nisch blicke

dave

von Harry (Gast)


Lesenswert?

Juhu! ich habs!

Also hier mal ne Fehlerbeschreibung.

Mein Prog löst eine START aus.
Dann wird gewartet bis die Hardware den START vollzogen hat.
Dann wird im Statusregister geguckt, ob der START gelungen ist(TWSR =
0x08). Ist dies nicht der Fall, wird die Error-Funftion aufgerufen.
Bei gelungenem START wird dann die Adresse und das Byte gesendet und
die ganze Sache mit nem STOP abgeschlossen. Es wird aber diesmal nicht
gewartet bis die Hardware mit dem STOP fertig ist!(Wozu auch?)
Da in meinen Prog hinternanderweg gesendet wird (rcall Senden ... rcall
Senden ...), wird die neue START-Kondition ausgelöst bevor überhaut ein
handfestes STOP am Bus anliegt. Dies kommt dann einem REPEATED-START
gleich und im Statusregister steht keine 0x08 sondern 0x10 (RESTART
gelungen), was natürlich zu unrecht die Error-Funktion aufruft. Ein
Aktzeptanz von TWSR=0x08 UND TWSR=0x10 nach dem START löst also mein
Problem.

Ich bedanke mich bei allen beteiligten!!!
Ohne euch würde ich immernoch an meinem TWBR zweifeln und hätte
bestimmt schon längst aufgegeben. Ihr seid die Größten!

Also Danke nochmal

     ªpppµpµppppppppppµppª
   ªªª¿¿ðUsUx2222UZÆÆg@L¿ªªª
 ªp÷Ô2¾ ¾2/2/222222ZZ2@ ¾2Ô÷pª
 ¾2  ¿  ¾2/2/222222ZZ2@  ¿  2¾
  ¿Ô¯   ¾2/2/222222ZZ2@   ¯Ô¿
    ¿Ô¯ ¾2/2/222222ZZ2@ ¯Ô¿
      ¿Ô¾2/2/222222ZZ2@Ô¿
    ª¿ ¾ ¾2Yx22222ZZ2@ ¾ ¿ª
    ¿ªª¿  ¿Ô2Yx2SZUÔL  ¿ªª¿
            ¿Ô22ZÔL
             ¾22Z@
             ¾22Z@
             ¾22Z@
         ªªpp222SSggªª
     ª¾¾¾ÔÔÔÔÔÔÔÔÔððð𶶶ª

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.