Forum: Mikrocontroller und Digitale Elektronik STM32F105R8T6 + USART2


von Jan H. (janiiix3)


Lesenswert?

Nabend.

Habe heute mein China Board bekommen (CAN + USART).
Drauf bestückt ist ein 8MHz Quarz.

Als Herzstück ist ein STM32F105R8T6 bestückt. Das ganze habe ich mit 
EmBitz compiliert.

Wenn ich jetzt via. USART was ausgeben möchte, kommen nur Sonderzeichen.
Vermutlich ist die Frequenz im Projekt nicht richtig eingestellt, so das 
die Baudrate überhaupt nicht richtig berechnet wird.

Oder sieht hier jemand einen fatalen Fehler, was die USART 
Initalisierung oder auch das senden betrifft?
1
void _uartInit(void)
2
{
3
    USART_InitTypeDef usart1_init_struct;
4
    GPIO_InitTypeDef gpioa_init_struct;
5
6
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA, ENABLE);
7
8
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
9
10
    /* GPIOA PIN9 alternative function Tx */
11
    gpioa_init_struct.GPIO_Pin = GPIO_Pin_2;
12
    gpioa_init_struct.GPIO_Speed = GPIO_Speed_10MHz;
13
    gpioa_init_struct.GPIO_Mode = GPIO_Mode_AF_PP;
14
    GPIO_Init(GPIOA, &gpioa_init_struct);
15
    /* GPIOA PIN9 alternative function Rx */
16
    gpioa_init_struct.GPIO_Pin = GPIO_Pin_3;
17
    gpioa_init_struct.GPIO_Speed = GPIO_Speed_10MHz;
18
    gpioa_init_struct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
19
    GPIO_Init(GPIOA, &gpioa_init_struct);
20
21
    USART_Cmd(USART2, ENABLE);
22
23
    usart1_init_struct.USART_BaudRate = 9600;
24
    usart1_init_struct.USART_WordLength = USART_WordLength_8b;
25
    usart1_init_struct.USART_StopBits = USART_StopBits_1;
26
    usart1_init_struct.USART_Parity = USART_Parity_No ;
27
    usart1_init_struct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
28
    usart1_init_struct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
29
    /* Configure USART1 */
30
    USART_Init(USART2, &usart1_init_struct);
31
}
32
33
void _uartChar(char c, USART_TypeDef *uart)
34
{
35
    while ((uart->SR & USART_SR_TXE) == 0);
36
    uart->DR = c;
37
}
38
39
void _uartStr(char *str, USART_TypeDef *uart)
40
{
41
    while(*str)
42
    {
43
        while ((uart->SR & USART_SR_TXE) == 0);
44
        _uartChar(*str++,uart);
45
    }
46
}
1
int main(void)
2
{
3
    _canInit();
4
    _ledInit();
5
    _uartInit();
6
7
    SystemInit();
8
    //SysTick_Config(2500000);
9
10
  while(1)
11
  {
12
    _uartStr("Herzlich Willkommen\r\n",USART2);
13
14
  }
15
}

: Bearbeitet durch User
von Jim M. (turboj)


Lesenswert?

Das SystemInit() sollte man als erstes machen, dort wird IIRC der Quarz 
eingeschaltet und die Clocks umprogrammiert.

Wenn man das nach der UART Initialisierung macht, sind dessen Baudraten 
Einstellungen hinterher falsch.

von Jan H. (janiiix3)


Lesenswert?

Jim M. schrieb:
> Das SystemInit() sollte man als erstes machen, dort wird IIRC der Quarz
> eingeschaltet und die Clocks umprogrammiert.
>
> Wenn man das nach der UART Initialisierung macht, sind dessen Baudraten
> Einstellungen hinterher falsch.

Ich bin mir nicht sicher, wie er konfiguriert ist. Läuft er jetzt mit 
25MHz?
Benutze die Standart Treiber von ST.

von Johannes S. (Gast)


Lesenswert?

da wo SystemInit definiert ist sollte es auch etwas wie 
'SystemCoreClock' geben, das kannst du ja über die serielle ausgeben 
(wenn sie funktioniert).

von Jan H. (janiiix3)


Lesenswert?

Johannes S. schrieb:
> da wo SystemInit definiert ist sollte es auch etwas wie
> 'SystemCoreClock' geben, das kannst du ja über die serielle ausgeben
> (wenn sie funktioniert).

Also in der Headerdatei steht nicht viel..
1
/******************************************************************************
2
 * @file:    system_stm32f10x_cl.h
3
 * @purpose: CMSIS Cortex-M3 Device Peripheral Access Layer Header File for the
4
 *           ST STM32 Connectivity Line Device Series
5
 * @version: V1.01
6
 * @date:    22. Jul. 2009
7
 *----------------------------------------------------------------------------
8
 *
9
 * Copyright (C) 2009 ARM Limited. All rights reserved.
10
 *
11
 * ARM Limited (ARM) is supplying this software for use with Cortex-Mx
12
 * processor based microcontrollers.  This file can be freely distributed
13
 * within development tools that are supporting such ARM based processors.
14
 *
15
 * THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED
16
 * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
17
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
18
 * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
19
 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
20
 *
21
 ******************************************************************************/
22
23
24
#ifndef __SYSTEM_STM32F10x_CL_H
25
#define __SYSTEM_STM32F10x_CL_H
26
27
#ifdef __cplusplus
28
 extern "C" {
29
#endif
30
31
extern uint32_t SystemFrequency;    /*!< System Clock Frequency (Core Clock)  */
32
33
34
/**
35
 * Initialize the system
36
 *
37
 * @param  none
38
 * @return none
39
 *
40
 * @brief  Setup the microcontroller system
41
 *         Initialize the Embedded Flash Interface,  initialize the PLL and update the SystemFrequency variable
42
 */
43
extern void SystemInit (void);
44
45
#ifdef __cplusplus
46
}
47
#endif
48
49
#endif /* __SYSTEM_STM32F10x_CL_H */

von Christopher J. (christopher_j23)


Lesenswert?

Das haben Header (zumindest bei C) so an sich, dass da nur die 
Deklarationen drin stehen. Für die Implementierung der Funktionen würde 
ich mal in der entsprechenden .c-Datei nachsehen.

Normalerweise (jedenfalls war das mal von ARM so vorgesehen) wird die 
SystemInit auch noch vor der eigentlichen main aufgerufen. Entsprechende 
Hinweise liefert der Startup-Code. Findest du dort ein "bl SystemInit" 
vor einem "bl main" kannst du dir den Aufruf in der main sowieso sparen.

von Jan H. (janiiix3)


Lesenswert?

Christopher J. schrieb:
> Das haben Header (zumindest bei C) so an sich, dass da nur die
> Deklarationen drin stehen. Für die Implementierung der Funktionen würde
> ich mal in der entsprechenden .c-Datei nachsehen.
>
> Normalerweise (jedenfalls war das mal von ARM so vorgesehen) wird die
> SystemInit auch noch vor der eigentlichen main aufgerufen. Entsprechende
> Hinweise liefert der Startup-Code. Findest du dort ein "bl SystemInit"
> vor einem "bl main" kannst du dir den Aufruf in der main sowieso sparen.

Wo sehe ich denn nun die aktuelle Frequenz mit der Initalisiert wird?

von A.. P. (arnonym)


Angehängte Dateien:

Lesenswert?

In deinem Projektverzeichnis sollte müsste noch eine gleichnamige 
Quelldatei liegen (in deinem Fall also system_stm32f10x_cl.c). Darin 
sind dann die Werte enthalten, die mit SystemInit() in die 
Controller-Register geschrieben werden.

Diese Datei kann man mit einem einfachen Excel-Tool erzeugen oder mit 
dem Programm STMCubeMX. Beides gibts bei ST auf der jeweiligen 
Produktseite für deinen Controller zum Download.

Im Anhang siehst du eine solche Datei, welche den Systemtakt einstellt 
(exemplarisch für einen STM32F2).

Gruß

von Jan H. (janiiix3)


Lesenswert?

A.. P. schrieb:
> In deinem Projektverzeichnis sollte müsste noch eine gleichnamige
> Quelldatei liegen (in deinem Fall also system_stm32f10x_cl.c). Darin
> sind dann die Werte enthalten, die mit SystemInit() in die
> Controller-Register geschrieben werden.
>
> Diese Datei kann man mit einem einfachen Excel-Tool erzeugen oder mit
> dem Programm STMCubeMX. Beides gibts bei ST auf der jeweiligen
> Produktseite für deinen Controller zum Download.
>
> Im Anhang siehst du eine solche Datei, welche den Systemtakt einstellt
> (exemplarisch für einen STM32F2).
>
> Gruß

Diese Datei die du meinst, muss ich mir erst noch erstellen?

von Dumpfbacke (Gast)


Lesenswert?

Jan H. schrieb:
> Diese Datei die du meinst, muss ich mir erst noch erstellen?

Er hat doch gerade erst geschrieben:

A.. P. schrieb:
> In deinem Projektverzeichnis sollte müsste noch eine gleichnamige
> Quelldatei liegen

von Jan H. (janiiix3)


Lesenswert?

Dumpfbacke schrieb:
> Jan H. schrieb:
>> Diese Datei die du meinst, muss ich mir erst noch erstellen?
>
> Er hat doch gerade erst geschrieben:
>
> A.. P. schrieb:
>> In deinem Projektverzeichnis sollte müsste noch eine gleichnamige
>> Quelldatei liegen

Diese gibt es eben nicht.

von A.. P. (arnonym)


Lesenswert?

Jan H. schrieb:
> Diese Datei die du meinst, muss ich mir erst noch erstellen?

Wie gesagt: entweder, sie ist da, oder du musst sie noch erstellen. Wenn 
du dein Programm kompilieren kannst, wird sie wohl schon da sein und du 
musst überprüfen, was drin steht und bei Bedarf auf den korrekten Wert 
einstellen.

Darüber hinaus muss USART_Cmd() nach USART_Init() aufgerufen werden. Zur 
besseren Orientierung findet man in der Standard Peripherals Library zu 
jeder Peripherie eine kurze Anleitung, wie man sie richtig 
initialisiert. So z.B. für den USART für einen STM32F1xx:
1
===============================================================================
2
                       ##### How to use this driver #####
3
 ===============================================================================
4
    [..]
5
        (#) Enable peripheral clock using RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE)
6
            function for USART1 or using RCC_APB1PeriphClockCmd(RCC_APB1Periph_USARTx, ENABLE)
7
            function for USART2 and USART3.
8
        (#) According to the USART mode, enable the GPIO clocks using 
9
            RCC_AHBPeriphClockCmd() function. (The I/O can be TX, RX, CTS, 
10
            or and SCLK). 
11
        (#) Peripheral's alternate function: 
12
            (++) Connect the pin to the desired peripherals' Alternate 
13
                 Function (AF) using GPIO_PinAFConfig() function.
14
            (++) Configure the desired pin in alternate function by:
15
                 GPIO_InitStruct->GPIO_Mode = GPIO_Mode_AF.
16
            (++) Select the type, pull-up/pull-down and output speed via 
17
                 GPIO_PuPd, GPIO_OType and GPIO_Speed members.
18
            (++) Call GPIO_Init() function.        
19
        (#) Program the Baud Rate, Word Length , Stop Bit, Parity, Hardware 
20
            flow control and Mode(Receiver/Transmitter) using the SPI_Init()
21
            function.  
22
        (#) For synchronous mode, enable the clock and program the polarity,
23
            phase and last bit using the USART_ClockInit() function.  
24
        (#) Enable the NVIC and the corresponding interrupt using the function 
25
            USART_ITConfig() if you need to use interrupt mode.   
26
        (#) When using the DMA mode: 
27
            (++) Configure the DMA using DMA_Init() function.
28
            (++) Active the needed channel Request using USART_DMACmd() function.   
29
        (#) Enable the USART using the USART_Cmd() function.   
30
        (#) Enable the DMA using the DMA_Cmd() function, when using DMA mode.   
31
    [..]
32
            Refer to Multi-Processor, LIN, half-duplex, Smartcard, IrDA sub-sections
33
            for more details.

Die genauen Werte für z.B. Konstanten oder Funktionsnamen musst du 
natürlich in deiner speziellen Version nachsehen, hier unterscheiden 
sich die Bezeichnungen bei den STMs von Familie zu Familie.

Gruß

: Bearbeitet durch User
von Jan H. (janiiix3)


Lesenswert?

A.. P. schrieb:
> In deinem Projektverzeichnis sollte müsste noch eine gleichnamige
> Quelldatei liegen (in deinem Fall also system_stm32f10x_cl.c). Darin
> sind dann die Werte enthalten, die mit SystemInit() in die
> Controller-Register geschrieben werden.
>
> Diese Datei kann man mit einem einfachen Excel-Tool erzeugen oder mit
> dem Programm STMCubeMX. Beides gibts bei ST auf der jeweiligen
> Produktseite für deinen Controller zum Download.
>
> Im Anhang siehst du eine solche Datei, welche den Systemtakt einstellt
> (exemplarisch für einen STM32F2).
>
> Gruß

Woher weißt du das sie genau so heißen muss?

von A.. P. (arnonym)


Lesenswert?

Weil es eine übliche Konvention bei C ist, dass eine Quell- und die 
zugehörige Header-Datei denselben Namen haben. Datei.c und Datei.h eben.

Da du aber schon so fragst und du scheinbar keine Probleme hast deinen 
Code zu kompilieren, solltest du dich mal auf die Suche machen, wo denn 
in deinem Code sonst noch die Werte versteckt sein könnten, die 
normalerweise in der system_xxxxx.c Datei stehen. Selbstverständlich 
kann der Code für die Initialisierung des Systemtakts in jeder 
x-beliebigen Datei mit unscheinbarem Namen stehen, solange die Header 
eingebunden werden - das wäre aber grober Unfug ;)

Wenn du einen Editor mit vernünftiger Suchfunktion hast, dann kannst du 
ja einfach mal in deinem Projektverzeichnis nach Zeichenketten wie 
"RCC->CR", "RCC->PLLCFGR" oder einfach "SystemCoreClock" suchen. Das 
sind nämlich so ein paar Zuweisungen, die passieren müssten, wenn der 
Takt konfiguriert ist. Die Datei, in der das steht ist vielleicht auch 
die Datei, die du suchst.

Viel, viel einfacher wäre es aber, einfach das Clock Configuration Tool 
von ST runterzuladen, dir eine saubere Datei zu erzeugen und sich nicht 
weiter darum zu kümmern. In den letzten 30 Minuten hättest du dir eine 
solche Datei ein Dutzend Mal erzeugt :D

Gruß

von holger (Gast)


Lesenswert?

>Woher weißt du das sie genau so heißen muss?

Ist doch egal. Mach ne Volltextsuche nach SystemInit
in deinem Projekt. Und wenn du gleich das ganze Projekt und nicht
nur Codeschnipsel geliefert hättest, wäre dein Problem längst gelöst.

Was ich noch so weiß ist das diese SystemInits oft für die EVAL
Boards ausgelegt sind. Da ist ein 25MHz Quarz drauf. Das passt dann
nicht zu deinem 8MHz Quarz.

Kompletten Code zeigen dürfte hier am schnellsten zur Lösung
beitragen.

von Jan H. (janiiix3)


Lesenswert?

A.. P. schrieb:
> Wenn du einen Editor mit vernünftiger Suchfunktion hast, dann kannst du
> ja einfach mal in deinem Projektverzeichnis nach Zeichenketten wie
> "RCC->CR", "RCC->PLLCFGR" oder einfach "SystemCoreClock" suchen. Das
> sind nämlich so ein paar Zuweisungen, die passieren müssten, wenn der
> Takt konfiguriert ist. Die Datei, in der das steht ist vielleicht auch
> die Datei, die du suchst.
>
> Viel, viel einfacher wäre es aber, einfach das Clock Configuration Tool
> von ST runterzuladen, dir eine saubere Datei zu erzeugen und sich nicht
> weiter darum zu kümmern. In den letzten 30 Minuten hättest du dir eine
> solche Datei ein Dutzend Mal erzeugt :D
>
> Gruß

Kannst du mir mal einen Link zum Tool posten?
Ist es das "STM32CubeMx"?

von A.. P. (arnonym)


Lesenswert?

holger schrieb:
> Was ich noch so weiß ist das diese SystemInits oft für die EVAL
> Boards ausgelegt sind. Da ist ein 25MHz Quarz drauf. Das passt dann
> nicht zu deinem 8MHz Quarz.

Ja, scheint tatsächlich häufig so zu sein. Deshalb sage ich ja: einfach 
diese Datei einmal selbst erzeugen (dauert doch nur 1 Minute) und fortan 
glücklich sein :)

von Jan H. (janiiix3)


Lesenswert?

A.. P. schrieb:
> holger schrieb:
>> Was ich noch so weiß ist das diese SystemInits oft für die EVAL
>> Boards ausgelegt sind. Da ist ein 25MHz Quarz drauf. Das passt dann
>> nicht zu deinem 8MHz Quarz.
>
> Ja, scheint tatsächlich häufig so zu sein. Deshalb sage ich ja: einfach
> diese Datei einmal selbst erzeugen (dauert doch nur 1 Minute) und fortan
> glücklich sein :)

Ja krass. Geht! Scheint so als würde "EmBitz" etwas falsch machen beim 
Projekt erstellen.

von A.. P. (arnonym)


Lesenswert?

Jan H. schrieb:
> Kannst du mir mal einen Link zum Tool posten?

http://www.st.com/content/st_com/en/products/microcontrollers/stm32-32-bit-arm-cortex-mcus/stm32-mainstream-mcus/stm32f1-series/stm32f105-107/stm32f105r8.html

Das ist die Produktseite für deinen Controller. Ab da musst du schon 
selbst was tun. Einfach mal nach Clock Configuration Tool suchen. Kommt 
meistens als Zip-Datei, obwohl nur ein Excel-Sheet und eine Lizenzdatei 
drinliegen.

von Oliver P. (ollus)


Lesenswert?

> Ja krass. Geht! Scheint so als würde "EmBitz" etwas falsch machen beim
> Projekt erstellen.

Nein, EmBitz kann ja Deine Hardware nicht kennen. Man kann da Quarze von 
3-25MHz dranhängen.

von A.. P. (arnonym)


Lesenswert?

Jan H. schrieb:
> Ja krass. Geht! Scheint so als würde "EmBitz" etwas falsch machen beim
> Projekt erstellen.

Ich würde diesem EmBitz (kenne das Tool nicht) nicht grundsätzlich 
unterstellen, dass es was falsch macht. Wahrscheinlich hat es nur eine 
Standardvorlage für ein solches Projekt enthalten, wo eben der Takt für 
einen 25 MHz Quarz konfiguriert wird. Daher plädiere ich immer dafür, 
nachzusehen, was unter der Haube tatsächlich vor sich geht und nicht 
einfach alles schlucken, was einem vor die Füße geschmissen wird. Dann 
können solche Problemchen gar nicht erst entstehen.

von Jan H. (janiiix3)


Lesenswert?

A.. P. schrieb:
> Jan H. schrieb:
>> Ja krass. Geht! Scheint so als würde "EmBitz" etwas falsch machen beim
>> Projekt erstellen.
>
> Ich würde diesem EmBitz (kenne das Tool nicht) nicht grundsätzlich
> unterstellen, dass es was falsch macht. Wahrscheinlich hat es nur eine
> Standardvorlage für ein solches Projekt enthalten, wo eben der Takt für
> einen 25 MHz Quarz konfiguriert wird. Daher plädiere ich immer dafür,
> nachzusehen, was unter der Haube tatsächlich vor sich geht und nicht
> einfach alles schlucken, was einem vor die Füße geschmissen wird. Dann
> können solche Problemchen gar nicht erst entstehen.

In diesem Fall also mit diesem Controller, war es ziemlich un 
übersichtlich. Bei anderen Controller Familien, war das deutlich 
einfacher festzustellen, wo und welche Taktquelle ich gerade einstelle.

von Jan H. (janiiix3)


Lesenswert?

Habe mir gerade mal die Frequenz ausgeben lassen..
1
typedef struct
2
{
3
  uint32_t SYSCLK_Frequency;  /*!< returns SYSCLK clock frequency expressed in Hz */
4
  uint32_t HCLK_Frequency;    /*!< returns HCLK clock frequency expressed in Hz */
5
  uint32_t PCLK1_Frequency;   /*!< returns PCLK1 clock frequency expressed in Hz */
6
  uint32_t PCLK2_Frequency;   /*!< returns PCLK2 clock frequency expressed in Hz */
7
  uint32_t ADCCLK_Frequency;  /*!< returns ADCCLK clock frequency expressed in Hz */
8
}RCC_ClocksTypeDef;
1
        RCC_ClocksTypeDef SysClk;
2
3
        char buff[20];
4
        itoa(SysClk.SYSCLK_Frequency,buff,10);
5
        _uartStr(buff,USART2);
6
        _uartStr("\r\n",USART2);

Ergebniss .: 536936408 Hz

Da kommt eine ziemlich krumme Zahl raus? Ist das jetzt wirklich die 
Systemfrequenz?

von A.. P. (arnonym)


Lesenswert?

Du kannst doch nicht einfach eine Variable vom Typ eines Structs 
anlegen, ohne vorherige Initialisierung oder dass damit vorher was 
passiert ist auf seine Member zugreifen und erwarten das was sinnvolles 
bei rauskommt.

Man kann ja auch nicht einfach
1
int i;
 in seinen Code schreiben und in der nächsten Zeile erwarten, dass i = 
2017 ist.

Schau dir nochmal an, wie dieses Struct, was du verwendest, korrekt 
verwendet und befüllt wird. Hinweis: es gibt eine Methode namens 
RCC_GetClocksFreq().

: Bearbeitet durch User
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.