STM32 und externer Quarz (12MHz)

OP #3192136
Lesenswert?

Hallo Forum,

wie der Betreff scho sagt habe ich ein Problem mit einem STM32 welcher 
mit einem externe Quarz von 12MHz arbeitet( oder soll). Ich weiß nicht 
genau ob ich den Controller richtig programmiert habe, denn folgendes 
Verhalten erscheint mir komisch. Der uC funktioniert eigentlich richtig, 
sprich ein Delay von 1000us sind (laut oszi und Pin togglen) auch 
1000us. Die Kommunikation über UART (115200 Baud) funktioniert tadellos 
und auch die Timer laufen richtig. NUR! der I2C (C2) will einfach nicht 
funktionieren. Suspekt ist allerdings, im Simulator wird er richtig 
erkannt und eingestellt, spiele ich allerdings das Programm auf den uC 
und lasse den Debugger laufen, sehe ich im I2C Fenster (IDE = Keil) 
nur(siehe auch Screenshot)
Clock Enabled
I2C Clock Error, FREQ set wrong

Ich bin mir nicht ganz sicher ob ich alle einstellungen auf die externen 
12MHz richtig umgestellt habe. Hier mal meine (teilweise) konfiguation:
1
 
2
void RCC_Configuration(void)   
3
{    
4
    RCC_DeInit(); // RCC system reset(for debug purpose)  
5
     RCC_HSEConfig(RCC_HSE_ON); // Enable HSE
6
    //RCC_HSEConfig(RCC_HSE_Bypass); // Enable HSE  
7

8
 while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET); // Wait till HSE is ready   
9
   
10
    RCC_HCLKConfig(RCC_SYSCLK_Div1); // HCLK = SYSCLK   
11
     
12
    RCC_PCLK2Config(RCC_HCLK_Div1); // PCLK2 = HCLK   
13
   
14
    RCC_PCLK1Config(RCC_HCLK_Div2); // PCLK1 = HCLK/2  
15
   
16
    FLASH_SetLatency(FLASH_Latency_2); // Flash 2 wait state   
17
    
18

19
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); // Enable Prefetch Buffer 
20
   
21
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_6); // PLLCLK = 12MHz * 6 = 72 MHz   
22
   
23
    RCC_PLLCmd(ENABLE); // Enable PLL  
24
   
25
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);  // Wait till PLL is ready
26
   
27
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); // Select PLL as system clock source 
28
   
29
    while(RCC_GetSYSCLKSource() != 0x08); // Wait till PLL is used as system clock source
30

31
  RCC->APB2ENR |= 1; // Enable Alternate function IO clock
32

33
  RCC->APB2ENR |= 8; // IO port B clock enable
34

35
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // DMA clock enable
36
}

stelle ich gleich in der 2. Zeile die Funktion
1
 RCC_HSEConfig(RCC_HSE_ON);
 auf
1
 RCC_HSEConfig(RCC_HSE_Bypass);
 um, funktioniert nichts mehr, der Controller hängt sich bei der 
Schleife
1
  while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);
 auf, bzw verweilt dort.
Die Konfiguration meines I2C Kanales schaut folgendermaßen aus:
1
void i2c_intern_conf(void)
2
{
3
  
4
  
5
  I2C_InitTypeDef I2C_InitStructure;
6
  I2C_DeInit(I2C2);
7
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
8
  RCC_AHBPeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); 
9
  I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;    //Beim Empfang der eigenen Adresse oder eines Datenbytes wird ein Acknowledgement Bit gesendet
10
  I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; //Bitlänge der eigenen Adresse im Slave Mode
11
  I2C_InitStructure.I2C_ClockSpeed = 400000;     //Frequenz der Taktleitung in Hz
12
  I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; //Legt das Verhältnis von low zu high im Fast-Mode (ab 100kHz) fest
13
  I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;  //I2C / SMBus
14
  I2C_InitStructure.I2C_OwnAddress1 = 0x00; //Definition der eigenen Adresse          adresse auf 1
15
  I2C_Init(I2C2, &I2C_InitStructure);
16
 
17
  I2C_ITConfig(I2C2, I2C_IT_EVT, ENABLE);  //IR wenn Start Bit oder Adresse gesendet, oder Byte übertragung vollständig
18
  I2C_ITConfig(I2C2, I2C_IT_BUF, ENABLE); //IR wenn  Receive Buffer ein neues Byte enthält oder der Transmit Buffer leer wird
19
  I2C_ITConfig(I2C2, I2C_IT_ERR, ENABLE);  //IR wenn Error
20
 
21
  I2C_Cmd(I2C2, ENABLE);
22

23

24

25
}

ich habe außerdem in der Datei: C:\Keil\ARM\INC\ST\STM32F10x  angepasst:
1
/**
2
 * @brief In the following line adjust the value of External High Speed oscillator (HSE)
3
   used in your application 
4
   
5
   Tip: To avoid modifying this file each time you need to use different HSE, you
6
        can define the HSE value in your toolchain compiler preprocessor.
7
  */           
8
#if !defined  HSE_VALUE
9
 #ifdef STM32F10X_CL   
10
  #define HSE_VALUE    ((uint32_t)12000000) /*!< Value of the External oscillator in Hz */
11
 #else 
12
  #define HSE_VALUE    ((uint32_t)12000000) /*!< Value of the External oscillator in Hz */
13
 #endif /* STM32F10X_CL */
14
#endif /* HSE_VALUE */

An den Pins des externen Quarzes schwingt es auch schön mit 12MHz.

Was mache ich falsch, bin für jeden Tipp sehr dankbar!


Gruß,

Nik
Angehängte Dateien:
#3192547
Lesenswert?

Ich kenne mich mit den STM Bibliotheken nicht aus, mache alles immer 
händisch (da kann ich wenigstens sicher sein, was passiert).

Zur clock des I2C: (hier für stm32f103)

Du hast im Register I2C_CCR
-) F/S = 0 für standard mode
-) DUTY kannst dur für F/S = 0 ignorieren
-) CCR[11:0]

für CCR lautet die Formel für standard mode:

CCR[11:0]=((1/gewünschte_I2C_frequenz)/(1/PCLK1))/2

wichtig ist auch TRISE[5:0]=(1000ns/(1/PCLK1))+1

Schau dir mal den sourcecode deiner bibliothek an und finde heraus, wie 
I2C_InitStructure.I2C_ClockSpeed in CCR ungewandelt wird.
#3192564
Lesenswert?

Zu deinem Quarz: ja, das ist ein passiver.
Das siehst du am ja im Datasheet, wo zwischen pin 1 und 3 ein Quarz 
eingezeichnet ist. Ein aktiver hätte zumindest VCC, GND und Output und 
erzeugt selbst ein Signal, das am OSC_IN angelegt wird. Der passive wird 
vom MCU zum Schwingen gebracht, deshalb braucht er auch OSC_OUT.
OP #3192611
Lesenswert?

Danke erstmal. Die Berechnung werde ich nachprüfen.
Habe den ULINK jetzt mal mit nach Hause genommen.
Auf diesem Rechner jetzt ist Keil gerade frisch installiert worden( der 
auf Arbeit teile ich mir teilweise mit andren Studenten, daher die 
Vermutung irgendow in der Standard Lib ist was verändert worden) und ich 
versuche ein Minimalbeispiel zum laufen zu bekommen.
1
#include "stm32f10x_conf.h"
2

3

4

5
int main(void)
6
{
7
  GPIO_InitTypeDef GPIO_InitStructure;
8
 
9
  SystemInit();
10
 
11
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
12
 
13
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
14
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
15
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
16
  GPIO_Init(GPIOC, &GPIO_InitStructure);
17
 
18
  GPIO_WriteBit(GPIOC, GPIO_Pin_9, Bit_SET);
19
 
20
  while(1)
21
  {
22
  }
23
}

Allerdings erkennt Keil jetzt die include nicht? Ich hab von der ST 
Seite einen ZIP Ordner mit der Standard Lib runter geladen, nur wo pack 
ich den jetzt hin? Im Ordner C:\Keil\ARM\INC\ST\STM32F10x befinden sich 
gerade nur vier Datein:
stm32f10x.h
stm32f10x_cl.j
system_stm32f10x.h
system_stm32f10x_cl.h

Kann ich einfach den entsprechenden Ordner aus der neuen Standard Lib 
dort rein kopieren?
Und was muss ich letztendlich alles im Keil per #include einbinden(und 
vorallem von WO???) damit ich zuminders mal ein minimal Beispiel und die 
Clocks setzen kann...
Irgendwie bin ich am Verzweifeln... Habe davor zwar schon mit einem 
Energymicro und nem NUC gearbeitet, da hatte ich aber keine solchen 
Probleme.

Vielen Vielen Dank schonmal!
#3192960
Lesenswert?

mach die ganze HSE sache da raus und stell bei Keil in der Konfiguration 
XTAL auf 12Mhz

und ansonsten führst du nur SYSTEMINIT aus wie im example project.
du kannst noch HSE 12000000 setzen in der compiler einstellung.

hast du denn die include-pfade auch alle richtig angegeben in den 
einstellugnen?
OP #3195473
Lesenswert?

Hallo,
entschuldigung das ich jetzt erst Antworte.

Ich glaube ich seh vor lauter Bäume den Wald nicht mehr.
Ich habe das jetzt so gelöst, bzw versucht.

Ordnerstruktur schaut so aus:
1
C:.
2
├───projekt
3
│       core_cm3.crf
4
│       core_cm3.d
5
│       core_cm3.o
6
│       core_cm3.__i
7
│       main.c
8
│       main.crf
9
│       main.d
10
│       main.__i
11
│       pupme.uvgui.Dominik
12
│       pupme.uvopt
13
│       pupme.uvproj
14
│       pupme_Target 1.dep
15
│       pupme_uvproj.bak
16
│       startup_stm32f10x_md.d
17
│       startup_stm32f10x_md.lst
18
│       startup_stm32f10x_md.o
19
│       stm32f10x_gpio.crf
20
│       stm32f10x_gpio.d
21
│       stm32f10x_gpio.__i
22
│       stm32f10x_rcc.crf
23
│       stm32f10x_rcc.d
24
│       stm32f10x_rcc.__i
25
│       system_stm32f10x.crf
26
│       system_stm32f10x.d
27
│       system_stm32f10x.__i
28
29
└───STM32F10x_StdPeriph_Lib_V3.5.0
30
    └───Libraries
31
        ├───CMSIS
32
        │   └───CM3
33
        │       ├───CoreSupport
34
        │       │       core_cm3.c
35
        │       │       core_cm3.h
36
        │       │
37
        │       └───DeviceSupport
38
        │           └───ST
39
        │               └───STM32F10x
40
        │                   │   stm32f10x.h
41
        │                   │   system_stm32f10x.c
42
        │                   │   system_stm32f10x.h
43
        │                   │
44
        │                   └───startup
45
        │                       └───arm
46
        │                               startup_stm32f10x_cl.s
47
        │                               startup_stm32f10x_hd.s
48
        │                               startup_stm32f10x_hd_vl.s
49
        │                               startup_stm32f10x_ld.s
50
        │                               startup_stm32f10x_ld_vl.s
51
        │                               startup_stm32f10x_md.s
52
        │                               startup_stm32f10x_md_vl.s
53
        │                               startup_stm32f10x_xl.s
54
55
        └───STM32F10x_StdPeriph_Driver
56
            │   Release_Notes.html
57
58
            ├───inc
59
            │       misc.h
60
            │       stm32f10x_adc.h
61
            │       stm32f10x_bkp.h
62
            │       stm32f10x_can.h
63
            │       stm32f10x_cec.h
64
            │       stm32f10x_crc.h
65
            │       stm32f10x_dac.h
66
            │       stm32f10x_dbgmcu.h
67
            │       stm32f10x_dma.h
68
            │       stm32f10x_exti.h
69
            │       stm32f10x_flash.h
70
            │       stm32f10x_fsmc.h
71
            │       stm32f10x_gpio.h
72
            │       stm32f10x_i2c.h
73
            │       stm32f10x_iwdg.h
74
            │       stm32f10x_pwr.h
75
            │       stm32f10x_rcc.h
76
            │       stm32f10x_rtc.h
77
            │       stm32f10x_sdio.h
78
            │       stm32f10x_spi.h
79
            │       stm32f10x_tim.h
80
            │       stm32f10x_usart.h
81
            │       stm32f10x_wwdg.h
82
83
            └───src
84
                    misc.c
85
                    stm32f10x_adc.c
86
                    stm32f10x_bkp.c
87
                    stm32f10x_can.c
88
                    stm32f10x_cec.c
89
                    stm32f10x_crc.c
90
                    stm32f10x_dac.c
91
                    stm32f10x_dbgmcu.c
92
                    stm32f10x_dma.c
93
                    stm32f10x_exti.c
94
                    stm32f10x_flash.c
95
                    stm32f10x_fsmc.c
96
                    stm32f10x_gpio.c
97
                    stm32f10x_i2c.c
98
                    stm32f10x_iwdg.c
99
                    stm32f10x_pwr.c
100
                    stm32f10x_rcc.c
101
                    stm32f10x_rtc.c
102
                    stm32f10x_sdio.c
103
                    stm32f10x_spi.c
104
                    stm32f10x_tim.c
105
                    stm32f10x_usart.c
106
                    stm32f10x_wwdg.c

Das Keil Projekt liegt im Ordner Projekt. Im Keil selber stelle ich 
unter Target die includes folgendermaßen ein (Screenshot 1). Allerdings 
bekomme ich beim Compilieren eine Fehlermeldung. Mache ich das 
eigentlich so richtig? So arbeite ich komplett nur mit den Datein im 
STM32F10x_StdPeriph_Lib_V3.5.0 Ordner, oder? Die Auto-includes habe ich 
abgeschaltet.

Danke nochmal für die Hilfe. Ich erkläre mich auch gern bereit das ganze 
dann ordentlich dokumentiert in die WIKI oder so aufzunehmen, bei 
Interesse.

Gruß,

Nik
Angehängte Dateien:
Gast #3196325
Lesenswert?

Weil Systeminit nicht von selbst weis wie der entsprechende PLL 
multiplikator und teiler eingestellt werden kann bei exotischen 
frequenzen.

[c]
#include "stm32f10x.h"                            /* STM32F10x Library 
Definitions      */
#include "misc.h"

]RCC_ClocksTypeDef RCC_ClockFreq;[/color]

void SetupClock (void)
{
 /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration 
-----------------------------*/

  /* RCC system reset(for debug purpose) */
  RCC_DeInit();

  /* Enable HSE */
  RCC_HSEConfig(RCC_HSE_ON);

  /* Wait till HSE is ready */
  HSEStartUpStatus = RCC_WaitForHSEStartUp();

  if(HSEStartUpStatus == SUCCESS)
  {
    /* Enable Prefetch Buffer */
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

    /* Flash 2 wait state */
    FLASH_SetLatency(FLASH_Latency_2);

    /* HCLK = SYSCLK */
    RCC_HCLKConfig(RCC_SYSCLK_Div1);

    /* PCLK2 = HCLK */
    RCC_PCLK2Config(RCC_HCLK_Div1);

    /* PCLK1 = HCLK/2 */
    RCC_PCLK1Config(RCC_HCLK_Div2);
  /*12Mhz / 2 = 6Mhz * 12 = 72 MHz */
    RCC_PLLConfig(RCC_PLLSource_HSE_Div2, RCC_PLLMul_12);
[/color]
    /* Enable PLL */
    RCC_PLLCmd(ENABLE);

    /* Wait till PLL is ready */
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
    {
    }

    /* Select PLL as system clock source */
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

    /* Wait till PLL is used as system clock source */
    while(RCC_GetSYSCLKSource() != 0x08)
    {
    }

   RCC_GetClocksFreq(&RCC_ClockFreq);[/color]

 }
[c]
OP #3196350
Lesenswert?

Alles klar, ich sollte aufhören heute... HSEStartUpStatus als Variable 
deklarieren. Ist klar... Sorry für die Frage. Es scheint als würde er 
die Clocks jetzt richtig setzen. Muss ich bei den Einstellungen für i2c 
auch nochmal die Faktoren verändern?

Er schreibt nämlich weiterhin I2C Clock = 150000 Hz, FREQ set wrong 
wobei ich es auf 10kHz einstelle.

Vielen Dank!

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren