Forum: Mikrocontroller und Digitale Elektronik STM32 und externer Quarz (12MHz)


von Nik D. (nik_uc)


Angehängte Dateien:

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

von Nik D. (nik_uc)


Lesenswert?

Kann es etwas damit zu tun haben das ich mit der STM32F10xR.LIB arbeite?


Gruß,

Nik

von Stefan S. (stefan2013)


Lesenswert?

Hallo!

Zu "RCC_HSEConfig(RCC_HSE_Bypass);":

Den Bypass schaltest du nur ein, wenn du einen aktiven Quartz = 
Quarzoszillator (die viereckigen Dinger mit 4 Pins) verwendest.

von Nik D. (nik_uc)


Lesenswert?

Ich verwende folgenden Quarz: 
http://www.farnell.com/datasheets/75371.pdf. Hat zwar auch 4Pins, ist 
aber wohl ein passiver, oder?
Also nix mit Bypass, sondern einfach nur RCC_HSEConfig(RCC_HSE_ON);

Sonst noch ideen ?

von Stefan S. (stefan2013)


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.

von Stefan S. (stefan2013)


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.

von Nik D. (nik_uc)


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!

von Ersi (cell85)


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?

von Nik D. (nik_uc)


Angehängte Dateien:

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

von Nik D. (nik_uc)


Angehängte Dateien:

Lesenswert?

Hallo nochmal,

Habe den Fehler gefunden, und das Programm (Minimalbeispiel von oben) 
lauffähig gebracht. Kann nochmal einer schnell über die 
Einstellungen(Screenshot 3) drüber schauen, ob das so alles passt?

Danke für die Hilfe, und schönen sonnigen Samstag noch.

von Ersi (cell85)


Lesenswert?

Was für eine mcu ist das? 108Mhz?

von Nik D. (nik_uc)


Lesenswert?

Joa, kam mir auch spanisch vor... das passiert wenn ich eben nur die 
SystemInit(); aufrufe, und im Keil XTAL auf 12Mhz stelle. Es ist ein 
STM32F103C8.

von Nik D. (nik_uc)


Lesenswert?

Stelle ich den XTAL wieder auf 8Mhz passen die Frequenzen wieder... Ich 
glaub ich schmeiß den externen 12Mhz Quarz runter und bau einen 8Mhz 
drauf...

von Mario (Gast)


Lesenswert?

ohjeeee...nein bist du verrückt?? 12mhz geht doch:

Der STM32f103 hat 72Mhz

12 Mhz HSE  ...multipliziert mal 12  und dann durch 2 = 72Mhz
(ich glaub 6 * 1 ist nicht möglich)

- fertig -

von Mario (Gast)


Lesenswert?

Clock Settings:
 - XTAL    =           12.00 MHz
 - SYSCLK  =           72.00 MHz
 - HCLK    = SYSCLK  = 72.00 MHz
 - PCLK1   = HCLK/2  = 36.00 MHz
 - PCLK2   = HCLK    = 72.00 MHz
 - ADCLK   = PCLK2/6 = 12.00 MHz

von Nik D. (nik_uc)


Lesenswert?

Wie gesagt, der letze Screenshot (der mit den 108Mhz) ist das direkte 
Ergebnis wenn ich XTAL auf 12Mhz stell, und dann die SystemInit() 
aufrufe. Wenn du mir sagen kannst warum da dann 108 MHz drinnen stehn, 
würde mir das helfen :)

von Mario (Gast)


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]

von Mario (Gast)


Lesenswert?

weis nich wie das [/color] reingekommen ist. mach das weg.

von Nik D. (nik_uc)


Angehängte Dateien:

Lesenswert?

Okay, das klingt natürlich logisch. In welcher Datei finde ich die 
Bezeichner (Screenshot 4) ?

Vielen Dank,

von Nik D. (nik_uc)


Lesenswert?

flash.c ok, die habe ich gefunden. Aber

init.c(202): error:  #20: identifier "HSEStartUpStatus" is undefined


fehlt noch. Wo ist das definiert?

von Nik D. (nik_uc)


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!

von Ersi (cell85)


Lesenswert?

ja du kannst die I2C nochmal separat einstellen.

Schau dir doch mal das clockconfig tool (ja ist für den F4 aber egal) 
an. Dort siehst du genau wie der I2C seine Frequenz herbekommt.

http://mark-stevens.co.uk/Wordpress/wp-content/uploads/2013/03/STClockConfigurationToolExpertMode.jpg

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.