Forum: Mikrocontroller und Digitale Elektronik S: Doku für SI5351 I2c LowLevel


von Pille (Gast)


Lesenswert?

Ich suche ein Datenblatt das abhandelt wie man ein Register des SI5351 
über I2C liest..also so wie das auch bei den 24Cxx EEPROMs dokumentiert 
ist.

Ich benutze kein HAL und ärgere mich mit der I2C Engine eines STM32F103 
herum..

Danke im Voraus..

Pille

von g457 (Gast)


Lesenswert?

> Ich suche ein Datenblatt das abhandelt wie man ein Register des SI5351
> über I2C liest..

Kuckst Du Datenplatt [0], steht alles drin.

HTH

[0] https://www.silabs.com/documents/public/data-sheets/Si5351-B.pdf

von Pille (Gast)


Lesenswert?

Hab dank, ich habs gefunden. Ich hatte mehrere DB überflogen, hatte aber 
entweder Tomaten auf den Augen oder es stand nicht drin.

Pille

von Bernd N (Gast)


Lesenswert?

Eine Idee zum Code für den Baustein bekommst du hier:
http://hanssummers.com/qsl/323-synth.html

von Pille (Gast)


Lesenswert?

Ich breche mir gerade die Finger an dem Ding.

Lat der obe verlinkten Doku sollte sich das Lesen eines Registers nicht 
vom Lesen einer Memory location in einem 24C08 von ST unterscheiden 
(https://pdf1.alldatasheet.com/datasheet-pdf/view/23688/STMICROELECTRONICS/ST24C08.html 
Seite 12, Random Adress Read). Genau das habe ich aber vor einiger Zeit 
schon mal gemacht und ich weiß das das funktioniert:
1
uint8_t I2C_EE_ByteRead( uint16_t ReadAddr)
2
{
3
        uint8_t tmp;
4
5
        I2C_AcknowledgeConfig(I2C_EE, ENABLE);
6
7
        /* While the bus is busy */
8
        while(I2C_GetFlagStatus(I2C_EE, I2C_FLAG_BUSY));
9
10
        if(I2C_GetFlagStatus(I2C_EE, I2C_FLAG_RXNE))    // read out some junk;
11
                tmp=I2C_ReceiveData(I2C_EE);
12
13
        /* Send START condition */
14
        I2C_GenerateSTART(I2C_EE, ENABLE);
15
16
        /* Test on EV5 and clear it */
17
        while(!I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_MODE_SELECT));
18
19
        /* Send EEPROM address for write */
20
        I2C_Send7bitAddress(I2C_EE, EEPROM_HW_ADDRESS, I2C_Direction_Transmitter);
21
22
        /* Test on EV6 and clear it */
23
        while(!I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
24
25
        /* Clear EV6 by setting again the PE bit */
26
        I2C_Cmd(I2C1, ENABLE);
27
28
#if 0 // 16 Bit address
29
30
        /* Send the EEPROM's internal address to read from: MSB of the address first */
31
        I2C_SendData(I2C_EE, (uint8_t)((ReadAddr & 0xFF00) >> 8));
32
33
        /* Test on EV8 and clear it */
34
        while(!I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
35
#endif
36
37
        /* Send the EEPROM's internal address to read from: LSB of the address */
38
        I2C_SendData(I2C_EE, (uint8_t)(ReadAddr & 0x00FF));
39
40
        /* Test on EV8 and clear it */
41
        while(!I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
42
43
44
        /* Send START condition a second time */
45
        I2C_GenerateSTART(I2C_EE, ENABLE);
46
47
        /* Test on EV5 and clear it */
48
        while(!I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_MODE_SELECT));
49
50
        /* Send EEPROM address for read */
51
        I2C_Send7bitAddress(I2C_EE, EEPROM_HW_ADDRESS,I2C_Direction_Receiver);
52
53
54
        /* Test on EV6 and clear it */
55
        while(!I2C_CheckEvent(I2C_EE,I2C_EVENT_MASTER_BYTE_RECEIVED));
56
57
58
        tmp=I2C_ReceiveData(I2C_EE);
59
60
        I2C_AcknowledgeConfig(I2C_EE, DISABLE);
61
62
63
        /* Send STOP Condition */
64
        I2C_GenerateSTOP(I2C_EE, ENABLE);
65
66
        /* Enable Acknowledgement to be ready for another reception */
67
68
69
        return tmp;
70
}

Die Entsprechung für den SI5351 bleibt aber regelmäßig im der Read 
Funktion
1
err_t si5351_read8(uint8_t reg, uint8_t *value)
2
{
3
4
        I2C_AcknowledgeConfig(I2C_EE, ENABLE);
5
6
        if(I2C_GetFlagStatus(I2C_EE, I2C_FLAG_BUSY));
7
8
        if(I2C_GetFlagStatus(I2C_EE, I2C_FLAG_RXNE))    // read out some junk
9
                I2C_ReceiveData(I2C_EE);
10
11
         /* Send START condition */
12
        I2C_GenerateSTART(I2C_EE, ENABLE);
13
14
        /* Test on EV5 and clear it */
15
        while(!I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_MODE_SELECT));
16
17
        /* Send SI5351 register address for write */
18
        I2C_Send7bitAddress(I2C_EE, SI5351_ADDRESS<<1, I2C_Direction_Transmitter);
19
20
        /* Test on EV6 and clear it */
21
        while(!I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
22
23
        /* Clear EV6 by setting again the PE bit */
24
        I2C_Cmd(I2C_EE,ENABLE);
25
26
        /* Send the SI5351's register address to read from */
27
        I2C_SendData(I2C_EE, (uint8_t)reg);
28
29
        /* Test on EV8 and clear it */
30
        while(!I2C_CheckEvent(I2C_EE,I2C_EVENT_MASTER_BYTE_TRANSMITTED));
31
32
         /* Send START condition 2nd time*/
33
        I2C_GenerateSTART(I2C_EE, ENABLE);
34
35
        /* Test on EV5 and clear it */
36
        while(!I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_MODE_SELECT));
37
38
        /* Send SI5351 register address for write */
39
        I2C_Send7bitAddress(I2C_EE, SI5351_ADDRESS<<1, I2C_Direction_Receiver);
40
41
        /* Test on EV6 and clear it */
42
        while(!I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_BYTE_RECEIVED));
43
44
        *value=I2C_ReceiveData(I2C_EE);
45
46
        snprintf(obp,40,"si5351 read8 nach ReceiveData"); USART3_PutString(obp), USART3_PutString("\r\n");;
47
48
        I2C_AcknowledgeConfig(I2C_EE, DISABLE);
49
50
        /* Send STOP Condition */
51
        I2C_GenerateSTOP(I2C_EE, ENABLE);
52
53
        /* Enable Acknowledgement to be ready for another reception */
54
//      I2C_AcknowledgeConfig(I2C_EE, ENABLE);
55
56
        return ERROR_NONE;
57
}

..hängen und mir sit nicht klar warum. Dummerweise bekomme ich auch 
gerade Pulseview auf meinem FreeBSD nicht übersetzt..

Hab ich wieder Tomaten auf den Augen? Sieht Einer was los ist?

von Bernd N (Gast)


Lesenswert?


von Pille (Gast)


Lesenswert?

Das Problem ist das im verlinkten Beispiel der Arduino keine 
Registeradresse benötigt um den Status zurück zu lesen.

Ich benötige

Start|Slave Addr|Write|Ack|Reg. Addr|Ack|Stop ||
Start|Slave Addr|Read|Ack|Rdata|Nack|Stop

Mein PCF8754 LCD Display am selben I2C Port funktioniert übrigens, 
genauso wie der 24C08, der aber auf einer anderen Platine.

Pille

von Bernd N (Gast)


Lesenswert?

Also, wenn du weit genug herunter scrollst dann ist da nix mit Arduino, 
nimm dir mal nen bischen Zeit beim Lesen.

Mit Hilfe der beiden Links habe ich den mit dem gleichen MC hier am 
laufen. Ich gebe aber zu das der Silabs Baustein es echt in sich hat 
daher der Link auf Hans Summers Seite. Er hat hier bereits ne Menge 
Hirnschmalz reingesteckt aber ich glaube nicht das du das schon 
verstanden hast.

von Achduschöneschande (Gast)


Angehängte Dateien:

Lesenswert?

Pille schrieb:
> Hab ich wieder Tomaten auf den Augen? Sieht Einer was los ist?

Ich habe vor allem Tomaten auf den Augen weil du es nicht schaffst
die Hinweise beim Posten von Sourcecode zu beachten. Bitte
beachte die Hinweise gefälligst damit man hier nicht den totalen
Verhau lesen muss.

Als längeren Sourecode betrachtet man Text der etwa eine Bild-
schirmseite überschreitet.

von Pille (Gast)


Lesenswert?

Bernd N schrieb:
> Also, wenn du weit genug herunter scrollst dann ist da nix mit
> Arduino,
> nimm dir mal nen bischen Zeit beim Lesen.
>


Der steuert da mit einer Bluepill einen Arduino der eine LED zum Blinken 
bringt, oder aber ausschaltet. Die Kommunikation zwischen Bluepill und 
Arduino erfolgt per I2C, der Arduino ist Slave. Ich habe schon richtig 
gelesen und der code ist auch nicht uninteressant, er benutzt je die 
selbe Standardperipherallib, ist nur etwas zusammengefaßt.
Der Fall den ich benötige ist darin aber nicht enthalten, ich versuche 
ein Beispiel das das HAL benutzt zu portieren:
1
/**************************************************************************/
2
/*!
3
    @brief  Reads an 8 bit value over I2C
4
*/
5
/**************************************************************************/
6
err_t si5351_read8(uint8_t reg, uint8_t *value)
7
{
8
        HAL_StatusTypeDef status = HAL_OK;
9
  
10
        while (HAL_I2C_IsDeviceReady(&hi2c1, (uint16_t)(SI5351_ADDRESS<<1), 3, 100) != HAL_OK) { }
11
    
12
    status = HAL_I2C_Mem_Read(&hi2c1,                                                   // i2c handle
13
                                                  (uint8_t)(SI5351_ADDRESS<<1),         // i2c address, left aligned
14
                                                          (uint8_t)reg,                 // register address
15
                                                          I2C_MEMADD_SIZE_8BIT,         // si5351 uses 8bit register addresses
16
                                                          (uint8_t*)(&value),           // write returned data to this variabl
17
e
18
                                                          1,                            // how many bytes to expect returned
19
                                                          100);                         // timeout
20
  
21
  return ERROR_NONE;
22
}
..und dieseenthält im Unterschied zu der LCD und Arduino Geschichte 
einen Memread Funktion, bei der das zu lesende Register ausgewählt wird.
Vom Arduino im Beispiel wird nur gelesen ohne zu adressieren.


> Mit Hilfe der beiden Links habe ich den mit dem gleichen MC hier am
> laufen. Ich gebe aber zu das der Silabs Baustein es echt in sich hat
> daher der Link auf Hans Summers Seite. Er hat hier bereits ne Menge
> Hirnschmalz reingesteckt aber ich glaube nicht das du das schon
> verstanden hast.

Nein, das ist vorerst auch gar nicht das Ziel, sondern erst mal eine 
Initialisierung aus einem Beispiel die da 32768Hz an Clock 2 erzeugt.
1
        si5351_Init();
2
3
// Set clock 0 to 16MHz
4
// 25mhz crystal osc * 32 == 800MHz
5
// 800MHz / 50 = 16Mhz
6
7
        si5351_setupPLLInt(SI5351_PLL_A, 32);
8
        si5351_setupMultisynthInt(0, SI5351_PLL_A, 50);
9
        si5351_setupRdiv(0, SI5351_R_DIV_1);
10
11
12
// Set clock 2 to 32.768KHz
13
// 25mhz crystal osc * (28 + (7012/390625)) = 700.448768
14
// 700.448768 / (1336 + (0 / 1)) = .524288
15
// .524288 / 16 = .032768 = 32.768KHz
16
17
        si5351_setupPLL(SI5351_PLL_B, 28, 7012, 390625);
18
        si5351_setupMultisynth(2, SI5351_PLL_B, 1336, 0, 1);
19
        si5351_setupRdiv(2, SI5351_R_DIV_16);
20
        si5351_enableOutputs(0xFF);
21
22
#endif


Ehe ich mich um Details kümmere möchte ich die erst einmal sehen, der 
Streß sollte also eigentlich erst später kommen.

Pille

von Pille (Gast)


Lesenswert?

Bernd N schrieb:
> Also, wenn du weit genug herunter scrollst dann ist da nix mit
> Arduino,
> nimm dir mal nen bischen Zeit beim Lesen.
>


Der steuert da mit einer Bluepill einen Arduino der eine LED zum Blinken 
bringt, oder aber ausschaltet. Die Kommunikation zwischen Bluepill und 
Arduino erfolgt per I2C, der Arduino ist Slave. Ich habe schon richtig 
gelesen und der code ist auch nicht uninteressant, er benutzt je die 
selbe Standardperipherallib, ist nur etwas zusammengefaßt.
Der Fall den ich benötige ist darin aber nicht enthalten, ich versuche 
ein Beispiel das das HAL benutzt zu portieren:
1
/**************************************************************************/
2
/*!
3
    @brief  Reads an 8 bit value over I2C
4
*/
5
/**************************************************************************/
6
err_t si5351_read8(uint8_t reg, uint8_t *value)
7
{
8
        HAL_StatusTypeDef status = HAL_OK;
9
  
10
        while (HAL_I2C_IsDeviceReady(&hi2c1, (uint16_t)(SI5351_ADDRESS<<1), 3, 100) != HAL_OK) { }
11
    
12
    status = HAL_I2C_Mem_Read(&hi2c1,                                                   // i2c handle
13
                                                  (uint8_t)(SI5351_ADDRESS<<1),         // i2c address, left aligned
14
                                                          (uint8_t)reg,                 // register address
15
                                                          I2C_MEMADD_SIZE_8BIT,         // si5351 uses 8bit register addresses
16
                                                          (uint8_t*)(&value),           // write returned data to this variabl
17
e
18
                                                          1,                            // how many bytes to expect returned
19
                                                          100);                         // timeout
20
  
21
  return ERROR_NONE;
22
}
..und dieseenthält im Unterschied zu der LCD und Arduino Geschichte 
einen Memread Funktion, bei der das zu lesende Register ausgewählt wird.
Vom Arduino im Beispiel wird nur gelesen ohne zu adressieren.


> Mit Hilfe der beiden Links habe ich den mit dem gleichen MC hier am
> laufen. Ich gebe aber zu das der Silabs Baustein es echt in sich hat
> daher der Link auf Hans Summers Seite. Er hat hier bereits ne Menge
> Hirnschmalz reingesteckt aber ich glaube nicht das du das schon
> verstanden hast.

Nein, das ist vorerst auch gar nicht das Ziel, sondern erst mal eine 
Initialisierung aus einem Beispiel die da 32768Hz an Clock 2 erzeugt.
1
        si5351_Init();
2
3
// Set clock 0 to 16MHz
4
// 25mhz crystal osc * 32 == 800MHz
5
// 800MHz / 50 = 16Mhz
6
7
        si5351_setupPLLInt(SI5351_PLL_A, 32);
8
        si5351_setupMultisynthInt(0, SI5351_PLL_A, 50);
9
        si5351_setupRdiv(0, SI5351_R_DIV_1);
10
11
12
// Set clock 2 to 32.768KHz
13
// 25mhz crystal osc * (28 + (7012/390625)) = 700.448768
14
// 700.448768 / (1336 + (0 / 1)) = .524288
15
// .524288 / 16 = .032768 = 32.768KHz
16
17
        si5351_setupPLL(SI5351_PLL_B, 28, 7012, 390625);
18
        si5351_setupMultisynth(2, SI5351_PLL_B, 1336, 0, 1);
19
        si5351_setupRdiv(2, SI5351_R_DIV_16);
20
        si5351_enableOutputs(0xFF);
21
22
#endif


Ehe ich mich um Details kümmere möchte ich die erst einmal sehen, der 
Streß sollte also eigentlich erst später kommen.

Pille

Achduschöneschande schrieb:
> Pille schrieb:
>> Hab ich wieder Tomaten auf den Augen? Sieht Einer was los ist?
>
> Ich habe vor allem Tomaten auf den Augen weil du es nicht schaffst
> die Hinweise beim Posten von Sourcecode zu beachten. Bitte
> beachte die Hinweise gefälligst damit man hier nicht den totalen
> Verhau lesen muss.
>
> Als längeren Sourecode betrachtet man Text der etwa eine Bild-
> schirmseite überschreitet.

Lies es doch gefälligst einfach nicht. Ich empfehle etwas Balsamico, Öl 
und Mozarella.

Pille

von Bernd N (Gast)


Lesenswert?

Es steht doch da alles auf der Seite, wo klemmt es denn da ?
http://www.qrp-labs.com/images/synth/demo2/main.c
http://www.qrp-labs.com/images/synth/demo2/si5351a.c
http://www.qrp-labs.com/images/synth/demo2/si5351a.h

Dazu noch das i2c Beispiel und gut ist. Du musst es nur zusammenfügen.

von Pille (Gast)


Angehängte Dateien:

Lesenswert?

Jain Bernd.

Das von Dir gezeigte Beispiel nutzt die Möglichkeit des SI5351 seine 
Register lesen zu können nicht. Es wird da nur geschrieben.
Ich hatte mich vorher im Web umgesehen und habe die Lösung fürs HAL 
gefunden, die ihrerseits wohl irgend ein Port einer Arduino Software 
ist.
Da sich die Nutzung des HAL im Wesentlichen auf die I2C Kram beschränkt, 
dachte ich ich drehe das auf StdLib um, da mein LCD Display und meine 
vorher schon genutzte EEPROM Mimik das auch benutzten, so weit so gut.

Die von mir verwendete Implementation benutzt aber in der Funktion
si5351_setupRdiv(uint8_t  output, si5351RDiv_t div)
das Auslesen eines Registers des SI5351:
1
err_t si5351_setupRdiv(uint8_t  output, si5351RDiv_t div) {
2
  ASSERT( output < 3, ERROR_INVALIDPARAMETER);  /* Channel range */
3
  
4
  uint8_t Rreg, regval, rDiv;
5
  rDiv=0;
6
  
7
  if (output == 0) Rreg = SI5351_REGISTER_44_MULTISYNTH0_PARAMETERS_3;
8
  if (output == 1) Rreg = SI5351_REGISTER_52_MULTISYNTH1_PARAMETERS_3;
9
  if (output == 2) Rreg = SI5351_REGISTER_60_MULTISYNTH2_PARAMETERS_3;
10
  
11
12
   si5351_read8(Rreg, &regval);
13
14
 
15
  regval &= 0x0F;
16
  uint8_t divider = div;
17
  divider &= 0x07;
18
  divider <<= 4;
19
  regval |= divider;
20
        snprintf(obp,35,"setupRdiv vor write Rreg %2x",Rreg); USART3_PutString(obp), USART3_PutString("\r\n");;
21
  si5351_write8(Rreg, regval);
22
23
        snprintf(obp,35,"setupRdiv nach write regval %2x",regval); USART3_PutString(obp), USART3_PutString("\r\n");;
24
    
25
  switch(div)
26
...

Ich versuche deshalb die Funktion si5351_read8(Rreg, &regval); 
nachzubauen und die liest eben ein in Rreg spezifiziertes Register des 
Si5351 aus und schafft den Inhalt nach regval, Register lesen sollte 
IMHO schon funktionieren, auch wenn es Implementierungen gibt die das 
nicht nutzen.

Ich habe mich gestern Abend nochmal damit befaßt pulseview neu zu 
übersetzen, funktioniert jetzt auch. Ich habe einen STM32F4 Discovery 
programmiert als "Openbench kompatibles SUMP Device (OLS)" als 
Logicanalyzer dran und kann mir recht detailliert ansehen was auf dem 
I2C Bus los ist Ausschnitt siehe Bild) und werde damit den Fehler auch 
finden können, habe ich beim 24C08 schon mal gemacht.
Der I2C Disassembler ist wesentlich detaillierter als der meines Siglent 
Oszis.

Nebenbei bemerkt habe ich festgestellt das da neuerdings ein Treiber 
über Ethernet für Siglent SDS1000/2000 drin ist..hoch interessant. Es 
handelt sich allerdings um eine erste Implementation und das ist leider 
noch nicht wirklich zu gebrauchen, habs mit meinem SDS1204X-E getestet.

Pille

von Bernd N (Gast)


Lesenswert?

Basierend auf dem was ich dir verlinkt habe kannst du dann so den Silabs 
Chip lesen:
1
uint8_t i2cReadRegister(uint8_t i2c_address, uint8_t reg)
2
{
3
    uint8_t rec_byte;
4
5
    I2C_GenerateSTART(I2C2, ENABLE);
6
    while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT));
7
    I2C_Send7bitAddress(I2C2, i2c_address << 1, I2C_Direction_Transmitter);
8
    while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
9
    I2C_SendData(I2C2, reg);
10
    while(!I2C_GetFlagStatus(I2C2, I2C_FLAG_BTF));
11
    I2C_GenerateSTART (I2C2, ENABLE);
12
    while(!I2C_GetFlagStatus (I2C2, I2C_FLAG_SB));
13
    I2C_Send7bitAddress (I2C2, i2c_address << 1, I2C_Direction_Receiver);
14
    while(!I2C_CheckEvent (I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
15
    while(!I2C_CheckEvent (I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED));
16
    rec_byte = I2C_ReceiveData(I2C2);
17
    I2C_GenerateSTOP (I2C2, ENABLE);
18
    return rec_byte;
19
}

von Stefan F. (Gast)


Lesenswert?

Pille schrieb:
> Ich benutze kein HAL und ärgere mich mit der I2C Engine eines STM32F103
> herum..

Dann solltest du unbedingt das Errata dazu lesen, denn die I²C 
Schnittstelle des STM32F103 hat Bugs, die man per Software umgehen kann.

Der Knackpunkt ist, dass du die drei letzten Bytes beim Empfang 
unterschiedlich behandeln musst. Deswegen kann das obige Konzept, wo 
einzelne Bytes empfangen werden, beim STM32F103 nicht funktionieren.

Pille schrieb:
> Ich benötige
>
> Start|Slave Addr|Write|Ack|Reg. Addr|Ack|Stop ||
> Start|Slave Addr|Read|Ack|Rdata|Nack|Stop

Vielleicht hilft es dir, von meinem Beispielcode abzugucken. Damit 
müsste das klappen: http://stefanfrings.de/stm32/stm32f1.html#i2c

von Kollega (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> denn die I²C Schnittstelle des STM32F103 hat Bugs

Plain Soft-I2C rulez!

Funktioniert mit jedem beliebigen Paar von Pins und mit jeder
(sogar) fehlerhaften I2C-Maschine weil man sie nicht braucht.

Echd! Isch schwör! Doppelschwör!

von Stefan F. (Gast)


Lesenswert?

Kollega schrieb:
> Plain Soft-I2C rulez!

Dann kannst den "analog noise filter" nicht nutzen und im Slave Modus 
müsstest du sehr viel CPU Leistung aufbringen.

von Kollega (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Dann kannst den "analog noise filter" nicht nutzen und im Slave Modus
> müsstest du sehr viel CPU Leistung aufbringen.

Ich will und brauche weder das eine noch das andere. Zeig mir
ein Beispiel hier auf uc.net wo jemand das nutzt. In 99.9 Prozent
aller Anwendungen völlig nutzlos.

von Stefan F. (Gast)


Lesenswert?

Kollega schrieb:
>> "analog noise filter" (sind)
> In 99.9 Prozent aller Anwendungen völlig nutzlos.

Das kann ich nicht beurteilen. Ich schätze aber, dass ST diese Filter 
ohne guten Grund nicht eingebaut hätte.

In den neueren L0 und F3 Serien sind die Parameter der Filter sogar 
konfigurierbar. Offenbar bestand Bedarf, ihre Funktion sogar noch zu 
erweitern.

Auch AVR haben Filter in der I²C Schnittstelle.

von Kollega (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Ich schätze aber, ......

Und welche Relevanz hat das für den TO?

Ich interpretiere deine Aussagen so dass du eben wieder mal
in korinthenkackerhafter Weise hier das letzte Wort und Recht
haben musst, so wie du es in so vielen anderen Fällen schon
gezeigt hast.

von Stefan F. (Gast)


Lesenswert?

Kollega schrieb:
> Und welche Relevanz hat das für den TO?

Nun, er möchte eine I²C Schnittstelle benutzen. Er wird von den Filtern 
profitieren, falls sie Sinn machen, wovon ich ausgehe.

Er kann auch andere Pins verwenden und damit deinem Vorschlag folgen. Er 
sollte sich aber der Konsequenzen bewusst sein, die sie daraus ergeben. 
Also konkret, dass er dann keine Filter mehr hat.

Kollega schrieb:
> Ich interpretiere deine Aussagen so dass du eben wieder mal
> in korinthenkackerhafter Weise hier das letzte Wort und Recht
> haben musst, so wie du es in so vielen anderen Fällen schon
> gezeigt hast.

Vielleicht magst du dazu ein Poster drucken und draußen aufhängen, wenn 
es dir dann besser geht.

von W.S. (Gast)


Angehängte Dateien:

Lesenswert?

Pille schrieb:
> Ich breche mir gerade die Finger an dem Ding.
>
> Lat der obe verlinkten Doku sollte sich das Lesen eines Registers nicht
> vom Lesen einer Memory location in einem 24C08 von ST unterscheiden

Ähem... wozu eigentlich?

Im Prinzip willst du ja den Chip so einstellen, wie du das haben willst 
- und dann weißt du auch selber, was du in ihn zuvor hineingeschriben 
hast. Da braucht es keinerlei Auslesen - höchstens für die Neugier.

Ich hänge dir mal einen Auszug aus einem meiner Radio-Projekte dran. Das 
ist so einigermaßen in verschiedenen Ebenen abgefaßt, also

- si5351a.c Das macht die Berechnungen, greift zu auf:
- si5351a_LL.c Das veranstaltet den I/O zum SI5351, greift zu auf:
- i2cs.c Das erledigt den physischen I2C Zugriff.

Bei diesem Projekt sieht gerade die unterste Ebene in i2cs.c ziemlich 
häßlich aus, weil ich (aus anderen Gründen) einen LPC1114 benutzt habe 
und dort einen zweiten I2C per Software hab einrichten müssen. Bei dem 
Chip ist der GPIO-Core ne Zumutung. Man kann zwar per 
Adressierungs-Trick auf die Ports maskiert zugreifen, aber die 
Ist-Zustände bei Opendrain-Ausgängen nicht lesen. Deshalb im untesten 
Level diese Umstände. Aber die gehen dich ja bei deinem µC nichts an. 
Häng einfach einen dir passenden Soft-I2C dran - aber laß den I2C-Core 
des STM32 links liegen, der macht nur Ärger - und spart dabei keinerlei 
Prozessorzeit.

W.S.

von W.S. (Gast)


Lesenswert?

Kollega schrieb:
> Funktioniert mit jedem beliebigen Paar von Pins und mit jeder
> (sogar) fehlerhaften I2C-Maschine weil man sie nicht braucht.
>
> Echd!

Naja, ich sag's mal so: mit einer reinen SW-Implementierung kann man 
tatsächlich auf die I2C-HW-Krücken pfeifen, was gerade beim Master sehr 
Sinn macht. Schließlich muß man ohnehin auf die gesamte Transmission 
warten. Aber manche Chips machen selbst bei blankem GPIO noch Späne, 
siehe weiter oben.

Stefan ⛄ F. schrieb:
> Dann kannst den "analog noise filter" nicht nutzen und im Slave Modus
> müsstest du sehr viel CPU Leistung aufbringen.

Hat hier denn IRGENDWER von einem µC im Slave-Modus geredet?
Nein, natürlich nicht.
Stattdessen soll hier ein SI5351 an einen µC angeschlossen werden.

W.S.

von Pille (Gast)


Lesenswert?

Kollega schrieb:
> Stefan ⛄ F. schrieb:
>> denn die I²C Schnittstelle des STM32F103 hat Bugs
>
> Plain Soft-I2C rulez!
>
> Funktioniert mit jedem beliebigen Paar von Pins und mit jeder
> (sogar) fehlerhaften I2C-Maschine weil man sie nicht braucht.
>
> Echd! Isch schwör! Doppelschwör!

Ja..auf Dich habe ich schon gewartet. :-)

Ich weiß ..und ich habe das das letzte Mal auf einem 8051 so 
gemacht..oder einem Z8..weiß ich nicht mehr, habe ich aber beim STM32 
nicht wirklich vor.

Pille

von Pille (Gast)


Lesenswert?

W.S. schrieb:
> Pille schrieb:
>> Ich breche mir gerade die Finger an dem Ding.
>>
>> Lat der obe verlinkten Doku sollte sich das Lesen eines Registers nicht
>> vom Lesen einer Memory location in einem 24C08 von ST unterscheiden
>
> Ähem... wozu eigentlich?
>
> Im Prinzip willst du ja den Chip so einstellen, wie du das haben willst
> - und dann weißt du auch selber, was du in ihn zuvor hineingeschriben
> hast. Da braucht es keinerlei Auslesen - höchstens für die Neugier.

Das ist eine Frage der Herangehensweise, ich hatte das schon 
angesprochen.
Ich habe mir ein Beispiel gesucht und versuche erst mal den SI5351 
"doof" zu initialisieren. Vom DB habe ich die Stellen zur 
Frequenzsynthese überhaupt noch nicht gelesen, ich möchte erst einmal 
sicherstellen das die Kommunikation zum und vom Chip funktioniert. 
Gedanken darüber warum der Code ein Register ausliest, habe ich mir noch 
gar nicht gemacht.

Da ich aber meine Codeschnipsel wenn sie einmal funktionieren auch für 
andere Dinge gerne wieder verwende, möchte ich erst einmal diese 
Baustelle fertigstellen.

>
> Ich hänge dir mal einen Auszug aus einem meiner Radio-Projekte dran. Das
> ist so einigermaßen in verschiedenen Ebenen abgefaßt, also
>
> - si5351a.c Das macht die Berechnungen, greift zu auf:
> - si5351a_LL.c Das veranstaltet den I/O zum SI5351, greift zu auf:
> - i2cs.c Das erledigt den physischen I2C Zugriff.

Ok, ziehe ich mir rein.

>
> Bei diesem Projekt sieht gerade die unterste Ebene in i2cs.c ziemlich
> häßlich aus, weil ich (aus anderen Gründen) einen LPC1114 benutzt habe
> und dort einen zweiten I2C per Software hab einrichten müssen. Bei dem
> Chip ist der GPIO-Core ne Zumutung. Man kann zwar per
> Adressierungs-Trick auf die Ports maskiert zugreifen, aber die
> Ist-Zustände bei Opendrain-Ausgängen nicht lesen. Deshalb im untesten
> Level diese Umstände. Aber die gehen dich ja bei deinem µC nichts an.
> Häng einfach einen dir passenden Soft-I2C dran - aber laß den I2C-Core
> des STM32 links liegen, der macht nur Ärger - und spart dabei keinerlei
> Prozessorzeit.
>
> W.S.

Naja..dieses Statement hatte ich schon gelesen als ich an der EEPROM 
Geschichte saß, habs aber auch hinbekommen. Jetzt habe ich hier einen 
I2C Bus an dem ein LCD mit PCF8574 und der SI hängt und an den auch noch 
ein EEPROM dran soll..muß doch zu machen sein.
Gut das Ihr hier nochmal auf die Bugs des F103 eingeht..da war was..muß 
ich mir nochmal raussuchen und lesen.
Ich habe übrigens extra eine Bluepill mitClone in der Mache (wohl ein 
APM32..Fälschung), habe aber daneben eine mit STM liegen und verifiziere 
jeweils ob es Differenzen im Verhalten gibt...bisher nicht.

Danke auch an Stefan und Bernd, ich melde mich.

Pille

von Pille (Gast)


Lesenswert?

BTW: @W.S.: "LMK Radio"....solls bei mir auch werden, allerdings 
hauptsächlich nur die verschiedenen Afu Bänder auf KW.

Ich habe vor ein Ding mit NE612 -> 10,7Mhz Quarzfilter, TDA4100 (A4100) 
mit ZF 525Khz zu basteln.
Ich brauche dafür VFO, Generator f. 1. Mischer (10,7-0,525, Ablage für 
SSB) und BFO für den Produktdetektor  525khz mit Ablage für SSB. Ablage 
jeweils für die Filterflanke mehrerer mechanischer Filter von Telefunken 
mit verschiedenen Bandbreiten. Ich habe von den Filtern nur noch einen 
Satz da, habe aber so 50 Sätze früher mal in meinem Onlineshop 
verkauft..Ex Bundeswehr Ersatzteile.
(die DDR MF200 währen mir lieber, habe ich auch mehr da, aber der 
TDA4100 kann nur ZF ab 300Khz wegen interner Kondensatorkopplung).

Die Threads in HF Funk und Felder habe ich gelesen..wie sind denn nun 
die Erfahrungen mit dem SI5351? Das ist Bastelei nur aus Jux, weder bin 
ich Funkamateur noch brauche ich so ein Radio..ich habe hinter mir einen 
EKD500 stehen und noch 2 weitere Empfänger in Petto (AWE Dabendorf mit 
Röhren und einen Kopena..wohl das einzige existierende Funktionsmuster)

Pille

von Pille (Gast)


Angehängte Dateien:

Lesenswert?

Ok..nach einiger Bastelei siehts jetzt halbwegs vernünftig aus denke 
ich.

Anbei die Lese- und die Schreibroutine.
Das nach dem Einlesen des Bytes (im 2. Bild) weitere Takte für ein 
"Ghost" Byte erzeugt werden, gehört wohl meiner Erinnerung nach zu den 
Bugs der STM32F103 Engine, ich glaube mich jedenfalls daran zu erinnern 
das mal gelesen zu haben. (korrigiert mich wenns nicht stimmt) Negative 
Auswirkungen dürfte das nicht haben. Für den SI5351 dürfte sich die 
Aktion erledigt haben, da er ein NACK nach dem 1. Byte gesehen hat und 
nur noch auf die Stopcondition wartet und der STM32F103 bringt das 
richtig gelesene Byte 00 zurück und verwirft das 2 Byte.

Hier die beiden Funktionen, evtl. kanns ja Einer gebrauchen.
1
err_t si5351_read8(uint8_t reg, uint8_t *value)
2
{
3
4
        I2C_AcknowledgeConfig(I2C_EE, ENABLE);
5
6
        if(I2C_GetFlagStatus(I2C_EE, I2C_FLAG_BUSY));
7
8
         /* Send START condition */
9
        I2C_GenerateSTART(I2C_EE, ENABLE);
10
11
        /* Test on EV5 and clear it */
12
        while(!I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_MODE_SELECT));
13
14
15
        /* Send SI5351 Slave address for write */
16
        I2C_Send7bitAddress(I2C_EE, SI5351_ADDRESS, I2C_Direction_Transmitter);
17
18
        /* Test on EV6 and clear it */
19
        while(!I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
20
21
        /* Send the SI5351's register address to read from */
22
        I2C_SendData(I2C_EE, (uint8_t)reg);
23
24
        /* Test on EV8 and clear it */
25
        while(!I2C_CheckEvent(I2C_EE,I2C_EVENT_MASTER_BYTE_TRANSMITTED));
26
27
        /* Send STOP Condition */
28
        I2C_GenerateSTOP(I2C_EE, ENABLE);
29
30
         /* Send START condition 2nd time*/
31
        I2C_GenerateSTART(I2C_EE, ENABLE);
32
33
        /* Test on EV5 and clear it */
34
        while(!I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_MODE_SELECT));
35
36
        I2C_AcknowledgeConfig(I2C_EE, DISABLE);
37
38
        /* Send SI5351 Slave address for write */
39
        I2C_Send7bitAddress(I2C_EE, SI5351_ADDRESS, I2C_Direction_Receiver);
40
41
        /* Test on EV6 and clear it */
42
        while(!I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_BYTE_RECEIVED));
43
44
        *value=I2C_ReceiveData(I2C_EE);
45
46
        /* Send STOP Condition */
47
        I2C_GenerateSTOP(I2C_EE, ENABLE);
48
49
        return ERROR_NONE;
50
}
1
err_t si5351_write8 (uint8_t reg, uint8_t value)
2
{
3
        I2C_AcknowledgeConfig(I2C_EE, ENABLE);          // reenable
4
5
        while(I2C_GetFlagStatus(I2C_EE, I2C_FLAG_BUSY));
6
        if(I2C_GetFlagStatus(I2C_EE, I2C_FLAG_RXNE))   // read out some junk;
7
                I2C_ReceiveData(I2C_EE);
8
9
        /* Send START condition */
10
        I2C_GenerateSTART(I2C_EE, ENABLE);
11
12
        /* Test on EV5 and clear it */
13
        while(!I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_MODE_SELECT));
14
15
        /* Send SI5351 address for write */
16
        I2C_Send7bitAddress(I2C_EE, SI5351_ADDRESS, I2C_Direction_Transmitter);
17
18
        /* Test on EV6 and clear it */
19
        while(!I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
20
21
        I2C_AcknowledgeConfig(I2C_EE, ENABLE);         // reenable
22
23
        /* Send the SI5351's register address to write to  */
24
        I2C_SendData(I2C_EE, (uint8_t)reg);
25
26
        /* Test on EV8 and clear it */
27
        while(! I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
28
29
        /* write actual value */
30
        I2C_SendData(I2C_EE, value);
31
32
        /* Test on EV8 and clear it */
33
        while(! I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
34
35
        /* Send STOP condition */
36
        I2C_GenerateSTOP(I2C_EE, ENABLE);
37
38
  return ERROR_NONE;
39
}

Das läuft auf (vermutlich) einem APM32F103CB, den STM32F103C8T6 probiere 
ich jetzt noch aus.

Pille

von Pille (Gast)


Angehängte Dateien:

Lesenswert?

Das Ergebnis für den STM32F103 ist exakt identisch, funktioniert also 
genauso.
Anbei noch das Bild vom Schreibzyklus..

Pille

von Pille (Gast)


Lesenswert?

...die Bildnamen sind vertauscht..nicht irre machen lassen :-)

Oben Die Leseoperation, darunter die Schreiboperation.
Richtig nett ist übrigens das es einfach funktioniert wenn man es 
richtig macht. Aus dem SI5351 kommen jetzt die beiden Frequenzen 16Mhz 
an CLK0 und 32768Khz an CLK2 raus, so wie es sein sollte.

Pille

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.