Forum: Mikrocontroller und Digitale Elektronik TWI mit USI nach AN-310


von Klaus R. (klaus2)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich möchte mit einem tiny44 einen PT2257 Digitalpoti steuern.

SDA, SCL laufen, die USI routine kommt bis zu dem Punkt, wo der Slave 
die Adresse ACKen soll - macht er aber nicht (laut Rückmeldung der 
Routine fehlt das ACK), weil auf dem Oszi ersichtlich nicht die im 
define angegebene 0x88 übertragen wird - habe ich bei der lib nach 
AVR-310 etwas verpasst?

Klaus.

von Klaus R. (klaus2)


Lesenswert?

...wie man erkennt, ist bei den daten zml zu beginn ein kurzer peak - 
DAS scheint bereits die erste 1 zu sein von 0b10001000 - aber ist das 
korrekt? Müsste die routine nicht warten, bis clk = 0 ist und wieder auf 
1 geht (also rising edge)? denn es kommen ja noch 8x clk HIGH für daten 
+ 1x clk HIGH für ACK...? Leigt das an der recht geringen clk von 10kHz?

Klaus.

von hofa (Gast)


Lesenswert?

Klaus R. schrieb:
>Müsste die routine nicht warten, bis clk = 0 ist und wieder auf
>1 geht (also rising edge)?

Normalerweise schon.
Zuerst die Startbedingung (die sieht noch OK aus)
"The SCL is set to HIGH and SDA shifts from HIGH to LOW state."
dann SCL->L, SDA->MSB(Adresse), SCL->H...

> Leigt das an der recht geringen clk von 10kHz?
lt. DB gibt es keine untere Grenze für fclk. Eventuell übersehen, den 
Standard-Modus im Programm zu aktivieren "The default setting is fast 
mode"?

Und warum hat SCL nur 2V, während SDA 4V hat. Das liegt zwar noch knapp 
innerhalt der Spezifikation von Vih=1,6V (Vdd=4V), aber ich würde 
dennoch die Pullup-Widerstände prüfen - besonders, wenn die Vdd höher 
sein sollte.

http://www.princeton.com.tw/Portals/0/Product/PT2257.pdf

von hofa (Gast)


Lesenswert?

hofa schrieb:
> Und warum hat SCL nur 2V, während SDA 4V hat.
Und warum hat SDA nur 2V, während SCL 4V hat?

Und warum seh ich das erst nach dem Absenden?

von Klaus2 (Gast)


Lesenswert?

@hofa: Weil die Bezugspotentiale vertikal verschoben sind auf dem Oszi? 
:)

FastMode habe ich abgeschaltet, klar...SCL läuft mit 11kHz derzeit. Ich 
frage mich aber, wie es passieren kann, dass SDA schon kurz nach dem 
Startup auf high geht, "der" müsste doch bis zur ersten clock warten mit 
der Übertragung...hmmm.

Klaus.

von spess53 (Gast)


Lesenswert?

Hi

>Ich frage mich aber, wie es passieren kann, dass SDA schon kurz nach dem
>Startup auf high geht, "der" müsste doch bis zur ersten clock warten mit
>der Übertragung...hmmm.

High ist der Ruhepegel von SDA/SCL.

MfG Spess

von Max D. (max_d)


Lesenswert?

Teil doch mal deinen Code mit uns. Da wird man dann schon sehen wo es 
hakt

von Klaus2 (Gast)


Lesenswert?

Hallo Max D.,

poste ich heute Abend gerne, habe ich aber direkt bei Atmel 
runtergeladen.

Irgendwie reagiert die USI_Master.c nicht so, wie sie soll.

@spess: Das ist mir schon klar, aber mit "high" versucht die funktion ja 
die erste 1 der Adresse 0x88 (10001000) des Potis zu übertragen - und 
das dürfte sie mMn erst beim darauf folgenden clockzyklus tun.

Klaus.

von spess53 (Gast)


Lesenswert?

Hi

>@spess: Das ist mir schon klar, aber mit "high" versucht die funktion ja
>die erste 1 der Adresse 0x88 (10001000) des Potis zu übertragen - und
>das dürfte sie mMn erst beim darauf folgenden clockzyklus tun.

Die Übertragung beginnt mit der Startcondition -> fallende Flanke von 
SDA bei High an SCL.

MfG Spess

von Klaus2 (Gast)


Lesenswert?

Hallo spess,

aber der Nadelimpuls, der ja scheinbar die erste 1 der Adresse sein 
soll, ist der nicht auch deiner meinung nach an der falschen Position? 
Ich würde erwarten, dass SDA low bliebt bis SCL auf high geht und DANN 
das MSB übertragen wird, also um einen clk zyklus nach rechts verschoben 
- und vor allem nicht nur als kurzer impuls.

der 9 clk zyklus, in dem der slave die adresse ACKen soll (SDA low 
ziehen), sieht man in dem bild nicht - der kommt aber auch noch.

Klaus.

von Marvin (Gast)


Lesenswert?

Der Nadelpuls ist ein Ack vom Slave...

Das Bild ist nicht vollständig....

Wahrscheinlich bestätigt der Slave hier schon die Adresse.

Gruß Marv

von Klaus2 (Gast)


Angehängte Dateien:

Lesenswert?

...hier nochmal zur Verdeutlichung mit Bild.

von Klaus2 (Gast)


Lesenswert?

Hallo Marvin,

die Adresse kommt danach - davor ist Ruhe und wenn ich diese auf 
10101010 setze, sehe ich das Muster genau hier in dem screenshot. Das 
ACK muss (müsste?) mit dem 9 clk kommen, der ist aber rechts außen - 
und, der ACK kommt natürlich nicht, da die Adresse ja so nicht stimmt.

Es geht mir primär darum, ob ich das richtig verstehe - ich werde das 
originale bsp mal so laufen lassen, wie ich es von avr runtergalden habe 
- nur um zu sehen, ob es sich dann auch so verhält...wobei es 
"eigentlich" auch nicht für einen tiny44 geschrieben wurde, ich musste 
es anpassen.

Klaus.

von spess53 (Gast)


Lesenswert?

Hi

>aber der Nadelimpuls, der ja scheinbar die erste 1 der Adresse sein
>soll, ist der nicht auch deiner meinung nach an der falschen Position?

Das passt aber nicht zu dem H ( beim Senden von 0b10001000) in der 
Mitte. Das liegt im 4.Bit. Außerdem ist der Spike für mich kein Bit. SDA 
darf sich in der Low-Phase von SCL ändern. Wo der Spike genau liegt kann 
ich an Hand des Bildes nicht entscheiden.

Hast du dir mal 'Atmel AVR310: Using the USI Module as a I2C Master

http://www.atmel.com/Images/Atmel-2561-Using-the-USI-Module-as-a-I2C-Master_AP-Note_AVR310.pdf

http://www.atmel.com/images/Atmel-2561-Using-the-USI-Module-as-a-I2C-Master_AP-Note_AVR310.zip

angesehen?

MfG Spess

von hofa (Gast)


Lesenswert?

Klaus2 schrieb:
> @hofa: Weil die Bezugspotentiale vertikal verschoben sind auf dem Oszi?

Und ich dachte, das blaue "2->" am linken Rand markiert die Nulllinie, 
während "CH2 2.00V" die Volt/Div angibt.

von Klaus2 (Gast)


Lesenswert?

@hofa: Hoppala. In der Tat, mea culpa...das muss ich mir mal ansehen.

@spess: Durchgelesen, nein. Angeschaut, ja. Der Code, den ich benutze, 
basiert ja direkt auf dieser AN. Mein "verständnis" für die 
Adressierung, datenübertragung etc habe ich nur aus dem PT2257 DB, da 
dort ja auch die anderen, wichtigen daten drinstehen. Deine Aussage ist 
genau, was ich meine - der Spike dürfte DA nicht sein, er muss als 
sauberer Impuls erst mit dem nächsten scl zyklus beginnen - dann rutscht 
auch der nachfolgende (saubere) sda puls auf bit 5 und alles passt -> 
10001000

Ich vermute, dass das triggern "jetzt sende das erste datenbit der 
adresse" in der routine zur AN-310 irgendwie nicht ganz sauber läuft und 
halt während der noch aktiven start-condition startet, also nicht 
wartet, bis der erste "echte" clk impuls zur datenübertragung 
kommt...ich poste die stelle nacher mal.

Als nächstes muss ich den code mal auf einem attiny85 mit einem i2c 
eeprom laufen lassen, damit ich vergleichen kann, ob es da genau so ist 
(dafür wurde sie urspr geschrieben).

Klaus.

von Klaus R. (klaus2)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

1) mit 4V läuft das Teil nicht sauber, damit wird SDA nicht richtig 
freigegeben und vom PT2257 immer halbseiden auf Masse gezogen, hmpf. Spg 
auf 4,5V erhöht, nun ist auch der blaue SDA Signalverlauf 0/4.5V

2) Code:
1
#if defined (__AVR_ATtiny44__)                        // ATtiny44
2
3
    OCR1A    =  (F_CPU / F_INTERRUPTS) - 1;                                // compare value: 1/15000 of CPU frequency
4
    TCCR1A   = (0 << WGM11) | (0 << WGM10);                  // switch CTC Mode on
5
  TCCR1B   = (1 << WGM12) | (0 << CS12) | (0 << CS11) | (1 << CS10);      // switch CTC Mode on, set prescaler to 1
6
7
8
#if defined (__AVR_ATmega8__)
9
                                                                           // ATmegaXX:
10
    OCR1A   =  (F_CPU / F_INTERRUPTS) - 1;                                  // compare value: 1/15000 of CPU frequency
11
    TCCR1B  = (1 << WGM12) | (1 << CS10);                                   // switch CTC Mode on, set prescaler to 1
12
#endif
13
14
#else
15
#  ERROR No valid device configured!
16
#endif
17
18
#ifdef TIMSK1
19
    TIMSK1  = 1 << OCIE1A;                                                  // OCIE1A: Interrupt by timer compare
20
#else
21
    TIMSK   = 1 << OCIE1A;                                                  // OCIE1A: Interrupt by timer compare
22
#endif
23
}
24
25
#ifdef TIM1_COMPA_vect                                                      // ATtiny84
26
#define COMPA_VECT  TIM1_COMPA_vect
27
#else
28
#define COMPA_VECT  TIMER1_COMPA_vect                                       // ATmega
29
#endif
30
31
...
32
33
void I2C_send (unsigned int data_01, unsigned int data_02) {
34
35
  unsigned int temp=TRUE, error=0;
36
37
  messageBuf[0] = (I2C_SLAVE_ADDR<<TWI_ADR_BITS) | (FALSE<<TWI_READ_BIT); // Adresse
38
    messageBuf[1] = data_01;                               // Daten_01
39
    messageBuf[2] = data_02;                                    // Daten_02
40
    
41
  temp = USI_TWI_Start_Transceiver_With_Data(messageBuf, 3);        // Senderoutine mit "messageBuf" aufrufen
42
  error = USI_TWI_Get_State_Info();
43
44
  if(temp == TRUE) PORTA ^= 1<<FREQ_UP;
45
  if(error) eeprom_write_word(&ee_errorcode, error);
46
47
  }
48
49
...
50
51
I2C_send (VOL_01, VOL_02); // Aufruf im main
52
53
...

Das sind die wichtigen Inhlate der Main, .c und .h der USI siehe Anhang, 
wie gesagt direkt aus der von Atmel runtergeladenen lib.

Problematisch scheint für mich diese Stelle (Ln 147 der .c) zu sein, wo 
nach erfolgreicher Start-Condition das erste Datenbit gesendet wird - 
ich glaube nicht, dass der Code an sich falsch ist, aber mir ist nicht 
klar, wie es zu dem bei mir ersichtlichen Fehler kommen kann...Signal 
Verify ist aktiv und wirft keinen Fehler, dann aber 
"USI_TWI_NO_ACK_ON_ADDRESS;" - zu Recht, was man ja am Oszi-Bild 
sieht...
1
#ifdef SIGNAL_VERIFY
2
  if( !(USISR & (1<<USISIF)) )
3
  {
4
    USI_TWI_state.errorState = USI_TWI_MISSING_START_CON;  
5
    return (FALSE);
6
  }
7
#endif
8
9
/*Write address and Read/Write data */
10
  do
11
  {
12
    /* If masterWrite cycle (or inital address tranmission)*/
13
    if (USI_TWI_state.addressMode || USI_TWI_state.masterWriteDataMode)
14
    {
15
      /* Write a byte */
16
      PORT_USI &= ~(1<<PIN_USI_SCL);                // Pull SCL LOW.
17
      USIDR     = *(msg++);                        // Setup data.
18
      USI_TWI_Master_Transfer( tempUSISR_8bit );    // Send 8 bits on bus.
19
      
20
      /* Clock and verify (N)ACK from slave */
21
      DDR_USI  &= ~(1<<PIN_USI_SDA);                // Enable SDA as input.
22
      if( USI_TWI_Master_Transfer( tempUSISR_1bit ) & (1<<TWI_NACK_BIT) ) 
23
      {
24
        if ( USI_TWI_state.addressMode )
25
          USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_ADDRESS;
26
        else
27
          USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_DATA;
28
        return (FALSE);
29
      }
30
      USI_TWI_state.addressMode = FALSE;            // Only perform address transmission once.
31
    }
32
    /* Else masterRead cycle*/
33
    else
34
    {
35
      /* Read a data byte */
36
      DDR_USI   &= ~(1<<PIN_USI_SDA);               // Enable SDA as input.
37
      *(msg++)  = USI_TWI_Master_Transfer( tempUSISR_8bit );
38
39
      /* Prepare to generate ACK (or NACK in case of End Of Transmission) */
40
      if( msgSize == 1)                            // If transmission of last byte was performed.
41
      {
42
        USIDR = 0xFF;                              // Load NACK to confirm End Of Transmission.
43
      }
44
      else
45
      {
46
        USIDR = 0x00;                              // Load ACK. Set data register bit 7 (output for SDA) low.
47
      }
48
      USI_TWI_Master_Transfer( tempUSISR_1bit );   // Generate ACK/NACK.
49
    }
50
  }while( --msgSize) ;                             // Until all data sent/received.

: Bearbeitet durch User
von Klaus R. (klaus2)


Angehängte Dateien:

Lesenswert?

...und im Anhang mal ein erklärendes Bild,wie zB 0xC0 übertragen werden 
sollte - genau so erwarte ich das mit 0x88 auch, kommt es aber nicht.

Das ist das letzte Puzzleteil in meiner Steuerung eines HK330C, damit 
ihr wisst, worums geht - alles für den WAF eines Vintage Receivers.

Klaus.

von Klaus R. (klaus2)


Lesenswert?

...ja f*ck die Henne. Wenn ich die Adresse um 1 shifte, dann gehts, also 
statt 0x88 = 0b10001000 schreibe ich 0b01000100, dann läuft es, wie es 
aussieht - muss nun testen, ob das Poti was tut - zumindest überträgt er 
jetzt 3 Byte und bricht NICHT ab...kann mir das bitte mal einer 
erklären?

EDIT: Das Poti loooft, ich werd verrückt...das kommt davon, wenn man 
beschissen dokumentierten Code aus LCCs weiterverwendet - genau wie auf 
der Maloche.

Klaus.

: Bearbeitet durch User
von spess53 (Gast)


Lesenswert?

Hi

>...ja f*ck die Henne. Wenn ich die Adresse um 1 shifte, dann gehts, also
>statt 0x88 = 0b10001000 schreibe ich 0b01000100, dann läuft es, wie es
>aussieht

Deine main.c erwartet einfach die 7-Bit-Adresse ohne das RW-Bit (Bit0) 
und shiftet die selbstständig nach Bit7..Bit1:

messageBuf[0] = (I2C_SLAVE_ADDR<<TWI_ADR_BITS) | (FALSE<<TWI_READ_BIT);
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

MfG Spess

von Tom (Gast)


Lesenswert?

Klaus R. schrieb:
> ...ja f*ck die Henne. Wenn ich die Adresse um 1 shifte, dann gehts, also
> statt 0x88 = 0b10001000 schreibe ich 0b01000100

Kein Wunder. 0x88 kann es nicht als I2C Adresse geben, weil die nur 
sieben Bit lang ist und damit dein oberstes Bit hinten runter fliegt.

von Klaus R. (klaus2)


Lesenswert?

...ist mir jetzt auch klar geworden, aber das hätte Ranjid da vll auch 
kurz per Randnotiz anmerken können, finde ich. Denn, de facto ist das ja 
NICHT die "normale" Adresse des Slaves. Das ist immerhin offizieller 
Code zu einer AN, nicht vom Software-AG-Server der 9b geklaut.

Klaus.

von Klaus R. (klaus2)


Lesenswert?

...Tom, dann guck mal ins DB des PT2257, das steht klipp & klar 0x88.

Aber ich habe dazu gelernt und deshalb macht man ja :)

Klaus.

von spess53 (Gast)


Lesenswert?

Hi

>Kein Wunder. 0x88 kann es nicht als I2C Adresse geben, weil die nur
>sieben Bit lang ist und damit dein oberstes Bit hinten runter fliegt.

Das ist eine Frage der Implementierung. Aber darüber wurden hier schon 
Glaubeskriege geführt. Mit deiner Ansicht könnte das wieder losgehen.

MfG Spess

von Klaus R. (klaus2)


Lesenswert?

Hehe :) Nein, ein Glaubenskrieg auf der Welt reicht, Danke.

Ich bin durch mit dem Thema und wie immer hat einmal drüber Schlafen zum 
Erfolg geführt.

Danke an Alle & GN8.

von spess53 (Gast)


Lesenswert?

Hi

>Ich bin durch mit dem Thema und wie immer hat einmal drüber Schlafen zum
>Erfolg geführt.

Hättest dir auch einfach mal deinen Quelltext ansehen können. Das 
steht doch eindeutig

messageBuf[0] = (I2C_SLAVE_ADDR<<TWI_ADR_BITS) | (FALSE<<TWI_READ_BIT);

und in der USI_TWI_Master.h

#define TWI_ADR_BITS  1 // Bit position for LSB of the slave address 
bits
                           in the init byte.

Also wird das Adressbyte um 1 Bit nach links geshiftet. Bei 0x100100 
geht dann halt ein Bit verloren.

MfG Spess

von Klaus R. (klaus2)


Lesenswert?

Hi spess,

ich hätte es plausibilisieren können, ja - es ist aber nicht mein 
Quellcode, ich habe eine lib benutzt. Und in dieser wird ganz am Anfang 
ein define gesetzt, hinter dem steht "// Slave Adress" - im PT2257 steht 
"Adress 0x88" - ergo...da stand nirgends, dass man nur die oberen 7 Bits 
eintragen darf.

Würde ich die libs auf der Arbeit aus dem repository auschecken und dann 
erst komplett "reviewen" müssen, würden wir ja nie fertig. Saubere Doku 
ist das A&O und ICH hätte den "7 Bit Hinweis" dort hinterlassen ODER das 
shifting dann in der nächsten Zeile automatisiert.

Klaus.

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.